Hello,
I am trying to implement Nunjucks' RemoteExtension in Jinja2.
The RemoteExtension info is
at http://mozilla.github.io/nunjucks/api.html#custom-tags
And I am using as a base example the FragmentCacheExtension example from
the docs: http://jinja.pocoo.org/docs/dev/extensions/#example-extension
The idea is to be able to request remote content (identified by a given
URL) and act upon it.
An example template might look like this:
content before
{% remote "http://google.com.br" %}
do something when the request is ok
{% error %}
do something else when the request failed
{% endremote %}
content after
Here is the extension class I wrote:
1. import jinja2
2. import jinja2.ext
3. import jinja2.nodes
4. import tornado.httpclient
5.
6. class RemoteExtension(jinja2.ext.Extension):
7.
8. tags = set(['remote'])
9.
10. def __init__(self, environment):
11. super(RemoteExtension, self).__init__(environment)
12. # TODO: Add some defaults?!
13.
14. def parse(self, parser):
15. lineno = parser.stream.next().lineno
16. args = [parser.parse_expression()]
17. body = parser.parse_statements(['name:endremote',
'name:error'])
18. args += body
19. if parser.stream.skip_if('name:error'):
20. error_body = parser.parse_statements(['name:endremote'],
drop_needle=True)
21. else:
22. error_body = [jinja2.nodes.Const(None)]
23. parser.stream.skip()
24. args += error_body
25.
26. # this works: return jinja2.nodes.Const('simple text')
27.
28. # this gives the error: "NameError: global name 't_1' is not
defined"
29. return jinja2.nodes.CallBlock(self.call_method(
'_remote_support', args), [], [], []).set_lineno(lineno)
30.
31. def get_http_client(self):
32. return tornado.httpclient.AsyncHTTPClient()
33.
34. def _remote_support(self, url, body, error_body, caller):
35. # TODO: perform async HTTP request with Tornado (check if
it's at all possible...?!)
36. pass
When I run my program, the template is loaded and parsed (seemingly
correctly) but the failure occurs when the rendering is executed.
ERROR:tornado.application:Uncaught exception GET / (::1)
HTTPServerRequest(protocol='http', host='localhost:5001', method='GET',
uri='/', version='HTTP/1.1', remote_ip='::1', headers={'Accept-Language':
'pt-BR,pt;q=0.8,he;q=0.6,en;q=0.4,es;q=0.2', 'Accept-Encoding': 'gzip,
deflate, sdch', 'Host': 'localhost:5001', 'Accept':
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36',
'Connection': 'keep-alive', 'Cookie':
'_xsrf=2|0ec96e53|896b633859a2ccf783ab4cd6a0f609fb|1415573549;
brlvs=bc386d71-595d-4f55-84fd-e3396067fdbe; s_v19=1420032782119;
s_ria=flash%2016%7Csilverlight%20not%20detected;
nav23155=13777809082_1131_8:15:14:11_PortoAlegre:SmallAppliance-Household-Family:Movie-Vehicle-Funny:Explorers;
s_val=http%3A%2F%2Flocalhost%3A8080%2Fparceiros.html%7C; s_cc=true;
dmpaudm=; dmpaudc=00000m_000000;
uv=1272ab117a197e17cdce5911ee2621542c5b4a31548fe8028573d61ce84dc12cc7b8bb3de8cedeeee;
_ga=GA1.1.1072705065.1420032782', 'Cache-Control': 'max-age=0'})
Traceback (most recent call last):
File
"/Users/roi.avidan/.virtualenvs/renderer/lib/python2.7/site-packages/tornado/web.py",
line 1332, in _execute
result = method(*self.path_args, **self.path_kwargs)
File "/Users/roi.avidan/code/python/Terra/renderer/app.py", line 11, in
get
return self.render2('remote.html', **data)
File "/Users/roi.avidan/code/python/Terra/renderer/HandlerWithJinja.py",
line 46, in render2
content = self.render_template(template_name, **kwargs)
File "/Users/roi.avidan/code/python/Terra/renderer/HandlerWithJinja.py",
line 24, in render_template
content = template.render(kwargs)
File
"/Users/roi.avidan/.virtualenvs/renderer/lib/python2.7/site-packages/jinja2/environment.py",
line 969, in render
return self.environment.handle_exception(exc_info, True)
File
"/Users/roi.avidan/.virtualenvs/renderer/lib/python2.7/site-packages/jinja2/environment.py",
line 742, in handle_exception
reraise(exc_type, exc_value, tb)
File "templates/remote.html", line 2, in top-level template code
{% remote "http://google.com.br" %}
*NameError: global name 't_1' is not defined*
I should add that I am using Jinja2 with Tornado, hence the tornado
references in the above stack trace.
Have been able to trace the error up to a certain point in the file
"environment.py":
class Template(object):
...
def render(self, *args, **kwargs):
"""This method accepts the same arguments as the `dict` constructor:
A dict, a dict subclass or some keyword arguments. If no arguments
are given the context will be empty. These two calls do the same::
template.render(knights='that say nih')
template.render({'knights': 'that say nih'})
This will return the rendered template as unicode string.
"""
vars = dict(*args, **kwargs)
try:
return concat(self.root_render_func(self.new_context(vars))) * <----
exception happens here*
except Exception:
exc_info = sys.exc_info()
return self.environment.handle_exception(exc_info, True)
Since Jinja compiles it's templates, I am not able to get into the point
where the exception occurs and inspect the stack trace, but I was able to
obtain the generated template code used for my function:
from __future__ import division
from jinja2.runtime import LoopContext, TemplateReference, Macro, Markup,
TemplateRuntimeError, missing, concat, escape, markup_join, unicode_join,
to_string, identity, TemplateNotFound
name = 'remote.html'
def root(context, environment=environment):
if 0: yield None
yield u'before\n'
def macro():
t_1 = []
pass
return concat(t_1)
caller = Macro(environment, macro, None, (), (), False, False, False)
yield
context.call(environment.extensions['RemoteExtension.RemoteExtension']._remote_support,
'http://google.com.br',
t_1.append(
u'\nok body\n',
),
t_1.append(
u'\nerror body\n',
), caller=caller)
yield u'\nafter'
blocks = {}
debug_info = '2=8'
I am not sure what I am doing wrong.
Any help is most appreciated!!
Thanks in advance,
Roi
--
You received this message because you are subscribed to the Google Groups
"pocoo-libs" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/pocoo-libs.
For more options, visit https://groups.google.com/d/optout.