diff options
author | Jason Madden <jamadden@gmail.com> | 2017-04-24 06:54:36 -0500 |
---|---|---|
committer | Jason Madden <jamadden@gmail.com> | 2017-04-24 08:00:59 -0500 |
commit | 9aaf59b541bc3e0616f9f9f95b6345d1a4400e68 (patch) | |
tree | a73601e4bf67de1d67fc67eb43065691c8648130 /src/zope/security/checker.py | |
parent | 6292afe78a5eee46405d982405fcc63603478504 (diff) | |
download | zope-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.py | 37 |
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) |