MCPcopy Index your code
hub / github.com/python/cpython / test_eval_order

Method test_eval_order

Lib/test/test_decorators.py:233–292  ·  view source on GitHub ↗
(self)

Source from the content-addressed store, hash-verified

231 "Application order of decorators is incorrect")
232
233 def test_eval_order(self):
234 # Evaluating a decorated function involves four steps for each
235 # decorator-maker (the function that returns a decorator):
236 #
237 # 1: Evaluate the decorator-maker name
238 # 2: Evaluate the decorator-maker arguments (if any)
239 # 3: Call the decorator-maker to make a decorator
240 # 4: Call the decorator
241 #
242 # When there are multiple decorators, these steps should be
243 # performed in the above order for each decorator, but we should
244 # iterate through the decorators in the reverse of the order they
245 # appear in the source.
246
247 actions = []
248
249 def make_decorator(tag):
250 actions.append('makedec' + tag)
251 def decorate(func):
252 actions.append('calldec' + tag)
253 return func
254 return decorate
255
256 class NameLookupTracer (object):
257 def __init__(self, index):
258 self.index = index
259
260 def __getattr__(self, fname):
261 if fname == 'make_decorator':
262 opname, res = ('evalname', make_decorator)
263 elif fname == 'arg':
264 opname, res = ('evalargs', str(self.index))
265 else:
266 assert False, "Unknown attrname %s" % fname
267 actions.append('%s%d' % (opname, self.index))
268 return res
269
270 c1, c2, c3 = map(NameLookupTracer, [ 1, 2, 3 ])
271
272 expected_actions = [ 'evalname1', 'evalargs1', 'makedec1',
273 'evalname2', 'evalargs2', 'makedec2',
274 'evalname3', 'evalargs3', 'makedec3',
275 'calldec3', 'calldec2', 'calldec1' ]
276
277 actions = []
278 @c1.make_decorator(c1.arg)
279 @c2.make_decorator(c2.arg)
280 @c3.make_decorator(c3.arg)
281 def foo(): return 42
282 self.assertEqual(foo(), 42)
283
284 self.assertEqual(actions, expected_actions)
285
286 # Test the equivalence claim in chapter 7 of the reference manual.
287 #
288 actions = []
289 def bar(): return 42
290 bar = c1.make_decorator(c1.arg)(c2.make_decorator(c2.arg)(c3.make_decorator(c3.arg)(bar)))

Callers

nothing calls this directly

Calls 4

make_decoratorMethod · 0.80
fooFunction · 0.70
barFunction · 0.50
assertEqualMethod · 0.45

Tested by

no test coverage detected