diff --git a/.travis.yml b/.travis.yml
index 92655c1..c5b8cc2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,8 @@ env:
     - TOXENV=docs
 install:
     - pip install -U pip
-    - pip install -U setuptools tox
+    - pip install -U setuptools
+    - pip install -U tox
 script:
     - tox
 notifications:
diff --git a/CHANGES.rst b/CHANGES.rst
index 13ea38e..1533b06 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,14 @@ Changes
 4.1.2 (unreleased)
 ------------------
 
-- TBD
+- Fix `issue 27 <https://github.com/zopefoundation/zope.security/issues/27>`_:
+  iteration of ``zope.interface.providedBy()`` is now allowed by
+  default on all versions of Python. Previously it only worked on
+  Python 2. Note that ``providedBy`` returns unproxied objects for backwards
+  compatibility.
+
+- Fix ``__length_hint__`` of proxied iterator objects. Previously it
+  was ignored.
 
 4.1.1 (2017-05-17)
 ------------------
diff --git a/appveyor.yml b/appveyor.yml
index 51053ff..567e1a5 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -20,10 +20,12 @@ install:
 # We need to install the C extensions that BTrees setup-requires
 # separately because we've seen problems with the BTrees build cleanup step trying
 # to delete a .pyd that was still open.
-  - pip install persistent
-  - pip install BTrees
-  - pip install zope.testrunner
-  - pip install .[test]
+  - python -m pip install -U pip
+  - pip install -U setuptools
+  - pip install -U persistent
+  - pip install -U BTrees
+  - pip install -U zope.testrunner
+  - pip install -U .[test]
 
 build: false
 
diff --git a/src/zope/security/_proxy.c b/src/zope/security/_proxy.c
index 27edbb3..5108065 100644
--- a/src/zope/security/_proxy.c
+++ b/src/zope/security/_proxy.c
@@ -177,8 +177,8 @@ check(SecurityProxy *self, PyObject *meth, PyObject *name)
     return self->proxy_checker->ob_type->tp_as_mapping->
       mp_ass_subscript(self->proxy_checker, self->proxy.proxy_object, name);
 
-  r = PyObject_CallMethodObjArgs(self->proxy_checker, meth, 
-                                 self->proxy.proxy_object, name, 
+  r = PyObject_CallMethodObjArgs(self->proxy_checker, meth,
+                                 self->proxy.proxy_object, name,
                                  NULL);
   if (r == NULL)
     return -1;
@@ -227,26 +227,26 @@ check2(PyObject *self, PyObject *other,
 {
   PyObject *result = NULL;
 
-  if (Proxy_Check(self)) 
+  if (Proxy_Check(self))
     {
       if (check((SecurityProxy*)self, str_check, opname) >= 0)
         {
-          result = operation(((SecurityProxy*)self)->proxy.proxy_object, 
+          result = operation(((SecurityProxy*)self)->proxy.proxy_object,
                              other);
           PROXY_RESULT(((SecurityProxy*)self), result);
         }
     }
-  else if (Proxy_Check(other)) 
+  else if (Proxy_Check(other))
     {
       if (check((SecurityProxy*)other, str_check, ropname) >= 0)
         {
-          result = operation(self, 
+          result = operation(self,
                              ((SecurityProxy*)other)->proxy.proxy_object);
-    
+
           PROXY_RESULT(((SecurityProxy*)other), result);
         }
     }
-  else 
+  else
     {
       Py_INCREF(Py_NotImplemented);
       return Py_NotImplemented;
@@ -261,10 +261,10 @@ check2i(SecurityProxy *self, PyObject *other,
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check, opname) >= 0) 
+  if (check(self, str_check, opname) >= 0)
     {
       result = operation(self->proxy.proxy_object, other);
-      if (result == self->proxy.proxy_object) 
+      if (result == self->proxy.proxy_object)
         {
           /* If the operation was really carried out inplace,
              don't create a new proxy, but use the old one. */
@@ -272,7 +272,7 @@ check2i(SecurityProxy *self, PyObject *other,
           Py_INCREF((PyObject *)self);
           result = (PyObject *)self;
         }
-      else 
+      else
         PROXY_RESULT(self, result);
     }
   return result;
@@ -372,7 +372,7 @@ proxy_iter(SecurityProxy *self)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check, str___iter__) >= 0) 
+  if (check(self, str_check, str___iter__) >= 0)
     {
       result = PyObject_GetIter(self->proxy.proxy_object);
       PROXY_RESULT(self, result);
@@ -385,7 +385,7 @@ proxy_iternext(SecurityProxy *self)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check_getattr, str_next) >= 0) 
+  if (check(self, str_check_getattr, str_next) >= 0)
     {
       result = PyIter_Next(self->proxy.proxy_object);
       PROXY_RESULT(self, result);
@@ -398,7 +398,7 @@ proxy_getattro(SecurityProxy *self, PyObject *name)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check_getattr, name) >= 0) 
+  if (check(self, str_check_getattr, name) >= 0)
     {
       result = PyObject_GetAttr(self->proxy.proxy_object, name);
       PROXY_RESULT(self, result);
@@ -449,7 +449,7 @@ default_repr(PyObject *object)
   Py_DECREF(klass);
   Py_XDECREF(name);
   Py_XDECREF(module);
-  
+
   return result;
 }
 
@@ -458,11 +458,11 @@ proxy_str(SecurityProxy *self)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check, str___str__) >= 0) 
+  if (check(self, str_check, str___str__) >= 0)
     {
       result = PyObject_Str(self->proxy.proxy_object);
     }
