i18n translation with a different domain in .py files - python

I'm a little confused on i18n translations in py files. I have a string where what needs to be translated is already in the plone domain in plone.pot so I want to specify the domain to be plone for that translation only. When I do the following, I get an error. And, this does get rendered in a page template so there's no need to call the translate function, is this correct?
raise ValueError(_(u'Some string', domain='plone'))
TypeError: __call__() got an unexpected keyword argument 'domain'
How should this be done? Thanks a lot!

You need to have two different message factories, i.e. where you do
from zope.i18nmessageid import MessageFactory
_ = MessageFactory('my.package')
you should be also instantiating the Plone one.
_p = MessageFactory('plone')
Then _p('Contributors') would give you the translated string.
Have a look here too.

Related

How to solve "ECitMatch() got multiple values for argument 'bdata'"?

I am new to use bioservices Python package. Now I am going to use that to retrieve PMIDs for two citations, given the specified information and this is the code I have tried:
from bioservices import EUtils
s = EUtils()
print(s.ECitMatch("pubmed",retmode="xml", bdata="proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|%0Dscience|1987|235|182|palmenberg+ac|Art2|"))
But it occurs an error:
"TypeError: ECitMatch() got multiple values for argument 'bdata'".
Could anyone help me to solve that problem?
I think the issue is that you have an unnamed argument (pubmed); if you look at the source code, you can see that the first argument should be bdata; if you provide the arguments like you do, it is, however, unclear whether bdata is "pubmed" or the named argument bdata, therefore the error you obtain.
You can reproduce it with this minimal example:
def dummy(a, b):
return a, b
dummy(10, a=3)
will return
TypeError: dummy() got multiple values for argument 'a'
If you remove "pubmed", the error disappears, however, the output is still incomplete:
from bioservices import EUtils
s = EUtils()
print(s.ECitMatch("proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|%0Dscience|1987|235|182|palmenberg+ac|Art2|"))
returns
'proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|2014248\n'
so only the first publication is taken into account. You can get the results for both by using the correct carriage return character \r:
print(s.ECitMatch(bdata="proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|\rscience|1987|235|182|palmenberg+ac|Art2|"))
will return
proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|2014248
science|1987|235|182|palmenberg+ac|Art2|3026048
I think you neither have to specify retmod nor the database (pubmed); if you look at the source code I linked above you can see:
query = "ecitmatch.cgi?db=pubmed&retmode=xml"
so seems it always uses pubmed and xml.
Two issues here: syntaxic and a bug.
The correct syntax is:
from bioservices import EUtils
s = EUtils()
query = "proc+natl+acad+sci+u+s+a|1991|88|3248|mann+bj|Art1|%0Dscience|1987|235|182|palmenberg+ac|Art2|"
print(s.ECitMatch(query))
Indeed, the underlying service related to ICitMatch has only one database (pubmed) and one format (xml) hence, those 2 parameters are not available : there are hard-coded. Therefore, only one argument is required: your query.
As for the second issue, as pointed above and reported on the bioservices issues page, your query would return only one publication. This was an issue with the special character %0D (in place of a return carriage) not being interpreted corectly by the URL request. This carriage character (either \n, \r or %0d) is now taken into account in the latest version on github or from pypi website if you use version 1.7.5
Thanks to willigot for filling the issue on bioservices page and bringing it to my attention.
disclaimer: i'm the main author of bioservices

Django domain + regex parameter not working on production machine

I currently have a django view with a fairly simple search function (takes user input, returns a list of objects). For usability, I'd like the option of passing search paramters via url like so:
www.example.com/search/mysearchstring
Where mysearchstring is the input to the search function. I'm using regex to validate any alphanumeric or underscore characters.
The problem I'm having is that while this works perfectly in my development environment, it breaks on the live machine.
Currently, I am using this exact same method (with different regex patterns) in other django views without any issues. This leads me to believe that either.
1) My regex is truly bad (more likely)
2) There is a difference in regex validators between environments (less likely)
The machine running this is using django 1.6 and python 2.7, which are slightly behind my development machine, but not significantly.
urls.py
SEARCH_REGEX = '(?P<pdom>\w*)?'
urlpatterns = patterns('',
....
url(r'^polls/search/' + SEARCH_REGEX, 'polls.views.search'),
...)
Which are passed to the view like this
views. py
def search(request, pdom):
...
When loading up the page, I get the following error:
ImproperlyConfigured: "^polls/search/(?P<pdom>\w*)?" is not a valid regular expression: nothing to repeat
I've been scratching my head over this one for a while. I've attempted to use a few different methods of encapsulation around the expression with no change in results. Would appreciate any insight!
I would change it to this:
SEARCH_REGEX = r'(?P<pdom>.+)$'
It's usually a good idea to use raw strings r'' for regular expressions in python.
The group will match the entire content of the search part of your url. I would handle query string validation in the view, instead of in the url regex. If someone tries to search polls/search/two+words, you should not return a 404, but instead a 400 status and a error message explaining that the search string was malformed.
Finally, you might want to follow the common convention for search urls. Which is to use a query parameter called q. So your url-pattern would be ^polls/search/$, and then you just handle the q in the view using something like this:
def search_page_view(request):
query_string = request.GET.get('q', '')

How to properly set variables in a latex template for Django

