# HG changeset patch # User cmlenz # Date 1212350968 0 # Node ID 01bdf155db95128e73cd41480dd2099bc72eadad # Parent 5e9d250ad3ad56df76da101bb515f3f50d82418e Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch. diff --git a/genshi/template/base.py b/genshi/template/base.py --- a/genshi/template/base.py +++ b/genshi/template/base.py @@ -244,6 +244,10 @@ """ return [(key, self.get(key)) for key in self.keys()] + def update(self, mapping): + """Update the context from the mapping provided.""" + self.frames[0].update(mapping) + def push(self, data): """Push a new scope on the stack. diff --git a/genshi/template/eval.py b/genshi/template/eval.py --- a/genshi/template/eval.py +++ b/genshi/template/eval.py @@ -33,6 +33,28 @@ 'Undefined', 'UndefinedError'] __docformat__ = 'restructuredtext en' +# Check for a Python 2.4 bug in the eval loop +try: + class _FakeMapping(object): + __getitem__ = __setitem__ = lambda *a: None + exec 'from sys import *' in {}, _FakeMapping() +except SystemError: + has_star_import_bug = True +else: + has_star_import_bug = False +del _FakeMapping + +def _star_import_patch(mapping, modname): + """This function is used as helper if a Python version with a broken + star-import opcode is in use. + """ + module = __import__(modname, None, None, ['__all__']) + if hasattr(module, '__all__'): + members = module.__all__ + else: + members = [x for x in module.__dict__ if not x.startswith('_')] + mapping.update((name, getattr(module, name)) for name in members) + class Code(object): """Abstract base class for the `Expression` and `Suite` classes.""" @@ -270,6 +292,7 @@ '_lookup_name': cls.lookup_name, '_lookup_attr': cls.lookup_attr, '_lookup_item': cls.lookup_item, + '_star_import_patch': _star_import_patch, 'UndefinedError': UndefinedError, } globals = classmethod(globals) @@ -492,6 +515,16 @@ node.doc, self.visit(node.code) ) + def visitFrom(self, node): + if not has_star_import_bug or node.names != [('*', None)]: + # This is a Python 2.4 bug. Only if we have a broken Python + # version we have to apply the hack + return node + return ast.Discard(ast.CallFunc( + ast.Name('_star_import_patch'), + [ast.Name('__data__'), ast.Const(node.modname)], None, None + ), lineno=node.lineno) + def visitFunction(self, node): args = [] if hasattr(node, 'decorators'): diff --git a/genshi/template/tests/eval.py b/genshi/template/tests/eval.py --- a/genshi/template/tests/eval.py +++ b/genshi/template/tests/eval.py @@ -571,6 +571,12 @@ suite.execute(data) assert 'ifilter' in data + def test_import_star(self): + suite = Suite("from itertools import *") + data = {} + suite.execute(data) + assert 'ifilter' in data + def test_for(self): suite = Suite("""x = [] for i in range(3):