Error: undeclared field: 'captures' for type nre.RegexMatch - regex

I'm trying to match a given string with nre:
from nre import findIter, re
const sourceString = """
39
00:04:01,116 --> 00:04:01,783
Attrape.
"""
let srtRex = re"\d+\R\d+:\d+:\d+,\d+ --> \d+:\d+:\d+,\d+\R(\w+)"
for m in findIter(sourceString, srtRex, 0):
echo(m.captures[0])
This doesn't compile though, it fails with Error: undeclared field: 'captures' for type nre.RegexMatch [declared in /usr/local/Cellar/nim/1.2.6/nim/lib/impure/nre.nim(149, 3)].
This is weird, because if I do echo(m), I get the raw strings, so the match itself worked fine. It's only this field I can't access. And that is weird, because in this issue the (working) example code is pretty much the same.

Importing whole modules is idiomatic in Nim, and leads to ambiguities rarely, thanks to a strong type system. see https://narimiran.github.io/2019/07/01/nim-import.html for a great rundown on why Nim doesn't share Python's import issues.
However, here's how to do what you want to do, even if it's not idiomatic Nim:
You're using more than just re and findIter, you also use the proc captures, and the [] proc, so your import line needs to be:
from nre import findIter, re, captures, `[]`
or, for complete namespace separation, but quite ugly, you can:
from nre import nil
let srtRex = nre.re"\d+\R\d+:\d+:\d+,\d+ --> \d+:\d+:\d+,\d+\R(\w+)"
for m in nre.findIter(sourceString, srtRex, 0):
echo(nre.`[]`(nre.captures(m),0))

It seems to be the imports. It works with import nre instead of from nre import findIter, re. But why? I want to keep my namespace clean!

Related

Searching for strings with BeuatifulSoup

I expected that the following code
from bs4 import BeautifulSoup
import re
sopa = BeautifulSoup('<ol><li>this is a string</li></ol>')
sopa.find_all(string=re.compile("a"))
would return [u'this is a string'] but it returns []. Why?
The BeautifulSoup 4 documentation gives this example:
soup.find_all(string=re.compile("Dormouse"))
which, when acting on a soup of an Alice in Wonderland excerpt, is supposed to return
[u"The Dormouse's story", u"The Dormouse's story"]
The documentation also says that bs4 uses re.match() (which matches the beginning of a string) but other places (as well as this example from the official docs) indicate re.search(), and changing the regex "a" to "this" has no effect on the result in any case.
Well it can also work if you print last line, I've tried, its working
print(sopa.find_all(string=re.compile("a")))
You can also get text by
print(sopa.getText())
and 3rd method
print(sopa.get_text())

How to return a lazy translation object with placeholders?

