Objects which are backed by native extensions do not provide
a __call__ attribute, but are none the less callable if the
native extension provides a 'tp_call' implementation.
The jinja2.runtime.Context.call method unconditionally
access the '__call__' attribute causing an exception to be
raised if the object was a native extension method.
A demo of the problem can be seen using PyGObject:
$ cat demo.py
#!/usr/bin/python
from gi.repository import Gio
from jinja2 import Environment
f = Gio.File.new_for_path("/some/file.txt")
print f.get_uri()
t = Environment().from_string("""{{f.get_uri()}}""")
print t.render(f=f)
Which when run results in
$ ./demo.py
file:///some/file.txt
Traceback (most recent call last):
File "./demo.py", line 10, in <module>
print t.render(f=f)
File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 969, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 742, in handle_exception
reraise(exc_type, exc_value, tb)
File "<template>", line 1, in top-level template code
AttributeError: 'gi.FunctionInfo' object has no attribute '__call__'
After this patch it produces
$ ./demo.py
file:///some/file.txt
file:///some/file.txt
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
__traceback_hide__ = True # noqa
# Allow callable classes to take a context
- fn = __obj.__call__
- for fn_type in ('contextfunction',
- 'evalcontextfunction',
- 'environmentfunction'):
- if hasattr(fn, fn_type):
- __obj = fn
- break
+ if hasattr(__obj, '__call__'):
+ fn = __obj.__call__
+ for fn_type in ('contextfunction',
+ 'evalcontextfunction',
+ 'environmentfunction'):
+ if hasattr(fn, fn_type):
+ __obj = fn
+ break
if isinstance(__obj, _context_function_types):
if getattr(__obj, 'contextfunction', 0):