diff options
Diffstat (limited to 'lib/python2.7/test/test_decorators.py')
-rw-r--r-- | lib/python2.7/test/test_decorators.py | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/lib/python2.7/test/test_decorators.py b/lib/python2.7/test/test_decorators.py deleted file mode 100644 index cf2bc30..0000000 --- a/lib/python2.7/test/test_decorators.py +++ /dev/null @@ -1,309 +0,0 @@ -import unittest -from test import test_support - -def funcattrs(**kwds): - def decorate(func): - func.__dict__.update(kwds) - return func - return decorate - -class MiscDecorators (object): - @staticmethod - def author(name): - def decorate(func): - func.__dict__['author'] = name - return func - return decorate - -# ----------------------------------------------- - -class DbcheckError (Exception): - def __init__(self, exprstr, func, args, kwds): - # A real version of this would set attributes here - Exception.__init__(self, "dbcheck %r failed (func=%s args=%s kwds=%s)" % - (exprstr, func, args, kwds)) - - -def dbcheck(exprstr, globals=None, locals=None): - "Decorator to implement debugging assertions" - def decorate(func): - expr = compile(exprstr, "dbcheck-%s" % func.func_name, "eval") - def check(*args, **kwds): - if not eval(expr, globals, locals): - raise DbcheckError(exprstr, func, args, kwds) - return func(*args, **kwds) - return check - return decorate - -# ----------------------------------------------- - -def countcalls(counts): - "Decorator to count calls to a function" - def decorate(func): - func_name = func.func_name - counts[func_name] = 0 - def call(*args, **kwds): - counts[func_name] += 1 - return func(*args, **kwds) - call.func_name = func_name - return call - return decorate - -# ----------------------------------------------- - -def memoize(func): - saved = {} - def call(*args): - try: - return saved[args] - except KeyError: - res = func(*args) - saved[args] = res - return res - except TypeError: - # Unhashable argument - return func(*args) - call.func_name = func.func_name - return call - -# ----------------------------------------------- - -class TestDecorators(unittest.TestCase): - - def test_single(self): - class C(object): - @staticmethod - def foo(): return 42 - self.assertEqual(C.foo(), 42) - self.assertEqual(C().foo(), 42) - - def test_staticmethod_function(self): - @staticmethod - def notamethod(x): - return x - self.assertRaises(TypeError, notamethod, 1) - - def test_dotted(self): - decorators = MiscDecorators() - @decorators.author('Cleese') - def foo(): return 42 - self.assertEqual(foo(), 42) - self.assertEqual(foo.author, 'Cleese') - - def test_argforms(self): - # A few tests of argument passing, as we use restricted form - # of expressions for decorators. - - def noteargs(*args, **kwds): - def decorate(func): - setattr(func, 'dbval', (args, kwds)) - return func - return decorate - - args = ( 'Now', 'is', 'the', 'time' ) - kwds = dict(one=1, two=2) - @noteargs(*args, **kwds) - def f1(): return 42 - self.assertEqual(f1(), 42) - self.assertEqual(f1.dbval, (args, kwds)) - - @noteargs('terry', 'gilliam', eric='idle', john='cleese') - def f2(): return 84 - self.assertEqual(f2(), 84) - self.assertEqual(f2.dbval, (('terry', 'gilliam'), - dict(eric='idle', john='cleese'))) - - @noteargs(1, 2,) - def f3(): pass - self.assertEqual(f3.dbval, ((1, 2), {})) - - def test_dbcheck(self): - @dbcheck('args[1] is not None') - def f(a, b): - return a + b - self.assertEqual(f(1, 2), 3) - self.assertRaises(DbcheckError, f, 1, None) - - def test_memoize(self): - counts = {} - - @memoize - @countcalls(counts) - def double(x): - return x * 2 - self.assertEqual(double.func_name, 'double') - - self.assertEqual(counts, dict(double=0)) - - # Only the first call with a given argument bumps the call count: - # - self.assertEqual(double(2), 4) - self.assertEqual(counts['double'], 1) - self.assertEqual(double(2), 4) - self.assertEqual(counts['double'], 1) - self.assertEqual(double(3), 6) - self.assertEqual(counts['double'], 2) - - # Unhashable arguments do not get memoized: - # - self.assertEqual(double([10]), [10, 10]) - self.assertEqual(counts['double'], 3) - self.assertEqual(double([10]), [10, 10]) - self.assertEqual(counts['double'], 4) - - def test_errors(self): - # Test syntax restrictions - these are all compile-time errors: - # - for expr in [ "1+2", "x[3]", "(1, 2)" ]: - # Sanity check: is expr is a valid expression by itself? - compile(expr, "testexpr", "exec") - - codestr = "@%s\ndef f(): pass" % expr - self.assertRaises(SyntaxError, compile, codestr, "test", "exec") - - # You can't put multiple decorators on a single line: - # - self.assertRaises(SyntaxError, compile, - "@f1 @f2\ndef f(): pass", "test", "exec") - - # Test runtime errors - - def unimp(func): - raise NotImplementedError - context = dict(nullval=None, unimp=unimp) - - for expr, exc in [ ("undef", NameError), - ("nullval", TypeError), - ("nullval.attr", AttributeError), - ("unimp", NotImplementedError)]: - codestr = "@%s\ndef f(): pass\nassert f() is None" % expr - code = compile(codestr, "test", "exec") - self.assertRaises(exc, eval, code, context) - - def test_double(self): - class C(object): - @funcattrs(abc=1, xyz="haha") - @funcattrs(booh=42) - def foo(self): return 42 - self.assertEqual(C().foo(), 42) - self.assertEqual(C.foo.abc, 1) - self.assertEqual(C.foo.xyz, "haha") - self.assertEqual(C.foo.booh, 42) - - def test_order(self): - # Test that decorators are applied in the proper order to the function - # they are decorating. - def callnum(num): - """Decorator factory that returns a decorator that replaces the - passed-in function with one that returns the value of 'num'""" - def deco(func): - return lambda: num - return deco - @callnum(2) - @callnum(1) - def foo(): return 42 - self.assertEqual(foo(), 2, - "Application order of decorators is incorrect") - - def test_eval_order(self): - # Evaluating a decorated function involves four steps for each - # decorator-maker (the function that returns a decorator): - # - # 1: Evaluate the decorator-maker name - # 2: Evaluate the decorator-maker arguments (if any) - # 3: Call the decorator-maker to make a decorator - # 4: Call the decorator - # - # When there are multiple decorators, these steps should be - # performed in the above order for each decorator, but we should - # iterate through the decorators in the reverse of the order they - # appear in the source. - - actions = [] - - def make_decorator(tag): - actions.append('makedec' + tag) - def decorate(func): - actions.append('calldec' + tag) - return func - return decorate - - class NameLookupTracer (object): - def __init__(self, index): - self.index = index - - def __getattr__(self, fname): - if fname == 'make_decorator': - opname, res = ('evalname', make_decorator) - elif fname == 'arg': - opname, res = ('evalargs', str(self.index)) - else: - assert False, "Unknown attrname %s" % fname - actions.append('%s%d' % (opname, self.index)) - return res - - c1, c2, c3 = map(NameLookupTracer, [ 1, 2, 3 ]) - - expected_actions = [ 'evalname1', 'evalargs1', 'makedec1', - 'evalname2', 'evalargs2', 'makedec2', - 'evalname3', 'evalargs3', 'makedec3', - 'calldec3', 'calldec2', 'calldec1' ] - - actions = [] - @c1.make_decorator(c1.arg) - @c2.make_decorator(c2.arg) - @c3.make_decorator(c3.arg) - def foo(): return 42 - self.assertEqual(foo(), 42) - - self.assertEqual(actions, expected_actions) - - # Test the equivalence claim in chapter 7 of the reference manual. - # - actions = [] - def bar(): return 42 - bar = c1.make_decorator(c1.arg)(c2.make_decorator(c2.arg)(c3.make_decorator(c3.arg)(bar))) - self.assertEqual(bar(), 42) - self.assertEqual(actions, expected_actions) - -class TestClassDecorators(unittest.TestCase): - - def test_simple(self): - def plain(x): - x.extra = 'Hello' - return x - @plain - class C(object): pass - self.assertEqual(C.extra, 'Hello') - - def test_double(self): - def ten(x): - x.extra = 10 - return x - def add_five(x): - x.extra += 5 - return x - - @add_five - @ten - class C(object): pass - self.assertEqual(C.extra, 15) - - def test_order(self): - def applied_first(x): - x.extra = 'first' - return x - def applied_second(x): - x.extra = 'second' - return x - @applied_second - @applied_first - class C(object): pass - self.assertEqual(C.extra, 'second') - -def test_main(): - test_support.run_unittest(TestDecorators) - test_support.run_unittest(TestClassDecorators) - -if __name__=="__main__": - test_main() |