summaryrefslogtreecommitdiff
path: root/src/zope/security/checker.py
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2017-04-24 06:54:36 -0500
committerJason Madden <jamadden@gmail.com>2017-04-24 08:00:59 -0500
commit9aaf59b541bc3e0616f9f9f95b6345d1a4400e68 (patch)
treea73601e4bf67de1d67fc67eb43065691c8648130 /src/zope/security/checker.py
parent6292afe78a5eee46405d982405fcc63603478504 (diff)
downloadzope-security-9aaf59b541bc3e0616f9f9f95b6345d1a4400e68.tar.gz
Fix iteration of BTrees.items() in pure-python; and 3.6 support
Also fix ``list(proxy_btree.items())`` (or a list comprehension of the same) in Python 3, which wants the ``__len__`` for a hint. This is a central place to make sure these all behave consistently. Fixes #20 Also drop pypy3 As a 3.2 implementation, it's not supported by pip anymore. There is a much more recent version, 3.5-beta, but it's not on Travis yet. The 3.3-alpha which is on Travis is a dead end.
Diffstat (limited to 'src/zope/security/checker.py')
-rw-r--r--src/zope/security/checker.py37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py
index d5f261c..d75cfd5 100644
--- a/src/zope/security/checker.py
+++ b/src/zope/security/checker.py
@@ -770,6 +770,43 @@ if PYTHON2:
_default_checkers[type({}.iterkeys())] = _iteratorChecker
_default_checkers[type({}.itervalues())] = _iteratorChecker
+try:
+ import BTrees
+except ImportError: # pragma: no cover
+ pass
+else:
+ # The C implementation of BTree.items() is its own iterator
+ # and doesn't need any special entries to enable iteration.
+ # But the Python implementation has to call __iter__ to be able
+ # to do iteration. Whitelist it so that they behave the same.
+ # In addition, Python 3 will attempt to call __len__ on iterators
+ # for a length hint, so the C implementations also need to be
+ # added to the _iteratorChecker.
+ # We do this here so that all users of zope.security can benefit
+ # without knowing implementation details.
+ # See https://github.com/zopefoundation/zope.security/issues/20
+
+ def _fixup_btrees():
+ import BTrees._base
+ _default_checkers[BTrees._base._TreeItems] = _iteratorChecker
+
+ for name in ('IF', 'II', 'IO', 'OI', 'OO'):
+ for family_name in ('family32', 'family64'):
+ family = getattr(BTrees, family_name)
+ btree = getattr(family, name).BTree()
+
+ empty_type = type(btree.items())
+ if empty_type not in _default_checkers:
+ _default_checkers[empty_type] = _iteratorChecker
+
+ btree[1] = 1
+ populated_type = type(btree.items())
+ if populated_type not in _default_checkers:
+ _default_checkers[populated_type] = _iteratorChecker
+
+ _fixup_btrees()
+ del _fixup_btrees
+
def _clear():
_checkers.clear()
_checkers.update(_default_checkers)