diff options
author | Andrey Lebedev <andrey@lebedev.lt> | 2013-02-19 19:07:25 +0200 |
---|---|---|
committer | Andrey Lebedev <andrey@lebedev.lt> | 2013-02-19 19:07:25 +0200 |
commit | 67e4c91acc5d16e1408696189d31771be73d311e (patch) | |
tree | b26882d8e014a081d5f3e6a74791a54187b244d1 | |
parent | e1d5f7cf375ccdfb8f6207c2bf813ca64c1d7bda (diff) | |
parent | aad857434f77e494a9c1ea1ba90f95bb1cc60551 (diff) | |
download | zope-security-67e4c91acc5d16e1408696189d31771be73d311e.tar.gz |
Merge branch 'moretests'
-rw-r--r-- | docs/api/checker.rst | 113 | ||||
-rw-r--r-- | docs/api/decorator.rst | 25 | ||||
-rw-r--r-- | docs/api/permission.rst | 10 | ||||
-rw-r--r-- | docs/api/zcml.rst | 14 | ||||
-rw-r--r-- | setup.py | 17 | ||||
-rw-r--r-- | src/zope/security/checker.py | 8 | ||||
-rw-r--r-- | src/zope/security/testing.py | 19 | ||||
-rw-r--r-- | tox.ini | 3 |
8 files changed, 99 insertions, 110 deletions
diff --git a/docs/api/checker.rst b/docs/api/checker.rst index 8b321db..58d3595 100644 --- a/docs/api/checker.rst +++ b/docs/api/checker.rst @@ -82,8 +82,7 @@ directly, or via interface: >>> context = AContext() >>> allow(context, attributes=['foo', 'bar'], interface=[I1, I2]) - >>> context.actions.sort( - ... lambda a, b: cmp(a['discriminator'], b['discriminator'])) + >>> context.actions.sort(key=lambda a: a['discriminator']) >>> pprint(context.actions) [{'args': ('testmodule', 'a', 'zope.Public'), 'callable': 1, @@ -136,8 +135,7 @@ directly, or via interface: >>> require(context, attributes=['foo', 'bar'], ... interface=[I1, I2], permission='p') - >>> context.actions.sort( - ... lambda a, b: cmp(a['discriminator'], b['discriminator'])) + >>> context.actions.sort(key=lambda a: a['discriminator']) >>> pprint(context.actions) [{'args': ('testmodule', 'a', 'p'), 'callable': 1, @@ -182,26 +180,26 @@ Protections for standard objects ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return getattr(object, attr) - ... except ForbiddenAttribute, e: - ... return 'ForbiddenAttribute: %s' % e[0] + ... except ForbiddenAttribute as e: + ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_setitem(object, item, value): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... object[item] = value - ... except ForbiddenAttribute, e: - ... return 'ForbiddenAttribute: %s' % e[0] + ... except ForbiddenAttribute as e: + ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_delitem(object, item): ... from zope.security.interfaces import ForbiddenAttribute ... try: ... del object[item] - ... except ForbiddenAttribute, e: - ... return 'ForbiddenAttribute: %s' % e[0] + ... except ForbiddenAttribute as e: + ... return 'ForbiddenAttribute: %s' % e.args[0] >>> def check_forbidden_call(callable, *args): # ** ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return callable(*args) # ** - ... except ForbiddenAttribute, e: - ... return 'ForbiddenAttribute: %s' % e[0] + ... except ForbiddenAttribute as e: + ... return 'ForbiddenAttribute: %s' % e.args[0] Rocks ##### @@ -217,16 +215,12 @@ Rocks are immuatle, non-callable objects without interesting methods. They 1 >>> int(type(ProxyFactory( 1.0 )) is float) 1 - >>> int(type(ProxyFactory( 1l )) is long) - 1 >>> int(type(ProxyFactory( 1j )) is complex) 1 >>> int(type(ProxyFactory( None )) is type(None)) 1 >>> int(type(ProxyFactory( 'xxx' )) is str) 1 - >>> int(type(ProxyFactory( u'xxx' )) is unicode) - 1 >>> int(type(ProxyFactory( True )) is type(True)) 1 @@ -270,18 +264,18 @@ We can do everything we expect to be able to do with proxied dicts. 1 >>> len(d) 2 - >>> list(d) + >>> sorted(list(d)) ['a', 'b'] >>> d.get('a') 1 - >>> int(d.has_key('a')) + >>> int('a' in d) 1 >>> c = d.copy() >>> check_forbidden_get(c, 'clear') 'ForbiddenAttribute: clear' >>> int(str(c) in ("{'a': 1, 'b': 2}", "{'b': 2, 'a': 1}")) 1 - >>> int(`c` in ("{'a': 1, 'b': 2}", "{'b': 2, 'a': 1}")) + >>> int(repr(c) in ("{'a': 1, 'b': 2}", "{'b': 2, 'a': 1}")) 1 >>> def sorted(x): ... x = list(x) @@ -293,27 +287,12 @@ We can do everything we expect to be able to do with proxied dicts. [1, 2] >>> sorted(d.items()) [('a', 1), ('b', 2)] - >>> sorted(d.iterkeys()) - ['a', 'b'] - >>> sorted(d.itervalues()) - [1, 2] - >>> sorted(d.iteritems()) - [('a', 1), ('b', 2)] -Always available: +Always available (note, that dicts in python-3.x are not orderable, so we are +not checking that under python > 2): .. doctest:: - >>> int(d < d) - 0 - >>> int(d > d) - 0 - >>> int(d <= d) - 1 - >>> int(d >= d) - 1 - >>> int(d == d) - 1 >>> int(d != d) 0 >>> int(bool(d)) @@ -351,7 +330,7 @@ We can do everything we expect to be able to do with proxied lists. 1 >>> str(l) '[1, 2]' - >>> `l` + >>> repr(l) '[1, 2]' >>> l + l [1, 2, 1, 2] @@ -398,7 +377,7 @@ We can do everything we expect to be able to do with proxied tuples. 1 >>> str(l) '(1, 2)' - >>> `l` + >>> repr(l) '(1, 2)' >>> l + l (1, 2, 1, 2) @@ -607,8 +586,8 @@ we can do everything we expect to be able to do with proxied frozensets. ... from zope.security.interfaces import ForbiddenAttribute ... try: ... return getattr(object, attr) - ... except ForbiddenAttribute, e: - ... return 'ForbiddenAttribute: %s' % e[0] + ... except ForbiddenAttribute as e: + ... return 'ForbiddenAttribute: %s' % e.args[0] >>> from zope.security.checker import ProxyFactory >>> from zope.security.interfaces import ForbiddenAttribute >>> us = frozenset((1, 2)) @@ -779,6 +758,8 @@ iterators .. doctest:: + >>> [a for a in ProxyFactory(iter([1, 2]))] + [1, 2] >>> list(ProxyFactory(iter([1, 2]))) [1, 2] >>> list(ProxyFactory(iter((1, 2)))) @@ -815,7 +796,7 @@ We can iterate over sequences >>> from zope.security.checker import NamesChecker >>> from zope.security.checker import ProxyFactory - >>> c = NamesChecker(['__getitem__']) + >>> c = NamesChecker(['__getitem__', '__len__']) >>> p = ProxyFactory(x, c) Even if they are proxied @@ -856,7 +837,7 @@ New-style classes >>> check_forbidden_get(C, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(C) - >>> s = `C` + >>> s = repr(C) >>> int(C.__module__ == __name__) 1 >>> len(C.__bases__) @@ -868,14 +849,6 @@ Always available: .. doctest:: - >>> int(C < C) - 0 - >>> int(C > C) - 0 - >>> int(C <= C) - 1 - >>> int(C >= C) - 1 >>> int(C == C) 1 >>> int(C != C) @@ -907,14 +880,6 @@ Always available: .. doctest:: - >>> int(c < c) - 0 - >>> int(c > c) - 0 - >>> int(c <= c) - 1 - >>> int(c >= c) - 1 >>> int(c == c) 1 >>> int(c != c) @@ -938,24 +903,16 @@ Classic Classes >>> check_forbidden_get(C, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(C) - >>> s = `C` + >>> s = repr(C) >>> int(C.__module__ == __name__) 1 >>> len(C.__bases__) - 0 + 1 Always available: .. doctest:: - >>> int(C < C) - 0 - >>> int(C > C) - 0 - >>> int(C <= C) - 1 - >>> int(C >= C) - 1 >>> int(C == C) 1 >>> int(C != C) @@ -984,14 +941,6 @@ Always available: .. doctest:: - >>> int(c < c) - 0 - >>> int(c > c) - 0 - >>> int(c <= c) - 1 - >>> int(c >= c) - 1 >>> int(c == c) 1 >>> int(c != c) @@ -1055,7 +1004,7 @@ We work with the ABCMeta meta class: >>> check_forbidden_get(PBar, '__dict__') 'ForbiddenAttribute: __dict__' >>> s = str(PBar) - >>> s = `PBar` + >>> s = repr(PBar) >>> int(PBar.__module__ == __name__) 1 >>> len(PBar.__bases__) @@ -1065,19 +1014,11 @@ Always available: .. doctest:: - >>> int(PBar < PBar) - 0 - >>> int(PBar > PBar) - 0 - >>> int(PBar <= PBar) - 1 - >>> int(PBar >= PBar) - 1 >>> int(PBar == PBar) 1 >>> int(PBar != PBar) 0 >>> int(bool(PBar)) 1 - >>> int(PBar.__class__ == abc.ABCMeta) + >>> int(PBar.__class__ == type) 1 diff --git a/docs/api/decorator.rst b/docs/api/decorator.rst index c4741b9..c05c692 100644 --- a/docs/api/decorator.rst +++ b/docs/api/decorator.rst @@ -48,13 +48,16 @@ Using `selectChecker()`, we can confirm that a `Foo` object uses .. doctest:: >>> from zope.security.checker import selectChecker + >>> from zope.security.interfaces import ForbiddenAttribute >>> foo = Foo() >>> selectChecker(foo) is fooChecker True >>> fooChecker.check(foo, 'a') - >>> fooChecker.check(foo, 'b') # doctest: +ELLIPSIS - Traceback (most recent call last): - ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>) + >>> try: + ... fooChecker.check(foo, 'b') # doctest: +ELLIPSIS + ... except ForbiddenAttribute as e: + ... e + ForbiddenAttribute('b', <Foo object ...>) and that a `Wrapper` object uses `wrappeChecker`: @@ -64,9 +67,11 @@ and that a `Wrapper` object uses `wrappeChecker`: >>> selectChecker(wrapper) is wrapperChecker True >>> wrapperChecker.check(wrapper, 'b') - >>> wrapperChecker.check(wrapper, 'a') # doctest: +ELLIPSIS - Traceback (most recent call last): - ForbiddenAttribute: ('a', <zope.security.decorator.Foo object ...>) + >>> try: + ... wrapperChecker.check(wrapper, 'a') # doctest: +ELLIPSIS + ... except ForbiddenAttribute as e: + ... e + ForbiddenAttribute('a', <Foo object ...>) (Note that the object description says `Foo` because the object is a proxy and generally looks and acts like the object it's proxying.) @@ -94,9 +99,11 @@ illustrate, we'll proxify `foo`: >>> secure_foo = ProxyFactory(foo) >>> secure_foo.a 'a' - >>> secure_foo.b # doctest: +ELLIPSIS - Traceback (most recent call last): - ForbiddenAttribute: ('b', <zope.security.decorator.Foo object ...>) + >>> try: + ... secure_foo.b # doctest: +ELLIPSIS + ... except ForbiddenAttribute as e: + ... e + ForbiddenAttribute('b', <Foo object ...>) when we wrap the secured `foo`: diff --git a/docs/api/permission.rst b/docs/api/permission.rst index 64a4250..819cc90 100644 --- a/docs/api/permission.rst +++ b/docs/api/permission.rst @@ -48,7 +48,7 @@ The :data:`zope.security.checker.CheckerPublic` permission always exists: >>> ids = list(allPermissions(None)) >>> ids.sort() >>> ids - [u'x', u'y'] + ['x', 'y'] .. autofunction:: zope.security.permission.PermissionsVocabulary @@ -100,9 +100,9 @@ The non-public permissions 'x' and 'y' are string values: .. doctest:: >>> vocab.getTermByToken('x').value - u'x' + 'x' >>> vocab.getTermByToken('y').value - u'y' + 'y' However, the public permission value is CheckerPublic: @@ -116,7 +116,7 @@ and its title is shortened: .. doctest:: >>> vocab.getTermByToken('zope.Public').title - u'Public' + 'Public' The terms are sorted by title except for the public permission, which is listed first: @@ -124,7 +124,7 @@ listed first: .. doctest:: >>> [term.title for term in vocab] - [u'Public', u'x', u'y'] + ['Public', 'x', 'y'] .. testcleanup:: diff --git a/docs/api/zcml.rst b/docs/api/zcml.rst index 5fdc3a0..a23075a 100644 --- a/docs/api/zcml.rst +++ b/docs/api/zcml.rst @@ -11,8 +11,9 @@ a couple of permissions: >>> from zope.component import getGlobalSiteManager >>> from zope.configuration.xmlconfig import XMLConfig + >>> from zope.component.testing import setUp >>> import zope.security - + >>> setUp() # clear global component registry >>> XMLConfig('permissions.zcml', zope.security)() >>> len(list(getGlobalSiteManager().registeredUtilities())) @@ -64,10 +65,13 @@ Now let's see whether validation works alright >>> field._validate('zope.ManageCode') >>> context._actions[0]['args'] (None, 'zope.foo') - >>> field._validate('3 foo') - Traceback (most recent call last): - ... - InvalidId: 3 foo + + >>> from zope.schema.interfaces import InvalidId + >>> try: + ... field._validate('3 foo') + ... except InvalidId as e: + ... e + InvalidId('3 foo') zope.Public is always valid >>> field._validate('zope.Public') @@ -32,6 +32,21 @@ TESTS_REQUIRE = [ 'zope.location', ] +def alltests(): + import os + import sys + import unittest + # use the zope.testrunner machinery to find all the + # test suites we've put under ourselves + import zope.testrunner.find + import zope.testrunner.options + here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')) + args = sys.argv[:] + defaults = ["--test-path", here] + options = zope.testrunner.options.get_options(args, defaults) + suites = list(zope.testrunner.find.find_suites(options)) + return unittest.TestSuite(suites) + here = os.path.abspath(os.path.dirname(__file__)) def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() @@ -130,7 +145,7 @@ setup(name='zope.security', 'zope.proxy >= 4.1.0', 'zope.schema', ], - test_suite = 'zope.security', + test_suite = '__main__.alltests', tests_require=TESTS_REQUIRE, extras_require = dict( pytz=["pytz"], diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py index e5f88dc..5f1d7df 100644 --- a/src/zope/security/checker.py +++ b/src/zope/security/checker.py @@ -595,7 +595,7 @@ _typeChecker = NamesChecker( '__implemented__']) _namedChecker = NamesChecker(['__name__']) -_iteratorChecker = NamesChecker(['next', '__iter__']) +_iteratorChecker = NamesChecker(['next', '__iter__', '__len__']) _setChecker = NamesChecker(['__iter__', '__len__', '__str__', '__contains__', 'copy', 'difference', 'intersection', 'issubset', @@ -642,9 +642,13 @@ _basic_types = { datetime.time: NoProxy, datetime.tzinfo: NoProxy, } -if PYTHON2: +if PYTHON2: _basic_types[long] = NoProxy _basic_types[unicode] = NoProxy +else: #pragma NO COVER + _basic_types[type({}.values())] = NoProxy + _basic_types[type({}.keys())] = NoProxy + _basic_types[type({}.items())] = NoProxy try: import pytz diff --git a/src/zope/security/testing.py b/src/zope/security/testing.py index 53d1ebe..ee13db8 100644 --- a/src/zope/security/testing.py +++ b/src/zope/security/testing.py @@ -15,13 +15,30 @@ This module provides some helper/stub objects for setting up interactions. """ +import sys +import re from zope import interface, component from zope.security import interfaces from zope.security.permission import Permission import contextlib import zope.security.management - +from zope.testing import renormalizing + +PY2 = sys.version_info[0] == 2 + +if PY2: + _u = unicode + rules = [(re.compile("b('.*?')"), r"\1"), + (re.compile('b(".*?")'), r"\1"), + ] + output_checker = renormalizing.RENormalizing(rules) +else: + _u = str + rules = [(re.compile("u('.*?')"), r"\1"), + (re.compile('u(".*?")'), r"\1"), + ] + output_checker = renormalizing.RENormalizing(rules) @interface.implementer(interfaces.IPrincipal) class Principal: @@ -13,6 +13,7 @@ deps = zope.component zope.location zope.proxy + zope.testrunner commands = python setup.py test -q @@ -40,7 +41,7 @@ deps = [testenv:docs] basepython = - python2.6 + python3.3 commands = sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest |