diff --git a/src/wrappers.py b/src/wrappers.py index 171cb36..125f507 100644 --- a/src/wrappers.py +++ b/src/wrappers.py @@ -129,11 +129,25 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): return bool(self.__wrapped__) def __setattr__(self, name, value): - if name.startswith('_self_') or name == '__wrapped__': + if name.startswith('_self_'): object.__setattr__(self, name, value) + + elif name == '__wrapped__': + object.__setattr__(self, name, value) + try: + object.__delattr__(self, '__qualname__') + except AttributeError: + pass + object.__setattr__(self, name, value) + try: + object.__setattr__(self, '__qualname__', value.__qualname__) + except AttributeError: + pass + elif name == '__qualname__': setattr(self.__wrapped__, name, value) object.__setattr__(self, name, value) + else: setattr(self.__wrapped__, name, value) @@ -141,11 +155,16 @@ class ObjectProxy(six.with_metaclass(_ObjectProxyMetaType)): return getattr(self.__wrapped__, name) def __delattr__(self, name): - if name.startswith('_self_') or name == '__wrapped__': + if name.startswith('_self_'): object.__delattr__(self, name) + + elif name == '__wrapped__': + raise TypeError('__wrapped__ must be an object') + elif name == '__qualname__': object.__delattr__(self, name) delattr(self.__wrapped__, name) + else: delattr(self.__wrapped__, name) diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 11809d5..ca4c900 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -51,14 +51,46 @@ class TestAttributeAccess(unittest.TestCase): return args, kwargs function2 = wrapt.ObjectProxy(function1) + self.assertEqual(function2, function1) self.assertEqual(function2.__wrapped__, function1) + self.assertEqual(function2.__name__, function1.__name__) + + if six.PY3: + self.assertEqual(function2.__qualname__, function1.__qualname__) function2.__wrapped__ = None - self.assertEqual(function2.__wrapped__, None) - self.assertFalse(hasattr(function1, '__wrapped__')) + self.assertEqual(function2, None) + self.assertEqual(function2.__wrapped__, None) + self.assertFalse(hasattr(function2, '__name__')) + + if six.PY3: + self.assertFalse(hasattr(function2, '__qualname__')) + + def function3(*args, **kwargs): + return args, kwargs + + function2.__wrapped__ = function3 + + self.assertEqual(function2, function3) + self.assertEqual(function2.__wrapped__, function3) + self.assertEqual(function2.__name__, function3.__name__) + + if six.PY3: + self.assertEqual(function2.__qualname__, function3.__qualname__) + + def test_delete_wrapped(self): + def function1(*args, **kwargs): + return args, kwargs + function2 = wrapt.ObjectProxy(function1) + + def run(*args): + del function2.__wrapped__ + + self.assertRaises(TypeError, run, ()) + def test_proxy_attribute(self): def function1(*args, **kwargs): return args, kwargs