comparison markup/eval.py @ 116:c77c113846d6 trunk

Merged [135:138/branches/experimental/cspeedups].
author cmlenz
date Tue, 01 Aug 2006 17:06:03 +0000
parents 5f9af749341c
children c392d38694d9
comparison
equal deleted inserted replaced
115:e92fb402ee04 116:c77c113846d6
69 """Create the expression. 69 """Create the expression.
70 70
71 @param source: the expression as string 71 @param source: the expression as string
72 """ 72 """
73 self.source = source 73 self.source = source
74 self.code = self._compile(source, filename, lineno) 74 self.code = _compile(source, filename, lineno)
75 75
76 def __repr__(self): 76 def __repr__(self):
77 return '<Expression "%s">' % self.source 77 return '<Expression "%s">' % self.source
78 78
79 def evaluate(self, data): 79 def evaluate(self, data):
85 retval = eval(self.code) 85 retval = eval(self.code)
86 if callable(retval): 86 if callable(retval):
87 retval = retval() 87 retval = retval()
88 return retval 88 return retval
89 89
90 def _compile(self, source, filename, lineno): 90
91 tree = parse(self.source, 'eval') 91 def _compile(source, filename=None, lineno=-1):
92 xform = ExpressionASTTransformer() 92 tree = parse(source, 'eval')
93 tree = xform.visit(tree) 93 xform = ExpressionASTTransformer()
94 94 tree = xform.visit(tree)
95 if isinstance(filename, unicode): 95
96 # pycodegen doesn't like unicode in the filename 96 if isinstance(filename, unicode):
97 filename = filename.encode('utf-8', 'replace') 97 # pycodegen doesn't like unicode in the filename
98 tree.filename = filename or '<string>' 98 filename = filename.encode('utf-8', 'replace')
99 99 tree.filename = filename or '<string>'
100 gen = ExpressionCodeGenerator(tree) 100
101 if lineno >= 0: 101 gen = ExpressionCodeGenerator(tree)
102 gen.emit('SET_LINENO', lineno) 102 if lineno >= 0:
103 103 gen.emit('SET_LINENO', lineno)
104 return gen.getCode() 104
105 105 return gen.getCode()
106 def _lookup_name(data, name, locals=None): 106
107 val = data.get(name) 107 def _lookup_name(data, name, locals=None):
108 if val is None and locals: 108 val = data.get(name)
109 val = locals.get(name) 109 if val is None and locals:
110 if val is None: 110 val = locals.get(name)
111 val = getattr(__builtin__, name, None) 111 if val is None:
112 return val 112 val = getattr(__builtin__, name, None)
113 _lookup_name = staticmethod(_lookup_name) 113 return val
114 114
115 def _lookup_attribute(data, obj, key): 115 def _lookup_attribute(data, obj, key):
116 if hasattr(obj, key): 116 if hasattr(obj, key):
117 return getattr(obj, key) 117 return getattr(obj, key)
118 try: 118 try:
119 return obj[key] 119 return obj[key]
120 except (KeyError, TypeError): 120 except (KeyError, TypeError):
121 return None 121 return None
122 _lookup_attribute = staticmethod(_lookup_attribute) 122
123 123 def _lookup_item(data, obj, key):
124 def _lookup_item(data, obj, key): 124 if len(key) == 1:
125 if len(key) == 1: 125 key = key[0]
126 key = key[0] 126 try:
127 try: 127 return obj[key]
128 return obj[key] 128 except (KeyError, IndexError, TypeError), e:
129 except (KeyError, IndexError, TypeError), e: 129 pass
130 pass 130 if isinstance(key, basestring):
131 if isinstance(key, basestring): 131 try:
132 try: 132 return getattr(obj, key)
133 return getattr(obj, key) 133 except (AttributeError, TypeError), e:
134 except (AttributeError, TypeError), e: 134 pass
135 pass
136 _lookup_item = staticmethod(_lookup_item)
137
138 135
139 class ASTTransformer(object): 136 class ASTTransformer(object):
140 """General purpose base class for AST transformations. 137 """General purpose base class for AST transformations.
141 138
142 Every visitor method can be overridden to return an AST node that has been 139 Every visitor method can be overridden to return an AST node that has been
249 """Concrete AST transformer that implements the AST transformations needed 246 """Concrete AST transformer that implements the AST transformations needed
250 for template expressions. 247 for template expressions.
251 """ 248 """
252 249
253 def visitGetattr(self, node, *args, **kwargs): 250 def visitGetattr(self, node, *args, **kwargs):
254 return ast.CallFunc( 251 return ast.CallFunc(ast.Name('_lookup_attribute'),
255 ast.Getattr(ast.Name('self'), '_lookup_attribute'),
256 [ast.Name('data'), self.visit(node.expr, *args, **kwargs), 252 [ast.Name('data'), self.visit(node.expr, *args, **kwargs),
257 ast.Const(node.attrname)] 253 ast.Const(node.attrname)]
258 ) 254 )
259 255
260 def visitListComp(self, node, *args, **kwargs): 256 def visitListComp(self, node, *args, **kwargs):
267 263
268 def visitName(self, node, *args, **kwargs): 264 def visitName(self, node, *args, **kwargs):
269 func_args = [ast.Name('data'), ast.Const(node.name)] 265 func_args = [ast.Name('data'), ast.Const(node.name)]
270 if kwargs.get('lookup_locals'): 266 if kwargs.get('lookup_locals'):
271 func_args.append(ast.CallFunc(ast.Name('locals'), [])) 267 func_args.append(ast.CallFunc(ast.Name('locals'), []))
272 return ast.CallFunc( 268 return ast.CallFunc(ast.Name('_lookup_name'), func_args)
273 ast.Getattr(ast.Name('self'), '_lookup_name'), func_args
274 )
275 return node 269 return node
276 270
277 def visitSubscript(self, node, *args, **kwargs): 271 def visitSubscript(self, node, *args, **kwargs):
278 return ast.CallFunc( 272 return ast.CallFunc(ast.Name('_lookup_item'),
279 ast.Getattr(ast.Name('self'), '_lookup_item'),
280 [ast.Name('data'), self.visit(node.expr, *args, **kwargs), 273 [ast.Name('data'), self.visit(node.expr, *args, **kwargs),
281 ast.Tuple(map(self.visit, node.subs, *args, **kwargs))] 274 ast.Tuple(map(self.visit, node.subs, *args, **kwargs))]
282 ) 275 )
Copyright (C) 2012-2017 Edgewall Software