summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2015-05-27 12:26:19 -0500
committerJason Madden <jamadden@gmail.com>2015-05-27 12:26:19 -0500
commit25241e111c15b6e75343ccdac912882ebff0cfd2 (patch)
treecd5f2ccbf737b36d668083b26831aa1178b38f61 /src
parent8f859a0c3ad345a7e427f07651264e1585c3fe9e (diff)
downloadzope-security-25241e111c15b6e75343ccdac912882ebff0cfd2.tar.gz
Let z.s.checker.Global objects be pickled when security-proxied under PyPy with zope.proxy 4.1.5
Diffstat (limited to 'src')
-rw-r--r--src/zope/security/proxy.py29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py
index 16bb95f..87b3f22 100644
--- a/src/zope/security/proxy.py
+++ b/src/zope/security/proxy.py
@@ -84,11 +84,34 @@ class ProxyPy(PyProxyBase):
checker = super(PyProxyBase, self).__getattribute__('_checker')
if name == '_checker':
return checker
- if name not in ['__cmp__', '__hash__', '__bool__', '__nonzero__',
+ if name not in ('__cmp__', '__hash__', '__bool__', '__nonzero__',
'__lt__', '__le__', '__eq__', '__ne__', '__ge__',
- '__gt__']:
+ '__gt__'):
checker.check_getattr(wrapped, name)
- return checker.proxy(super(ProxyPy, self).__getattribute__(name))
+ if name in ('__reduce__', '__reduce_ex__'):
+ # The superclass specifically denies access to __reduce__
+ # and __reduce__ex__, not letting proxies be pickled. But
+ # for backwards compatibility, we need to be able to
+ # pickle proxies. See checker:Global for an example.
+ val = getattr(wrapped, name)
+ elif name == '__module__':
+ # The superclass deals with descriptors found in the type
+ # of this object just like the Python language spec states, letting
+ # them have precedence over things found in the instance. This
+ # normally makes us a better proxy implementation. However, the
+ # C version of this code in _proxy doesn't take that same care and instead
+ # uses the generic object attribute access methods directly on
+ # the wrapped object. This is a behaviour difference; so far, it's
+ # only been noticed for the __module__ attribute, which checker:Global
+ # wants to override but couldn't because this object's type's __module__ would
+ # get in the way. That broke pickling, and checker:Global can't return
+ # anything more sophisticated than a str (a tuple) because it gets proxied
+ # and breaks pickling again. Our solution is to match the C version for this
+ # one attribute.
+ val = getattr(wrapped, name)
+ else:
+ val = super(ProxyPy, self).__getattribute__(name)
+ return checker.proxy(val)
def __getattr__(self, name):
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')