From 31dc25752f7eeacf128299f721b9d0f488732cc7 Mon Sep 17 00:00:00 2001 From: Michael Howitz Date: Mon, 30 Aug 2021 10:21:35 +0200 Subject: Lint the code. Add support for Python 3.9. --- src/zope/security/__init__.py | 1 - src/zope/security/_compat.py | 4 +- src/zope/security/_definitions.py | 2 + src/zope/security/adapter.py | 2 + src/zope/security/checker.py | 154 ++++++++++------ src/zope/security/decorator.py | 3 +- src/zope/security/examples/sandbox.py | 73 +++++--- src/zope/security/examples/sandbox_security.py | 64 +++---- src/zope/security/interfaces.py | 25 ++- src/zope/security/management.py | 15 +- src/zope/security/metaconfigure.py | 10 +- src/zope/security/metadirectives.py | 32 ++-- src/zope/security/permission.py | 7 + src/zope/security/protectclass.py | 2 + src/zope/security/proxy.py | 93 +++++----- src/zope/security/testing.py | 6 +- src/zope/security/tests/__init__.py | 3 +- src/zope/security/tests/exampleclass.py | 4 + src/zope/security/tests/module.py | 18 +- src/zope/security/tests/test_adapter.py | 53 ++++-- src/zope/security/tests/test_checker.py | 240 ++++++++++++++++--------- src/zope/security/tests/test_decorator.py | 25 ++- src/zope/security/tests/test_location.py | 1 + src/zope/security/tests/test_management.py | 5 +- src/zope/security/tests/test_metaconfigure.py | 35 +++- src/zope/security/tests/test_permission.py | 7 +- src/zope/security/tests/test_protectclass.py | 1 + src/zope/security/tests/test_proxy.py | 220 +++++++++++++++-------- src/zope/security/tests/test_simplepolicies.py | 4 +- src/zope/security/tests/test_testing.py | 5 +- src/zope/security/tests/test_zcml.py | 21 +-- src/zope/security/tests/test_zcml_functest.py | 34 ++-- src/zope/security/zcml.py | 5 + 33 files changed, 752 insertions(+), 422 deletions(-) (limited to 'src') diff --git a/src/zope/security/__init__.py b/src/zope/security/__init__.py index 5f079f6..d6f39f4 100644 --- a/src/zope/security/__init__.py +++ b/src/zope/security/__init__.py @@ -21,4 +21,3 @@ from zope.security.checker import canWrite, canAccess # zope.location's LocationProxy as soon someone uses security proxies by # importing zope.security.proxy: import zope.security.decorator - diff --git a/src/zope/security/_compat.py b/src/zope/security/_compat.py index 07b3a02..6f7dc0a 100644 --- a/src/zope/security/_compat.py +++ b/src/zope/security/_compat.py @@ -22,7 +22,7 @@ py_impl = getattr(platform, 'python_implementation', lambda: None) PYPY = py_impl() == 'PyPy' PURE_PYTHON = os.environ.get('PURE_PYTHON', PYPY) -if sys.version_info[0] < 3: # pragma: no cover +if sys.version_info[0] < 3: # pragma: no cover CLASS_TYPES = (type, types.ClassType) _BUILTINS = '__builtin__' @@ -30,7 +30,7 @@ if sys.version_info[0] < 3: # pragma: no cover PYTHON3 = False PYTHON2 = True -else: # pragma: no cover +else: # pragma: no cover CLASS_TYPES = (type,) _BUILTINS = 'builtins' diff --git a/src/zope/security/_definitions.py b/src/zope/security/_definitions.py index 929823c..070a345 100644 --- a/src/zope/security/_definitions.py +++ b/src/zope/security/_definitions.py @@ -20,10 +20,12 @@ from zope.security import interfaces thread_local = threading.local() + @zope.interface.implementer(interfaces.ISystemPrincipal) class SystemUser(object): id = u'zope.security.management.system_user' title = u'System' description = u'' + system_user = SystemUser() diff --git a/src/zope/security/adapter.py b/src/zope/security/adapter.py index 661e49d..c8c44b6 100644 --- a/src/zope/security/adapter.py +++ b/src/zope/security/adapter.py @@ -18,6 +18,7 @@ from zope.security.checker import ProxyFactory from zope.security.proxy import removeSecurityProxy from zope.location import ILocation, LocationProxy + def assertLocation(adapter, parent): """ Assert locatable adapters. @@ -59,6 +60,7 @@ class LocatingTrustedAdapterFactory(object): ``__parent__`` is None, we set the ``__parent__`` to the adapter's context. """ + def __init__(self, factory): self.factory = factory self.__name__ = factory.__name__ diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py index 2dbc4e1..67723e8 100644 --- a/src/zope/security/checker.py +++ b/src/zope/security/checker.py @@ -36,14 +36,16 @@ You can set the environment variable ``ZOPE_WATCH_CHECKERS`` before this module is imported to get additional security checker debugging output on the standard error. -Setting ``ZOPE_WATCH_CHECKERS`` to 1 will display messages about unauthorized or -forbidden attribute access. Setting it to a larger number will also display +Setting ``ZOPE_WATCH_CHECKERS`` to 1 will display messages about unauthorized +or forbidden attribute access. Setting it to a larger number will also display messages about granted attribute access. Note that the ``ZOPE_WATCH_CHECKERS`` mechanism may eventually be replaced with a more general security auditing mechanism. -.. seealso:: :class:`CheckerLoggingMixin`, :class:`WatchingChecker`, :class:`WatchingCombinedChecker` +.. seealso:: :class:`CheckerLoggingMixin` +.. seealso:: :class:`WatchingChecker` +.. seealso:: :class:`WatchingCombinedChecker` API === @@ -88,16 +90,16 @@ from zope.security.proxy import getChecker try: from zope.exceptions import DuplicationError -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover class DuplicationError(Exception): """A duplicate registration was attempted""" WATCH_CHECKERS = 0 -if os.environ.get('ZOPE_WATCH_CHECKERS'): +if os.environ.get('ZOPE_WATCH_CHECKERS'): # pragma: no cover try: WATCH_CHECKERS = int(os.environ.get('ZOPE_WATCH_CHECKERS')) - except ValueError: # pragma: no cover + except ValueError: WATCH_CHECKERS = 1 @@ -129,12 +131,14 @@ def ProxyFactory(object, checker=None): return Proxy(object, checker) + directlyProvides(ProxyFactory, ISecurityProxyFactory) # This import represents part of the API for the proxy module from . import proxy proxy.ProxyFactory = ProxyFactory + def canWrite(obj, name): """Check whether the interaction may write an attribute named name on obj. @@ -169,6 +173,7 @@ def canWrite(obj, name): # should be passed through uncaught, as they indicate programmer error return True + def canAccess(obj, name): """Check whether the interaction may access an attribute named name on obj. @@ -187,6 +192,7 @@ def canAccess(obj, name): # indicates a programming or configuration error return True + @implementer(INameBasedChecker) class CheckerPy(object): """ @@ -230,7 +236,6 @@ class CheckerPy(object): if self.set_permissions: return self.set_permissions.get(name) - def check_setattr(self, object, name): 'See IChecker' if self.set_permissions: @@ -240,9 +245,9 @@ class CheckerPy(object): if permission is not None: if permission is CheckerPublic: - return # Public + return # Public if thread_local.interaction.checkPermission(permission, object): - return # allowed + return # allowed else: __traceback_supplement__ = (TracebackSupplement, object) raise Unauthorized(object, name, permission) @@ -255,7 +260,7 @@ class CheckerPy(object): permission = self.get_permissions.get(name) if permission is not None: if permission is CheckerPublic: - return # Public + return # Public if thread_local.interaction.checkPermission(permission, object): return else: @@ -268,7 +273,7 @@ class CheckerPy(object): __traceback_supplement__ = (TracebackSupplement, object) raise ForbiddenAttribute(name, object) - check_getattr = check # 'See IChecker' + check_getattr = check # 'See IChecker' def proxy(self, value): 'See IChecker' @@ -281,7 +286,9 @@ class CheckerPy(object): return value return Proxy(value, checker) -Checker = CheckerPy # in case no C optimizations + + +Checker = CheckerPy # in case no C optimizations # Helper class for __traceback_supplement__ @@ -296,19 +303,19 @@ class TracebackSupplement(object): cls = self.obj.__class__ if hasattr(cls, "__module__"): s = "%s.%s" % (cls.__module__, cls.__name__) - else: # pragma: no cover XXX + else: # pragma: no cover XXX s = str(cls.__name__) result.append(" - class: " + s) - except: # pragma: no cover XXX + except: # pragma: no cover # noqa: E722 do not use bare 'except' pass try: cls = type(self.obj) if hasattr(cls, "__module__"): s = "%s.%s" % (cls.__module__, cls.__name__) - else: # pragma: no cover XXX + else: # pragma: no cover XXX s = str(cls.__name__) result.append(" - type: " + s) - except: # pragma: no cover XXX + except: # pragma: no cover # noqa: E722 do not use bare 'except' pass return "\n".join(result) @@ -322,7 +329,7 @@ class Global(object): """ def __init__(self, name, module=None): - if module is None: # pragma: no cover XXX + if module is None: # pragma: no cover XXX module = sys._getframe(1).f_locals['__name__'] self.__name__ = name @@ -344,7 +351,7 @@ CP_HACK_XXX = CheckerPublic # XXX: This means that we can't directly document it with # sphinx because issubclass() will fail. d = {} -CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy +CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy d['__reduce__'] = CheckerPublic d['__module__'] = CheckerPublic del d @@ -353,6 +360,7 @@ del d # granted to __reduce__. We might want to bother to prevent this in # general and only allow it in this specific case. + def NamesChecker(names=(), permission_id=CheckerPublic, **__kw__): """Return a checker that grants access to a set of names. @@ -371,6 +379,7 @@ def NamesChecker(names=(), permission_id=CheckerPublic, **__kw__): return Checker(data) + def InterfaceChecker(interface, permission_id=CheckerPublic, **__kw__): """ Create a :func:`NamesChecker` for all the names defined in the *interface* @@ -378,6 +387,7 @@ def InterfaceChecker(interface, permission_id=CheckerPublic, **__kw__): """ return NamesChecker(interface.names(all=True), permission_id, **__kw__) + def MultiChecker(specs): """ Create a checker from a sequence of specifications @@ -415,6 +425,7 @@ def MultiChecker(specs): return Checker(data) + def selectCheckerPy(object): """Get a checker for the given object @@ -428,13 +439,13 @@ def selectCheckerPy(object): # TODO: we really need formal proxy introspection - #if type(object) is Proxy: + # if type(object) is Proxy: # # Is this already a security proxy? # return None checker = _getChecker(type(object), _defaultChecker) - #checker = _getChecker(getattr(object, '__class__', type(object)), + # checker = _getChecker(getattr(object, '__class__', type(object)), # _defaultChecker) if checker is NoProxy: @@ -447,12 +458,18 @@ def selectCheckerPy(object): return None return checker -selectChecker = selectCheckerPy # in case no C optimizations + + +selectChecker = selectCheckerPy # in case no C optimizations + def getCheckerForInstancesOf(class_): return _checkers.get(class_) + DEFINABLE_TYPES = CLASS_TYPES + (types.ModuleType,) + + def defineChecker(type_, checker): """Define a checker for a given type of object @@ -466,9 +483,11 @@ def defineChecker(type_, checker): raise DuplicationError(type_) _checkers[type_] = checker + def undefineChecker(type_): del _checkers[type_] + NoProxy = object() # _checkers is a mapping. @@ -488,13 +507,13 @@ _available_by_default = [] # Get optimized versions _c_available = not PURE_PYTHON -if _c_available: +if _c_available: # pragma: no cover try: import zope.security._zope_security_checker - except (ImportError, AttributeError): # pragma: no cover PyPy / PURE_PYTHON + except (ImportError, AttributeError): _c_available = False -if _c_available: +if _c_available: # pragma: no cover from zope.security._zope_security_checker import _checkers, selectChecker from zope.security._zope_security_checker import NoProxy, Checker from zope.security._zope_security_checker import _defaultChecker @@ -504,6 +523,7 @@ if _c_available: _getChecker = _checkers.get + @implementer_if_needed(IChecker) class CombinedChecker(Checker): """A checker that combines two other checkers in a logical-or fashion. @@ -527,7 +547,7 @@ class CombinedChecker(Checker): +--------------------+--------------------+-------------------------------------+ | ForbiddenAttribute | ForbiddenAttribute | ForbiddenAttribute | +--------------------+--------------------+-------------------------------------+ - """ + """ # noqa: E501 line too long def __init__(self, checker1, checker2): """Create a combined checker.""" @@ -544,7 +564,8 @@ class CombinedChecker(Checker): except ForbiddenAttribute: self._checker2.check(object, name) except Unauthorized as unauthorized_exception: - try: self._checker2.check(object, name) + try: + self._checker2.check(object, name) except ForbiddenAttribute: raise unauthorized_exception @@ -562,6 +583,7 @@ class CombinedChecker(Checker): except ForbiddenAttribute: raise unauthorized_exception + class CheckerLoggingMixin(object): """ Debugging mixin for checkers. @@ -649,6 +671,8 @@ class WatchingChecker(CheckerLoggingMixin, Checker): module is imported. """ verbosity = WATCH_CHECKERS + + class WatchingCombinedChecker(CombinedChecker, WatchingChecker): """ A checker that will perform verbose logging. This will be set @@ -657,7 +681,8 @@ class WatchingCombinedChecker(CombinedChecker, WatchingChecker): """ verbosity = WATCH_CHECKERS -if WATCH_CHECKERS: # pragma: no cover + +if WATCH_CHECKERS: # pragma: no cover # When we make these the default, we also need to be sure # to update the _defaultChecker's type (if it's not the C # extension) so that selectCheckerPy can properly recognize @@ -669,9 +694,11 @@ if WATCH_CHECKERS: # pragma: no cover if not _c_available: _defaultChecker.__class__ = Checker + def _instanceChecker(inst): return _checkers.get(inst.__class__, _defaultChecker) + def moduleChecker(module): """ Return the :class:`zope.security.interfaces.IChecker` defined for the @@ -713,11 +740,13 @@ _setChecker = NamesChecker([ '__le__', '__ge__', ]) + class _BasicTypes(dict): """Basic Types Dictionary Make sure that checkers are really updated, when a new type is added. """ + def __setitem__(self, name, value): dict.__setitem__(self, name, value) _checkers[name] = value @@ -734,6 +763,7 @@ class _BasicTypes(dict): dict.update(self, d) _checkers.update(d) + _basic_types = { object: NoProxy, int: NoProxy, @@ -742,7 +772,7 @@ _basic_types = { type(None): NoProxy, str: NoProxy, bytes: NoProxy, - Message: NoProxy, # Messages are immutable, so it's okay + Message: NoProxy, # Messages are immutable, so it's okay bool: NoProxy, datetime.timedelta: NoProxy, datetime.datetime: NoProxy, @@ -750,10 +780,10 @@ _basic_types = { datetime.time: NoProxy, datetime.tzinfo: NoProxy, } -if PYTHON2: - _basic_types[long] = NoProxy - _basic_types[unicode] = NoProxy -else: # pragma: no cover +if PYTHON2: # pragma: no cover + _basic_types[long] = NoProxy # noqa: F821 undefined name 'long' + _basic_types[unicode] = NoProxy # noqa: F821 undefined name 'unicode' +else: _basic_types[type({}.values())] = NoProxy _basic_types[type({}.keys())] = NoProxy _basic_types[type({}.items())] = NoProxy @@ -784,26 +814,29 @@ BasicTypes_examples = { Message: Message('message', domain='hello') } -if PYTHON2: - BasicTypes_examples[unicode] = u'uabc' - BasicTypes_examples[long] = long(65536) +if PYTHON2: # pragma: no cover + BasicTypes_examples[unicode] = u'uabc' # noqa: F821 undefined name + BasicTypes_examples[long] = long(65536) # noqa: F821 undefined name class _Sequence(object): def __len__(self): raise NotImplementedError() + def __getitem__(self, i): raise NotImplementedError() + _Declaration_checker = InterfaceChecker( IDeclaration, _implied=CheckerPublic, subscribe=CheckerPublic, unsubscribe=CheckerPublic, __call__=CheckerPublic, - ) +) + -def f(): # pragma: no cover +def f(): # pragma: no cover yield f @@ -837,7 +870,7 @@ _default_checkers = { 'max', 'min', 'normalize', 'quantize', 'remainder_near', 'same_quantum', 'sqrt', - 'to_eng_string', 'to_integral' ]), + 'to_eng_string', 'to_integral']), # YAGNI: () a rock tuple: NamesChecker(['__getitem__', '__getslice__', '__add__', '__radd__', @@ -851,8 +884,8 @@ _default_checkers = { types.BuiltinMethodType: _callableChecker, type: _typeChecker, types.ModuleType: lambda module: _checkers.get(module, _namedChecker), - type(iter([])): _iteratorChecker, # Same types in Python 2.2.1, - type(iter(())): _iteratorChecker, # different in Python 2.3. + type(iter([])): _iteratorChecker, # Same types in Python 2.2.1, + type(iter(())): _iteratorChecker, # different in Python 2.3. type(iter({})): _iteratorChecker, type(iter(set())): _iteratorChecker, type(iter(_Sequence())): _iteratorChecker, @@ -875,7 +908,7 @@ _default_checkers = { zope.interface.declarations.Declaration: _Declaration_checker, abc.ABCMeta: _typeChecker, } -if PYTHON2: +if PYTHON2: # pragma: no cover _default_checkers[types.ClassType] = _typeChecker _default_checkers[types.InstanceType] = _instanceChecker # slot description @@ -884,6 +917,7 @@ if PYTHON2: _default_checkers[type({}.iterkeys())] = _iteratorChecker _default_checkers[type({}.itervalues())] = _iteratorChecker + def _fixup_dictlike(dict_type): empty_dict = dict_type() populated_dict = dict_type({1: 2}) @@ -898,20 +932,24 @@ def _fixup_dictlike(dict_type): if iter_type not in _default_checkers: _default_checkers[iter_type] = _iteratorChecker + def _fixup_odict(): # OrderedDicts have three different implementations: Python 2 (pure # python, returns generators and lists), Python <=3.4 (pure Python, # uses view classes) and CPython 3.5+ (implemented in C). These should # all be iterable. from collections import OrderedDict - _fixup_dictlike(OrderedDict) + # The `_fixup_dictlike` is detected as undefined because it is deleted + # later on but this function is called beforehand: + _fixup_dictlike(OrderedDict) # noqa: F821 undefined name '_fixup_dictlike' + _fixup_odict() del _fixup_odict try: - import BTrees -except ImportError: # pragma: no cover + import BTrees # noqa: F401 'BTrees' imported but unused +except ImportError: # pragma: no cover pass else: # The C implementation of BTree.items() is its own iterator @@ -934,13 +972,16 @@ else: for family_name in ('family32', 'family64'): family = getattr(BTrees, family_name) btree = getattr(family, name).BTree - _fixup_dictlike(btree) + # The `_fixup_dictlike` is detected as undefined because it is + # deleted later on but this function is called beforehand: + _fixup_dictlike(btree) # noqa: F821 undefined name _fixup_btrees() del _fixup_btrees del _fixup_dictlike + def _fixup_zope_interface(): # Make sure the provided and implementedBy objects # can be iterated. @@ -948,7 +989,8 @@ def _fixup_zope_interface(): # we use NoProxy to be sure that the results (of iteration or not) are not # proxied. On Python 2, these objects are builtin and don't go through the # checking process at all, much like BTrees, so NoProxy is necessary for - # compatibility. On Python 3, prior to this, iteration was simply not allowed. + # compatibility. On Python 3, prior to this, iteration was simply not + # allowed. from zope.interface import providedBy from zope.interface import alsoProvides @@ -959,11 +1001,10 @@ def _fixup_zope_interface(): pass @implementer(I1) - class O(object): + class Obj(object): pass - o = O() - + o = Obj() # This will be athe zope.interface.implementedBy from the class # a zope.interface.declarations.Implements @@ -973,6 +1014,7 @@ def _fixup_zope_interface(): # This will be the zope.interface.Provides from the instance _default_checkers[type(providedBy(o))] = NoProxy + _fixup_zope_interface() del _fixup_zope_interface @@ -998,8 +1040,10 @@ def _fixup_itertools(): _default_checkers[type_grouper] = _iteratorChecker # There are also many other custom types in itertools that need the - # same treatment. See a similar list in test_checker.py:test_itertools_checkers - pred = lambda x: x + # same treatment. See a similar list in + # test_checker.py:test_itertools_checkers + def pred(x): + return x iterable = (1, 2, 3) pred_iterable = (pred, iterable) missing_in_py3 = {'ifilter', 'ifilterfalse', 'imap', @@ -1034,7 +1078,8 @@ def _fixup_itertools(): func = getattr(itertools, func) except AttributeError: assert func in missing, "Expected %s but not found" % (func,) - continue # pragma: no cover This is hit on Python 2, but it doesn't always show + # The following line is hit on PY2, but it doesn't always show: + continue # pragma: no cover result = func(*args) if func == itertools.tee: @@ -1043,19 +1088,22 @@ def _fixup_itertools(): if tresult not in _default_checkers: _default_checkers[tresult] = _iteratorChecker + _fixup_itertools() del _fixup_itertools + def _clear(): _checkers.clear() _checkers.update(_default_checkers) _checkers.update(BasicTypes) + _clear() try: from zope.testing.cleanup import addCleanUp -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover pass else: addCleanUp(_clear) diff --git a/src/zope/security/decorator.py b/src/zope/security/decorator.py index 82ae6e2..dfd6fc7 100644 --- a/src/zope/security/decorator.py +++ b/src/zope/security/decorator.py @@ -30,6 +30,7 @@ from zope.security.proxy import getChecker class DecoratedSecurityCheckerDescriptor(object): """Descriptor for a Decorator that provides a decorated security checker. """ + def __get__(self, inst, cls=None): if inst is None: return self @@ -58,7 +59,7 @@ class DecoratedSecurityCheckerDescriptor(object): class SecurityCheckerDecoratorBase(ProxyBase): - """Base class for a proxy that provides additional security declarations.""" + """Base class for proxy that provides additional security declarations.""" __Security_checker__ = DecoratedSecurityCheckerDescriptor() diff --git a/src/zope/security/examples/sandbox.py b/src/zope/security/examples/sandbox.py index 8a17984..eb6499f 100644 --- a/src/zope/security/examples/sandbox.py +++ b/src/zope/security/examples/sandbox.py @@ -13,13 +13,15 @@ ############################################################################## """A small sandbox application. """ -import time, random +import time +import random from zope.interface import Interface, implementer + class IAgent(Interface): """A player/agent in the world. - + The agent represents an autonomous unit, that lives in various homes/sandboxes and accesses services present at the sandboxes. Agents are imbued with a sense of wanderlust and attempt to find new homes after a @@ -40,7 +42,7 @@ class IAgent(Interface): class IService(Interface): """Marker to designate some form of functionality. - + Services are available from sandboxes, examples include time service, agent discovery, and sandbox discovery. """ @@ -63,20 +65,21 @@ class ISandbox(Interface): class SandboxError(Exception): - """A sandbox error is thrown, if any action could not be performed.""" + """A sandbox error is thrown, if any action could not be performed.""" pass class Identity(object): """Mixin for pretty printing and identity method""" + def __init__(self, id, *args, **kw): self.id = id def getId(self): return self.id - def __str__ (self): - return "<%s> %s"%(str(self.__class__.__name__), str(self.id)) + def __str__(self): + return "<%s> %s" % (str(self.__class__.__name__), str(self.id)) __repr__ = __str__ @@ -124,92 +127,109 @@ class Sandbox(Identity): def getAgentIds(self): return self._agents.keys() + def getAgents(self): return self._agents.values() + def getServiceIds(self): return self._services.keys() + def getService(self, sid): return self._services.get(sid) + def getHome(self): return self - def addAgent(self, agent): - if not self._agents.has_key(agent.getId()) \ - and IAgent.providedBy(agent): - self._agents[agent.getId()]=agent + if agent.getId() not in self._agents \ + and IAgent.providedBy(agent): + self._agents[agent.getId()] = agent agent.setHome(self) else: - raise SandboxError("couldn't add agent %s"%agent) + raise SandboxError("couldn't add agent %s" % agent) def addService(self, service): - if not self._services.has_key(service.getId()) \ - and IService.providedBy(service): - self._services[service.getId()]=service + if not service.getId() in self._services \ + and IService.providedBy(service): + self._services[service.getId()] = service service.setHome(self) else: - raise SandboxError("couldn't add service %s"%service) + raise SandboxError("couldn't add service %s" % service) def transportAgent(self, agent, destination): - if self._agents.has_key(agent.getId()) \ - and destination is not self \ - and ISandbox.providedBy(destination): + if agent.getId() in self._agents \ + and destination is not self \ + and ISandbox.providedBy(destination): destination.addAgent(agent) del self._agents[agent.getId()] else: - raise SandboxError("couldn't transport agent %s to %s"%( + raise SandboxError("couldn't transport agent %s to %s" % ( agent, destination) - ) + ) + @implementer(IService) class Service(object): def getId(self): return self.__class__.__name__ + def setHome(self, home): self._home = home + def getHome(self): return getattr(self, '_home') + class HomeDiscoveryService(Service): """ returns the ids of available agent homes """ + def getAvailableHomes(self): return _homes.keys() + class AgentDiscoveryService(Service): """ returns the agents available at a given home """ + def getLocalAgents(self, home): return home.getAgents() + class TimeService(Service): """ returns the local time """ + def getTime(self): return time.time() + default_service_factories = ( HomeDiscoveryService, AgentDiscoveryService, TimeService - ) +) + def action_find_homes(agent, home): home_service = home.getService('HomeDiscoveryService') return home_service.getAvailableHomes() + def action_find_neighbors(agent, home): agent_service = home.getService('AgentDiscoveryService') return agent_service.getLocalAgents(home) + def action_find_time(agent, home): time_service = home.getService('TimeService') return time_service.getTime() + class TimeGenerator(object): """Represents the passage of time in the agent simulation. @@ -238,7 +258,7 @@ class TimeGenerator(object): except Exception as e: print('-- Exception --') print('"%s" in "%s" not allow to "%s"' - % (a, h, a._action.__name__)) + % (a, h, a._action.__name__)) print(e) print() self.teardownAgent(a) @@ -253,7 +273,8 @@ class TimeGenerator(object): home.transportAgent(a, new_home) except Exception as e: print('-- Exception --') - print('moving "%s" from "%s" to "%s"' %(a, h, repr(new_home))) + print('moving "%s" from "%s" to "%s"' % + (a, h, repr(new_home))) print(e) print() self.teardownAgent(a) @@ -264,6 +285,7 @@ def WanderLust(agent): if int(random.random()*100) <= 30: return 1 + def GreenerPastures(agent): """ where do they want to go today """ global _homes @@ -286,7 +308,7 @@ all_homes = ( origin = all_homes[1] for h in all_homes: - _homes[h.getId()]=h + _homes[h.getId()] = h agents = [ @@ -296,7 +318,7 @@ agents = [ Agent('thucydides', None, 'greek men', action_find_time), Agent('archimedes', None, 'greek men', action_find_neighbors), Agent('prometheus', None, 'greek men', action_find_homes), - ] +] for a in agents: origin.addAgent(a) @@ -312,5 +334,6 @@ def main(): for h in _homes.values(): print(h.getId(), h.getAgentIds()) + if __name__ == '__main__': main() diff --git a/src/zope/security/examples/sandbox_security.py b/src/zope/security/examples/sandbox_security.py index d0bfe15..5115ca7 100644 --- a/src/zope/security/examples/sandbox_security.py +++ b/src/zope/security/examples/sandbox_security.py @@ -17,13 +17,13 @@ This module is responsible of securing the sandbox application and run it in a secure mode. There are several steps that are taken to set up the security 1. map permissions to actions - + 2. map authentication tokens/principals onto permissions - + 3. implement checker and security policies that affect 1,2 - + 4. bind checkers to classes/instances - + 5. proxy wrap as necessary """ import sandbox @@ -32,7 +32,7 @@ from zope.security import checker, management, simplepolicies from zope.interface import implementer -# Define all permissions that will be available +# Define all permissions that will be available NotAllowed = 'Not Allowed' Public = checker.CheckerPublic TransportAgent = 'Transport Agent' @@ -43,9 +43,10 @@ AccessAgentService = 'Access Agent Service' AccessHomeService = 'Access Home Service' AddAgent = 'Add Agent' -ALL='All' +ALL = 'All' + -NoSetAttr = lambda name: NotAllowed +def NoSetAttr(name): return NotAllowed class SimulationSecurityDatabase(object): @@ -55,20 +56,20 @@ class SimulationSecurityDatabase(object): permissions. """ origin = { - 'any' : [ALL] - } + 'any': [ALL] + } jail = { - 'norse legend' : [TransportAgent, AccessServices, AccessAgentService, - AccessHomeService, TransportAgent, AccessAgents], - 'any' : [AccessTimeService, AddAgent] - } + 'norse legend': [TransportAgent, AccessServices, AccessAgentService, + AccessHomeService, TransportAgent, AccessAgents], + 'any': [AccessTimeService, AddAgent] + } valhalla = { - 'norse legend' : [AddAgent], - 'any' : [AccessServices, AccessTimeService, AccessAgentService, - AccessHomeService, TransportAgent, AccessAgents] - } + 'norse legend': [AddAgent], + 'any': [AccessServices, AccessTimeService, AccessAgentService, + AccessHomeService, TransportAgent, AccessAgents] + } class SimulationSecurityPolicy(simplepolicies.ParanoidSecurityPolicy): @@ -108,7 +109,6 @@ class AgentParticipation(object): A very simple participation that is specific to the simulations. """ - def __init__(self, agent): self.principal = agent self.interaction = None @@ -130,27 +130,27 @@ def PermissionMapChecker(permissions_map=None, set_permissions=None): ################################# # sandbox security settings sandbox_security = { - AccessServices : ['getService', 'addService', 'getServiceIds'], - AccessAgents : ['getAgentsIds', 'getAgents'], - AddAgent : ['addAgent'], - TransportAgent : ['transportAgent'], - Public : ['getId','getHome'] - } + AccessServices: ['getService', 'addService', 'getServiceIds'], + AccessAgents: ['getAgentsIds', 'getAgents'], + AddAgent: ['addAgent'], + TransportAgent: ['transportAgent'], + Public: ['getId', 'getHome'] +} sandbox_checker = PermissionMapChecker(sandbox_security) ################################# # service security settings # time service -tservice_security = { AccessTimeService:['getTime'] } +tservice_security = {AccessTimeService: ['getTime']} time_service_checker = PermissionMapChecker(tservice_security) # home service -hservice_security = { AccessHomeService:['getAvailableHomes'] } +hservice_security = {AccessHomeService: ['getAvailableHomes']} home_service_checker = PermissionMapChecker(hservice_security) # agent service -aservice_security = { AccessAgentService:['getLocalAgents'] } +aservice_security = {AccessAgentService: ['getLocalAgents']} agent_service_checker = PermissionMapChecker(aservice_security) @@ -164,14 +164,14 @@ def wire_security(): checker.defineChecker(sandbox.HomeDiscoveryService, home_service_checker) def addAgent(self, agent): - if not self._agents.has_key(agent.getId()) \ - and sandbox.IAgent.providedBy(agent): - self._agents[agent.getId()]=agent + if (agent.getId() not in self._agents + and sandbox.IAgent.providedBy(agent)): + self._agents[agent.getId()] = agent agentChecker = checker.selectChecker(self) wrapped_home = agentChecker.proxy(self) agent.setHome(wrapped_home) else: - raise sandbox.SandboxError("couldn't add agent %s" %agent) + raise sandbox.SandboxError("couldn't add agent %s" % agent) sandbox.Sandbox.addAgent = addAgent @@ -191,7 +191,7 @@ def wire_security(): _homes = sandbox._homes possible_homes = _homes.keys() possible_homes.remove(agent.getHome().getId()) - new_home = _homes.get(random.choice(possible_homes)) + new_home = _homes.get(random.choice(possible_homes)) return checker.selectChecker(new_home).proxy(new_home) sandbox.GreenerPastures = GreenerPastures diff --git a/src/zope/security/interfaces.py b/src/zope/security/interfaces.py index 74cd385..890e6fc 100644 --- a/src/zope/security/interfaces.py +++ b/src/zope/security/interfaces.py @@ -62,6 +62,7 @@ from zope.security.i18n import ZopeMessageFactory as _ #: .. versionadded:: 4.2.0 PUBLIC_PERMISSION_NAME = 'zope.Public' + class IUnauthorized(IException): """ The action is not authorized. @@ -69,6 +70,7 @@ class IUnauthorized(IException): Implemented in :class:`Unauthorized`. """ + @implementer(IUnauthorized) class Unauthorized(Exception): """ @@ -77,6 +79,7 @@ class Unauthorized(Exception): Default implementation of :class:`IUnauthorized`. """ + class IForbidden(IException): """ A resource cannot be accessed under any circumstances @@ -84,6 +87,7 @@ class IForbidden(IException): Implemented in :class:`Forbidden`. """ + @implementer(IForbidden) class Forbidden(Exception): """ @@ -92,6 +96,7 @@ class Forbidden(Exception): Default implementation if :class:`IForbidden`. """ + class IForbiddenAttribute(IForbidden, IAttributeError): """ An attribute is unavailable because it is forbidden (private). @@ -99,6 +104,7 @@ class IForbiddenAttribute(IForbidden, IAttributeError): Implemented in :class:`ForbiddenAttribute`. """ + @implementer(IForbiddenAttribute) class ForbiddenAttribute(Forbidden, AttributeError): """ @@ -137,9 +143,9 @@ class ISecurityChecking(Interface): :param str permission: The permission name. :param object: The object being accessed according to the permission. - :keyword interaction: An :class:`IInteraction`, providing access to information - such as authenticated principals. If it is None, the current - interaction is used. + :keyword interaction: An :class:`IInteraction`, providing access to + information such as authenticated principals. If it is None, the + current interaction is used. """ @@ -257,7 +263,8 @@ class INameBasedChecker(IChecker): """ Return the permission used to check attribute access on *name*. - This permission is used by both :meth:`check` and :meth:`check_getattr`. + This permission is used by both :meth:`check` and + :meth:`check_getattr`. """ def setattr_permission_id(name): @@ -322,6 +329,7 @@ class NoInteraction(Exception): """No interaction started """ + class IInteractionManagement(Interface): """ Interaction management API. @@ -362,6 +370,7 @@ class IInteractionManagement(Interface): Does nothing if there is no interaction. """ + class IPrincipal(Interface): """ Principals are security artifacts that execute actions in a @@ -417,7 +426,9 @@ class IGroupAwarePrincipal(IPrincipal): """ groups = Attribute( - 'An iterable of :class:`IGroup` objects to which the principal directly belongs') + 'An iterable of :class:`IGroup` objects to which the principal' + ' directly belongs') + class IGroupClosureAwarePrincipal(IGroupAwarePrincipal): """ @@ -428,11 +439,13 @@ class IGroupClosureAwarePrincipal(IGroupAwarePrincipal): allGroups = Attribute( "An iterable of the full closure of the principal's groups.") + class IGroup(IPrincipal): """ Group of principals """ + class IMemberGetterGroup(IGroup): """ A group that can get its members. @@ -441,6 +454,7 @@ class IMemberGetterGroup(IGroup): def getMembers(): """Return an iterable of the members of the group""" + class IMemberAwareGroup(IMemberGetterGroup): """ A group that can both set and get its members. @@ -452,6 +466,7 @@ class IMemberAwareGroup(IMemberGetterGroup): *value*. """ + class IPermission(Interface): """A permission object. diff --git a/src/zope/security/management.py b/src/zope/security/management.py index 1acc3d3..2daf0ce 100644 --- a/src/zope/security/management.py +++ b/src/zope/security/management.py @@ -52,10 +52,12 @@ moduleProvides( # ISecurityManagement implementation # + def getSecurityPolicy(): """Get the system default security policy.""" return _defaultPolicy + def setSecurityPolicy(aSecurityPolicy): """Set the system default security policy, and return the previous value. @@ -78,6 +80,7 @@ def queryInteraction(): """Return a current interaction, if there is one.""" return getattr(thread_local, 'interaction', None) + def getInteraction(): """Get the current interaction.""" try: @@ -85,14 +88,16 @@ def getInteraction(): except AttributeError: raise NoInteraction + class ExistingInteraction(ValueError, - AssertionError, #BBB - ): + AssertionError, # BBB + ): """ The exception that :func:`newInteraction` will raise if called during an existing interaction. """ + def newInteraction(*participations): """Start a new interaction.""" if queryInteraction() is not None: @@ -100,6 +105,7 @@ def newInteraction(*participations): " while another interaction is active.") thread_local.interaction = getSecurityPolicy()(*participations) + def endInteraction(): """End the current interaction.""" @@ -116,6 +122,7 @@ def endInteraction(): else: del thread_local.interaction + def restoreInteraction(): try: previous = thread_local.previous_interaction @@ -127,6 +134,7 @@ def restoreInteraction(): else: thread_local.interaction = previous + def checkPermission(permission, object, interaction=None): """Return whether security policy allows permission on object. @@ -155,9 +163,10 @@ def _clear(): global _defaultPolicy _defaultPolicy = ParanoidSecurityPolicy + try: from zope.testing.cleanup import addCleanUp -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover pass else: addCleanUp(_clear) diff --git a/src/zope/security/metaconfigure.py b/src/zope/security/metaconfigure.py index a9ac6ed..ee437da 100644 --- a/src/zope/security/metaconfigure.py +++ b/src/zope/security/metaconfigure.py @@ -40,16 +40,18 @@ def dottedName(klass): return 'None' return klass.__module__ + '.' + klass.__name__ + class ProtectionDeclarationException(Exception): """Security-protection-specific exceptions.""" pass + class ClassDirective(object): def __init__(self, _context, class_): - self.__id = dottedName(class_) # this would barf on a module, anyway + self.__id = dottedName(class_) # this would barf on a module, anyway self.__class = class_ - if isinstance(self.__class, ModuleType): #pragma NO COVER + if isinstance(self.__class, ModuleType): # pragma: no cover raise ConfigurationError('Content class attribute must be a class') self.__context = _context @@ -198,12 +200,12 @@ def protectModule(module, name, permission): def _names(attributes, interfaces): seen = {} for name in attributes: - if not name in seen: + if name not in seen: seen[name] = 1 yield name for interface in interfaces: for name in interface: - if not name in seen: + if name not in seen: seen[name] = 1 yield name diff --git a/src/zope/security/metadirectives.py b/src/zope/security/metadirectives.py index c0830d6..3e85cfd 100644 --- a/src/zope/security/metadirectives.py +++ b/src/zope/security/metadirectives.py @@ -26,13 +26,15 @@ import zope.security.zcml from zope.security.i18n import ZopeMessageFactory as _ from zope.security.zcml import Permission + class IClassDirective(zope.interface.Interface): """Make statements about a class""" class_ = zope.configuration.fields.GlobalObject( title=_("Class"), required=True - ) + ) + class IImplementsSubdirective(zope.interface.Interface): """Declare that the class given by the content directive's class @@ -43,7 +45,8 @@ class IImplementsSubdirective(zope.interface.Interface): title=_("One or more interfaces"), required=True, value_type=zope.configuration.fields.GlobalInterface() - ) + ) + class IRequireSubdirective(zope.interface.Interface): """Indicate that the a specified list of names or the names in a @@ -56,7 +59,7 @@ class IRequireSubdirective(zope.interface.Interface): Specifies the permission by id that will be required to access or mutate the attributes and methods specified."""), required=False, - ) + ) attributes = zope.configuration.fields.Tokens( title=_("Attributes and methods"), @@ -64,7 +67,7 @@ class IRequireSubdirective(zope.interface.Interface): " that can be accessed."), required=False, value_type=zope.configuration.fields.PythonIdentifier(), - ) + ) set_attributes = zope.configuration.fields.Tokens( title=_("Attributes that can be set"), @@ -72,7 +75,7 @@ class IRequireSubdirective(zope.interface.Interface): " modified/mutated."), required=False, value_type=zope.configuration.fields.PythonIdentifier(), - ) + ) interface = zope.configuration.fields.Tokens( title=_("Interfaces"), @@ -80,7 +83,7 @@ class IRequireSubdirective(zope.interface.Interface): " can be accessed."), required=False, value_type=zope.configuration.fields.GlobalInterface(), - ) + ) set_schema = zope.configuration.fields.Tokens( title=_("The attributes specified by the schema can be set"), @@ -88,7 +91,7 @@ class IRequireSubdirective(zope.interface.Interface): " modified/mutated."), required=False, value_type=zope.configuration.fields.GlobalInterface(), - ) + ) like_class = zope.configuration.fields.GlobalObject( title=_("Configure like this class"), @@ -97,7 +100,8 @@ class IRequireSubdirective(zope.interface.Interface): same way the specified class' security is. If this argument is specified, no other argument can be used."""), required=False, - ) + ) + class IAllowSubdirective(zope.interface.Interface): """ @@ -110,13 +114,14 @@ class IAllowSubdirective(zope.interface.Interface): title=_("Attributes"), required=False, value_type=zope.configuration.fields.PythonIdentifier(), - ) + ) interface = zope.configuration.fields.Tokens( title=_("Interface"), required=False, value_type=zope.configuration.fields.GlobalInterface(), - ) + ) + class IFactorySubdirective(zope.interface.Interface): """Specify the factory used to create this content object""" @@ -128,21 +133,22 @@ class IFactorySubdirective(zope.interface.Interface): identification scheme. If not given, defaults to the literal string given as the content directive's 'class' attribute."""), required=False, - ) + ) title = zope.configuration.fields.MessageID( title=_("Title"), description=_("Text suitable for use in the 'add content' menu" " of a management interface"), required=False, - ) + ) description = zope.configuration.fields.MessageID( title=_("Description"), description=_("Longer narrative description of what this" " factory does"), required=False, - ) + ) + class IModule(Interface): """Group security declarations about a module""" diff --git a/src/zope/security/permission.py b/src/zope/security/permission.py index 88ba978..da0dd40 100644 --- a/src/zope/security/permission.py +++ b/src/zope/security/permission.py @@ -29,6 +29,7 @@ from zope.security.checker import CheckerPublic from zope.security.interfaces import IPermission from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + @implementer(IPermission) class Permission(object): """ @@ -40,6 +41,7 @@ class Permission(object): self.title = title self.description = description + def checkPermission(context, permission_id): """ Check whether a given permission object exists in the provided @@ -50,6 +52,7 @@ def checkPermission(context, permission_id): if not queryUtility(IPermission, permission_id, context=context): raise ValueError("Undefined permission ID", permission_id) + def allPermissions(context=None): """ Get the IDs of all defined permission object utilities. @@ -58,6 +61,7 @@ def allPermissions(context=None): if name != zope_Public: yield name + def PermissionsVocabulary(context=None): """ A vocabulary of permission IDs. @@ -69,8 +73,10 @@ def PermissionsVocabulary(context=None): terms.append(SimpleTerm(permission, name)) return SimpleVocabulary(terms) + directlyProvides(PermissionsVocabulary, IVocabularyFactory) + def PermissionIdsVocabulary(context=None): """ A vocabulary of permission IDs. @@ -100,4 +106,5 @@ def PermissionIdsVocabulary(context=None): terms.insert(0, SimpleTerm(CheckerPublic, zope_Public, u'Public')) return SimpleVocabulary(terms) + directlyProvides(PermissionIdsVocabulary, IVocabularyFactory) diff --git a/src/zope/security/protectclass.py b/src/zope/security/protectclass.py index 1b93994..ee897cd 100644 --- a/src/zope/security/protectclass.py +++ b/src/zope/security/protectclass.py @@ -37,6 +37,7 @@ def protectName(class_, name, permission): protections = checker.get_permissions protections[name] = permission + def protectSetAttribute(class_, name, permission): """Set a permission on a particular name.""" checker = getCheckerForInstancesOf(class_) @@ -58,6 +59,7 @@ def protectSetAttribute(class_, name, permission): protections = checker.set_permissions protections[name] = permission + def protectLikeUnto(class_, like_unto): """Use the protections from like_unto for the given class.""" diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py index b64fd0a..1f4281c 100644 --- a/src/zope/security/proxy.py +++ b/src/zope/security/proxy.py @@ -22,10 +22,11 @@ import sys from zope.proxy import PyProxyBase from zope.security._compat import PURE_PYTHON from zope.security._compat import _BUILTINS -from zope.security.interfaces import ForbiddenAttribute + def _check_name(meth, wrap_result=True): name = meth.__name__ + def _wrapper(self, *args, **kw): wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') @@ -36,8 +37,10 @@ def _check_name(meth, wrap_result=True): return checker.proxy(res) return functools.update_wrapper(_wrapper, meth) + def _check_name_inplace(meth): name = meth.__name__ + def _wrapper(self, *args, **kw): wrapped = super(PyProxyBase, self).__getattribute__('_wrapped') checker = super(PyProxyBase, self).__getattribute__('_checker') @@ -47,19 +50,20 @@ def _check_name_inplace(meth): # The proxy object cannot change; we are modifying in place. self._wrapped = w_meth(*args, **kw) return self - x_name = '__%s__' % name[3:-2] + x_name = '__%s__' % name[3:-2] return ProxyPy(getattr(wrapped, x_name)(*args, **kw), checker) return functools.update_wrapper(_wrapper, meth) + def _fmt_address(obj): # Try to replicate PyString_FromString("%p", obj), which actually uses # the platform sprintf(buf, "%p", obj), which we cannot access from Python # directly (and ctypes seems like overkill). if sys.platform != 'win32': return '0x%0x' % id(obj) - if sys.maxsize < 2**32: # pragma: no cover + if sys.maxsize < 2**32: # pragma: no cover return '0x%08X' % id(obj) - return '0x%016X' % id(obj) # pragma: no cover + return '0x%016X' % id(obj) # pragma: no cover class ProxyPy(PyProxyBase): @@ -114,15 +118,16 @@ class ProxyPy(PyProxyBase): # 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. + # 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) @@ -146,8 +151,8 @@ class ProxyPy(PyProxyBase): # explicitly do the same. The consequence is that we lose a # good stack trace if the object implemented its own methods # but we're consistent. We would provide a better error - # message or even subclass of AttributeError, but that's liable to break - # (doc)tests. + # message or even subclass of AttributeError, but that's liable to + # break (doc)tests. wrapped = super(ProxyPy, self).__getattribute__('_wrapped') checker = super(ProxyPy, self).__getattribute__('_checker') checker.check_getattr(wrapped, name) @@ -170,7 +175,7 @@ class ProxyPy(PyProxyBase): delattr(wrapped, name) @_check_name - def __getslice__(self, start, end): + def __getslice__(self, start, end): # pragma: no cover PY2 wrapped = object.__getattribute__(self, '_wrapped') try: getslice = wrapped.__getslice__ @@ -179,7 +184,7 @@ class ProxyPy(PyProxyBase): return getslice(start, end) @_check_name - def __setslice__(self, start, end, value): + def __setslice__(self, start, end, value): # pragma: no cover PY2 wrapped = object.__getattribute__(self, '_wrapped') try: setslice = wrapped.__setslice__ @@ -187,10 +192,10 @@ class ProxyPy(PyProxyBase): return wrapped.__setitem__(slice(start, end), value) return setslice(start, end, value) - def __cmp__(self, other): + def __cmp__(self, other): # pragma: no cover PY2 # no check wrapped = super(ProxyPy, self).__getattribute__('_wrapped') - return cmp(wrapped, other) + return cmp(wrapped, other) # noqa: F821 undefined name 'cmp' def __lt__(self, other): # no check @@ -243,7 +248,7 @@ class ProxyPy(PyProxyBase): else: return hint() - def __coerce__(self, other): + def __coerce__(self, other): # pragma: no cover PY2 # For some reason _check_name does not work for coerce() wrapped = super(ProxyPy, self).__getattribute__('_wrapped') checker = super(ProxyPy, self).__getattribute__('_checker') @@ -258,10 +263,10 @@ class ProxyPy(PyProxyBase): # the wrong type of object. except TypeError: raise - except: + except: # noqa: E722 do not use bare 'except' # The C implementation catches all exceptions. wrapped = super(ProxyPy, self).__getattribute__('_wrapped') - return '' %( + return '' % ( wrapped.__class__.__module__, wrapped.__class__.__name__, _fmt_address(wrapped)) @@ -273,28 +278,29 @@ class ProxyPy(PyProxyBase): # the wrong type of object. except TypeError: raise - except: + except: # noqa: E722 do not use bare 'except' wrapped = super(ProxyPy, self).__getattribute__('_wrapped') - return '' %( + return '' % ( wrapped.__class__.__module__, wrapped.__class__.__name__, _fmt_address(wrapped)) + for name in ['__call__', - #'__repr__', - #'__str__', - #'__unicode__', # Unchecked in C proxy + # '__repr__', + # '__str__', + # '__unicode__', # Unchecked in C proxy '__reduce__', '__reduce_ex__', - #'__lt__', # Unchecked in C proxy (rich coparison) - #'__le__', # Unchecked in C proxy (rich coparison) - #'__eq__', # Unchecked in C proxy (rich coparison) - #'__ne__', # Unchecked in C proxy (rich coparison) - #'__ge__', # Unchecked in C proxy (rich coparison) - #'__gt__', # Unchecked in C proxy (rich coparison) - #'__nonzero__', # Unchecked in C proxy (rich coparison) - #'__bool__', # Unchecked in C proxy (rich coparison) - #'__hash__', # Unchecked in C proxy (rich coparison) - #'__cmp__', # Unchecked in C proxy + # '__lt__', # Unchecked in C proxy (rich coparison) + # '__le__', # Unchecked in C proxy (rich coparison) + # '__eq__', # Unchecked in C proxy (rich coparison) + # '__ne__', # Unchecked in C proxy (rich coparison) + # '__ge__', # Unchecked in C proxy (rich coparison) + # '__gt__', # Unchecked in C proxy (rich coparison) + # '__nonzero__', # Unchecked in C proxy (rich coparison) + # '__bool__', # Unchecked in C proxy (rich coparison) + # '__hash__', # Unchecked in C proxy (rich coparison) + # '__cmp__', # Unchecked in C proxy '__getitem__', '__setitem__', '__delitem__', @@ -341,7 +347,7 @@ for name in ['__call__', '__rand__', '__rxor__', '__ror__', - ]: + ]: meth = getattr(PyProxyBase, name) setattr(ProxyPy, name, _check_name(meth)) @@ -364,16 +370,18 @@ for name in ['__iadd__', '__ixor__', '__ior__', '__ipow__', - ]: + ]: meth = getattr(PyProxyBase, name) setattr(ProxyPy, name, _check_name_inplace(meth)) + def getCheckerPy(proxy): return super(ProxyPy, proxy).__getattribute__('_checker') _builtin_isinstance = sys.modules[_BUILTINS].isinstance + def getObjectPy(proxy): if not _builtin_isinstance(proxy, ProxyPy): return proxy @@ -381,10 +389,10 @@ def getObjectPy(proxy): _c_available = not PURE_PYTHON -if _c_available: +if _c_available: # pragma: no cover try: from zope.security._proxy import _Proxy - except (ImportError, AttributeError): # pragma: no cover PyPy / PURE_PYTHON + except (ImportError, AttributeError): _c_available = False @@ -392,13 +400,14 @@ getChecker = getCheckerPy getObject = getObjectPy Proxy = ProxyPy -if _c_available: +if _c_available: # pragma: no cover from zope.security._proxy import getChecker from zope.security._proxy import getObject Proxy = _Proxy removeSecurityProxy = getObject + def getTestProxyItems(proxy): """Return a sorted sequence of checker names and permissions for testing """ diff --git a/src/zope/security/testing.py b/src/zope/security/testing.py index bd4b889..792813f 100644 --- a/src/zope/security/testing.py +++ b/src/zope/security/testing.py @@ -37,6 +37,7 @@ rules = [ ] output_checker = renormalizing.RENormalizing(rules) + @interface.implementer(interfaces.IPrincipal) class Principal(object): """ @@ -55,8 +56,10 @@ class Principal(object): @interface.implementer(interfaces.IParticipation) class Participation(object): """ - A trivial implementation of :class:`zope.security.interfaces.IParticipation`. + A trivial implementation of + :class:`zope.security.interfaces.IParticipation`. """ + def __init__(self, principal): self.principal = principal self.interaction = None @@ -82,6 +85,7 @@ def addCheckerPublic(): return perm + def create_interaction(principal_id, **kw): """ Create a new interaction for the given principal ID, make it the diff --git a/src/zope/security/tests/__init__.py b/src/zope/security/tests/__init__.py index cab4c90..e8db221 100644 --- a/src/zope/security/tests/__init__.py +++ b/src/zope/security/tests/__init__.py @@ -9,7 +9,8 @@ class QuietWatchingChecker(object): def setUp(self): from zope.security import checker self.__old_file = checker.CheckerLoggingMixin._file - checker.CheckerLoggingMixin._file = io.StringIO() if bytes is not str else io.BytesIO() + checker.CheckerLoggingMixin._file = ( + io.StringIO() if bytes is not str else io.BytesIO()) def tearDown(self): from zope.security import checker diff --git a/src/zope/security/tests/exampleclass.py b/src/zope/security/tests/exampleclass.py index 1d73b4b..385dda0 100644 --- a/src/zope/security/tests/exampleclass.py +++ b/src/zope/security/tests/exampleclass.py @@ -15,14 +15,18 @@ """ from zope.interface import Interface + class ExampleClass(object): pass + class IExample(Interface): pass + class IExample2(Interface): pass + class IExampleContainer(Interface): pass diff --git a/src/zope/security/tests/module.py b/src/zope/security/tests/module.py index 5b26ff5..a4f9e73 100644 --- a/src/zope/security/tests/module.py +++ b/src/zope/security/tests/module.py @@ -21,23 +21,28 @@ modules, themselves. from zope.interface import Interface from zope.schema import Text -class I(Interface): + +class I(Interface): # noqa: E742 ambiguous class definition 'I' def m1(): - "m1" + """m1""" + def m2(): - "m2" + """m2""" + class I2(I): def m4(): - "m4" + """m4""" + class I3(Interface): def m3(): - "m3" + """m3""" + class I4(Interface): def m2(): - "m2" + """m2""" class S(Interface): @@ -45,6 +50,7 @@ class S(Interface): bar = Text() baro = Text(readonly=True) + class S2(Interface): foo2 = Text() bar2 = Text() diff --git a/src/zope/security/tests/test_adapter.py b/src/zope/security/tests/test_adapter.py index a3dd541..2d68b0e 100644 --- a/src/zope/security/tests/test_adapter.py +++ b/src/zope/security/tests/test_adapter.py @@ -21,6 +21,7 @@ from zope.proxy import getProxiedObject # pylint:disable=attribute-defined-outside-init,protected-access + class Test_assertLocation(unittest.TestCase): def _callFUT(self, adapter, parent): @@ -49,6 +50,7 @@ class Test_assertLocation(unittest.TestCase): def test_w_ILocation_w_parent(self): parent = object() + @implementer(ILocation) class _Adapter(object): __parent__ = parent @@ -73,6 +75,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' _called_with = () + def __call__(self, *args): self._called_with = args return self @@ -88,6 +91,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): def test__call__w_non_ILocation_non_spacesuit(self): factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -97,11 +101,12 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in returned.__dict__.items() if k != '_called_with'} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_non_spacesuit_multiple_args(self): factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -112,13 +117,14 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in returned.__dict__.items() if k != '_called_with'} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_existing_parent_non_spacesuit(self): factory = self._makeFactory() parent = factory.__parent__ = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -131,6 +137,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -143,6 +150,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -157,13 +165,14 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_w_spacesuit_multiple_args(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -179,15 +188,17 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass + class _Extra(object): pass adapter = _NotAdapter() @@ -203,7 +214,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_spacesuit(self): from zope.security.proxy import getObject @@ -213,6 +224,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = factory.__name__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _Adapter(object): pass adapter = _Adapter() @@ -229,7 +241,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): if k not in ('_called_with', '__parent__')} self.assertEqual(factory._called_with, (adapter,)) self.assertIs(factory.__parent__, adapter) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_spacesuit_w_existing_parent(self): from zope.security.proxy import getObject @@ -240,6 +252,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = parent = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _Adapter(object): pass adapter = _Adapter() @@ -255,7 +268,7 @@ class LocatingTrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs class TrustedAdapterFactoryTests(unittest.TestCase): @@ -271,6 +284,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): class _Factory(object): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' + def __call__(self, *args): self._called_with = args return self @@ -281,6 +295,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -294,13 +309,14 @@ class TrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_w_spacesuit_multiple_args(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -315,15 +331,17 @@ class TrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_multiple_args_extra_spacesuit(self): from zope.security.proxy import ProxyFactory from zope.security.proxy import removeSecurityProxy factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass + class _Extra(object): pass adapter = _NotAdapter() @@ -338,7 +356,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with',)} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_spacesuit(self): from zope.security.proxy import ProxyFactory @@ -347,6 +365,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = factory.__name__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _Adapter(object): pass adapter = _Adapter() @@ -361,7 +380,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_spacesuit_w_existing_parent(self): from zope.security.proxy import ProxyFactory @@ -371,6 +390,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = parent = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _Adapter(object): pass adapter = _Adapter() @@ -385,7 +405,7 @@ class TrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in unwrapped.__dict__.items() if k not in ('_called_with', '__parent__')} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): @@ -402,6 +422,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): __name__ = 'testing' __module__ = 'zope.security.tests.test_adapter' _called_with = () + def __call__(self, *args): self._called_with = args return self @@ -417,6 +438,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): def test__call__w_non_ILocation(self): factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -428,11 +450,12 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in returned.__dict__.items() if k != '_called_with'} self.assertEqual(factory._called_with, (adapter,)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_non_ILocation_multiple_args(self): factory = self._makeFactory() ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -445,13 +468,14 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): after = {k: v for k, v in returned.__dict__.items() if k != '_called_with'} self.assertEqual(factory._called_with, (adapter, extra)) - self.assertEqual(after, before) # no added attrs + self.assertEqual(after, before) # no added attrs def test__call__w_ILocation_w_existing_parent(self): factory = self._makeFactory() parent = factory.__parent__ = object() directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() @@ -464,6 +488,7 @@ class LocatingUntrustedAdapterFactoryTests(unittest.TestCase): factory.__parent__ = None directlyProvides(factory, ILocation) ltaf = self._makeOne(factory) + class _NotAdapter(object): pass adapter = _NotAdapter() diff --git a/src/zope/security/tests/test_checker.py b/src/zope/security/tests/test_checker.py index 3473886..a8b3990 100644 --- a/src/zope/security/tests/test_checker.py +++ b/src/zope/security/tests/test_checker.py @@ -33,6 +33,7 @@ class Test_ProxyFactory(unittest.TestCase): def test_w_already_proxied_no_checker(self): from zope.security.proxy import Proxy, getChecker obj = object() + def _check(*x): raise AssertionError("Never called") proxy = Proxy(obj, _check) @@ -43,6 +44,7 @@ class Test_ProxyFactory(unittest.TestCase): def test_w_already_proxied_same_checker(self): from zope.security.proxy import Proxy, getChecker obj = object() + def _check(*x): raise AssertionError("Never called") proxy = Proxy(obj, _check) @@ -53,9 +55,11 @@ class Test_ProxyFactory(unittest.TestCase): def test_w_already_proxied_different_checker(self): from zope.security.proxy import Proxy obj = object() + def _check(*x): raise AssertionError("Never called") proxy = Proxy(obj, _check) + def _sneaky(*x): raise AssertionError("Never called") self.assertRaises(TypeError, self._callFUT, proxy, _sneaky) @@ -63,6 +67,7 @@ class Test_ProxyFactory(unittest.TestCase): def test_w_explicit_checker(self): from zope.security.proxy import getChecker obj = object() + def _check(*x): raise AssertionError("Never called") returned = self._callFUT(obj, _check) @@ -76,7 +81,8 @@ class Test_ProxyFactory(unittest.TestCase): def test_no_checker_w_dunder(self): from zope.security.proxy import getChecker, getObject - _check = object() # don't use a func, due to bound method + _check = object() # don't use a func, due to bound method + class _WithChecker(object): __Security_checker__ = _check obj = _WithChecker() @@ -90,10 +96,12 @@ class Test_ProxyFactory(unittest.TestCase): from zope.security.checker import _checkers from zope.security.checker import _clear from zope.security.proxy import getChecker, getObject + class _Obj(object): pass obj = _Obj() _checker = Checker({}) + def _check(*args): return _checker _checkers[_Obj] = _check @@ -117,6 +125,7 @@ class Test_canWrite(unittest.TestCase): def check_getattr(self, obj, name): if ch_get is not None: raise ch_get() + def check_setattr(self, obj, name): if ch_set is not None: raise ch_set() @@ -196,6 +205,7 @@ class Test_canAccess(unittest.TestCase): _marker = object() + class CheckerTestsBase(QuietWatchingChecker): # pylint:disable=no-member @@ -267,6 +277,7 @@ class CheckerTestsBase(QuietWatchingChecker): def test_check_setattr_w_interaction_allows(self): from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return True @@ -281,6 +292,7 @@ class CheckerTestsBase(QuietWatchingChecker): def test_check_setattr_w_interaction_denies(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False @@ -313,6 +325,7 @@ class CheckerTestsBase(QuietWatchingChecker): def test_check_non_public_w_interaction_allows(self): from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return True @@ -327,6 +340,7 @@ class CheckerTestsBase(QuietWatchingChecker): def test_check_non_public_w_interaction_denies(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False @@ -342,6 +356,7 @@ class CheckerTestsBase(QuietWatchingChecker): def test_proxy_already_proxied(self): from zope.security.proxy import Proxy, getChecker obj = object() + def _check(*x): raise AssertionError("Never called") proxy = Proxy(obj, _check) @@ -358,7 +373,8 @@ class CheckerTestsBase(QuietWatchingChecker): def test_proxy_no_checker_w_dunder(self): from zope.security.proxy import getChecker, getObject - _check = object() # don't use a func, due to bound method + _check = object() # don't use a func, due to bound method + class _WithChecker(object): __Security_checker__ = _check obj = _WithChecker() @@ -373,10 +389,12 @@ class CheckerTestsBase(QuietWatchingChecker): from zope.security.checker import _checkers from zope.security.checker import _clear from zope.security.proxy import getChecker, getObject + class _Obj(object): pass obj = _Obj() _checker = Checker({}) + def _check(*args): return _checker _checkers[_Obj] = _check @@ -420,8 +438,8 @@ class CheckerTestsBase(QuietWatchingChecker): self.assertEqual(proxy // Decimal('1'), Decimal('1')) self.assertEqual(float(proxy), 1.1) self.assertEqual(int(proxy), 1) - if PY2: - self.assertEqual(long(proxy), 1) + if PY2: # pragma: no cover PY2 + self.assertEqual(long(proxy), 1) # noqa: F821 undefined name self.assertEqual(proxy ** 2, Decimal('1.21')) self.assertEqual(1 ** proxy, Decimal('1')) self.assertEqual(proxy.adjusted(), 0) @@ -451,7 +469,6 @@ class CheckerTestsBase(QuietWatchingChecker): self.assertEqual([1], list(proxy)) self.assertEqual([2], list(proxy.values())) - def test_iteration_of_btree_items_keys_values(self): # iteration of BTree.items() is allowed by default. import BTrees @@ -486,10 +503,10 @@ class CheckerTestsBase(QuietWatchingChecker): pass @implementer(I1) - class O(object): + class Obj(object): pass - o = O() + o = Obj() checker = Checker({}) @@ -497,9 +514,9 @@ class CheckerTestsBase(QuietWatchingChecker): # Since the object itself doesn't have any interfaces, # the providedBy will return the implementedBy of the class - l = list(providedBy(proxy)) + provided_by = list(providedBy(proxy)) - self.assertEqual(l, [I1]) + self.assertEqual(provided_by, [I1]) def test_iteration_of_interface_providesBy(self): # Iteration of zope.interface.Provides is allowed by default @@ -519,10 +536,10 @@ class CheckerTestsBase(QuietWatchingChecker): pass @implementer(I1) - class O(object): + class Obj(object): pass - o = O() + o = Obj() alsoProvides(o, I2) checker = Checker({}) @@ -531,9 +548,9 @@ class CheckerTestsBase(QuietWatchingChecker): # Since the object has its own interfaces, provided # by will return a zope.interface.Provides object - l = list(providedBy(proxy)) + provided_by = list(providedBy(proxy)) - self.assertEqual(l, [I2, I1]) + self.assertEqual(provided_by, [I2, I1]) def test_iteration_with_length_hint(self): # PEP 424 implemented officially in Python 3.4 and @@ -577,19 +594,16 @@ class CheckerTestsBase(QuietWatchingChecker): # The hint is called when we proxy the root object i = Iter() proxy = Proxy(i, _iteratorChecker) - l = list(proxy) - self.assertEqual(l, [0, 1, 2]) + self.assertEqual(list(proxy), [0, 1, 2]) self.assertTrue(i.hint_called, "__length_hint__ should be called") # The hint is called when we proxy its iterator i = Iter() it = iter(i) proxy = Proxy(it, _iteratorChecker) - l = list(proxy) - self.assertEqual(l, [0, 1, 2]) + self.assertEqual(list(proxy), [0, 1, 2]) self.assertTrue(i.hint_called, "__length_hint__ should be called") - def test_iteration_of_itertools_groupby(self): # itertools.groupby is a custom iterator type. # The groups it returns are also custom. @@ -630,6 +644,7 @@ class TestChecker(CheckerTestsBase, unittest.TestCase): def _getTargetClass(self): return sec_checker.Checker + @unittest.skipIf(sec_checker.Checker is sec_checker.WatchingChecker, "WatchingChecker is the default") class TestWatchingChecker(TestChecker): @@ -637,6 +652,7 @@ class TestWatchingChecker(TestChecker): def _getTargetClass(self): return sec_checker.WatchingChecker + class TestTracebackSupplement(unittest.TestCase): def _getTargetClass(self): @@ -654,12 +670,12 @@ class TestTracebackSupplement(unittest.TestCase): ((), 'tuple'), ([], 'list'), ({}, 'dict'), - ]: + ]: tbs = self._makeOne(val) self.assertEqual(tbs.getInfo().splitlines(), [' - class: %s.%s' % (_BUILTINS, typ), ' - type: %s.%s' % (_BUILTINS, typ), - ]) + ]) def test_getInfo_newstyle_instance(self): class C(object): @@ -668,7 +684,7 @@ class TestTracebackSupplement(unittest.TestCase): self.assertEqual(tbs.getInfo().splitlines(), [' - class: %s.C' % self.__class__.__module__, ' - type: %s.C' % self.__class__.__module__, - ]) + ]) def test_getInfo_classic_instance(self): class C: @@ -678,7 +694,9 @@ class TestTracebackSupplement(unittest.TestCase): lines = tbs.getInfo().splitlines() self.assertEqual(lines[0], ' - class: %s.C' % self.__class__.__module__) - kind = '__builtin__.instance' if PY2 else '%s.C' % self.__class__.__module__ + kind = ('__builtin__.instance' + if PY2 + else '%s.C' % self.__class__.__module__) self.assertEqual(lines[1], ' - type: ' + kind) @@ -763,6 +781,7 @@ class Test_InterfaceChecker(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic + class IFoo(Interface): bar = Attribute('Bar') checker = self._callFUT(IFoo) @@ -772,6 +791,7 @@ class Test_InterfaceChecker(unittest.TestCase): def test_simple_iface_w_explicit_permission(self): from zope.interface import Attribute from zope.interface import Interface + class IFoo(Interface): bar = Attribute('Bar') other_perm = object() @@ -782,6 +802,7 @@ class Test_InterfaceChecker(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic + class IFoo(Interface): bar = Attribute('Bar') other_perm = object() @@ -794,8 +815,10 @@ class Test_InterfaceChecker(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic + class IFoo(Interface): bar = Attribute('Bar') + class IBar(IFoo): baz = Attribute('Baz') checker = self._callFUT(IBar) @@ -807,6 +830,7 @@ class Test_InterfaceChecker(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import DuplicationError + class IFoo(Interface): bar = Attribute('Bar') bam = Attribute('Bam') @@ -839,6 +863,7 @@ class Test_MultiChecker(unittest.TestCase): def test_w_spec_as_iface(self): from zope.interface import Attribute from zope.interface import Interface + class IFoo(Interface): bar = Attribute('Bar') other_perm = object() @@ -850,6 +875,7 @@ class Test_MultiChecker(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.checker import CheckerPublic + class IFoo(Interface): bar = Attribute('Bar') other_perm = object() @@ -865,6 +891,7 @@ class Test_MultiChecker(unittest.TestCase): from zope.interface import Interface from zope.security.checker import CheckerPublic from zope.security.checker import DuplicationError + class IFoo(Interface): bar = Attribute('Bar') other_perm = object() @@ -877,7 +904,7 @@ class Test_MultiChecker(unittest.TestCase): other_perm = object() spec = {'foo': CheckerPublic, 'bar': other_perm, - } + } checker = self._callFUT([spec]) self.assertIs(checker.permission_id('foo'), CheckerPublic) self.assertIs(checker.permission_id('bar'), other_perm) @@ -895,7 +922,6 @@ class Test_MultiChecker(unittest.TestCase): [(('foo', 'bar'), CheckerPublic), spec]) - class _SelectCheckerBase(object): # pylint:disable=no-member @@ -927,12 +953,13 @@ class _SelectCheckerBase(object): datetime.date.today(), datetime.datetime.now().time(), datetime.tzinfo(), - ]: + ]: self.assertIsNone(self._callFUT(obj)) def test_w_checker_inst(self): from zope.security.checker import Checker from zope.security.checker import _checkers + class Foo(object): pass checker = _checkers[Foo] = Checker({}) @@ -941,9 +968,11 @@ class _SelectCheckerBase(object): def test_w_factory_returning_checker(self): from zope.security.checker import Checker from zope.security.checker import _checkers + class Foo(object): pass checker = Checker({}) + def _factory(obj): return checker _checkers[Foo] = _factory @@ -952,8 +981,10 @@ class _SelectCheckerBase(object): def test_w_factory_returning_NoProxy(self): from zope.security.checker import NoProxy from zope.security.checker import _checkers + class Foo(object): pass + def _factory(obj): return NoProxy _checkers[Foo] = _factory @@ -961,8 +992,10 @@ class _SelectCheckerBase(object): def test_w_factory_returning_None(self): from zope.security.checker import _checkers + class Foo(object): pass + def _factory(obj): pass _checkers[Foo] = _factory @@ -971,11 +1004,14 @@ class _SelectCheckerBase(object): def test_w_factory_factory(self): from zope.security.checker import Checker from zope.security.checker import _checkers + class Foo(object): pass checker = Checker({}) + def _factory(obj): return checker + def _factory_factory(obj): return _factory _checkers[Foo] = _factory_factory @@ -983,16 +1019,17 @@ class _SelectCheckerBase(object): def test_itertools_checkers(self): from zope.security.checker import _iteratorChecker - import sys import itertools - pred = lambda x: x + + def pred(x): + return x iterable = (1, 2, 3) pred_iterable = (pred, iterable) missing_in_py3 = {'ifilter', 'ifilterfalse', 'imap', 'izip', 'izip_longest'} missing_in_py2 = {'zip_longest', 'accumulate', 'compress', 'combinations', 'combinations_with_replacement'} - missing = missing_in_py3 if sys.version_info[0] >= 3 else missing_in_py2 + missing = missing_in_py3 if PY3 else missing_in_py2 for func, args in ( ('count', ()), ('cycle', ((),)), @@ -1037,12 +1074,11 @@ class Test_selectCheckerPy(_SelectCheckerBase, unittest.TestCase): return selectCheckerPy(obj) - @unittest.skipIf(sec_checker.selectChecker is sec_checker.selectCheckerPy, "Pure Python") class Test_selectChecker(_SelectCheckerBase, unittest.TestCase): - def _callFUT(self, obj): + def _callFUT(self, obj): # pragma: no cover from zope.security.checker import selectChecker return selectChecker(obj) @@ -1068,6 +1104,7 @@ class Test_getCheckerForInstancesOf(unittest.TestCase): def test_hit(self): from zope.security.checker import _checkers + class Foo(object): pass checker = _checkers[Foo] = object() @@ -1097,12 +1134,13 @@ class Test_defineChecker(unittest.TestCase): u'text', b'binary', True, - ]: + ]: self.assertRaises(TypeError, self._callFUT, obj, checker) def test_w_duplicate(self): from zope.exceptions import DuplicationError from zope.security.checker import _checkers + class Foo(object): pass checker1, checker2 = object(), object() @@ -1112,6 +1150,7 @@ class Test_defineChecker(unittest.TestCase): def test_w_newstyle_class(self): from zope.security.checker import _checkers checker = object() + class Foo(object): pass self._callFUT(Foo, checker) @@ -1127,6 +1166,7 @@ class Test_defineChecker(unittest.TestCase): def test_w_oldstyle_class(self): from zope.security.checker import _checkers checker = object() + class Foo: pass self._callFUT(Foo, checker) @@ -1154,6 +1194,7 @@ class Test_undefineChecker(unittest.TestCase): def test_hit(self): from zope.security.checker import _checkers + class Foo(object): pass _checkers[Foo] = object() @@ -1196,40 +1237,43 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_lhs_ok_rhs_not_called(self): from zope.security.checker import CheckerPublic from zope.security.checker import Checker + class _NeverCalled(Checker): - def check(self, object, name): # pylint:disable=redefined-builtin + def check(self, object, name): # pylint:disable=redefined-builtin raise AssertionError("Never called") lhs = self._makeOther({'name': CheckerPublic}) rhs = _NeverCalled({}) combined = self._makeOne(lhs, rhs) - combined.check(object(), 'name') # no raise + combined.check(object(), 'name') # no raise def test_check_lhs_unauth_rhs_ok(self): from zope.security.checker import CheckerPublic from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther({'name': 'view'}) # unauth + lhs = self._makeOther({'name': 'view'}) # unauth rhs = self._makeOther({'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: - combined.check(object(), 'name') #no raise + combined.check(object(), 'name') # no raise finally: del thread_local.interaction def test_check_lhs_unauth_rhs_forbidden(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther({'name': 'view'}) # unauth - rhs = self._makeOther() # forbidden + lhs = self._makeOther({'name': 'view'}) # unauth + rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: @@ -1241,11 +1285,12 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_lhs_unauth_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther({'name': 'view'}) # unauth + lhs = self._makeOther({'name': 'view'}) # unauth rhs = self._makeOther({'name': 'inspect'}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() @@ -1258,16 +1303,16 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_lhs_forbidden_rhs_ok(self): from zope.security.checker import CheckerPublic - lhs = self._makeOther() # forbidden + lhs = self._makeOther() # forbidden rhs = self._makeOther({'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) - combined.check(object(), 'name') # no raise + combined.check(object(), 'name') # no raise def test_check_lhs_forbidden_rhs_forbidden(self): from zope.security.interfaces import Forbidden - lhs = self._makeOther() # forbidden - rhs = self._makeOther() # forbidden + lhs = self._makeOther() # forbidden + rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) self.assertRaises(Forbidden, combined.check, object(), 'name') @@ -1275,11 +1320,12 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_lhs_forbidden_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther() # Forbidden + lhs = self._makeOther() # Forbidden rhs = self._makeOther({'name': 'inspect'}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() @@ -1292,40 +1338,43 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_setattr_lhs_ok_rhs_not_called(self): from zope.security.checker import CheckerPublic from zope.security.checker import Checker + class _NeverCalled(Checker): - def check_setattr(self, object, name): # pylint:disable=redefined-builtin + def check_setattr(self, object, name): raise AssertionError("Never called") lhs = self._makeOther(set_permissions={'name': CheckerPublic}) rhs = _NeverCalled({}) combined = self._makeOne(lhs, rhs) - combined.check_setattr(object(), 'name') # no raise + combined.check_setattr(object(), 'name') # no raise def test_check_setattr_lhs_unauth_rhs_ok(self): from zope.security.checker import CheckerPublic from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther(set_permissions={'name': 'update'}) # unauth + lhs = self._makeOther(set_permissions={'name': 'update'}) # unauth rhs = self._makeOther(set_permissions={'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: - combined.check_setattr(object(), 'name') # no raise + combined.check_setattr(object(), 'name') # no raise finally: del thread_local.interaction def test_check_setattr_lhs_unauth_rhs_forbidden(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth - rhs = self._makeOther() # forbidden + lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth + rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: @@ -1337,12 +1386,13 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_setattr_lhs_unauth_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth - rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth + lhs = self._makeOther(set_permissions={'name': 'view'}) # unauth + rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: @@ -1354,16 +1404,16 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_setattr_lhs_forbidden_rhs_ok(self): from zope.security.checker import CheckerPublic - lhs = self._makeOther() # forbidden + lhs = self._makeOther() # forbidden rhs = self._makeOther(set_permissions={'name': CheckerPublic}) combined = self._makeOne(lhs, rhs) - combined.check_setattr(object(), 'name') # no raise + combined.check_setattr(object(), 'name') # no raise def test_check_setattr_lhs_forbidden_rhs_forbidden(self): from zope.security.interfaces import Forbidden - lhs = self._makeOther() # forbidden - rhs = self._makeOther() # forbidden + lhs = self._makeOther() # forbidden + rhs = self._makeOther() # forbidden combined = self._makeOne(lhs, rhs) self.assertRaises(Forbidden, combined.check_setattr, object(), 'name') @@ -1371,12 +1421,13 @@ class TestCombinedChecker(QuietWatchingChecker, def test_check_setattr_lhs_forbidden_rhs_unauth(self): from zope.security.interfaces import Unauthorized from zope.security._definitions import thread_local + class _Interaction(object): def checkPermission(self, obj, perm): return False - lhs = self._makeOther() # forbidden - rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth + lhs = self._makeOther() # forbidden + rhs = self._makeOther(set_permissions={'name': 'inspect'}) # unauth combined = self._makeOne(lhs, rhs) thread_local.interaction = _Interaction() try: @@ -1385,13 +1436,16 @@ class TestCombinedChecker(QuietWatchingChecker, finally: del thread_local.interaction -@unittest.skipIf(sec_checker.WatchingCombinedChecker is sec_checker.CombinedChecker, - "WatchingCombinedChecker is the default") + +@unittest.skipIf( + sec_checker.WatchingCombinedChecker is sec_checker.CombinedChecker, + "WatchingCombinedChecker is the default") class TestWatchingCombinedChecker(TestCombinedChecker): def _getTargetClass(self): return sec_checker.WatchingCombinedChecker + class TestCheckerLoggingMixin(unittest.TestCase): def _getTargetClass(self): @@ -1403,10 +1457,12 @@ class TestCheckerLoggingMixin(unittest.TestCase): def __init__(self, raising, stream): self._file = stream self._raising = raising + def check(self, obj, name): if self._raising: raise self._raising check_getattr = check_setattr = check + class _Derived(self._getTargetClass(), _Checker): pass return _Derived(raising, self._makeStream()) @@ -1572,12 +1628,14 @@ class Test__instanceChecker(unittest.TestCase): def test_miss(self): from zope.security.checker import _defaultChecker + class Foo(object): pass self.assertIs(self._callFUT(Foo()), _defaultChecker) def test_hit(self): from zope.security.checker import _checkers + class Foo(object): pass checker = _checkers[Foo] = object() @@ -1609,8 +1667,6 @@ class Test_moduleChecker(unittest.TestCase): self.assertIs(self._callFUT(verify), checker) - - # Pre-geddon tests start here class TestSecurityPolicy(QuietWatchingChecker, @@ -1645,6 +1701,7 @@ class TestSecurityPolicy(QuietWatchingChecker, def _makeSecurityPolicy(self): from zope.interface import implementer from zope.security.interfaces import ISecurityPolicy + @implementer(ISecurityPolicy) class SecurityPolicy(object): def checkPermission(self, permission, _object): @@ -1655,6 +1712,7 @@ class TestSecurityPolicy(QuietWatchingChecker, from zope.security.checker import defineChecker from zope.security.checker import NamesChecker old_type = self._get_old_class_type() + class ClassicClass: __metaclass__ = old_type self.assertIsInstance(ClassicClass, old_type) @@ -1664,6 +1722,7 @@ class TestSecurityPolicy(QuietWatchingChecker, def test_defineChecker_newstyle_class(self): from zope.security.checker import defineChecker from zope.security.checker import NamesChecker + class NewStyleClass(object): pass self.assertIsInstance(NewStyleClass, type) @@ -1684,16 +1743,21 @@ class TestSecurityPolicy(QuietWatchingChecker, def _makeClasses(self): old_type = self._get_old_class_type() + class OldInst: a = 1 + def b(self): raise AssertionError("Never called") c = 2 + def gete(self): raise AssertionError("Never called") e = property(gete) + def __getitem__(self, x): raise AssertionError("Never called") + def __setitem__(self, x, v): raise AssertionError("Never called") @@ -1704,6 +1768,7 @@ class TestSecurityPolicy(QuietWatchingChecker, # __metaclass__ = type def gete(self): raise AssertionError("Never called") + def sete(self, v): raise AssertionError("Never called") e = property(gete, sete) @@ -1851,10 +1916,11 @@ class TestSecurityPolicy(QuietWatchingChecker, self.assertEqual(next(proxy), 1) def testLayeredProxies(self): - #Test that a Proxy will not be re-proxied. + # Test that a Proxy will not be re-proxied. from zope.security.proxy import Proxy, getObject from zope.security.checker import Checker from zope.security.checker import NamesChecker + class Base: __Security_checker__ = NamesChecker(['__Security_checker__']) base = Base() @@ -1870,7 +1936,6 @@ class TestSecurityPolicy(QuietWatchingChecker, self.assertIs(proxy2, proxy1) self.assertIs(getObject(proxy2), base) - def testMultiChecker(self): from zope.interface import Interface @@ -1925,6 +1990,7 @@ class TestSecurityPolicy(QuietWatchingChecker, def testAlwaysAvailable(self): from zope.security.checker import NamesChecker checker = NamesChecker(()) + class C(object): pass self.assertEqual(checker.check(C, '__hash__'), None) @@ -1965,6 +2031,7 @@ class TestSecurityPolicy(QuietWatchingChecker, from zope.security.checker import ProxyFactory from zope.security.proxy import getChecker from zope.security.proxy import Proxy + class SomeClass(object): pass checker = NamesChecker() @@ -1997,6 +2064,7 @@ class TestSecurityPolicy(QuietWatchingChecker, from zope.security.checker import defineChecker from zope.security.checker import NamesChecker from zope.security.checker import undefineChecker + class SomeClass(object): pass obj = SomeClass() @@ -2012,6 +2080,7 @@ class TestSecurityPolicy(QuietWatchingChecker, def test_ProxyFactory_using_proxy(self): from zope.security.checker import ProxyFactory from zope.security.checker import NamesChecker + class SomeClass(object): pass obj = SomeClass() @@ -2045,6 +2114,7 @@ class TestSecurityPolicy(QuietWatchingChecker, from zope.security.checker import canAccess from zope.security.checker import canWrite from zope.security.checker import defineChecker + class SomeClass(object): pass obj = SomeClass() @@ -2057,24 +2127,24 @@ class TestSecurityPolicy(QuietWatchingChecker, # For these tests, the SecurityPolicy defined at the top of this file # is in place. It is a stub. Normally, the security policy would # have knowledge of interactions and participants, and would determine - # on the basis of the particpants and the object if a certain permission - # were authorized. This stub simply says that the 'test_allowed' - # permission is authorized and nothing else is, for any object you pass - # it. + # on the basis of the participants and the object if a certain + # permission were authorized. This stub simply says that the + # 'test_allowed' permission is authorized and nothing else is, for any + # object you pass it. # Therefore, according to the checker created here, the current # 'interaction' (as stubbed out in the security policy) will be allowed # to access and write foo, and access bar. The interaction is # unauthorized for accessing baz and writing bar. Any other access or - # write is not merely unauthorized but forbidden--including write access - # for baz. + # write is not merely unauthorized but forbidden--including write + # access for baz. checker = Checker( - {'foo':'test_allowed', # these are the read settings - 'bar':'test_allowed', - 'baz':'you_will_not_have_this_permission'}, - {'foo':'test_allowed', # these are the write settings - 'bar':'you_will_not_have_this_permission', - 'bing':'you_will_not_have_this_permission'}) + {'foo': 'test_allowed', # these are the read settings + 'bar': 'test_allowed', + 'baz': 'you_will_not_have_this_permission'}, + {'foo': 'test_allowed', # these are the write settings + 'bar': 'you_will_not_have_this_permission', + 'bing': 'you_will_not_have_this_permission'}) defineChecker(SomeClass, checker) # so, our hapless interaction may write and access foo... @@ -2110,6 +2180,7 @@ class TestSecurityPolicy(QuietWatchingChecker, self.assertTrue(not canWrite(obj, 'bing')) self.assertRaises(Forbidden, canAccess, obj, 'bing') + class TestCheckerPublic(unittest.TestCase): def test_that_pickling_CheckerPublic_retains_identity(self): @@ -2154,14 +2225,17 @@ class TestMixinDecoratedChecker(unittest.TestCase): def _makeSecurityPolicy(self): from zope.interface import implementer from zope.security.interfaces import ISecurityPolicy + @implementer(ISecurityPolicy) class RecordedSecurityPolicy(object): def __init__(self): self._checked = [] self.permissions = {} + def checkPermission(self, permission, _obj): self._checked.append(permission) return self.permissions.get(permission, True) + def checkChecked(self, checked): res = self._checked == checked self._checked = [] @@ -2209,6 +2283,7 @@ class TestMixinDecoratedChecker(unittest.TestCase): from zope.security.checker import Checker return Checker(self.decorationGetMap, self.decorationSetMap) + class TestCombinedCheckerMixin(QuietWatchingChecker, TestMixinDecoratedChecker, unittest.TestCase): @@ -2235,7 +2310,7 @@ class TestCombinedCheckerMixin(QuietWatchingChecker, self.assertTrue( self.interaction.checkChecked(['dc_get_permission', 'get_permission']) - ) + ) # This should raise Unauthorized instead of ForbiddenAttribute, since # access can be granted if you e.g. login with different credentials. @@ -2263,6 +2338,7 @@ class TestBasicTypes(unittest.TestCase): def test___setitem__(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers + class Foo(object): pass checker = object() @@ -2273,6 +2349,7 @@ class TestBasicTypes(unittest.TestCase): def test___delitem__(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers + class Foo(object): pass checker = object() @@ -2288,6 +2365,7 @@ class TestBasicTypes(unittest.TestCase): def test_update(self): from zope.security.checker import BasicTypes from zope.security.checker import _checkers + class Foo(object): pass checker = object() @@ -2295,14 +2373,15 @@ class TestBasicTypes(unittest.TestCase): self.assertIs(BasicTypes[Foo], checker) self.assertIs(_checkers[Foo], checker) - def test(self): from zope.security.checker import BasicTypes from zope.security.checker import NoProxy from zope.security.checker import _checkers from zope.security.checker import _clear + class MyType(object): pass + class MyType2(object): pass @@ -2342,10 +2421,10 @@ class TestBasicTypes(unittest.TestCase): self.assertIn(str, keys) try: unicode - except NameError: # pragma: no cover Py3k + except NameError: pass - else: # pragma: no cover Python2 - self.assertIn(unicode, keys) + else: # pragma: no cover PY2 + self.assertIn(unicode, keys) # noqa: F821 undefined name 'unicode' self.assertIn(object, keys) # ... @@ -2353,5 +2432,6 @@ class TestBasicTypes(unittest.TestCase): # unwanted deletions. self.assertRaises(NotImplementedError, BasicTypes.clear) + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) diff --git a/src/zope/security/tests/test_decorator.py b/src/zope/security/tests/test_decorator.py index 650380d..285f7ef 100644 --- a/src/zope/security/tests/test_decorator.py +++ b/src/zope/security/tests/test_decorator.py @@ -64,27 +64,27 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, class Foo(object): a = 'a' - fooChecker = NamesChecker(['a']) # a is public + fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() - fooChecker.check(foo, 'a') # no raise + fooChecker.check(foo, 'a') # no raise self.assertRaises(ForbiddenAttribute, fooChecker.check, foo, 'b') class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() - wrapperChecker = NamesChecker(['b']) # b is public + wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) wrapper = Wrapper(foo) self.assertRaises(ForbiddenAttribute, wrapperChecker.check, foo, 'a') - wrapperChecker.check(foo, 'b') # no raise + wrapperChecker.check(foo, 'b') # no raise checker = wrapper.__Security_checker__ self.assertTrue(isinstance(checker, CombinedChecker)) - checker.check(wrapper, 'a') # no raise - checker.check(wrapper, 'b') # no raise + checker.check(wrapper, 'a') # no raise + checker.check(wrapper, 'b') # no raise def test_only_wrapper_has_checker(self): from zope.proxy import ProxyBase @@ -100,7 +100,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() - wrapperChecker = NamesChecker(['b']) # b is public + wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) wrapper = Wrapper(foo) self.assertTrue(wrapper.__Security_checker__ is wrapperChecker) @@ -113,7 +113,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, class Foo(object): a = 'a' - fooChecker = NamesChecker(['a']) # a is public + fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() @@ -124,7 +124,6 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, wrapper = Wrapper(foo) self.assertTrue(wrapper.__Security_checker__ is fooChecker) - def test_both_wrapper_and_object_have_checkers_security_proxied(self): from zope.proxy import ProxyBase from zope.security.checker import CombinedChecker @@ -134,7 +133,7 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, class Foo(object): a = 'a' - fooChecker = NamesChecker(['a']) # a is public + fooChecker = NamesChecker(['a']) # a is public defineChecker(Foo, fooChecker) foo = Foo() f_sec = ProxyFactory(foo) @@ -142,14 +141,14 @@ class DecoratedSecurityCheckerDescriptorTests(QuietWatchingChecker, class Wrapper(ProxyBase): b = 'b' __Security_checker__ = self._makeOne() - wrapperChecker = NamesChecker(['b']) # b is public + wrapperChecker = NamesChecker(['b']) # b is public defineChecker(Wrapper, wrapperChecker) w_sec = Wrapper(f_sec) checker = w_sec.__Security_checker__ self.assertTrue(isinstance(checker, CombinedChecker)) - checker.check(w_sec, 'a') # no raise - checker.check(w_sec, 'b') # no raise + checker.check(w_sec, 'a') # no raise + checker.check(w_sec, 'b') # no raise def test_cannot_overwrite(self): from zope.proxy import ProxyBase diff --git a/src/zope/security/tests/test_location.py b/src/zope/security/tests/test_location.py index bc5fb03..194fc52 100644 --- a/src/zope/security/tests/test_location.py +++ b/src/zope/security/tests/test_location.py @@ -26,6 +26,7 @@ class LocationSecurityProxyTests(QuietWatchingChecker, from zope.security.checker import defineChecker from zope.security.checker import NamesChecker from zope.security.proxy import ProxyFactory + class Unlocated(object): a = 'a' unlocated = Unlocated() diff --git a/src/zope/security/tests/test_management.py b/src/zope/security/tests/test_management.py index 93ce19d..78dd78d 100644 --- a/src/zope/security/tests/test_management.py +++ b/src/zope/security/tests/test_management.py @@ -83,7 +83,7 @@ class Test(unittest.TestCase): from zope.security.management import newInteraction from zope.security.management import queryInteraction newInteraction() - interaction = queryInteraction() + queryInteraction() endInteraction() self.assertEqual(queryInteraction(), None) endInteraction() @@ -106,7 +106,7 @@ class Test(unittest.TestCase): from zope.security.management import restoreInteraction newInteraction() self.assertTrue(queryInteraction() is not None) - restoreInteraction() # restore to no interaction + restoreInteraction() # restore to no interaction self.assertTrue(queryInteraction() is None) def test_restoreInteraction_after_neither(self): @@ -170,7 +170,6 @@ class Test(unittest.TestCase): self.assertEqual(checkPermission(None, obj), True) self.assertEqual(checkPermission(CheckerPublic, obj), True) - def test_system_user(self): from zope.interface.verify import verifyObject from zope.security.interfaces import IPrincipal diff --git a/src/zope/security/tests/test_metaconfigure.py b/src/zope/security/tests/test_metaconfigure.py index 20477c0..c8631e9 100644 --- a/src/zope/security/tests/test_metaconfigure.py +++ b/src/zope/security/tests/test_metaconfigure.py @@ -16,6 +16,7 @@ import unittest from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + class Test_dottedName(unittest.TestCase): def _callFUT(self, obj): @@ -40,7 +41,7 @@ class ClassDirectiveTests(unittest.TestCase): def _makeOne(self, _context, class_): return self._getTargetClass()(_context, class_) - #def test_ctor_non_class(self): TODO needs better guard in __init__ + # def test_ctor_non_class(self): TODO needs better guard in __init__ def test_implements_empty(self): context = DummyZCMLContext() @@ -52,6 +53,7 @@ class ClassDirectiveTests(unittest.TestCase): from zope.component.interface import provideInterface from zope.interface import Interface from zope.interface import classImplements + class IFoo(Interface): pass context = DummyZCMLContext() @@ -59,7 +61,7 @@ class ClassDirectiveTests(unittest.TestCase): directive.implements(context, [IFoo]) self.assertEqual(len(context._actions), 2) self.assertEqual(context._actions[0]['discriminator'][:2], - ('ContentDirective', Foo, )) #3rd is object() + ('ContentDirective', Foo, )) # 3rd is object() self.assertTrue(context._actions[0]['callable'] is classImplements) self.assertEqual(context._actions[0]['args'], (Foo, IFoo)) self.assertTrue(context._actions[1]['discriminator'] is None) @@ -71,8 +73,10 @@ class ClassDirectiveTests(unittest.TestCase): from zope.component.interface import provideInterface from zope.interface import Interface from zope.interface import classImplements + class IFoo(Interface): pass + class IBar(Interface): pass context = DummyZCMLContext() @@ -80,7 +84,7 @@ class ClassDirectiveTests(unittest.TestCase): directive.implements(context, [IFoo, IBar]) self.assertEqual(len(context._actions), 4) self.assertEqual(context._actions[0]['discriminator'][:2], - ('ContentDirective', Foo, )) #3rd is object() + ('ContentDirective', Foo, )) # 3rd is object() self.assertTrue(context._actions[0]['callable'] is classImplements) self.assertEqual(context._actions[0]['args'], (Foo, IFoo)) self.assertTrue(context._actions[1]['discriminator'] is None) @@ -88,7 +92,7 @@ class ClassDirectiveTests(unittest.TestCase): self.assertEqual(context._actions[1]['args'], ('zope.security.tests.test_metaconfigure.IFoo', IFoo)) self.assertEqual(context._actions[2]['discriminator'][:2], - ('ContentDirective', Foo, )) #3rd is object() + ('ContentDirective', Foo, )) # 3rd is object() self.assertTrue(context._actions[2]['callable'] is classImplements) self.assertEqual(context._actions[2]['args'], (Foo, IBar)) self.assertTrue(context._actions[3]['discriminator'] is None) @@ -98,6 +102,7 @@ class ClassDirectiveTests(unittest.TestCase): def test_require_only_like_class(self): from zope.security.protectclass import protectLikeUnto + class Bar(object): pass context = DummyZCMLContext() @@ -105,7 +110,7 @@ class ClassDirectiveTests(unittest.TestCase): directive.require(context, like_class=Bar) self.assertEqual(len(context._actions), 1) self.assertEqual(context._actions[0]['discriminator'][:2], - ('mimic', Foo, )) #3rd is object() + ('mimic', Foo, )) # 3rd is object() self.assertTrue(context._actions[0]['callable'] is protectLikeUnto) self.assertEqual(context._actions[0]['args'], (Foo, Bar)) @@ -120,14 +125,15 @@ class ClassDirectiveTests(unittest.TestCase): from zope.configuration.exceptions import ConfigurationError context = DummyZCMLContext() directive = self._makeOne(context, Foo) - self.assertRaises(ConfigurationError, - directive.require, context, attributes=('foo', 'bar')) + with self.assertRaises(ConfigurationError): + directive.require(context, attributes=('foo', 'bar')) def test_require_w_single_interface(self): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName + class IFoo(Interface): bar = Attribute("Bar") baz = Attribute("Baz") @@ -153,13 +159,16 @@ class ClassDirectiveTests(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName + class IFoo(Interface): bar = Attribute("Bar") + class IBar(Interface): baz = Attribute("Baz") context = DummyZCMLContext() directive = self._makeOne(context, Foo) - directive.require(context, permission='testing', interface=[IFoo, IBar]) + directive.require(context, permission='testing', + interface=[IFoo, IBar]) self.assertEqual(len(context._actions), 4) self.assertEqual(context._actions[0]['discriminator'], ('protectName', Foo, 'bar')) @@ -215,6 +224,7 @@ class ClassDirectiveTests(unittest.TestCase): from zope.schema import Field from zope.interface import Interface from zope.security.protectclass import protectSetAttribute + class IFoo(Interface): bar = Field(u"Bar") baz = Field(u"Baz") @@ -239,6 +249,7 @@ class ClassDirectiveTests(unittest.TestCase): from zope.component.interface import provideInterface from zope.interface import Attribute from zope.interface import Interface + class IFoo(Interface): bar = Attribute("Bar") context = DummyZCMLContext() @@ -254,6 +265,7 @@ class ClassDirectiveTests(unittest.TestCase): from zope.component.interface import provideInterface from zope.schema import Field from zope.interface import Interface + class IFoo(Interface): bar = Field(u"Bar", readonly=True) context = DummyZCMLContext() @@ -276,6 +288,7 @@ class ClassDirectiveTests(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName + class IFoo(Interface): bar = Attribute("Bar") baz = Attribute("Baz") @@ -303,8 +316,10 @@ class ClassDirectiveTests(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.protectclass import protectName + class IFoo(Interface): bar = Attribute("Bar") + class IBar(Interface): baz = Attribute("Baz") context = DummyZCMLContext() @@ -489,6 +504,7 @@ class Test_allow(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule + class IFoo(Interface): bar = Attribute('Bar') context = DummyZCMLContext() @@ -506,6 +522,7 @@ class Test_allow(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule + class IFoo(Interface): bar = Attribute('Bar') baz = Attribute('Baz') @@ -586,6 +603,7 @@ class Test_requre(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule + class IFoo(Interface): bar = Attribute('Bar') context = DummyZCMLContext() @@ -604,6 +622,7 @@ class Test_requre(unittest.TestCase): from zope.interface import Attribute from zope.interface import Interface from zope.security.metaconfigure import protectModule + class IFoo(Interface): bar = Attribute('Bar') baz = Attribute('Baz') diff --git a/src/zope/security/tests/test_permission.py b/src/zope/security/tests/test_permission.py index 82ddea2..9e03496 100644 --- a/src/zope/security/tests/test_permission.py +++ b/src/zope/security/tests/test_permission.py @@ -17,6 +17,7 @@ import unittest from zope.component.testing import PlacelessSetup from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + class PermissionTests(unittest.TestCase): def _getTargetClass(self): @@ -62,7 +63,7 @@ class Test_checkPermission(PlacelessSetup, unittest.TestCase): def test_w_CheckerPublic(self): from zope.security.checker import CheckerPublic - self._callFUT(None, CheckerPublic) # no raise + self._callFUT(None, CheckerPublic) # no raise def test_miss(self): self.assertRaises(ValueError, self._callFUT, None, 'nonesuch') @@ -72,7 +73,7 @@ class Test_checkPermission(PlacelessSetup, unittest.TestCase): from zope.security.interfaces import IPermission permission = object() provideUtility(permission, IPermission, 'testing') - self._callFUT(None, 'testing') # no raise + self._callFUT(None, 'testing') # no raise class Test_allPermissions(PlacelessSetup, unittest.TestCase): @@ -143,7 +144,6 @@ class Test_PermissionsVocabulary(PlacelessSetup, unittest.TestCase): from zope.security.interfaces import IPermission from zope.schema import getValidationErrors - xmlconfig.file('configure.zcml', zope.security) vocabulary = self._callFUT() vocabulary = sorted(vocabulary, key=lambda term: term.token) @@ -155,6 +155,7 @@ class Test_PermissionsVocabulary(PlacelessSetup, unittest.TestCase): verifyObject(IPermission, p) self.assertEqual([], getValidationErrors(IPermission, p)) + class Test_PermissionIdsVocabulary(PlacelessSetup, unittest.TestCase): def _callFUT(self): diff --git a/src/zope/security/tests/test_protectclass.py b/src/zope/security/tests/test_protectclass.py index 759f151..2f8e490 100644 --- a/src/zope/security/tests/test_protectclass.py +++ b/src/zope/security/tests/test_protectclass.py @@ -16,6 +16,7 @@ import unittest from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + class Test_protectName(unittest.TestCase): def setUp(self): diff --git a/src/zope/security/tests/test_proxy.py b/src/zope/security/tests/test_proxy.py index cecac86..ef664ee 100644 --- a/src/zope/security/tests/test_proxy.py +++ b/src/zope/security/tests/test_proxy.py @@ -17,18 +17,21 @@ import unittest from zope.security._compat import PYTHON2, PURE_PYTHON + def _skip_if_not_Py2(testfunc): return unittest.skipUnless(PYTHON2, "Only on Py2")(testfunc) # pylint:disable=protected-access,eval-used,too-many-lines,too-many-public-methods -if not PYTHON2: # pragma: no cover (Python 3) + +if not PYTHON2: # pragma: PY3 def coerce(*args): raise NotImplementedError("Not on Python 3") cmp = coerce long = int unicode = str + class AbstractProxyTestBase(object): # pylint:disable=no-member,blacklisted-name @@ -67,6 +70,7 @@ class AbstractProxyTestBase(object): def test___getattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized + class Foo(object): bar = 'Bar' target = Foo() @@ -77,6 +81,7 @@ class AbstractProxyTestBase(object): def test___getattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute + class Foo(object): bar = 'Bar' target = Foo() @@ -90,6 +95,7 @@ class AbstractProxyTestBase(object): def test__getattr__w_checker_ok_dynamic_attribute_called_once(self): class Dynamic(object): count = 0 + def __getattr__(self, name): self.count += 1 if self.count == 1: @@ -118,6 +124,7 @@ class AbstractProxyTestBase(object): def test___setattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized + class Foo(object): bar = 'Bar' target = Foo() @@ -128,6 +135,7 @@ class AbstractProxyTestBase(object): def test___setattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute + class Foo(object): bar = 'Bar' target = Foo() @@ -150,6 +158,7 @@ class AbstractProxyTestBase(object): def test___delattr___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized + class Foo(object): def __init__(self): self.bar = 'Bar' @@ -162,6 +171,7 @@ class AbstractProxyTestBase(object): def test___delattr___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute + class Foo(object): def __init__(self): self.bar = 'Bar' @@ -192,9 +202,10 @@ class AbstractProxyTestBase(object): def test___str___fails_return(self): from zope.security.interfaces import ForbiddenAttribute + class CustomStr(object): def __str__(self): - "" # Docstring, not a return + "" # Docstring, not a return target = CustomStr() checker = DummyChecker(ForbiddenAttribute, allowed=('__str__')) @@ -224,12 +235,14 @@ class AbstractProxyTestBase(object): def test___str___falls_through_to_repr_when_both_allowed(self): from zope.security.interfaces import ForbiddenAttribute + class CustomRepr(object): def __repr__(self): return "" target = CustomRepr() - checker = DummyChecker(ForbiddenAttribute, allowed=("__str__", '__repr__')) + checker = DummyChecker( + ForbiddenAttribute, allowed=("__str__", '__repr__')) proxy = self._makeOne(target, checker) self.assertEqual(repr(proxy), "") self.assertEqual(str(target), "") @@ -237,6 +250,7 @@ class AbstractProxyTestBase(object): def test___str___doesnot_fall_through_to_repr_when_str_not_allowed(self): from zope.security.interfaces import ForbiddenAttribute + class CustomRepr(object): def __repr__(self): return "" @@ -250,6 +264,7 @@ class AbstractProxyTestBase(object): def test___str___doesnot_fall_through_to_repr_when_repr_not_allowed(self): from zope.security.interfaces import ForbiddenAttribute + class CustomRepr(object): def __repr__(self): return "" @@ -263,9 +278,10 @@ class AbstractProxyTestBase(object): def test___str___falls_through_to_repr_but_repr_fails_return(self): from zope.security.interfaces import ForbiddenAttribute + class CustomRepr(object): def __repr__(self): - "" # Docstring, not a return + "" # Docstring, not a return target = CustomRepr() checker = DummyChecker(ForbiddenAttribute, allowed=('__repr__')) @@ -276,62 +292,62 @@ class AbstractProxyTestBase(object): repr(proxy) @_skip_if_not_Py2 - def test___cmp___w_self(self): + def test___cmp___w_self(self): # pragma: no cover target = object() - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, proxy), 0) @_skip_if_not_Py2 - def test___cmp___w_target(self): + def test___cmp___w_target(self): # pragma: no cover target = object() - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, target), 0) @_skip_if_not_Py2 - def test___cmp___w_other(self): + def test___cmp___w_other(self): # pragma: no cover target = object() other = object() - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertNotEqual(cmp(proxy, other), 0) @_skip_if_not_Py2 - def test___cmp___w_other_proxy(self): + def test___cmp___w_other_proxy(self): # pragma: no cover target = object() - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) o_proxy = self._makeOne(target, checker) self.assertEqual(cmp(proxy, o_proxy), 0) def test__le__(self): target = 1 - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertTrue(proxy <= 1) def test__ne__(self): target = 1 - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertFalse(proxy != 1) def test__ge__(self): target = 1 - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertTrue(proxy >= 1) def test__gt__(self): target = 1 - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertTrue(proxy > 0) def test___hash___w_self(self): target = object() - checker = object() # checker not consulted + checker = object() # checker not consulted proxy = self._makeOne(target, checker) self.assertEqual(hash(proxy), hash(target)) @@ -348,6 +364,7 @@ class AbstractProxyTestBase(object): def test___call___w_checker_unauthorized(self): from zope.security.interfaces import Unauthorized + class Foo(object): def __call__(self): raise AssertionError("Never called") @@ -359,6 +376,7 @@ class AbstractProxyTestBase(object): def test___call___w_checker_forbidden_attribute(self): from zope.security.interfaces import ForbiddenAttribute + class Foo(object): def __call__(self): raise AssertionError("Never called") @@ -399,7 +417,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__float__') @_skip_if_not_Py2 - def test___long___w_checker_allows(self): + def test___long___w_checker_allows(self): # pragma: no cover target = 3.0 checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -407,7 +425,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__long__') @_skip_if_not_Py2 - def test___long___w_checker_forbids(self): + def test___long___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) @@ -416,7 +434,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__long__') @_skip_if_not_Py2 - def test___oct___w_checker_allows(self): + def test___oct___w_checker_allows(self): # pragma: no cover target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -424,7 +442,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__oct__') @_skip_if_not_Py2 - def test___oct___w_checker_forbids(self): + def test___oct___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) @@ -433,7 +451,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__oct__') @_skip_if_not_Py2 - def test___hex___w_checker_allows(self): + def test___hex___w_checker_allows(self): # pragma: no cover target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -441,7 +459,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__hex__') @_skip_if_not_Py2 - def test___hex___w_checker_forbids(self): + def test___hex___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) @@ -599,20 +617,24 @@ class AbstractProxyTestBase(object): self.assertRaises(ForbiddenAttribute, lambda: pow(x, proxy)) self.assertEqual(checker._checked, '__rpow__') - def test___pow___w_z_proxied_allowed(self): + @unittest.expectedFailure + def test___pow___w_z_proxied_allowed2(self): + # There is no method `__3pow__` - is this test obsolete? x, y, z = 3, 4, 7 checker = DummyChecker() proxy = self._makeOne(z, checker) self.assertEqual(pow(x, y, proxy), pow(x, y, z)) - self.assertEqual(checker._checked, '__3pow__') + self.assertEqual(checker._checked, '__3pow__') # pragma: no cover - def test___pow___w_z_proxied_forbidden(self): + @unittest.expectedFailure + def test___pow___w_z_proxied_forbidden2(self): + # There is no method `__3pow__` - is this test obsolete? from zope.security.interfaces import ForbiddenAttribute x, y, z = 3, 4, 7 checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(z, checker) self.assertRaises(ForbiddenAttribute, lambda: pow(x, y, proxy)) - self.assertEqual(checker._checked, '__3pow__') + self.assertEqual(checker._checked, '__3pow__') # pragma: no cover def test___neg___w_checker_allows(self): target = 3 @@ -756,7 +778,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__or__') @_skip_if_not_Py2 - def test___coerce___w_checker_allows(self): + def test___coerce___w_checker_allows(self): # pragma: no cover target = 3 checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -764,7 +786,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__coerce__') @_skip_if_not_Py2 - def test___coerce___w_checker_forbids(self): + def test___coerce___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = 3 checker = DummyChecker(ForbiddenAttribute) @@ -785,6 +807,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __iadd__(self, rhs): self.value += rhs return self @@ -818,6 +841,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __isub__(self, rhs): self.value -= rhs return self @@ -851,6 +875,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __imul__(self, rhs): self.value *= rhs return self @@ -884,6 +909,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __idiv__(self, rhs): self.value /= rhs return self @@ -918,6 +944,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __itruediv__(self, rhs): self.value /= rhs return self @@ -952,6 +979,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __ifloordiv__(self, rhs): self.value //= rhs return self @@ -985,6 +1013,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __imod__(self, rhs): self.value %= rhs return self @@ -1018,6 +1047,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __ipow__(self, rhs): self.value **= rhs return self @@ -1051,6 +1081,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __ilshift__(self, rhs): self.value <<= rhs return self @@ -1084,6 +1115,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __irshift__(self, rhs): self.value >>= rhs return self @@ -1117,6 +1149,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __iand__(self, rhs): self.value &= rhs return self @@ -1150,6 +1183,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __ixor__(self, rhs): self.value ^= rhs return self @@ -1185,6 +1219,7 @@ class AbstractProxyTestBase(object): class Foo(object): def __init__(self, value): self.value = value + def __ior__(self, rhs): self.value |= rhs return self @@ -1290,6 +1325,7 @@ class AbstractProxyTestBase(object): target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) + def _try(): proxy[4] = 7 self.assertRaises(IndexError, _try) @@ -1300,13 +1336,14 @@ class AbstractProxyTestBase(object): target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) + def _try(): proxy[4] = 7 self.assertRaises(ForbiddenAttribute, _try) self.assertEqual(checker._checked, '__setitem__') @_skip_if_not_Py2 - def test___getslice___w_checker_allows(self): + def test___getslice___w_checker_allows(self): # pragma: no cover target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -1316,11 +1353,13 @@ class AbstractProxyTestBase(object): def test___getslice___error_propagates(self): class Missing(Exception): pass + class Get(object): def __getitem__(self, x): - raise Missing('__getitem__') # pragma: no cover (only py3) - def __getslice__(self, start, stop): - raise Missing("__getslice__") + raise Missing('__getitem__') + + def __getslice__(self, start, stop): # PY2 + raise Missing("__getslice__") # pragma: no cover target = Get() checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -1333,6 +1372,7 @@ class AbstractProxyTestBase(object): def test___getslice___dne_uses_getitem(self): class Missing(Exception): pass + class Get(object): def __getitem__(self, x): raise Missing('__getitem__') @@ -1347,7 +1387,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, self.getslice) @_skip_if_not_Py2 - def test___getslice___w_checker_forbids(self): + def test___getslice___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) @@ -1356,7 +1396,7 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__getslice__') @_skip_if_not_Py2 - def test___setslice___w_checker_allows(self): + def test___setslice___w_checker_allows(self): # pragma: no cover target = [0, 1, 2] checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -1365,11 +1405,12 @@ class AbstractProxyTestBase(object): self.assertEqual(checker._checked, '__setslice__') @_skip_if_not_Py2 - def test___setslice___w_checker_forbids(self): + def test___setslice___w_checker_forbids(self): # pragma: no cover from zope.security.interfaces import ForbiddenAttribute target = [0, 1, 2] checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) + def _try(): proxy[1:3] = [3, 4] self.assertRaises(ForbiddenAttribute, _try) @@ -1378,11 +1419,13 @@ class AbstractProxyTestBase(object): def test___setslice___error_propagates(self): class Missing(Exception): pass + class Set(object): def __setitem__(self, k, v): - raise Missing('__setitem__') # pragma: no cover (only py3) - def __setslice__(self, start, stop, value): - raise Missing("__setslice__") + raise Missing('__setitem__') + + def __setslice__(self, start, stop, value): # PY2 + raise Missing("__setslice__") # pragma: no cover target = Set() checker = DummyChecker() proxy = self._makeOne(target, checker) @@ -1395,6 +1438,7 @@ class AbstractProxyTestBase(object): def test___setslice___dne_uses_setitem(self): class Missing(Exception): pass + class Set(object): def __setitem__(self, k, v): raise Missing('__setitem__') @@ -1443,6 +1487,7 @@ class AbstractProxyTestBase(object): target = {'a': 0, 'b': 1, 'c': 2} checker = DummyChecker(ForbiddenAttribute) proxy = self._makeOne(target, checker) + def _try(): proxy['a'] = 7 self.assertRaises(ForbiddenAttribute, _try) @@ -1451,7 +1496,7 @@ class AbstractProxyTestBase(object): binops = [ "x+y", "x-y", "x*y", "x/y", "divmod(x, y)", "x**y", "x//y", "x<>y", "x&y", "x|y", "x^y", - ] + ] def test_binops(self): from zope.security.proxy import removeSecurityProxy @@ -1467,28 +1512,27 @@ class AbstractProxyTestBase(object): self.assertEqual(removeSecurityProxy(eval(expr)), z, "x=%r; y=%r; expr=%r" % (x, y, expr)) - @_skip_if_not_Py2 - def test___unicode___allowed_by_default(self): + def test___unicode___allowed_by_default(self): # pragma: no cover # https://github.com/zopefoundation/zope.security/issues/10 class Foo(object): def __unicode__(self): return u'I am unicode' - checker = object() # checker not consulted + checker = object() # checker not consulted target = Foo() proxy = self._makeOne(target, checker) self.assertEqual(unicode(target), u'I am unicode') self.assertEqual(unicode(target), unicode(proxy)) @_skip_if_not_Py2 - def test___unicode___falls_through_to_str_by_default(self): + def test___unicode___falls_through_to_str_by_default(self): # pragma: no cover # noqa: E501 line too long # https://github.com/zopefoundation/zope.security/issues/10 class Foo(object): def __str__(self): return 'I am str' - checker = object() # checker not consulted + checker = object() # checker not consulted target = Foo() proxy = self._makeOne(target, checker) self.assertEqual(unicode(target), u'I am str') @@ -1497,11 +1541,12 @@ class AbstractProxyTestBase(object): self.assertIsInstance(unicode(proxy), unicode) @_skip_if_not_Py2 - def test___unicode___falls_through_to_str_even_if_str_not_allowed(self): + def test___unicode___falls_through_to_str_even_if_str_not_allowed(self): # pragma: no cover # noqa: E501 line too long # https://github.com/zopefoundation/zope.security/issues/10 # Note that this is inconsistent with str() and probably not a good # idea overall, so this test is strictly a regression test. from zope.security.interfaces import ForbiddenAttribute + class Foo(object): def __str__(self): return 'I am str' @@ -1525,7 +1570,7 @@ class AbstractProxyTestBase(object): class ProxyCTests(AbstractProxyTestBase, unittest.TestCase): - def _getTargetClass(self): + def _getTargetClass(self): # pragma: no cover from zope.security.proxy import _Proxy return _Proxy @@ -1548,6 +1593,7 @@ class ProxyPyTests(AbstractProxyTestBase, def test_access_checker_from_subclass(self): target = object() checker = DummyChecker() + class Sub(self._getTargetClass()): def get_checker(self): return self._checker @@ -1568,6 +1614,7 @@ class ProxyPyTests(AbstractProxyTestBase, target = object() checker = object() proxy = self._makeOne(target, checker) + def test(): del proxy._wrapped self.assertRaises(AttributeError, test) @@ -1576,6 +1623,7 @@ class ProxyPyTests(AbstractProxyTestBase, target = object() checker = object() proxy = self._makeOne(target, checker) + def test(): del proxy._checker self.assertRaises(AttributeError, test) @@ -1616,7 +1664,8 @@ class ProxyPyTests(AbstractProxyTestBase, orig_builtin_isinstance = zope.security.proxy._builtin_isinstance zope.security.proxy._builtin_isinstance = None try: - self.assertRaises(TypeError, zope.security.proxy.getObjectPy, proxy) + self.assertRaises( + TypeError, zope.security.proxy.getObjectPy, proxy) finally: zope.security.proxy._builtin_isinstance = orig_builtin_isinstance @@ -1646,17 +1695,21 @@ class ProxyPyTests(AbstractProxyTestBase, proxy = self._makeOne(module, DummyChecker()) self.assertEqual(WithModule.__module__, proxy.__module__) + class DummyChecker(object): _proxied = _checked = None + def __init__(self, raising=None, allowed=()): self._raising = raising self._allowed = allowed + def check(self, target, name): self._checked = name if name not in self._allowed: if self._raising is not None: raise self._raising(name) check_getattr = check_setattr = check + def proxy(self, value): self._proxied = value return value @@ -1703,6 +1756,7 @@ class Test_isinstance(unittest.TestCase): def test_w_proxied_object(self): from zope.security.checker import Checker from zope.security.proxy import Proxy + class Foo(object): pass target = Foo() @@ -1717,7 +1771,7 @@ class Checker(object): ok = 1 - unproxied_types = {str,} + unproxied_types = {str, } def check_getattr(self, _object, name): if name not in ("foo", "next", "__class__", "__name__", "__module__"): @@ -1741,32 +1795,45 @@ class Checker(object): class Something: def __init__(self): self.foo = [1, 2, 3] + def __getitem__(self, key): return self.foo[key] + def __setitem__(self, key, value): self.foo[key] = value + def __delitem__(self, key): del self.foo[key] + def __call__(self, arg): return 42 + def __eq__(self, other): return self is other + def __hash__(self): return 42 + def __iter__(self): return self + def __next__(self): - return 42 # Infinite sequence + return 42 # Infinite sequence next = __next__ + def __len__(self): return 42 - def __nonzero__(self): - return 1 - def __getslice__(self, i, j): - return [42] - def __setslice__(self, i, j, value): - if value != [42]: + + def __nonzero__(self): # PY2 + return 1 # pragma: no cover + + def __getslice__(self, i, j): # PY2 + return [42] # pragma: no cover + + def __setslice__(self, i, j, value): # PY2 + if value != [42]: # pragma: no cover raise AssertionError("Value should be [42]") + def __contains__(self, x): return x == 42 @@ -1800,7 +1867,7 @@ class ProxyFactoryTests(unittest.TestCase): self.assertTrue(s.startswith( ">y", "x&y", "x|y", "x^y", - ] + ] def test_binops(self): from zope.security.proxy import removeSecurityProxy @@ -2046,7 +2114,7 @@ class ProxyFactoryTests(unittest.TestCase): self.shouldFail(doit2) @_skip_if_not_Py2 - def test_coerce(self): + def test_coerce(self): # pragma: no cover from zope.security.proxy import removeSecurityProxy P = self.c.proxy @@ -2203,8 +2271,8 @@ class LocationProxySecurityCheckerTests(unittest.TestCase): import zope.security try: from importlib import reload as _reload - except ImportError: - _reload = reload # Python 2 + except ImportError: # pragma: PY2 + _reload = reload # noqa: F821 undefined name 'reload' # This attribute is set when zope.security.decorator is imported, to # show that it will be set too, if zope.security.proxy is imported diff --git a/src/zope/security/tests/test_simplepolicies.py b/src/zope/security/tests/test_simplepolicies.py index ce5c483..fcbc8de 100644 --- a/src/zope/security/tests/test_simplepolicies.py +++ b/src/zope/security/tests/test_simplepolicies.py @@ -35,7 +35,7 @@ class ConformsToIInteraction(object): class ParanoidSecurityPolicyTests(unittest.TestCase, ConformsToIInteraction, - ): + ): def _getTargetClass(self): from zope.security.simplepolicies import ParanoidSecurityPolicy @@ -87,6 +87,7 @@ class ParanoidSecurityPolicyTests(unittest.TestCase, def test_checkPermission_w_non_public_only_system_user(self): from zope.security._definitions import system_user + class Participation(object): interaction = None principal = system_user @@ -111,6 +112,7 @@ class ParanoidSecurityPolicyTests(unittest.TestCase, self.assertTrue(policy.checkPermission(None, None)) self.assertTrue(policy.checkPermission(self, self)) + class PermissiveSecurityPolicyTests(unittest.TestCase, ConformsToIInteraction): diff --git a/src/zope/security/tests/test_testing.py b/src/zope/security/tests/test_testing.py index 42eebd0..cc11037 100644 --- a/src/zope/security/tests/test_testing.py +++ b/src/zope/security/tests/test_testing.py @@ -18,6 +18,7 @@ from zope.testing.cleanup import CleanUp from zope.security import testing from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + class TestTestingFunctions(CleanUp, unittest.TestCase): @@ -50,6 +51,7 @@ class TestTestingFunctions(CleanUp, def test_contextmanager_ends_interaction_on_exception(self): from zope.security.management import queryInteraction + class MyError(Exception): pass @@ -59,7 +61,6 @@ class TestTestingFunctions(CleanUp, self.assertFalse(queryInteraction()) - def test_addCheckerPublic(self): from zope import component from zope.security.interfaces import IPermission @@ -69,7 +70,5 @@ class TestTestingFunctions(CleanUp, self.assertIs(perm, utility) - - def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) diff --git a/src/zope/security/tests/test_zcml.py b/src/zope/security/tests/test_zcml.py index 9fb1cc4..2cdf62a 100644 --- a/src/zope/security/tests/test_zcml.py +++ b/src/zope/security/tests/test_zcml.py @@ -14,6 +14,7 @@ import unittest from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public + class ConformsToIFromUnicode(object): def test_class_conforms_to_IFromUnicode(self): @@ -29,7 +30,7 @@ class ConformsToIFromUnicode(object): class PermissionTests(unittest.TestCase, ConformsToIFromUnicode, - ): + ): def _getTargetClass(self): from zope.security.zcml import Permission @@ -147,38 +148,38 @@ class Test_redefinePermission(unittest.TestCase): def test_wo_existing_mapping(self): z_context = DummyZCMLContext() + class Context(object): pass context = z_context.context = Context() after = object() self._callFUT(z_context, 'before.permission', after) - self.assertTrue(context.permission_mapping['before.permission'] - is after) + self.assertIs(context.permission_mapping['before.permission'], after) def test_w_existing_mapping_wo_existing_key(self): z_context = DummyZCMLContext() + class Context(object): pass context = z_context.context = Context() mapping = context.permission_mapping = {} after = object() self._callFUT(z_context, 'before.permission', after) - self.assertTrue(context.permission_mapping is mapping) - self.assertTrue(context.permission_mapping['before.permission'] - is after) + self.assertIs(context.permission_mapping, mapping) + self.assertIs(context.permission_mapping['before.permission'], after) def test_w_existing_mapping_w_existing_key(self): z_context = DummyZCMLContext() + class Context(object): pass context = z_context.context = Context() mapping = context.permission_mapping = {} - before = mapping['before.permission'] = object() + mapping['before.permission'] = object() after = object() self._callFUT(z_context, 'before.permission', after) - self.assertTrue(context.permission_mapping is mapping) - self.assertTrue(context.permission_mapping['before.permission'] - is after) + self.assertIs(context.permission_mapping, mapping) + self.assertIs(context.permission_mapping['before.permission'], after) class DummyZCMLContext(object): diff --git a/src/zope/security/tests/test_zcml_functest.py b/src/zope/security/tests/test_zcml_functest.py index b669847..2486af6 100644 --- a/src/zope/security/tests/test_zcml_functest.py +++ b/src/zope/security/tests/test_zcml_functest.py @@ -52,7 +52,6 @@ class TestClassDirective(unittest.TestCase): import zope.security XMLConfig('meta.zcml', zope.security)() - def testEmptyDirective(self): from zope.configuration.xmlconfig import xmlconfig self._meta() @@ -62,7 +61,6 @@ class TestClassDirective(unittest.TestCase): """) xmlconfig(f) - def testImplements(self): from zope.component.interface import queryInterface from zope.configuration.xmlconfig import xmlconfig @@ -83,7 +81,6 @@ class TestClassDirective(unittest.TestCase): self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample"), IExample) - def testMulImplements(self): from zope.component.interface import queryInterface from zope.configuration.xmlconfig import xmlconfig @@ -112,7 +109,7 @@ class TestClassDirective(unittest.TestCase): "zope.security.tests.exampleclass.IExample"), IExample) self.assertEqual(queryInterface( "zope.security.tests.exampleclass.IExample2"), - IExample2) + IExample2) def testRequire(self): from zope.configuration.xmlconfig import xmlconfig @@ -162,7 +159,6 @@ class TestFactorySubdirective(unittest.TestCase): import zope.security XMLConfig('meta.zcml', zope.security)() - def testFactory(self): from zope.component import getUtility from zope.component.interfaces import IFactory @@ -208,7 +204,6 @@ class TestFactorySubdirective(unittest.TestCase): self.assertEqual(factory.title, "Example content") self.assertEqual(factory.description, "Example description") - def testFactoryPublicPermission(self): from zope.component import getUtility from zope.component.interfaces import IFactory @@ -251,7 +246,6 @@ class TestFactoryDirective(unittest.TestCase): from zope.configuration.xmlconfig import XMLConfig XMLConfig('meta.zcml', zope.security)() - def testFactory(self): from zope.component import createObject from zope.configuration.xmlconfig import xmlconfig @@ -272,11 +266,11 @@ class TestFactoryDirective(unittest.TestCase): self.assertTrue(proxy.isinstance(obj, exampleclass.ExampleClass)) - def _pfx(name): from zope.security.tests import module return module.__name__ + '.' + name + def defineDirectives(): from zope.configuration.xmlconfig import XMLConfig from zope.configuration.xmlconfig import xmlconfig @@ -289,11 +283,13 @@ def defineDirectives(): """)) + NOTSET = () P1 = "zope.Extravagant" P2 = "zope.Paltry" + class TestRequireDirective(unittest.TestCase): def setUp(self): @@ -306,6 +302,7 @@ class TestRequireDirective(unittest.TestCase): class B(object): def m1(self): raise AssertionError("Never called") + def m2(self): raise AssertionError("Never called") @@ -313,6 +310,7 @@ class TestRequireDirective(unittest.TestCase): class C(B): def m3(self): raise AssertionError("Never called") + def m4(self): raise AssertionError("Never called") @@ -328,7 +326,7 @@ class TestRequireDirective(unittest.TestCase): tearDown() def assertState(self, m1P=NOTSET, m2P=NOTSET, m3P=NOTSET): - #Verify that class, instance, and methods have expected permissions + # Verify that class, instance, and methods have expected permissions from zope.security.checker import selectChecker from zope.security.tests import module checker = selectChecker(module.test_instance) @@ -399,7 +397,6 @@ class TestRequireDirective(unittest.TestCase): self.assertEqual(queryInterface(_pfx("S")), module.S) - checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), None) self.assertEqual(checker.setattr_permission_id('m2'), None) @@ -426,7 +423,6 @@ class TestRequireDirective(unittest.TestCase): self.assertEqual(queryInterface(_pfx("S")), module.S) self.assertEqual(queryInterface(_pfx("S2")), module.S2) - checker = selectChecker(module.test_instance) self.assertEqual(checker.setattr_permission_id('m1'), None) self.assertEqual(checker.setattr_permission_id('m2'), None) @@ -454,7 +450,6 @@ class TestRequireDirective(unittest.TestCase): # Make sure we know about the interfaces self.assertEqual(queryInterface(_pfx("I")), module.I) - def testMultipleInterface(self): from zope.component.interface import queryInterface from zope.security.tests import module @@ -478,7 +473,6 @@ class TestRequireDirective(unittest.TestCase): # "testComposite*TopPerm" exercises tags with permission in containing tag. # "testComposite*ElementPerm" exercises tags w/permission in children. - def testCompositeNoPerm(self): # Establish rejection of declarations lacking a permission spec. from zope.configuration.exceptions import ConfigurationError @@ -490,7 +484,6 @@ class TestRequireDirective(unittest.TestCase): with self.assertRaises(ConfigurationError): self.assertDeclaration(declaration) - def testCompositeMethodsPluralElementPerm(self): declaration = (''' ''' % (_pfx("test_base"), P1, - _pfx("test_class"), _pfx("test_base"))) + _pfx("test_class"), _pfx("test_base"))) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, m1P=P1, m2P=P1) - def testMimicAsDefault(self): declaration = (''' ''' % (_pfx("test_base"), P1, - _pfx("test_class"), _pfx("test_base"), P2)) + _pfx("test_class"), _pfx("test_base"), P2)) # m1 and m2 are in the interface, so should be set, and m3 should not: self.assertDeclaration(declaration, @@ -564,21 +553,22 @@ def apply_declaration(declaration): '''Apply the xmlconfig machinery.''' from zope.configuration.xmlconfig import xmlconfig if isinstance(declaration, bytes): - declaration = declaration.decode("utf-8") + declaration = declaration.decode("utf-8") # pragma: no cover PY2 return xmlconfig(io.StringIO(declaration)) - def make_dummy(): from zope.interface import Interface import zope.security.zcml global IDummy + class IDummy(Interface): perm = zope.security.zcml.Permission(title=u'') perms = [] + def dummy(context_, perm): global perms perms.append(perm) diff --git a/src/zope/security/zcml.py b/src/zope/security/zcml.py index 473c06e..4e3c17c 100644 --- a/src/zope/security/zcml.py +++ b/src/zope/security/zcml.py @@ -65,6 +65,7 @@ class ISecurityPolicyDirective(Interface): description=u"Pointer to the object that will handle the security.", required=True) + def securityPolicy(_context, component): _context.action( discriminator='defaultPolicy', @@ -72,6 +73,7 @@ def securityPolicy(_context, component): args=(component,) ) + class IPermissionDirective(Interface): """Define a new security object.""" @@ -90,6 +92,7 @@ class IPermissionDirective(Interface): description=u"Provides a description for the object.", required=False) + def permission(_context, id, title, description=u''): from zope.security.interfaces import IPermission from zope.security.permission import Permission @@ -97,6 +100,7 @@ def permission(_context, id, title, description=u''): permission = Permission(id, title, description) utility(_context, IPermission, permission, name=id) + class IRedefinePermission(Interface): """Define a permission to replace another permission.""" @@ -110,6 +114,7 @@ class IRedefinePermission(Interface): description=u"Substituted permission ID.", required=True) + def redefinePermission(_context, from_, to): _context = _context.context -- cgit v1.2.1