diff options
author | Tres Seaver <tseaver@palladion.com> | 2013-02-14 15:22:59 -0500 |
---|---|---|
committer | Tres Seaver <tseaver@palladion.com> | 2013-02-14 15:22:59 -0500 |
commit | d59c575269bafa1429608f9433bdaccb0f5568ee (patch) | |
tree | b961dbdf166b52ada30582d57631df3242cef7c2 /src | |
parent | 7b543eacbf0b7addd00afedbd899ba9984fbc622 (diff) | |
download | zope-security-d59c575269bafa1429608f9433bdaccb0f5568ee.tar.gz |
Checkpoint to ask for help.
Diffstat (limited to 'src')
-rw-r--r-- | src/zope/security/proxy.py | 185 | ||||
-rw-r--r-- | src/zope/security/tests/test_proxy.py | 29 |
2 files changed, 205 insertions, 9 deletions
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py index 4c189dc..899970a 100644 --- a/src/zope/security/proxy.py +++ b/src/zope/security/proxy.py @@ -15,11 +15,188 @@ """ __docformat__ = 'restructuredtext' +import functools -from zope.security._proxy import getChecker -from zope.security._proxy import getObject -from zope.security._proxy import _Proxy -Proxy = _Proxy + +from zope.proxy import PyProxyBase + + +def _check_name(meth): + name = meth.__name__ + func = meth.__func__ + def _wrapper(self, *args, **kw): + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + checker = super(PyProxyBase, self).__getattribute__('_checker') + checker.check_getattr(wrapped, name) + return getattr(wrapped, name)(*args, **kw) + return functools.update_wrapper(_wrapper, meth) + +def _check_name_inplace(meth): + name = meth.__name__ + func = meth.__func__ + def _wrapper(self, *args, **kw): + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + checker = super(PyProxyBase, self).__getattribute__('_checker') + checker.check_getattr(wrapped, name) + w_meth = getattr(wrapped, name, None) + if w_meth is not None: + return w_meth(*args, **kw) + x_name = '__%s__' % name[3:-2] + return ProxyPy(getattr(wrapped, x_name)(*args, **kw), checker) + return functools.update_wrapper(_wrapper, meth) + + +class ProxyPy(PyProxyBase): + __slots__ = ('_wrapped', '_checker') + + def __new__(cls, value, checker): + inst = super(PyProxyBase, cls).__new__(cls) + inst._wrapped = value + inst._checker = checker + return inst + + def __init__(self, value, checker): + if checker is None: + raise ValueError('checker may now be None') + self._wrapped = value + self._checker = checker + + # Attribute protocol + def __getattribute__(self, name): + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + checker = super(PyProxyBase, self).__getattribute__('_checker') + if name == '_wrapped': + return wrapped + if name == '_checker': + return checker + if name not in ['__cmp__', '__hash__', '__bool__']: + checker.check_getattr(wrapped, name) + return super(ProxyPy, self).__getattribute__(name) + + def __getattr__(self, name): + return getattr(self._wrapped, name) + + def __setattr__(self, name, value): + if name in ('_wrapped', '_checker'): + return super(PyProxyBase, self).__setattr__(name, value) + setattr(self._wrapped, name, value) + + def __delattr__(self, name): + if name in ('_wrapped', '_checker'): + raise AttributeError() + delattr(self._wrapped, name) + + def __cmp__(self, other): + # no check + import pdb; pdb.set_trace() + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + return cmp(wrapped, other) + + def __hash__(self): + # no check + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + return hash(wrapped) + + def __nonzero__(self): + # no check + wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') + return bool(wrapped) + __bool__ = __nonzero__ + +for name in ['__call__', + '__repr__', + '__str__', + '__unicode__', + '__reduce__', + '__reduce_ex__', + '__lt__', + '__le__', + '__eq__', + '__ge__', + '__gt__', + #'__cmp__', # Unchecked in C proxy + #'__nonzero__', # Unchecked in C proxy + #'__bool__', # Unchecked in C proxy + #'__hash__', # Unchecked in C proxy + '__len__', + '__getitem__', + '__setitem__', + '__delitem__', + '__iter__', + '__next__', + 'next', + '__contains__', + '__neg__', + '__pos__', + '__abs__', + '__invert__', + '__complex__', + '__int__', + '__float__', + '__long__', + '__oct__', + '__hex__', + '__index__', + '__coerce__', + '__add__', + '__sub__', + '__mul__', + '__div__', + '__truediv__', + '__floordiv__', + '__mod__', + '__divmod__', + '__pow__', + '__radd__', + '__rsub__', + '__rmul__', + '__rdiv__', + '__rtruediv__', + '__rfloordiv__', + '__rmod__', + '__rdivmod__', + '__rpow__', + '__lshift__', + '__rshift__', + '__and__', + '__xor__', + '__or__', + '__rlshift__', + '__rrshift__', + '__rand__', + '__rxor__', + '__ror__', + ]: + meth = getattr(PyProxyBase, name) + setattr(ProxyPy, name, _check_name(meth)) + +for name in ['__iadd__', + '__isub__', + '__imul__', + '__idiv__', + '__itruediv__', + '__ifloordiv__', + '__imod__', + '__ilshift__', + '__irshift__', + '__iand__', + '__ixor__', + '__ior__', + '__ipow__', + ]: + meth = getattr(PyProxyBase, name) + setattr(ProxyPy, name, _check_name_inplace(meth)) + +try: + from zope.security._proxy import _Proxy +except ImportError: + #getChecker = getCheckerPy + #getObject = getObjectPy + Proxy = ProxyPy +else: + from zope.security._proxy import getChecker + from zope.security._proxy import getObject + Proxy = _Proxy # We need the injection of DecoratedSecurityCheckerDescriptor into # zope.location's LocationProxy as soon someone uses security proxies by diff --git a/src/zope/security/tests/test_proxy.py b/src/zope/security/tests/test_proxy.py index dbf4a1d..877616d 100644 --- a/src/zope/security/tests/test_proxy.py +++ b/src/zope/security/tests/test_proxy.py @@ -36,11 +36,7 @@ def _skip_if_Py2(testfunc): return testfunc -class ProxyCTests(unittest.TestCase): - - def _getTargetClass(self): - from zope.security.proxy import _Proxy - return _Proxy +class ProxyTestBase(object): def _makeOne(self, object, checker): return self._getTargetClass()(object, checker) @@ -1290,6 +1286,28 @@ class ProxyCTests(unittest.TestCase): self.assertEqual(checker._checked, '__setitem__') +class ProxyCTests(unittest.TestCase, ProxyTestBase): + + def _getTargetClass(self): + from zope.security.proxy import _Proxy + return _Proxy + + +class ProxyPyTests(unittest.TestCase, ProxyTestBase): + + def _getTargetClass(self): + from zope.security.proxy import ProxyPy + return ProxyPy + + def test_ctor_w_checker(self): + # Can't access '_wrapped' / '_checker' in C version + target = object() + checker = object() + proxy = self._makeOne(target, checker) + self.assertTrue(proxy._wrapped is target) + self.assertTrue(proxy._checker is checker) + + class DummyChecker(object): _proxied = _checked = None def __init__(self, raising=None, allowed=()): @@ -1832,6 +1850,7 @@ class LocationProxySecurityCheckerTests(unittest.TestCase): def test_suite(): return unittest.TestSuite(( + unittest.makeSuite(ProxyPyTests), unittest.makeSuite(ProxyCTests), unittest.makeSuite(Test_getTestProxyItems), unittest.makeSuite(Test_isinstance), |