I want to create a pdf with latex through a django view. I created the view and set up a latex template and it works fine except for one thing. When I place a variable in the latex template I have to use spaces around the curly brackets like so:
\somevalue{ {{variable}} }
Otherwise django won't check that it is as a variable. The latex syntax checker already tells me "Unintendes whitespace around }?!". I can pass the variable into the template through my view and the pdf get created but then I have whitespaces around the inserted text.
Does anybody has an idea how to solve this?
Based on some google research, I'd recommend switching templating engines to Jinja, which is supported by Django and has configurable syntax.
Be warned, I haven't fully tested this.
Here's how your latex templates would look like:
\somevalue{((variable))}
The most important part is setting the variable_start_string and variable_end_string options:
>>> import jinja2
>>> env = jinja2.Environment(variable_start_string='((', variable_end_string='))')
>>> t = env.from_string("\somevalue{((variable))}")
>>> t.render(name='Attention!')
'\\somevalue{Attention!}'
Jinja's switching documentation outlines the (few) syntax differences. From the FAQ:
The default syntax of Jinja2 matches Django syntax in many ways. However this similarity doesn’t mean that you can use a Django template unmodified in Jinja2. For example filter arguments use a function call syntax rather than a colon to separate filter name and arguments. Additionally the extension interface in Jinja is fundamentally different from the Django one which means that your custom tags won’t work any longer.
Django 1.9 and 1.8 and maybe other versions have built-in support for Jinja.
I haven't found an example of configuring Jinja syntax in Django, and I can't test this at the moment but I believe you need to change the
TEMPLATES['OPTIONS'] dictionary as needed:
block_start_string='(#',
block_end_string='#)',
variable_start_string='((',
variable_end_string='))',
comment_start_string='((#',
comment_end_string='#))',
The solution I found is to remove extra spaces after template rendering:
template = select_template(self.get_template_names())
latex_content = template.render(context)
latex_content = re.sub(r'\{ ', '{', latex_content)
latex_content = re.sub(r' \}', '}', latex_content)
This has the benefit of not requiring extra template tags flooding the template. However this as the drawback to require template writers to be aware of this behavior and take it into account wherever curly braces are used.
In practice, it would probably be better to write a custom Template class that handles this.
Edit
Note that using this method, there is no reason to use a space as separator rather than any other character. In order to make it clearer for template writers/readers, you can use another character that would ring him a bell. For instance:
template.tex
\somevalue{§{{ variable }}§}
views.py
template = select_template(self.get_template_names())
latex_content = template.render(context)
latex_content = re.sub(r'\{§', '{', latex_content)
latex_content = re.sub(r'§\}', '}', latex_content)
Which makes it clear that if there is a space, it is intended. And I think it's already clear that § everywhere is not intended to be displayed.

How to, provide URL parameters using github-flask for {+path}?

First, I am a total n00b to Python. I am using github-flask, and flask obviously, to pull data from the GitHub API. I am trying to use the contents_url and retrieve a file. The URL from the GitHub API is something like:
// json
{
...
"contents_url": "https://api.github.com/repos/<org_name>/<repo_name>/contents/{+path}"
...
}
... and when I try and give that to the github-flask instance I get a TypeError, "TypeError: request() got an unexpected keyword argument 'path'" using:
# python
contents = github.get(repo['contents_url'], path='.gitignore')
I'm pretty sure I am missing something simple. I don't have to resort to string manipulation do I?
Python's recommended string interpolation is the .format method. Your code will work with that with just a few minor changes:
contents = github.get(repo['contents_url'].format(path='.gitignore'))
But you'll also have to change your contents_url slightly:
https://api.github.com/repos/<org_name>/<repo_name>/contents/{path}
Just be careful - .format interpolates based on curly braces, so any literal curly braces need to be escaped. More information is available here: https://docs.python.org/3/library/string.html#formatstrings
Edit: As you mentioned in the comment below, the URL is coming directly from GitHub's API and you can't/shouldn't change it. It turns out they're using RFC 6570 URL templates (see https://developer.github.com/v3/#hypermedia). If you use the uritemplate library I suggested below, the code will look like this:
from uritemplate import expand
# ...
contents = github.get(expand(repo['contents_url'], {'path': '.gitignore'}))

Template tags successfully translated but ugettext_lazy() in utils not translating

I successfully managed to get trans and blocktrans to translate text.
However...
I have a function defined in utils.py that returns a dictionary containing strings of which some of them I need converted to the current language.
EDIT: *This is a utils.py that I've created in my project directory that are called by views to perform certain auxillary functions on a dict and then return the updated dict
I have done something like this:
try:
path = default_storage.save(customercode + '/' + file.name, ContentFile(file.read()))
results['status'] = 'success'
results['message'] = _(u'Your file has been successfully uploaded')
except Exception as e:
results['status'] = 'error'
results['message'] = _(u'There was an error uploading your file: ') + str(e)
return results
I have also added from django.utils.translation import ugettext_lazy as _ to the top of this utils.py file..
And this "results" dictionary is used in one of my views wherein the whole dictionary after some further processing is passed as a context variable to the template.
I have correctly set the translation in the .po file. All other template tags translate perfectly. Only the above mentioned strings do not translate.
Any help would be greatly appreciated.
UPDATE: I tried the same process in a forms filed label and it translated just fine. It's only the aforementioned areas where it won't translate!
PS: This is my first question on stackoverflow. I apologize in advance if I've made mistakes asking this question.
Just as I expected,
I was making a very silly mistake. I accessed the incorrect variable in the template while trying to print the translated value! >_<
But I guess one thing I've learnt is staying away from a problem and then coming back to it after a long time helps. You've got to learn the problem again and that sometimes helps you find silly bugs like these!

Categories