In my Django v1.6.5 project running on Python v2.7.x, I have a Model that returns its configuration as a string. I need the returned string to be a gettext_lazy object, so I can evaluate it in any language required later.
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _, string_concat
...
class MyModel(models.Model):
key = models.CharField(...)
value = models.CharField(...)
#property
def config_str(self):
return _('some configuration')
This seems to work fine in these scenarios:
Static string: (see above) - works!
String concatenation: return string_concat(self.key, _(' equals '), self.value) - works!
What is not working, is using gettext_lazy with placeholders, a la:
return _('“%(key)s” equals “%(value)s”' % {key: self.key, value: self.value})
or using the .format() mechanism:
return _('“{key}” equals “{value}”').format(key=self.key, value=self.value)
When I do this, my .po file does contain:
#, python-format
msgid "“%(key)s” equals “%(value)s”" or
msgid "«{key}» equals «{value}»"
but even when I populate this Eg.:
msgstr "«%(key)s» est égal à «%(value)s»" or
msgstr "«{key}» est égal à «{value}»"
and I run compilemessages, the translation seems to be ignored. When I translate the promise returned by the model instance, I always get an EN string with the placeholders filled E.g., '“foo” equals “bar”'. Note, I get an EN string even when the first calling context is FR (for example). This tells me that the translations just aren't even occurring. It is my theory that by the time I eval the lazy object, gettext is looking for the literal string "“foo” equals “bar”" (for example) in the translation catalog rather than something with placeholders and named values.
With this in mind, I've also tried wrapping the whole format() in the lazy object like this:
return _('“{key}” equals “{value}”'.format(key=self.key, value=self.value))
But it seems to have made zero difference. =/
I can get by with string_concat() for now, but sometimes, the placeholders will need to be moved around in some translations, so I'd like to figure this out.
I'm beginning to think that one simply cannot use placeholders with gettext_lazy.
NOTE: I have reviewed django: Translation with variables inside, but a) that has no accepted answer and b) he's using gettext, not gettext_lazy.
OK, the solution here is to provide an extra layer of laziness (Thanks, Django core dev: Florian Apolloner AKA “apollo13”).
Here's my modified function that WORKS:
from django.utils import six
from django.utils.functional import lazy
class MyModel(models.Model):
key = models.CharField(...)
value = models.CharField(...)
#property
def configuration_string(self):
def wrapper():
return _('“{key}” equals “{value}”').format(
key=self.key,
value=self.value
)
return lazy(
wrapper,
six.text_type
)
The only thing is, where I use this, I must remember to eval the wrapper function as follows:
from django.utils.encoding import force_text
config = my_model_instance.configuration_string
# NOTE: Evaluate the lazy function wrapper inside the force_text()
config_str = force_text(config())
Now, in my case, I need to support cases where 3rd party devs write the function configuration_string returning either the lazy function wrapper, a lazily evaluated translation string or just a regular string, so I use:
import types
from django.utils.encoding import force_text
from django.functional import Promise
config = my_model_instance.configuration_string
if isinstance(config, types.FunctionType):
config_str = force_text(config())
elif isinstance(config, Promise):
config_str = force_text(config)
else:
config_str = config
Thanks again to Apollo13 for guidance!
I had a very similar problem and found that using gettext_noop instead of gettext_lazy worked for me available since Django 1.11.

TypeError : 'NoneType' object not callable Python with BeautifulSoup XML

I have the following XML file :
<user-login-permission>true</user-login-permission>
<total-matched-record-number>15000</total-matched-record-number>
<total-returned-record-number>15000</total-returned-record-number>
<active-user-records>
<active-user-record>
<active-user-name>username</active-user-name>
<authentication-realm>realm</authentication-realm>
<user-roles>Role</user-roles>
<user-sign-in-time>date</user-sign-in-time>
<events>0</events>
<agent-type>text</agent-type>
<login-node>node</login-node>
</active-user-record>
There are many records
I'm trying to get values from tags and save them in a different text file using the following code :
soup = BeautifulSoup(open("path/to/xmlfile"), features="xml")
with open('path/to/outputfile', 'a') as f:
for i in range(len(soup.findall('active-user-name'))):
f.write ('%s\t%s\t%s\t%s\n' % (soup.findall('active-user-name')[i].text, soup.findall('authentication-realm')[i].text, soup.findall('user-roles')[i].text, soup.findall('login-node')[i].text))
I get the error TypeError : 'NoneType' object not callable Python with BeautifulSoup XML for line : for i in range(len(soup.findall('active-user-name'))):
Any idea what could be causing this?
Thanks!
There are a number of issues that need to be addressed with this, the first is that the XML file you provided is not valid XML - a root element is required.
Try something like this as the XML:
<root>
<user-login-permission>true</user-login-permission>
<total-matched-record-number>15000</total-matched-record-number>
<total-returned-record-number>15000</total-returned-record-number>
<active-user-records>
<active-user-record>
<active-user-name>username</active-user-name>
<authentication-realm>realm</authentication-realm>
<user-roles>Role</user-roles>
<user-sign-in-time>date</user-sign-in-time>
<events>0</events>
<agent-type>text</agent-type>
<login-node>node</login-node>
</active-user-record>
</active-user-records>
</root>
Now onto the python. First off there is not a findall method, it's either findAll or find_all. findAll and find_all are equivalent, as documented here
Next up I would suggest altering your code so you aren't making use of the find_all method quite so often - using find instead will improve the efficiency, especially for large XML files. Additionally the code below is easier to read and debug:
from bs4 import BeautifulSoup
xml_file = open('./path_to_file.xml', 'r')
soup = BeautifulSoup(xml_file, "xml")
with open('./path_to_output_f.txt', 'a') as f:
for s in soup.findAll('active-user-record'):
username = s.find('active-user-name').text
auth = s.find('authentication-realm').text
role = s.find('user-roles').text
node = s.find('login-node').text
f.write("{}\t{}\t{}\t{}\n".format(username, auth, role, node))
Hope this helps. Let me know if you require any further assistance!
The solution is simple: don't use findall method - use find_all.
Why? Because there is no findall method at all, there are findAll and find_all, which are equivalent. See docs for more information.
Though, I agree, error message is confusing.
Hope that helps.
The fix for my version of this problem is to coerce the BeautifulSoup instance into a type string. You do this following:
https://groups.google.com/forum/#!topic/comp.lang.python/ymrea29fMFI
you use the following pythonic:
From python manual
str( [object])
Return a string containing a nicely printable representation of an
object. For strings, this returns the string itself. The difference
with repr(object) is that str(object) does not always attempt to
return a string that is acceptable to eval(); its goal is to return a
printable string. If no argument is given, returns the empty string,

