Commit 9a2d8ad8 authored by Tres Seaver's avatar Tres Seaver

Fix 'non_overridable' decorator under pure Python.

parent 406f1ca7
...@@ -30,9 +30,8 @@ def ProxyIterator(p): ...@@ -30,9 +30,8 @@ def ProxyIterator(p):
p = getProxiedObject(p) p = getProxiedObject(p)
yield p yield p
def non_overridable(func):
return property(lambda self: func.__get__(self))
_MARKER = object()
class PyProxyBase(object): class PyProxyBase(object):
"""Reference implementation. """Reference implementation.
...@@ -62,6 +61,9 @@ class PyProxyBase(object): ...@@ -62,6 +61,9 @@ class PyProxyBase(object):
def __reduce__(self): def __reduce__(self):
raise pickle.PicklingError raise pickle.PicklingError
def __reduce_ex__(self, proto):
raise pickle.PicklingError
# Rich comparison protocol # Rich comparison protocol
def __lt__(self, other): def __lt__(self, other):
return self._wrapped < other return self._wrapped < other
...@@ -89,6 +91,24 @@ class PyProxyBase(object): ...@@ -89,6 +91,24 @@ class PyProxyBase(object):
return hash(self._wrapped) return hash(self._wrapped)
# Attribute protocol # Attribute protocol
def __getattribute__(self, name):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
if name == '_wrapped':
return wrapped
try:
mine = super(PyProxyBase, self).__getattribute__(name)
except AttributeError:
mine = _MARKER
else:
if isinstance(mine, PyNonOverridable):
return mine.desc.__get__(self)
try:
return getattr(wrapped, name)
except AttributeError:
if mine is not _MARKER:
return mine
raise
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self._wrapped, name) return getattr(self._wrapped, name)
...@@ -392,6 +412,10 @@ def py_removeAllProxies(obj): ...@@ -392,6 +412,10 @@ def py_removeAllProxies(obj):
obj = obj._wrapped obj = obj._wrapped
return obj return obj
class PyNonOverridable(object):
def __init__(self, method_desc):
self.desc = method_desc
try: try:
# Python API: not used in this module # Python API: not used in this module
from zope.proxy._zope_proxy_proxy import ProxyBase from zope.proxy._zope_proxy_proxy import ProxyBase
...@@ -415,3 +439,7 @@ except ImportError: #pragma NO COVER ...@@ -415,3 +439,7 @@ except ImportError: #pragma NO COVER
queryProxy = py_queryProxy queryProxy = py_queryProxy
queryInnerProxy = py_queryInnerProxy queryInnerProxy = py_queryInnerProxy
removeAllProxies = py_removeAllProxies removeAllProxies = py_removeAllProxies
non_overridable = PyNonOverridable
else:
def non_overridable(func):
return property(lambda self: func.__get__(self))
...@@ -117,7 +117,7 @@ class PyProxyBaseTestCase(unittest.TestCase): ...@@ -117,7 +117,7 @@ class PyProxyBaseTestCase(unittest.TestCase):
"""This class is expected to be a classic class.""" """This class is expected to be a classic class."""
w = self._makeOne(Thing()) w = self._makeOne(Thing())
self.assertRaises(pickle.PicklingError, self.assertRaises(pickle.PicklingError,
pickle.dumps, w) pickle.dumps, w)
def test___eq___and___ne__(self): def test___eq___and___ne__(self):
w = self._makeOne('foo') w = self._makeOne('foo')
...@@ -187,6 +187,17 @@ class PyProxyBaseTestCase(unittest.TestCase): ...@@ -187,6 +187,17 @@ class PyProxyBaseTestCase(unittest.TestCase):
w = self._makeOne(o) w = self._makeOne(o)
self.assertEqual(w.foo, 1) self.assertEqual(w.foo, 1)
def test___getattr__delegates_to_wrapped_when_conflict(self):
class Proxy(self._getTargetClass()):
def foo(self):
return 'PROXY'
class Foo(object):
def foo(self):
return 'FOO'
o = Foo()
w = Proxy(o)
self.assertEqual(w.foo(), 'FOO')
def test___setattr__delegates_to_wrapped(self): def test___setattr__delegates_to_wrapped(self):
class Foo(object): class Foo(object):
pass pass
......
...@@ -3,7 +3,7 @@ envlist = ...@@ -3,7 +3,7 @@ envlist =
# Jython support pending 2.7 support, due 2012-07-15 or so. See: # Jython support pending 2.7 support, due 2012-07-15 or so. See:
# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
# py26,py27,py32,jython,pypy,coverage # py26,py27,py32,jython,pypy,coverage
py26,py27,py32,coverage,docs py26,py27,py32,pypy,coverage,docs
[testenv] [testenv]
commands = commands =
......
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