Commit f8fea38b authored by Jason Madden's avatar Jason Madden

Fix #7. Make the Python Acquirer cooperatively call super, and test this. Also...

Fix #7. Make the Python Acquirer cooperatively call super, and test this. Also provides a more informative traceback if lookup failed in that case which assists debugging if the inheritance hierarchy is complex.
parent 6f20ea96
......@@ -4,7 +4,9 @@ Changelog
4.2.2 (unreleased)
------------------
- TBD
- Make the pure-Python Acquirer objects cooperatively use the
superclass ``__getattribute__`` method, like the C implementation.
See https://github.com/zopefoundation/Acquisition/issues/7.
4.2.1 (2015-04-23)
------------------
......
......@@ -44,12 +44,21 @@ if sys.version_info < (3,):
if isinstance(method, types.MethodType):
method = types.MethodType(method.im_func, wrapper, method.im_class)
return method
exec("""def _reraise(tp, value, tb=None):
raise tp, value, tb
""")
else: # pragma: no cover (python 2 is currently our reference)
def _rebound_method(method, wrapper):
"""Returns a version of the method with self bound to `wrapper`"""
if isinstance(method, types.MethodType):
method = types.MethodType(method.__func__, wrapper)
return method
def _reraise(tp, value, tb=None):
if value is None:
value = tp()
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
###
# Wrapper object protocol, mostly ported from C directly
......@@ -684,11 +693,12 @@ class _Acquirer(ExtensionClass.Base):
def __getattribute__(self, name):
try:
return ExtensionClass.Base.__getattribute__(self, name)
return super(_Acquirer,self).__getattribute__(name)
except AttributeError:
# the doctests have very specific error message
# requirements
raise AttributeError(name)
# requirements (but at least we can preserve the traceback)
t, v, tb = sys.exc_info()
_reraise(AttributeError, AttributeError(name), tb)
def __of__(self, context):
return type(self)._Wrapper(self, context)
......
......@@ -3124,6 +3124,30 @@ class TestAcquire(unittest.TestCase):
found = self.acquire(self.a.b.c, AQ_PARENT)
self.assertTrue(found.aq_self is self.a.b.aq_self)
class TestCooperativeBase(unittest.TestCase):
def _make_acquirer(self, kind):
from ExtensionClass import Base
class ExtendsBase(Base):
def __getattribute__(self, name):
if name == 'magic':
return 42
return super(ExtendsBase,self).__getattribute__(name)
class Acquirer(kind, ExtendsBase):
pass
return Acquirer()
def _check___getattribute___is_cooperative(self, acquirer):
self.assertEqual(getattr(acquirer, 'magic'), 42)
def test_implicit___getattribute__is_cooperative(self):
self._check___getattribute___is_cooperative(self._make_acquirer(Acquisition.Implicit))
def test_explicit___getattribute__is_cooperative(self):
self._check___getattribute___is_cooperative(self._make_acquirer(Acquisition.Explicit))
class TestUnicode(unittest.TestCase):
......@@ -3537,6 +3561,7 @@ def test_suite():
unittest.makeSuite(TestAcquire),
unittest.makeSuite(TestUnicode),
unittest.makeSuite(TestProxying),
unittest.makeSuite(TestCooperativeBase),
]
# This file is only available in a source checkout, skip it
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment