Skip to content

Commit

Permalink
Merge pull request #73 from zopefoundation/consistent-interfaces
Browse files Browse the repository at this point in the history
Ensure all objects have consistent interface resolution orders.
  • Loading branch information
jamadden committed Mar 23, 2020
2 parents 4382cde + 027ce52 commit 6c99bcb
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pyc
*.pyo
*.so
__pycache__
*.egg
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ env:
TWINE_USERNAME: zope.wheelbuilder
TWINE_PASSWORD:
secure: "U6CeZtNEPDN3qKXfrLcvHFLrowqNWxmapXLWygZRxKgfR+ypowe1Y0a4kCBEBZKtysbY26MmIkrMV07tEMxny1yUWVCvRvUaQw0Ic3t5CM0R019zjVh9fQUTdWGCwri86Qj/OaeuPeMR0LCr6d9nMSun0GWSWhjOUhkTCdchfQw="
ZOPE_INTERFACE_STRICT_IRO: 1

python:
- 2.7
Expand Down
6 changes: 4 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
Changes
=========

5.2.0 (unreleased)
5.1.1 (unreleased)
==================

- Nothing changed yet.
- Ensure all objects have consistent interface resolution orders (if
all dependencies are up-to-date). See `issue 71
<https://github.com/zopefoundation/zope.security/issues/71>`_.


5.1.0 (2020-02-14)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def __str__(self):


setup(name='zope.security',
version='5.2.0.dev0',
version='5.1.1.dev0',
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Security Framework',
Expand Down
23 changes: 22 additions & 1 deletion src/zope/security/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,25 @@
PYTHON2 = False


_BLANK = u''
class implementer_if_needed(object):
# Helper to make sure we don't redundantly implement interfaces
# already inherited. Doing so tends to produce problems with the
# C3 order. Even though here we could easily statically determine
# if we need the interface or not, this is used for clarity, to
# reduce the testing load, and to insulate against changes in
# super classes.
def __init__(self, *ifaces):
self._ifaces = ifaces

def __call__(self, cls):
from zope.interface import implementedBy
from zope.interface import implementer

ifaces_needed = []
implemented = implementedBy(cls)
ifaces_needed = [
iface
for iface in self._ifaces
if not implemented.isOrExtends(iface)
]
return implementer(*ifaces_needed)(cls)
3 changes: 2 additions & 1 deletion src/zope/security/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
from zope.security._compat import CLASS_TYPES
from zope.security._compat import PYTHON2
from zope.security._compat import PURE_PYTHON
from zope.security._compat import implementer_if_needed
from zope.security.proxy import Proxy
from zope.security.proxy import getChecker

Expand Down Expand Up @@ -503,7 +504,7 @@ def undefineChecker(type_):

_getChecker = _checkers.get

@implementer(IChecker)
@implementer_if_needed(IChecker)
class CombinedChecker(Checker):
"""A checker that combines two other checkers in a logical-or fashion.
Expand Down
9 changes: 5 additions & 4 deletions src/zope/security/zcml.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@
from zope.configuration.fields import GlobalObject
from zope.configuration.fields import MessageID
from zope.interface import Interface
from zope.interface import implementer
from zope.schema import Id
from zope.schema.interfaces import IFromUnicode

from zope.security._compat import implementer_if_needed
from zope.security.permission import checkPermission
from zope.security.management import setSecurityPolicy
from zope.security.interfaces import PUBLIC_PERMISSION_NAME as zope_Public

@implementer(IFromUnicode)

@implementer_if_needed(IFromUnicode)
class Permission(Id):
r"""This field describes a permission.
"""

def fromUnicode(self, u):
u = super(Permission, self).fromUnicode(u)
def fromUnicode(self, value):
u = super(Permission, self).fromUnicode(value)

map = getattr(self.context, 'permission_mapping', {})
return map.get(u, u)
Expand Down
24 changes: 3 additions & 21 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,10 @@ extras =
test
docs
deps =

[testenv:py27-watch]
basepython =
python2.7
setenv =
PURE_PYTHON = 1
ZOPE_WATCH_CHECKERS = 1
PIP_CACHE_DIR = {envdir}/.cache

[testenv:py37-watch]
basepython =
python3.7
setenv =
ZOPE_WATCH_CHECKERS = 1
PIP_CACHE_DIR = {envdir}/.cache

[testenv:py37-pure]
basepython =
python3.7
setenv =
PURE_PYTHON = 1
PIP_CACHE_DIR = {envdir}/.cache
ZOPE_INTERFACE_STRICT_IRO = 1
watch: ZOPE_WATCH_CHECKERS = 1
pure: PURE_PYTHON = 1

[testenv:coverage]
usedevelop = true
Expand Down

0 comments on commit 6c99bcb

Please sign in to comment.