Call overloaded methods from Ironpython

I would like to call the Curve.Trim(CurveEnd, Double) method from the RhinoCommon API via IronPython. How can I make sure I don't get the overload for Curve.Trim(Double, Double)?
crv.Trim(geo.CurveEnd.End, 8.8)
#raised: Message: expected float, got CurveEnd
Note: If you want to try it yourself you will need to install a trial version of Rhino. It includes a Python editor.
Edit / Addition: the .Overloads property as mentioned by Jeff does not work here either. A snippet for testing:
import rhinoscriptsyntax as rs
import Rhino.Geometry as geo
import System
# first draw a curve longer than 8.8 units
crvO = rs.GetObject() # to pick that curve on the 3d GUI screen
crv = rs.coercecurve(crvO) # to get Rhino.Geometry.Curve
# these both don't work:
crv.Trim(geo.CurveEnd.End, 8.8)
#Message: expected float, got CurveEnd
crv.Trim.Overloads[geo.CurveEnd, System.Double](geo.CurveEnd.End, 8.8)
#Message: Trim() takes at least 2147483647 arguments (2 given)
rhinscriptsyntax is a library based on Rhino namespace from RhinoCommon
Use the .Overloads property to access a method's overloads:
csv.Trim.Overloads[CurveEnd, float](geo.CurveEnd.End, 8.8)
The docs.
I'm late to the party. But this code works (out the override).
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
import System
crv_id = rs.GetObject()
crv = rs.coercecurve(crv_id)
trimmed = crv.Trim(Rhino.Geometry.CurveEnd.End, 4)
sc.doc.Objects.Replace(crv_id, trimmed)
sc.doc.Views.Redraw()

Django validation array of errors

I am using
rf['email'].errors
As said in docs, I can use it to have array of errors.
[str(e) for e in rf['email'].errors] #give me ["<django.utils.functional.__proxy__>"]
If repr or str - it gives ul's or string of array.
So it worked only when I used repr and eval together. But I think its stupid solution.
eval(`rf['email'].errors`)
You have a couple options depending on the output you'd like.
Option one, use the unicode constructor to convert the data:
list_of_error_texts = [unicode(e) for e in rf['email'].errors]
(Django's proxy object implements a method that responds to unicode.)
Option two, get the ErrorList as text. This produces a newline separated list of error text, with each line preceded by an asterisk:
print rf['email'].errors.as_text()
* My error one
* My error two
Option three, use django's force_unicode function. This is like unicode, but has some extra safety features:
from django.utils.encoding import force_unicode
list_of_error_texts = [force_unicode(e) for e in rf['email'].errors]