diff options
| author | fabrizio ettore messina <fabrizio.messina@mistralpay.com> | 2015-08-11 13:35:50 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-09-18 19:04:29 -0400 |
| commit | 186eb21dc159807dba83148f7c9c50d470745708 (patch) | |
| tree | b906d98d94bde119bef7ee542cb842e91f1c51ab /tests/decorators | |
| parent | d8d853378b3ff75c03d8bd91ea026d2b8c642b0f (diff) | |
| download | django-186eb21dc159807dba83148f7c9c50d470745708.tar.gz | |
Fixed #25269 -- Allowed method_decorator() to accept a list/tuple of decorators.
Diffstat (limited to 'tests/decorators')
| -rw-r--r-- | tests/decorators/tests.py | 81 |
1 files changed, 73 insertions, 8 deletions
diff --git a/tests/decorators/tests.py b/tests/decorators/tests.py index 0f0f0f52c2..3414264f72 100644 --- a/tests/decorators/tests.py +++ b/tests/decorators/tests.py @@ -212,22 +212,52 @@ class MethodDecoratorTests(SimpleTestCase): self.assertEqual(getattr(func, 'myattr', False), True) self.assertEqual(getattr(func, 'myattr2', False), True) - # Now check method_decorator - class Test(object): + # Decorate using method_decorator() on the method. + class TestPlain(object): @myattr_dec_m @myattr2_dec_m def method(self): "A method" pass - self.assertEqual(getattr(Test().method, 'myattr', False), True) - self.assertEqual(getattr(Test().method, 'myattr2', False), True) + # Decorate using method_decorator() on both the class and the method. + # The decorators applied to the methods are applied before the ones + # applied to the class. + @method_decorator(myattr_dec_m, "method") + class TestMethodAndClass(object): + @method_decorator(myattr2_dec_m) + def method(self): + "A method" + pass - self.assertEqual(getattr(Test.method, 'myattr', False), True) - self.assertEqual(getattr(Test.method, 'myattr2', False), True) + # Decorate using an iterable of decorators. + decorators = (myattr_dec_m, myattr2_dec_m) - self.assertEqual(Test.method.__doc__, 'A method') - self.assertEqual(Test.method.__name__, 'method') + @method_decorator(decorators, "method") + class TestIterable(object): + def method(self): + "A method" + pass + + for Test in (TestPlain, TestMethodAndClass, TestIterable): + self.assertEqual(getattr(Test().method, 'myattr', False), True) + self.assertEqual(getattr(Test().method, 'myattr2', False), True) + + self.assertEqual(getattr(Test.method, 'myattr', False), True) + self.assertEqual(getattr(Test.method, 'myattr2', False), True) + + self.assertEqual(Test.method.__doc__, 'A method') + self.assertEqual(Test.method.__name__, 'method') + + def test_bad_iterable(self): + decorators = {myattr_dec_m, myattr2_dec_m} + # The rest of the exception message differs between Python 2 and 3. + with self.assertRaisesMessage(TypeError, "'set' object"): + @method_decorator(decorators, "method") + class TestIterable(object): + def method(self): + "A method" + pass # Test for argumented decorator def test_argumented(self): @@ -291,6 +321,41 @@ class MethodDecoratorTests(SimpleTestCase): self.assertTrue(Test().method()) + def test_tuple_of_decorators(self): + """ + @method_decorator can accept a tuple of decorators. + """ + def add_question_mark(func): + def _wrapper(*args, **kwargs): + return func(*args, **kwargs) + "?" + return _wrapper + + def add_exclamation_mark(func): + def _wrapper(*args, **kwargs): + return func(*args, **kwargs) + "!" + return _wrapper + + # The order should be consistent with the usual order in which + # decorators are applied, e.g. + # @add_exclamation_mark + # @add_question_mark + # def func(): + # ... + decorators = (add_exclamation_mark, add_question_mark) + + @method_decorator(decorators, name="method") + class TestFirst(object): + def method(self): + return "hello world" + + class TestSecond(object): + @method_decorator(decorators) + def method(self): + return "hello world" + + self.assertEqual(TestFirst().method(), "hello world?!") + self.assertEqual(TestSecond().method(), "hello world?!") + def test_invalid_non_callable_attribute_decoration(self): """ @method_decorator on a non-callable attribute raises an error. |
