I have a pyramid application that uses a translation factory defined in this way:
from pyramid.i18n import get_localizer, TranslationStringFactory
from pyramid.threadlocal import get_current_request
def add_renderer_globals(event):
request = event.get('request')
if request is None:
request = get_current_request()
event['_'] = request.translate
event['localizer'] = request.localizer
tsf = TranslationStringFactory('climmob3')
def add_localizer(event):
request = event.request
localizer = get_localizer(request)
def auto_translate(string):
return localizer.translate(tsf(string))
request.localizer = localizer
request.translate = auto_translate
It works fine, however somewhere else I use jinja2 render() function to render small pieces of reusable code (snippets) as a jinja2 extension:
from jinja2 import Environment
jinjaEnv = Environment(extensions=['jinja2.ext.i18n'])
output = template.render(snippetVars=kw,renderer='snippet')
The problem here is that when I use the '_' translation function in the template code I get:
UndefinedError: 'gettext' is undefined
I saw some posts that maybe I need to use jinjaEnv.install_gettext_translations() but I cannot make it work. I tried:
jinjaEnv.install_gettext_translations(pyramid.il8n)
jinjaEnv.install_gettext_translations(tsf)
How can I integrate jinjaEnv.install_gettext_translations() with my pyramid translation factory?
Depending on your exact case, you could use pyramid_jinja2 or get inspiration from it. It creates a GetTextWrapper https://github.com/Pylons/pyramid_jinja2/blob/28944ce627745691ccd1603c56251e038aadd892/pyramid_jinja2/i18n.py that makes its way in the options passed when creating the Environment https://github.com/Pylons/pyramid_jinja2/blob/28944ce627745691ccd1603c56251e038aadd892/pyramid_jinja2/settings.py#L133
https://github.com/Pylons/pyramid_jinja2/blob/28944ce627745691ccd1603c56251e038aadd892/pyramid_jinja2/__init__.py#L394
https://github.com/Pylons/pyramid_jinja2/blob/28944ce627745691ccd1603c56251e038aadd892/pyramid_jinja2/__init__.py#L404-L405
The wrapper is needed because the localizer will change every request, depending on the user locale.
Or you can pass the gettext and ngettext arguments directly when you render. In you case, it would look something like:
localizer = request.localizer
def gt(message):
return localizer.translate(message, domain='your-domain')
def ngt(singular, plural, n):
return localizer.pluralize(singular, plural, n, domain='your-domain')
output = template.render(
snippetVars=kw,
renderer='snippet',
gettext=gt,
ngettext=ngt,
)
Related
i have a question about micro-python that how to make and call functions in micro-python or any other idea related to functions
my code throwing an error that NameError: name 'my_func' isn't defined
import time
from machine import Pin
led = Pin(2, Pin.OUT)
btn = Pin(4, Pin.IN, Pin.PULL_UP)
while True:
if not btn.value():
my_func()
while not btn():
pass
def my_func():
led(not led())
time.sleep_ms(300)
Generaly, what I do following: Imports then Functions and after that- rest of the flow
Slightly modified your code to pass LED object for function
import time
from machine import Pin
def my_func(myLed):
myLed.value(not myLed.value()) # invert boolean value
time.sleep_ms(300)
led = Pin(2, Pin.OUT)
btn = Pin(4, Pin.IN, Pin.PULL_UP)
while True:
if not btn.value():
my_func(led)
while not btn():
pass
you need to import a function before it can be called.
I know this is odd, but I'm trying to provide a pass through interface in a taglib that allows the caller to pass in any other tag to be displayed in a container with additional processing.
To this effect, I'm trying to dynamically call an arbitrary tag in an arbitrary namespace. This may be clearer by example.
GSP:
<myLib:myTag someProp="blah" anotherProp="blah2" size="80" namespace="g" tag="textField">
In my taglib, I'm trying to display the tag they pass.
Taglib:
def myTag = {
String id = //some processing, not specified by caller
attrs.put("id", id)
def namespace = attrs.remove("namespace")
def tag = attrs.remove("tag")
out << ?????
}
The problem comes after the out... I'm having trouble calling the tag. I've tried the following with the following errors
namespace.tag(attrs) //No signature of method: java.lang.String.tag()
namespace."${tag}"(attrs) //No signature of method: java.lang.String.textField()
"${namespace}"."${tag}"(attrs) //No signature of method: java.lang.String.textField()
This seems to work, but the method needs to support tags in other namespaces
g."${tag}"(attrs)
So the question is How can I use reflection to use a dynamically defined taglib?
I don't have them pass the fully formed tag in the body() because I need to interact with it in the taglib.
I believe the following works, I'm not completely certain this is the best answer, so will leave the question open for suggestions from others.
String namespace = attrs.remove("namespace")
String tag = attrs.remove("tag")
GrailsTagLibClass tagLibClass = grailsApplication.getTagLibClasses().find { it.namespace == namespace && it.hasTag(tag)}
def tagLibBean = grailsApplication.mainContext.getBean(tagLibClass.getFullName())
out << tagLibBean."${tag}"(attrs)
Grails converters can be configured to pretty print (or not) by default.
I like to use the respond method instead any MarkupBuilder, JsonBuilder or whatever other library that I should handle response format.
respond myObject
The user can query xml, json or hal.
How can I allow the user to query for a pretty print (assuming default is not)
If the user pass a parameter in the url like this:
/foos?pretty=true
How can I force the respond to pretty print?
Obs. I saw this question but they all solve the problem statically. I want to change it dinamically on request scope.
Since you want to be able to select the format based on a controller parameter, I think a Grails converter long with render() will be better than using respond(). Here's an example:
import grails.converters.*
class SomeController {
def foos() {
def pretty = params.pretty
def prettyType
def myObject = /* whatever */
if(pretty == 'xml') prettyType = XML
if(pretty == 'json') prettyType = JSON
if(prettyType) render myObject.asType(prettyType)
else render myObject
}
}
The URL would be something like: /foos?pretty=xml or /foos?pretty=json.
I am working on two parts of a program. One that creates small groovy scripts and another that executes them in a Job. Each script is used to convert information from a map to a Domain object. The job will then save the domain object for future use.
Here is a small example.
Domain
class Report {
Date date
Country country
}
Map
Map<String, String> map = new HashMap<String, String>();
map.put("date", "2015-04-21 11:31:11");
map.put("country", "United States");
Date Script
String script = "x.date = Date.parse('y-M-d h:m:s', y['date'])"
The script is currently executed using Eval.
Eval(report, map, script)
There are other more complicated scripts that need to look up information and make decisions based on values.
The date script works fine but when the country script executes I get an error.
Country Script
String script = "import app.Country\nx.country = Country.findByName(y['country'])"
Error
Script1.groovy: 1: unable to resolve class app.Country
It seems like the Country class is not getting loaded in the call to Eval. How can I do an import in Eval? Should I use Eval or GroovyShell?
You need to instantiate a GroovyShell passing as argument the grailsApplication class loader, see the example below:
Bootstrap.groovy
Map bindingValues = new HashMap()
bindingValues.sessionFactory = sessionFactory
bindingValues.propertyInstanceMap = propertyInstanceMap
bindingValues.dataSource = dataSource
bindingValues.ctx = grailsApplication.mainContext
GroovyShell gs = new GroovyShell(grailsApplication.classLoader, new Binding(bindingValues))
gs.evaluate new File("docs/CargaAvaliacoes.groovy")
CargaAvaliacoes.groovy
import avaliacao.Colaborador
import modelo.ModeloAvaliacao
import programa.Programa
def programa = Programa.get(1)
def modelo = ModeloAvaliacao.get(1)
def avaliadores = ["02270789332":"1020016","11388449681":"1010002","02231772331":"1010004","04247774332":"1020002"]
def avaliacaoService = ctx.getBean("avaliacaoService")
avaliadores.each {
def avaliador = Colaborador.findByCpf(it.key)
def avaliados = Colaborador.findAllBySetorAndCpfNotEqual(it.value,it.key)
avaliados.each {
avaliacaoService.cadastrar(programa, modelo, avaliador, it)
}
}
** You need to specify the grailsApplication.classLoader because this class loader is used to load the Grails domain classes.
I have tried, under Plone 4.3.3, to customize a class method of an archetype content type in one of my products.
I have a product bsw.produit_1 with a content type MyContent defined as follows:
class MyContent(base.ATCTContent):
implements(IMyContent)
meta_type = "MyContent"
schema = MyContent`
def ma_fonction(self):
......
return res
I want to modify the code of my function ma_fonction in another product. I have tried using an adapter and following the plone docs, but without success.
The class where I wish to customize the function:
class CustomClass(object):
""" """
implements(IMyContent)
adapts(IMyContent)
def at_post_payment_script(self, obj_transaction):
""" """
......
# My new code
return res
The configure.zcml where I declared my adapter:
<adapter for="bsw.produit_1.content.mycontent.MyContent"
provides="bsw.produit_1.interfaces.IMyContent"
factory=".customclass.CustomClass" />
In my zcml declaration, I've also tried putting archetypes.schemaextender.interfaces.ISchemaExtender as provides or putting the interface IMyContent for for instead of the class.
None of these worked, every time, the customized code is not executed. Does anybody have a solution for this?
The solution you need depends on what you want to achieve.
But archetypes.schemaextender is the wrong solution.
schemaextender is there to modify the schema, this includes:
fields order
field/widget attributes
schemata
setter/getter of a field
new fields
override fields
To implement your own adaptera is definitely the right approach.
First you need to implement a adapter for the default behavior.
Second, you need to adapt the context and the request. The request is important, since that's a way to define a more specific adapter if your other product is installed.
Python code for the default implementation (adapter.py):
from zope.component import adapts
from zope.interface import Interface
from zope.interface import implements
class IBehavior(Interface):
def __init__(context, request)
"""Adapts context and request"""
# ... more ...
class DefaultBehavior(object):
implements(IBehavior)
adapts(IMyContent, Interface) # IMPORTAN two discriminators
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your default implementation goes here.
Register the adapter with zcml:
<adapter factory=".adapter.DefaultBehavior" />
Your now able to call the default adapter in ma_fonction
from zope.component import getMultiAdapter
class MyContent(base.ATCTContent)
def ma_fonction(self):
adapter = getMultiAdapter((self, self.REQUEST), IDefaultBehavior)
return adapter()
Now you can implement a more specific adapter in your other product using a browserlayer. Check documentation, how to register a browserlayer
In your otherpackage you can now register a adapter which implements the same IBehavior interface, but also adapts your browserlayer.
from other.package.interfaces import IOtherPackageLayer
from zope.component import adapts
from zope.interface import implements
class DifferenBehavior(object):
implements(IBehavior)
adapts(IMyContent, IOtherPackageLayer) # IMPORTAN adapt the browserlayer not Interface
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your different implementation goes here.
Register also with zcml:
<adapter factory=".adapter.DifferenBehavior" />
Your ma_fonctionnow calls the default adapter, if the other package is not installed. And the different adapter if the other package is installed.
The simplest method you can use (although not politically correct!) is monkey-patching.
Take a look at collective.monkeypatcher, you simply need a configuration like that (in your 3rd party product):
<monkey:patch
description=""
class="your.package.MyContent"
original="ma_fonction"
replacement=".monkeys.new_ma_fonction"
/>
Then in your package create also a monkeys.py module with the new method inside:
def new_ma_fonction(self):
# do stuff
return res