Skip to content

Commit

Permalink
Let z.s.checker.Global objects be pickled when security-proxied under…
Browse files Browse the repository at this point in the history
… PyPy with zope.proxy 4.1.5
  • Loading branch information
jamadden committed May 27, 2015
1 parent 8f859a0 commit 25241e1
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
------------------
Expand Down
29 changes: 26 additions & 3 deletions src/zope/security/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,34 @@ def __getattribute__(self, name):
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')
Expand Down

0 comments on commit 25241e1

Please sign in to comment.