Skip to content

Commit

Permalink
- Make sure that __str__ and __repr__ never fail by catching all exce…
Browse files Browse the repository at this point in the history
…ptions

  and using the custom fallback. (This is equivalent to the C Proxy behavior.)

- Allow __getslice__ and __setslice__ to access the original object's
  implementation instead of always falling back to __getitem__ and
  __setitem__. Do we really want to support this or just remove the test?
  (It is deprecated this Python 2.0!)

- Make sure that Checker.set_permissions is set initiated as an empty dict, if
  not provided. While not immediately obvious, this is the C-based checker
  behavior as well.

Oh yeah, all tests pass now on py26, py27, py32, py33, and pypy!
  • Loading branch information
strichter committed Mar 11, 2013
1 parent 82fd54d commit 9286583
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/zope/security/_compat.py
Expand Up @@ -14,11 +14,13 @@
""" Python 2 / 3 compatibility
"""
import platform
import os
import sys
import types

py_impl = getattr(platform, 'python_implementation', lambda: None)
PYPY = py_impl() == 'PyPy'
PURE_PYTHON = os.environ.get('PURE_PYTHON', False)

This comment has been minimized.

Copy link
@tseaver

tseaver Mar 11, 2013

Member

Maybe add tox environments which test this under 2.7 and 3.3?


if sys.version_info[0] < 3: #pragma NO COVER

Expand Down
2 changes: 2 additions & 0 deletions src/zope/security/checker.py
Expand Up @@ -177,6 +177,8 @@ def __init__(self, get_permissions, set_permissions=None):
if set_permissions is not None:
if not isinstance(set_permissions, dict):
raise TypeError('set_permissions must be a dict')
else:
set_permissions = {}
self.set_permissions = set_permissions

def permission_id(self, name):
Expand Down
1 change: 0 additions & 1 deletion src/zope/security/protectclass.py
Expand Up @@ -38,7 +38,6 @@ def protectName(class_, name, permission):

def protectSetAttribute(class_, name, permission):
"""Set a permission on a particular name."""

checker = getCheckerForInstancesOf(class_)
if checker is None:
checker = Checker({}, {})
Expand Down
28 changes: 16 additions & 12 deletions src/zope/security/proxy.py
Expand Up @@ -114,13 +114,19 @@ def __delattr__(self, name):

@_check_name
def __getslice__(self, start, end):
getitem = PyProxyBase.__getattribute__(self, '__getitem__')
return getitem(slice(start, end))
try:
return self._wrapped.__getslice__(start, end)
except:
getitem = PyProxyBase.__getattribute__(self, '__getitem__')
return getitem(slice(start, end))

@_check_name
def __setslice__(self, i, j, value):
setitem = PyProxyBase.__getattribute__(self, '__setitem__')
return setitem(slice(i, j), value)
try:
return self._wrapped.__setslice__(i, j, value)
except:
setitem = PyProxyBase.__getattribute__(self, '__setitem__')
return setitem(slice(i, j), value)

def __cmp__(self, other):
# no check
Expand Down Expand Up @@ -172,17 +178,14 @@ def __coerce__(self, other):
# For some reason _check_name does not work for coerce()
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
checker = super(PyProxyBase, self).__getattribute__('_checker')
checker.check_getattr(wrapped, '__coerce__')
# Re-implement __coerce__(), so we do not depend on self._wrapped
left, right = coerce(wrapped, other)
if left == wrapped and type(left) is type(wrapped):
left = self
return left, right
checker.check(wrapped, '__coerce__')
return super(ProxyPy, self).__coerce__(other)

def __str__(self):
try:
return _check_name(PyProxyBase.__str__)(self)
except ForbiddenAttribute:
except:
# The C implementation catches all exceptions.
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
return '<security proxied %s.%s instance at %s>' %(
wrapped.__class__.__module__, wrapped.__class__.__name__,
Expand All @@ -191,7 +194,8 @@ def __str__(self):
def __repr__(self):
try:
return _check_name(PyProxyBase.__repr__)(self)
except ForbiddenAttribute:
except:
# The C implementation catches all exceptions.
wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
return '<security proxied %s.%s instance at %s>' %(
wrapped.__class__.__module__, wrapped.__class__.__name__,
Expand Down
4 changes: 2 additions & 2 deletions src/zope/security/tests/test_proxy.py
Expand Up @@ -16,7 +16,7 @@
import unittest
import sys

from zope.security._compat import PYTHON2, PYPY
from zope.security._compat import PYTHON2, PYPY, PURE_PYTHON

def _skip_if_not_Py2(testfunc):
from functools import update_wrapper
Expand Down Expand Up @@ -1946,6 +1946,6 @@ def test_suite():
unittest.makeSuite(ProxyTests),
unittest.makeSuite(LocationProxySecurityCheckerTests),
))
if not PYPY:
if not (PYPY or PURE_PYTHON):
suite.addTest(unittest.makeSuite(ProxyCTests))
return suite

0 comments on commit 9286583

Please sign in to comment.