From 6568fe4f06ec93963f627adb26ef5cb6626663c2 Mon Sep 17 00:00:00 2001 From: Graham Dumpleton Date: Mon, 5 Aug 2013 22:24:01 +0800 Subject: [PATCH] Updates to unit tests. --- wrapt/tests/test_function.py | 24 ++--- wrapt/tests/test_inner_classmethod.py | 60 +++++++++++- wrapt/tests/test_inner_staticmethod.py | 2 +- wrapt/tests/test_instancemethod.py | 121 +++++++++++++++++++++++-- wrapt/tests/test_nested_function.py | 54 ++++++++--- wrapt/tests/test_outer_classmethod.py | 68 +++++++++++++- wrapt/tests/test_outer_staticmethod.py | 2 +- 7 files changed, 294 insertions(+), 37 deletions(-) diff --git a/wrapt/tests/test_function.py b/wrapt/tests/test_function.py index 1d5b3f4..da58636 100644 --- a/wrapt/tests/test_function.py +++ b/wrapt/tests/test_function.py @@ -7,55 +7,57 @@ import wrapt from .decorators import passthru_function_decorator -def function(arg): +def function1(arg): '''documentation''' return arg -original = function +function1o = function1 @passthru_function_decorator def function(arg): '''documentation''' return arg +function1d = function1 + class TestNamingFunction(unittest.TestCase): def test_object_name(self): # Test preservation of function __name__ attribute. - self.assertEqual(function.__name__, original.__name__) + self.assertEqual(function1d.__name__, function1o.__name__) def test_object_qualname(self): # Test preservation of function __qualname__ attribute. try: - __qualname__ = original.__qualname__ + __qualname__ = function1o.__qualname__ except AttributeError: pass else: - self.assertEqual(function.__qualname__, __qualname__) + self.assertEqual(function1d.__qualname__, __qualname__) def test_module_name(self): # Test preservation of function __module__ attribute. - self.assertEqual(function.__module__, __name__) + self.assertEqual(function1d.__module__, __name__) def test_doc_string(self): # Test preservation of function __doc__ attribute. - self.assertEqual(function.__doc__, original.__doc__) + self.assertEqual(function1d.__doc__, function1o.__doc__) def test_argspec(self): # Test preservation of function argument specification. - original_argspec = inspect.getargspec(original) - function_argspec = inspect.getargspec(function) - self.assertEqual(original_argspec, function_argspec) + function1o_argspec = inspect.getargspec(function1o) + function1d_argspec = inspect.getargspec(function1d) + self.assertEqual(function1o_argspec, function1d_argspec) def test_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(function, type(original))) + self.assertTrue(isinstance(function1d, type(function1o))) class TestCallingFunction(unittest.TestCase): diff --git a/wrapt/tests/test_inner_classmethod.py b/wrapt/tests/test_inner_classmethod.py index fd4ddbf..29743ae 100644 --- a/wrapt/tests/test_inner_classmethod.py +++ b/wrapt/tests/test_inner_classmethod.py @@ -3,6 +3,8 @@ from __future__ import print_function import unittest import inspect +import wrapt + from .decorators import passthru_generic_decorator class Class(object): @@ -20,7 +22,7 @@ class Class(object): '''documentation''' return arg -class TestCase(unittest.TestCase): +class TestNamingInnerClassMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. @@ -103,3 +105,59 @@ class TestCase(unittest.TestCase): self.assertTrue(isinstance(Class().function, type(Original().function))) + +class TestCallingInnerClassMethod(unittest.TestCase): + + def test_class_call_function(self): + # Test calling classmethod. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertEqual(obj, None) + self.assertNotEqual(cls, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @_decorator + @classmethod + def _function(cls, *args, **kwargs): + return (args, kwargs) + + result = Class._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) + + def test_instance_call_function(self): + # Test calling classmethod via class instance. The instance + # passed to the wrapper will not be None because our decorator + # surrounds the classmethod decorator. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertNotEqual(obj, None) + self.assertNotEqual(cls, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @_decorator + @classmethod + def _function(cls, *args, **kwargs): + return (args, kwargs) + + result = Class()._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) diff --git a/wrapt/tests/test_inner_staticmethod.py b/wrapt/tests/test_inner_staticmethod.py index 7e316ea..0407dca 100644 --- a/wrapt/tests/test_inner_staticmethod.py +++ b/wrapt/tests/test_inner_staticmethod.py @@ -20,7 +20,7 @@ class Class(object): '''documentation''' return arg -class TestCase(unittest.TestCase): +class TestNamingInnerStaticMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. diff --git a/wrapt/tests/test_instancemethod.py b/wrapt/tests/test_instancemethod.py index 3f6f393..c4c44a4 100644 --- a/wrapt/tests/test_instancemethod.py +++ b/wrapt/tests/test_instancemethod.py @@ -7,19 +7,21 @@ import wrapt from .decorators import passthru_instancemethod_decorator -class OldClass1d(): +class OldClass1(): def function(self, arg): '''documentation''' return arg -OldClass1o = OldClass1d +OldClass1o = OldClass1 -class OldClass1d(): +class OldClass1(): @passthru_instancemethod_decorator def function(self, arg): '''documentation''' return arg +OldClass1d = OldClass1 + class TestNamingInstanceMethodOldStyle(unittest.TestCase): def test_class_object_name(self): @@ -104,19 +106,21 @@ class TestNamingInstanceMethodOldStyle(unittest.TestCase): self.assertTrue(isinstance(OldClass1d().function, type(OldClass1o().function))) -class NewClass1d(object): +class NewClass1(object): def function(self, arg): '''documentation''' return arg -NewClass1o = NewClass1d +NewClass1o = NewClass1 -class NewClass1d(object): +class NewClass1(object): @passthru_instancemethod_decorator def function(self, arg): '''documentation''' return arg +NewClass1d = NewClass1 + class TestNamingInstanceMethodNewStyle(unittest.TestCase): def test_class_object_name(self): @@ -205,14 +209,13 @@ class TestCallingInstanceMethodOldStyle(unittest.TestCase): def test_class_call_function(self): # Test calling instancemethod via class and passing in the class - # instance directly. This is bypassing the descriptor protocol. + # instance directly. _args = (1, 2) _kwargs = { 'one': 1, 'two': 2 } @wrapt.instancemethod_decorator def _decorator(wrapped, obj, cls, args, kwargs): - print('_DECORATOR', wrapped, obj, cls, args, kwargs) self.assertNotEqual(obj, None) return wrapped(*args, **kwargs) @@ -253,6 +256,58 @@ class TestCallingInstanceMethodOldStyle(unittest.TestCase): self.assertEqual(result, (_args, _kwargs)) + def test_class_call_function_generic_decorator(self): + # Test calling instancemethod via class and passing in the class + # instance directly. The generic decorator does not perform the + # fiddle that the instance method decorator does when called via + # the class type with the instance as first argument. Thus the + # instance passed to the wrapper will be None. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertEqual(obj, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(): + @_decorator + def _function(self, *args, **kwargs): + return (args, kwargs) + + result = Class._function(*((Class(),)+_args), **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) + + def test_instance_call_function_generic_decorator(self): + # Test calling instancemethod via class instance. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertNotEqual(obj, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(): + @_decorator + def _function(self, *args, **kwargs): + return (args, kwargs) + + result = Class()._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) + class TestCallingInstanceMethodNewStyle(unittest.TestCase): def test_class_call_function(self): @@ -264,7 +319,6 @@ class TestCallingInstanceMethodNewStyle(unittest.TestCase): @wrapt.instancemethod_decorator def _decorator(wrapped, obj, cls, args, kwargs): - print('_DECORATOR', wrapped, obj, cls, args, kwargs) self.assertNotEqual(obj, None) return wrapped(*args, **kwargs) @@ -304,3 +358,52 @@ class TestCallingInstanceMethodNewStyle(unittest.TestCase): result = Class()._function(*_args, **_kwargs) self.assertEqual(result, (_args, _kwargs)) + + def test_class_call_function_generic_decorator(self): + # Test calling instancemethod via class and passing in the class + # instance directly. This is bypassing the descriptor protocol. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertEqual(obj, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @_decorator + def _function(self, *args, **kwargs): + return (args, kwargs) + + result = Class._function(Class(), *_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) + + def test_instance_call_function_generic_decorator(self): + # Test calling instancemethod via class instance. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertNotEqual(obj, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @_decorator + def _function(self, *args, **kwargs): + return (args, kwargs) + + result = Class()._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) diff --git a/wrapt/tests/test_nested_function.py b/wrapt/tests/test_nested_function.py index 1442a78..8f4b622 100644 --- a/wrapt/tests/test_nested_function.py +++ b/wrapt/tests/test_nested_function.py @@ -3,58 +3,86 @@ from __future__ import print_function import unittest import inspect +import wrapt + from .decorators import passthru_function_decorator -def function(): +def function1(): def inner(arg): '''documentation''' return arg return inner -original = function +function1o = function1 -def function(): +def function1(): @passthru_function_decorator def inner(arg): '''documentation''' return arg return inner -class TestCase(unittest.TestCase): +function1d = function1 + +class TestNamingNestedFunction(unittest.TestCase): def test_object_name(self): # Test preservation of function __name__ attribute. - self.assertEqual(function().__name__, original().__name__) + self.assertEqual(function1d().__name__, function1o().__name__) def test_object_qualname(self): # Test preservation of function __qualname__ attribute. try: - __qualname__ = original().__qualname__ + __qualname__ = function1o().__qualname__ except AttributeError: pass else: - self.assertEqual(function().__qualname__, __qualname__) + self.assertEqual(function1d().__qualname__, __qualname__) def test_module_name(self): # Test preservation of function __module__ attribute. - self.assertEqual(function().__module__, __name__) + self.assertEqual(function1d().__module__, __name__) def test_doc_string(self): # Test preservation of function __doc__ attribute. - self.assertEqual(function().__doc__, original().__doc__) + self.assertEqual(function1d().__doc__, function1o().__doc__) def test_argspec(self): # Test preservation of function argument specification. - original_argspec = inspect.getargspec(original()) - function_argspec = inspect.getargspec(function()) - self.assertEqual(original_argspec, function_argspec) + function1o_argspec = inspect.getargspec(function1o()) + function1d_argspec = inspect.getargspec(function1d()) + self.assertEqual(function1o_argspec, function1d_argspec) def test_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(function(), type(original()))) + self.assertTrue(isinstance(function1d(), type(function1o()))) + +class TestCallingNestedFunction(unittest.TestCase): + + def test_call_function(self): + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.function_decorator + def _decorator(wrapped, args, kwargs): + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + def _function(): + @passthru_function_decorator + def inner(*args, **kwargs): + return args, kwargs + return inner + + result = _function()(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) diff --git a/wrapt/tests/test_outer_classmethod.py b/wrapt/tests/test_outer_classmethod.py index 21ef3ab..3a99d29 100644 --- a/wrapt/tests/test_outer_classmethod.py +++ b/wrapt/tests/test_outer_classmethod.py @@ -3,6 +3,8 @@ from __future__ import print_function import unittest import inspect +import wrapt + from .decorators import passthru_generic_decorator class Class(object): @@ -20,7 +22,7 @@ class Class(object): '''documentation''' return arg -class TestCase(unittest.TestCase): +class TestNamingOuterClassMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. @@ -103,3 +105,67 @@ class TestCase(unittest.TestCase): self.assertTrue(isinstance(Class().function, type(Original().function))) + +class TestCallingOuterClassMethod(unittest.TestCase): + + def test_class_call_function(self): + # Test calling classmethod. The instance and class passed to the + # wrapper will both be None because our decorator is surrounded + # by the classmethod decorator. The classmethod decorator + # doesn't bind the method and treats it like a normal function, + # explicitly passing the class as the first argument with the + # actual arguments following that. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertEqual(obj, None) + self.assertEqual(cls, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @classmethod + @_decorator + def _function(cls, *args, **kwargs): + return (args, kwargs) + + result = Class._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) + + def test_instance_call_function(self): + # Test calling classmethod via class instance. The instance + # and class passed to the wrapper will both be None because our + # decorator is surrounded by the classmethod decorator. The + # classmethod decorator doesn't bind the method and treats it + # like a normal function, explicitly passing the class as the + # first argument with the actual arguments following that. + + _args = (1, 2) + _kwargs = { 'one': 1, 'two': 2 } + + @wrapt.generic_decorator + def _decorator(wrapped, obj, cls, args, kwargs): + self.assertEqual(obj, None) + self.assertEqual(cls, None) + return wrapped(*args, **kwargs) + + @_decorator + def _function(*args, **kwargs): + return args, kwargs + + class Class(object): + @classmethod + @_decorator + def _function(cls, *args, **kwargs): + return (args, kwargs) + + result = Class()._function(*_args, **_kwargs) + + self.assertEqual(result, (_args, _kwargs)) diff --git a/wrapt/tests/test_outer_staticmethod.py b/wrapt/tests/test_outer_staticmethod.py index 9f879d9..118b5b0 100644 --- a/wrapt/tests/test_outer_staticmethod.py +++ b/wrapt/tests/test_outer_staticmethod.py @@ -20,7 +20,7 @@ class Class(object): '''documentation''' return arg -class TestCase(unittest.TestCase): +class TestNamingOuterStaticMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute.