diff options
author | Jason Madden <jamadden@gmail.com> | 2015-05-27 12:26:19 -0500 |
---|---|---|
committer | Jason Madden <jamadden@gmail.com> | 2015-05-27 12:26:19 -0500 |
commit | 25241e111c15b6e75343ccdac912882ebff0cfd2 (patch) | |
tree | cd5f2ccbf737b36d668083b26831aa1178b38f61 | |
parent | 8f859a0c3ad345a7e427f07651264e1585c3fe9e (diff) | |
download | zope-security-25241e111c15b6e75343ccdac912882ebff0cfd2.tar.gz |
Let z.s.checker.Global objects be pickled when security-proxied under PyPy with zope.proxy 4.1.5
-rw-r--r-- | CHANGES.rst | 2 | ||||
-rw-r--r-- | src/zope/security/proxy.py | 29 |
2 files changed, 27 insertions, 4 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 76a6154..cfe3bb9 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changes 4.0.2 (unreleased) ------------------ -- TBD +- Compatibility with ``zope.proxy`` 4.1.5 under PyPy. 4.0.1 (2014-03-19) ------------------ 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') |