-  else 
+  else
     {
       PyErr_Clear();
       result = default_repr(self->proxy.proxy_object);
@@ -504,7 +504,7 @@ proxy_call(SecurityProxy *self, PyObject *args, PyObject *kwds)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check, str___call__) >= 0) 
+  if (check(self, str_check, str___call__) >= 0)
     {
       result = PyObject_Call(self->proxy.proxy_object, args, kwds);
       PROXY_RESULT(self, result);
@@ -558,7 +558,7 @@ proxy_pow(PyObject *self, PyObject *other, PyObject *modulus)
 {
   PyObject *result = NULL;
 
-  if (Proxy_Check(self)) 
+  if (Proxy_Check(self))
     {
       if (check((SecurityProxy*)self, str_check, str___pow__) >= 0)
         {
@@ -567,21 +567,21 @@ proxy_pow(PyObject *self, PyObject *other, PyObject *modulus)
           PROXY_RESULT(((SecurityProxy*)self), result);
         }
     }
-  else if (Proxy_Check(other)) 
+  else if (Proxy_Check(other))
     {
       if (check((SecurityProxy*)other, str_check, str___rpow__) >= 0)
-        {      
-          result = PyNumber_Power(self, 
-                                  ((SecurityProxy*)other)->proxy.proxy_object, 
+        {
+          result = PyNumber_Power(self,
+                                  ((SecurityProxy*)other)->proxy.proxy_object,
                                   modulus);
           PROXY_RESULT(((SecurityProxy*)other), result);
         }
     }
-  else if (modulus != NULL && Proxy_Check(modulus)) 
+  else if (modulus != NULL && Proxy_Check(modulus))
     {
       if (check((SecurityProxy*)modulus, str_check, str___3pow__) >= 0)
-        {      
-          result = PyNumber_Power(self, other, 
+        {
+          result = PyNumber_Power(self, other,
                                ((SecurityProxy*)modulus)->proxy.proxy_object);
           PROXY_RESULT(((SecurityProxy*)modulus), result);
         }
@@ -608,7 +608,7 @@ proxy_coerce(PyObject **p_self, PyObject **p_other)
 
   assert(Proxy_Check(self));
 
-  if (check((SecurityProxy*)self, str_check, str___coerce__) >= 0) 
+  if (check((SecurityProxy*)self, str_check, str___coerce__) >= 0)
     {
       PyObject *left = ((SecurityProxy*)self)->proxy.proxy_object;
       PyObject *right = other;
@@ -697,6 +697,21 @@ proxy_length(SecurityProxy *self)
   return -1;
 }
 
+static PyObject *
+proxy_length_hint(SecurityProxy *self)
+{
+  PyObject *result = NULL;
+  result = PyObject_CallMethod(self->proxy.proxy_object, "__length_hint__", NULL);
+  if (result == NULL) {
+      if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+            PyErr_Clear();
+            result = Py_NotImplemented;
+            Py_INCREF(result);
+      }
+  }
+  return result;
+}
+
 /* sq_item and sq_ass_item may be called by PySequece_{Get,Set}Item(). */
 static PyObject *proxy_getitem(SecurityProxy *, PyObject *);
 static int proxy_setitem(SecurityProxy *, PyObject *, PyObject *);
@@ -765,7 +780,7 @@ proxy_getitem(SecurityProxy *self, PyObject *key)
 {
   PyObject *result = NULL;
 
-  if (check(self, str_check, str___getitem__) >= 0) 
+  if (check(self, str_check, str___getitem__) >= 0)
     {
       result = PyObject_GetItem(self->proxy.proxy_object, key);
       PROXY_RESULT(self, result);
@@ -884,6 +899,13 @@ disallowed.  The proxy method should return a proxy for the object\n\
 if one is needed, otherwise the object itself.\n\
 ";
 
+static PyMethodDef proxy_methods[] = {
+    {"__length_hint__", (PyCFunction)proxy_length_hint, METH_NOARGS,
+     "Guess the length of the object"},
+    {NULL,              NULL}           /* sentinel */
+};
+
+
 static PyTypeObject SecurityProxyType = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zope.security._proxy._Proxy",
@@ -925,7 +947,7 @@ static PyTypeObject SecurityProxyType = {
     0,                                        /* tp_weaklistoffset */
     (getiterfunc)proxy_iter,                  /* tp_iter */
     (iternextfunc)proxy_iternext,             /* tp_iternext */
-    0,                                        /* tp_methods */
+    proxy_methods,                            /* tp_methods */
     0,                                        /* tp_members */
     0,                                        /* tp_getset */
     0,                                        /* tp_base */
@@ -963,7 +985,7 @@ module_getObject(PyObject *self, PyObject *arg)
     result = arg;
   else
     result = ((SecurityProxy*)arg)->proxy.proxy_object;
-  
+
   Py_INCREF(result);
   return result;
 }
@@ -974,7 +996,7 @@ module___doc__[] = "Security proxy implementation.";
 static PyMethodDef
 module_functions[] = {
   {"getChecker", module_getChecker, METH_O, "get checker from proxy"},
-  {"getObject", module_getObject, METH_O, 
+  {"getObject", module_getObject, METH_O,
    "Get the proxied object\n\nReturn the original object if not proxied."},
   {NULL}
 };
@@ -1069,19 +1091,19 @@ if((str_op_##S = INTERN("__" #S "__")) == NULL) return MOD_ERROR_VAL
   INIT_STRING(__setitem__);
   INIT_STRING(__setslice__);
   INIT_STRING(__str__);
-  
+
 
   __class__str = FROM_STRING("__class__");
   if (! __class__str)
      return MOD_ERROR_VAL;
-  
+
   __name__str = FROM_STRING("__name__");
   if (! __name__str)
     return MOD_ERROR_VAL;
-  
+
   __module__str = FROM_STRING("__module__");
   if (! __module__str) return MOD_ERROR_VAL;
-  
+
   SecurityProxyType.tp_alloc = PyType_GenericAlloc;
   SecurityProxyType.tp_free = PyObject_GC_Del;
   SecurityProxyType.tp_base = &ProxyType;
diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py
index 344428c..f870a13 100644
--- a/src/zope/security/checker.py
+++ b/src/zope/security/checker.py
@@ -604,7 +604,8 @@ _typeChecker = NamesChecker(
      '__implemented__'])
 _namedChecker = NamesChecker(['__name__'])
 
-_iteratorChecker = NamesChecker(['next', '__next__', '__iter__', '__len__'])
+_iteratorChecker = NamesChecker(['next', '__next__', '__iter__', '__len__',
+                                 '__length_hint__',])
 
 _setChecker = NamesChecker(['__iter__', '__len__', '__str__', '__contains__',
                             'copy', 'difference', 'intersection', 'issubset',
@@ -823,6 +824,42 @@ else:
 
 del _fixup_dictlike
 
+def _fixup_zope_interface():
+    # Make sure the provided and implementedBy objects
+    # can be iterated.
+    # Note that we DO NOT use the _iteratorChecker, but instead
+    # 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.
+    from zope.interface import providedBy
+    from zope.interface import alsoProvides
+
+    class I1(Interface):
+        pass
+
+    class I2(Interface):
+        pass
+
+    @implementer(I1)
+    class O(object):
+        pass
+
+    o = O()
+
+
+    # This will be athe zope.interface.implementedBy from the class
+    # a zope.interface.declarations.Implements
+    _default_checkers[type(providedBy(o))] = NoProxy
+
+    alsoProvides(o, I2)
+    # This will be the zope.interface.Provides from the instance
+    _default_checkers[type(providedBy(o))] = NoProxy
+
+_fixup_zope_interface()
+del _fixup_zope_interface
+
+
 def _clear():
     _checkers.clear()
     _checkers.update(_default_checkers)
diff --git a/src/zope/security/proxy.py b/src/zope/security/proxy.py
index d7f12e2..77a82d4 100644
--- a/src/zope/security/proxy.py
+++ b/src/zope/security/proxy.py
@@ -199,6 +199,11 @@ class ProxyPy(PyProxyBase):
         return bool(wrapped)
     __bool__ = __nonzero__
 
+    def __length_hint__(self):
+        # no check
+        wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')
+        return wrapped.__length_hint__()
+
     def __coerce__(self, other):
         # For some reason _check_name does not work for coerce()
         wrapped = super(PyProxyBase, self).__getattribute__('_wrapped')

Proxied zope.interface.Provides and implementedBy can't be put in a list in Python 3 but can in Py2
This is similar to #23 and #20, except with `__len__`, not `__iter__`. And it only happens in Python 3.

When you write `list(thing)` in CPython 3, CPython will look for the `__len__` slot in the C struct for the object's type. If that's filled in, and calling it raises any exception besides a `TypeError`, that exception is propageted. This is implemented in `Objects/abstract.c:PyObject_LengthHint`. This is defined in [PEP 424](https://www.python.org/dev/peps/pep-0424/) and implemented in Python 3.4.

In Python 2.7 and earlier, there is a private CPython function `_PyObject_LengthHint` that ignores both `TypeError` and `AttributeError` when it tries to get the `__len__`. zope.security's `ForbiddenAttribute` exception derives from `AttributeError` and so is ignored for this purpose.

Here's sample code:

```python
from zope.security.proxy import Proxy
from zope.security.checker import Checker
from zope.security.checker import CheckerPublic

from zope.interface import providedBy
from zope.interface import alsoProvides
from zope.interface import implementer
from zope.interface import Interface

class I1(Interface):
	pass

class I2(Interface):
	pass

@implementer(I1)
class O(object):
	pass

o = O()
# alsoProvides(o, I2)

checker = Checker({})

proxy = Proxy(o, checker)

list(providedBy(proxy))
```

Under Python 3.4+ this raises (PURE_PYTHON used for a slightly more clear stack trace; the same thing happens with all the C extensions in place):
```
PURE_PYTHON=1 python /tmp/test.py
Traceback (most recent call last):
  File "/tmp/test.py", line 22, in <module>
    list(providedBy(proxy))
  File "//lib/python3.5/site-packages/zope/security/proxy.py", line 28, in _wrapper
    checker.check(wrapped, name)
  File "//lib/python3.5/site-packages/zope/security/checker.py", line 229, in check
    raise ForbiddenAttribute(name, object)
zope.security.interfaces.ForbiddenAttribute: ('__len__', <implementedBy __main__.O>)
```

If you uncomment the `alsoProvides` line, you get a similar but different exception:
```
Traceback (most recent call last):
  File "/tmp/test.py", line 27, in <module>
    list(providedBy(proxy))
  File "//lib/python3.5/site-packages/zope/security/proxy.py", line 28, in _wrapper
    checker.check(wrapped, name)
  File "//lib/python3.5/site-packages/zope/security/checker.py", line 229, in check
    raise ForbiddenAttribute(name, object)
zope.security.interfaces.ForbiddenAttribute: ('__len__', <zope.interface.Provides object at 0x1060f2048>)
```

**Under Python 2.7, these both run just fine.**

How should we address this discrepancy (assuming we should)? 

* Should we keep playing whack-a-mole and add those two types of objects to the set for which `_iteratorChecker` is used by default? 
* Or should we alter the `Checker` implementation to ignore requests for `__len__`, as it already does for `__iter__`? 
* Or maybe these two types of objects (the attributes) shouldn't be wrapped in proxies at all? (I don't think we trivially have that capability.)
* Other options?

If we do anything, we should probably also adapt the same solution for the other half of PEP424 and do the same thing for the `__length_hint__` method.

I ran into this considering a potential efficiency change in `zope.app.apidoc`.
diff --git a/src/zope/security/tests/test_checker.py b/src/zope/security/tests/test_checker.py
index 03a8883..b82799f 100644
--- a/src/zope/security/tests/test_checker.py
+++ b/src/zope/security/tests/test_checker.py
@@ -434,6 +434,125 @@ class CheckerTestsBase(object):
         # iteration of regular dict is allowed by default
         self._check_iteration_of_dict_like(dict())
 
+    def test_iteration_of_interface_implementedBy(self):
+        # Iteration of implementedBy is allowed by default
+        # See https://github.com/zopefoundation/zope.security/issues/27
+        from zope.security.proxy import Proxy
+        from zope.security.checker import Checker
+
+        from zope.interface import providedBy
+        from zope.interface import implementer
+        from zope.interface import Interface
+
+        class I1(Interface):
+            pass
+
+        @implementer(I1)
+        class O(object):
+            pass
+
+        o = O()
+
+        checker = Checker({})
+
+        proxy = Proxy(o, checker)
+
+        # Since the object itself doesn't have any interfaces,
+        # the providedBy will return the implementedBy of the class
+        l = list(providedBy(proxy))
+
+        self.assertEqual(l, [I1])
+
+    def test_iteration_of_interface_providesBy(self):
+        # Iteration of zope.interface.Provides is allowed by default
+        # See https://github.com/zopefoundation/zope.security/issues/27
+        from zope.security.proxy import Proxy
+        from zope.security.checker import Checker
+
+        from zope.interface import providedBy
+        from zope.interface import alsoProvides
+        from zope.interface import implementer
+        from zope.interface import Interface
+
+        class I1(Interface):
+            pass
+
+        class I2(Interface):
+            pass
+
+        @implementer(I1)
+        class O(object):
+            pass
+
+        o = O()
+        alsoProvides(o, I2)
+
+        checker = Checker({})
+
+        proxy = Proxy(o, checker)
+
+        # Since the object has its own interfaces, provided
+        # by will return a zope.interface.Provides object
+        l = list(providedBy(proxy))
+
+        self.assertEqual(l, [I2, I1])
+
+    def test_iteration_with_length_hint(self):
+        # PEP 424 implemented officially in Python 3.4 and
+        # unofficially before in cPython and PyPy that allows for a
+        # __length_hint__ method to be defined on iterators. It should
+        # be allowed by default. See
+        # https://github.com/zopefoundation/zope.security/issues/27
+        from zope.security.proxy import Proxy
+        from zope.security.checker import _iteratorChecker
+        from zope.security.checker import Checker
+
+        class Iter(object):
+            __Security_checker__ = _iteratorChecker
+
+            items = (0, 1, 2)
+            index = 0
+            hint = len(items)
+            hint_called = False
+
+            def __iter__(self):
+                return self
+
+            def __next__(self):
+                try:
+                    return self.items[self.index]
+                except IndexError:
+                    raise StopIteration()
+                finally:
+                    self.index += 1
+
+            next = __next__
+
+            def __length_hint__(self):
+                self.hint_called = True
+                return self.hint
+
+        # The hint is called on raw objects
+        i = Iter()
+        list(i)
+        self.assertTrue(i.hint_called, "__length_hint__ should be called")
+
+        # 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.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.assertTrue(i.hint_called, "__length_hint__ should be called")
+
+
 class CheckerPyTests(unittest.TestCase, CheckerTestsBase):
 
     def _getTargetClass(self):

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest coverage
apt-get update apt-get install -y gcc
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
coverage==6.2
importlib-metadata==4.8.3
iniconfig==1.1.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0
zope.component==5.1.0
zope.event==4.6
zope.hookable==5.4
zope.i18nmessageid==5.1.1
zope.interface==5.5.2
zope.location==4.3
zope.proxy==4.6.1
zope.schema==6.2.1
-e git+https://github.com/zopefoundation/zope.security.git@4e08d85f4ad2d9fb1f1acbe1fad004c81b6d33c0#egg=zope.security

name: zope.security
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - coverage==6.2
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
      - zope-component==5.1.0
      - zope-event==4.6
      - zope-hookable==5.4
      - zope-i18nmessageid==5.1.1
      - zope-interface==5.5.2
      - zope-location==4.3
      - zope-proxy==4.6.1
      - zope-schema==6.2.1
prefix: /opt/conda/envs/zope.security

src/zope/security/tests/test_checker.py::CheckerPyTests::test_iteration_of_interface_implementedBy src/zope/security/tests/test_checker.py::CheckerPyTests::test_iteration_of_interface_providesBy src/zope/security/tests/test_checker.py::CheckerTests::test_iteration_of_interface_implementedBy src/zope/security/tests/test_checker.py::CheckerTests::test_iteration_of_interface_providesBy
src/zope/security/tests/test_checker.py::CheckerPyTests::test_iteration_with_length_hint src/zope/security/tests/test_checker.py::CheckerTests::test_iteration_with_length_hint src/zope/security/tests/test_checker.py::Test_defineChecker::test_w_duplicate src/zope/security/tests/test_checker.py::Test::testMultiChecker
src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_no_checker_no_dunder_no_select src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_no_checker_no_dunder_w_select src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_no_checker_w_dunder src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_w_already_proxied_different_checker src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_w_already_proxied_no_checker src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_w_already_proxied_same_checker src/zope/security/tests/test_checker.py::Test_ProxyFactory::test_w_explicit_checker src/zope/security/tests/test_checker.py::Test_canWrite::test_ok src/zope/security/tests/test_checker.py::Test_canWrite::test_w_setattr_forbidden_getattr_allowed src/zope/security/tests/test_checker.py::Test_canWrite::test_w_setattr_forbidden_getattr_forbidden src/zope/security/tests/test_checker.py::Test_canWrite::test_w_setattr_forbidden_getattr_unauth src/zope/security/tests/test_checker.py::Test_canWrite::test_w_setattr_unauth src/zope/security/tests/test_checker.py::Test_canAccess::test_ok src/zope/security/tests/test_checker.py::Test_canAccess::test_w_getattr_unauth src/zope/security/tests/test_checker.py::Test_canAccess::test_w_setattr_forbidden_getattr_allowed src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_available_by_default src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_miss src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_non_public_w_interaction_allows src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_non_public_w_interaction_denies src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_public src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_setattr_miss src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_setattr_miss_none_set src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_setattr_public src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_setattr_w_interaction_allows src/zope/security/tests/test_checker.py::CheckerPyTests::test_check_setattr_w_interaction_denies src/zope/security/tests/test_checker.py::CheckerPyTests::test_class_conforms_to_IChecker src/zope/security/tests/test_checker.py::CheckerPyTests::test_ctor_w_non_dict_get_permissions src/zope/security/tests/test_checker.py::CheckerPyTests::test_ctor_w_non_dict_set_permissions src/zope/security/tests/test_checker.py::CheckerPyTests::test_instance_conforms_to_IChecker src/zope/security/tests/test_checker.py::CheckerPyTests::test_iteration_of_dict_items_keys_values src/zope/security/tests/test_checker.py::CheckerPyTests::test_iteration_of_odict_items_keys_values src/zope/security/tests/test_checker.py::CheckerPyTests::test_permission_id_hit src/zope/security/tests/test_checker.py::CheckerPyTests::test_permission_id_miss src/zope/security/tests/test_checker.py::CheckerPyTests::test_proxy_already_proxied src/zope/security/tests/test_checker.py::CheckerPyTests::test_proxy_no_checker_no_dunder_w_select src/zope/security/tests/test_checker.py::CheckerPyTests::test_proxy_no_checker_w_dunder src/zope/security/tests/test_checker.py::CheckerPyTests::test_proxy_no_dunder_no_select src/zope/security/tests/test_checker.py::CheckerPyTests::test_setattr_permission_id_hit src/zope/security/tests/test_checker.py::CheckerPyTests::test_setattr_permission_id_miss src/zope/security/tests/test_checker.py::CheckerPyTests::test_setattr_permission_id_miss_none_set src/zope/security/tests/test_checker.py::CheckerTests::test_check_available_by_default src/zope/security/tests/test_checker.py::CheckerTests::test_check_miss src/zope/security/tests/test_checker.py::CheckerTests::test_check_non_public_w_interaction_allows src/zope/security/tests/test_checker.py::CheckerTests::test_check_non_public_w_interaction_denies src/zope/security/tests/test_checker.py::CheckerTests::test_check_public src/zope/security/tests/test_checker.py::CheckerTests::test_check_setattr_miss src/zope/security/tests/test_checker.py::CheckerTests::test_check_setattr_miss_none_set src/zope/security/tests/test_checker.py::CheckerTests::test_check_setattr_public src/zope/security/tests/test_checker.py::CheckerTests::test_check_setattr_w_interaction_allows src/zope/security/tests/test_checker.py::CheckerTests::test_check_setattr_w_interaction_denies src/zope/security/tests/test_checker.py::CheckerTests::test_class_conforms_to_IChecker src/zope/security/tests/test_checker.py::CheckerTests::test_ctor_w_non_dict_get_permissions src/zope/security/tests/test_checker.py::CheckerTests::test_ctor_w_non_dict_set_permissions src/zope/security/tests/test_checker.py::CheckerTests::test_instance_conforms_to_IChecker src/zope/security/tests/test_checker.py::CheckerTests::test_iteration_of_dict_items_keys_values src/zope/security/tests/test_checker.py::CheckerTests::test_iteration_of_odict_items_keys_values src/zope/security/tests/test_checker.py::CheckerTests::test_permission_id_hit src/zope/security/tests/test_checker.py::CheckerTests::test_permission_id_miss src/zope/security/tests/test_checker.py::CheckerTests::test_proxy_already_proxied src/zope/security/tests/test_checker.py::CheckerTests::test_proxy_no_checker_no_dunder_w_select src/zope/security/tests/test_checker.py::CheckerTests::test_proxy_no_checker_w_dunder src/zope/security/tests/test_checker.py::CheckerTests::test_proxy_no_dunder_no_select src/zope/security/tests/test_checker.py::CheckerTests::test_setattr_permission_id_hit src/zope/security/tests/test_checker.py::CheckerTests::test_setattr_permission_id_miss src/zope/security/tests/test_checker.py::CheckerTests::test_setattr_permission_id_miss_none_set src/zope/security/tests/test_checker.py::TracebackSupplementTests::test_getInfo_builtin_types src/zope/security/tests/test_checker.py::TracebackSupplementTests::test_getInfo_newstyle_instance src/zope/security/tests/test_checker.py::GlobalTests::test___reduce__ src/zope/security/tests/test_checker.py::GlobalTests::test___repr__ src/zope/security/tests/test_checker.py::GlobalTests::test_ctor_name_and_module src/zope/security/tests/test_checker.py::Test_NamesChecker::test_empty_names_no_kw src/zope/security/tests/test_checker.py::Test_NamesChecker::test_w_names_no_kw src/zope/security/tests/test_checker.py::Test_NamesChecker::test_w_names_no_kw_explicit_permission src/zope/security/tests/test_checker.py::Test_NamesChecker::test_w_names_w_kw_no_clash src/zope/security/tests/test_checker.py::Test_NamesChecker::test_w_names_w_kw_w_clash src/zope/security/tests/test_checker.py::Test_InterfaceChecker::test_derived_iface src/zope/security/tests/test_checker.py::Test_InterfaceChecker::test_simple_iface_w_explicit_permission src/zope/security/tests/test_checker.py::Test_InterfaceChecker::test_simple_iface_w_kw src/zope/security/tests/test_checker.py::Test_InterfaceChecker::test_simple_iface_wo_kw src/zope/security/tests/test_checker.py::Test_InterfaceChecker::test_w_clash src/zope/security/tests/test_checker.py::Test_MultiChecker::test_empty src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_iface src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_mapping src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_names src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_names_and_iface src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_names_and_iface_clash src/zope/security/tests/test_checker.py::Test_MultiChecker::test_w_spec_as_names_and_mapping_clash src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_basic_types_NoProxy src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_checker_inst src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_factory_factory src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_factory_returning_NoProxy src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_factory_returning_None src/zope/security/tests/test_checker.py::Test_selectCheckerPy::test_w_factory_returning_checker src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_basic_types_NoProxy src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_checker_inst src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_factory_factory src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_factory_returning_NoProxy src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_factory_returning_None src/zope/security/tests/test_checker.py::Test_selectChecker::test_w_factory_returning_checker src/zope/security/tests/test_checker.py::Test_getCheckerForInstancesOf::test_hit src/zope/security/tests/test_checker.py::Test_getCheckerForInstancesOf::test_miss src/zope/security/tests/test_checker.py::Test_defineChecker::test_w_module src/zope/security/tests/test_checker.py::Test_defineChecker::test_w_newstyle_class src/zope/security/tests/test_checker.py::Test_defineChecker::test_w_wrong_type src/zope/security/tests/test_checker.py::Test_undefineChecker::test_hit src/zope/security/tests/test_checker.py::Test_undefineChecker::test_miss src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_forbidden_rhs_forbidden src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_forbidden_rhs_ok src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_forbidden_rhs_unauth src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_ok_rhs_not_called src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_unauth_rhs_forbidden src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_unauth_rhs_ok src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_lhs_unauth_rhs_unauth src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_forbidden_rhs_forbidden src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_forbidden_rhs_ok src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_forbidden_rhs_unauth src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_ok_rhs_not_called src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_unauth_rhs_forbidden src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_unauth_rhs_ok src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_check_setattr_lhs_unauth_rhs_unauth src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_class_conforms_to_IChecker src/zope/security/tests/test_checker.py::CombinedCheckerTests::test_instance_conforms_to_IChecker src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_forbidden_attribute src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_getattr_forbidden_attribute src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_getattr_ok_normal_verbosity src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_getattr_ok_raised_verbosity_available_by_default src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_getattr_ok_raised_verbosity_normal_name src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_getattr_unauthorized src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_ok_normal_verbosity src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_ok_raised_verbosity_available_by_default src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_ok_raised_verbosity_normal_name src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_setattr_forbidden_attribute src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_setattr_ok_normal_verbosity src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_setattr_ok_raised_verbosity_normal_name src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_setattr_unauthorized src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_setitem_unauthorized src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_unauthorized src/zope/security/tests/test_checker.py::CheckerLoggingMixinTests::test_check_unauthorized_raised_verbosity src/zope/security/tests/test_checker.py::Test__instanceChecker::test_hit src/zope/security/tests/test_checker.py::Test__instanceChecker::test_miss src/zope/security/tests/test_checker.py::Test_moduleChecker::test_hit src/zope/security/tests/test_checker.py::Test_moduleChecker::test_miss src/zope/security/tests/test_checker.py::BasicTypesTests::test___delitem__ src/zope/security/tests/test_checker.py::BasicTypesTests::test___setitem__ src/zope/security/tests/test_checker.py::BasicTypesTests::test_clear src/zope/security/tests/test_checker.py::BasicTypesTests::test_update src/zope/security/tests/test_checker.py::Test::testAlwaysAvailable src/zope/security/tests/test_checker.py::Test::testLayeredProxies src/zope/security/tests/test_checker.py::Test::test_ProxyFactory src/zope/security/tests/test_checker.py::Test::test_ProxyFactory_using_proxy src/zope/security/tests/test_checker.py::Test::test_canWrite_canAccess src/zope/security/tests/test_checker.py::Test::test_defineChecker_error src/zope/security/tests/test_checker.py::Test::test_defineChecker_module src/zope/security/tests/test_checker.py::Test::test_defineChecker_newstyle_class src/zope/security/tests/test_checker.py::Test::test_define_and_undefineChecker src/zope/security/tests/test_checker.py::Test::test_iteration src/zope/security/tests/test_checker.py::TestCheckerPublic::test_that_CheckerPublic_identity_works_even_when_proxied src/zope/security/tests/test_checker.py::TestCheckerPublic::test_that_pickling_CheckerPublic_retains_identity src/zope/security/tests/test_checker.py::TestCombinedChecker::test_checking src/zope/security/tests/test_checker.py::TestCombinedChecker::test_interface src/zope/security/tests/test_checker.py::TestBasicTypes::test src/zope/security/tests/test_checker.py::test_suite
src/zope/security/checker.py src/zope/security/proxy.py .travis.yml CHANGES.rst appveyor.yml src/zope/security/_proxy.c
src/zope/security/checker.py src/zope/security/proxy.py .travis.yml CHANGES.rst appveyor.yml src/zope/security/_proxy.c