[Zope3-checkins] SVN: Zope3/branches/jim-call-checkers/src/zope/ Implemented

Jim Fulton jim at zope.com
Fri Oct 7 16:31:21 EDT 2005


Log message for revision 38905:
  Implemented 
  http://dev.zope.org/Zope3/SecurityCheckersBecomeSecurityProxyFactories
  in Python version.
  

Changed:
  U   Zope3/branches/jim-call-checkers/src/zope/app/decorator.py
  U   Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_field.py
  U   Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_schemautility.py
  U   Zope3/branches/jim-call-checkers/src/zope/security/checker.py
  U   Zope3/branches/jim-call-checkers/src/zope/security/tests/test_checker.py
  U   Zope3/branches/jim-call-checkers/src/zope/security/tests/test_proxy.py

-=-
Modified: Zope3/branches/jim-call-checkers/src/zope/app/decorator.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/app/decorator.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/app/decorator.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -19,7 +19,8 @@
 $Id$
 """
 from zope.proxy import getProxiedObject, ProxyBase
-from zope.security.checker import selectChecker, CombinedChecker
+from zope.security.checker import selectChecker, CombinedChecker, queryChecker
+from zope.security.checker import defaultChecker
 from zope.security.proxy import Proxy, getChecker
 from zope.interface.declarations import ObjectSpecificationDescriptor
 from zope.interface.declarations import getObjectSpecification
@@ -169,11 +170,8 @@
 
     When the wrapper has a checker but the proxied object doesn't:
 
-      >>> from zope.security.checker import NoProxy, _checkers
-      >>> del _checkers[Foo]
-      >>> defineChecker(Foo, NoProxy)
-      >>> selectChecker(foo) is None
-      True
+      >>> from zope.security.checker import undefineChecker
+      >>> undefineChecker(Foo)
       >>> selectChecker(wrapper) is wrapperChecker
       True
 
@@ -185,14 +183,8 @@
 
     When the proxied object has a checker but the wrapper doesn't:
 
-      >>> del _checkers[Wrapper]
-      >>> defineChecker(Wrapper, NoProxy)
-      >>> selectChecker(wrapper) is None
-      True
-      >>> del _checkers[Foo]
+      >>> undefineChecker(Wrapper)
       >>> defineChecker(Foo, fooChecker)
-      >>> selectChecker(foo) is fooChecker
-      True
 
     the decorator uses only the proxied object checker:
 
@@ -201,12 +193,7 @@
 
     Finally, if neither the wrapper not the proxied have checkers:
 
-      >>> del _checkers[Foo]
-      >>> defineChecker(Foo, NoProxy)
-      >>> selectChecker(foo) is None
-      True
-      >>> selectChecker(wrapper) is None
-      True
+      >>> undefineChecker(Foo)
 
     the decorator doesn't have a checker:
 
@@ -219,14 +206,14 @@
             return self
         else:
             proxied_object = getProxiedObject(inst)
-            if type(proxied_object) is Proxy:
+            if isinstance(proxied_object, Proxy):
                 checker = getChecker(proxied_object)
             else:
-                checker = getattr(proxied_object, '__Security_checker__', None)
-                if checker is None:
-                    checker = selectChecker(proxied_object)
+                checker = queryChecker(proxied_object)
+
             wrapper_checker = selectChecker(inst)
-            if wrapper_checker is None:
+            if wrapper_checker is defaultChecker:
+                # optimization
                 return checker
             elif checker is None:
                 return wrapper_checker

Modified: Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_field.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_field.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_field.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -25,7 +25,7 @@
 from zope.security.management import system_user, newInteraction
 from zope.app.testing import setup
 from zope.app.schema.wrapper import Struct
-from zope.security.checker import getChecker, _defaultChecker
+from zope.security.checker import getChecker, defaultChecker
 import zope.app.schema.tests
 
 
@@ -62,8 +62,8 @@
         f2 = Struct(f2)
         f2 = ProxyFactory(f2)
         self.assertEquals(getChecker(f1), getChecker(f2))
-        self.failIf(getChecker(f1) is _defaultChecker)
-        self.failIf(getChecker(f2) is _defaultChecker)
+        self.failIf(getChecker(f1) is defaultChecker)
+        self.failIf(getChecker(f2) is defaultChecker)
 
     def tearDown(self):
         setup.placefulTearDown()

Modified: Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_schemautility.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_schemautility.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/app/schema/tests/test_schemautility.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -19,7 +19,7 @@
 
 from zope.configuration import xmlconfig
 from zope.schema import Text, getFieldNamesInOrder, getFieldsInOrder
-from zope.security.checker import getChecker, _defaultChecker, ProxyFactory
+from zope.security.checker import getChecker, ProxyFactory
 from zope.app.schema.schema import SchemaUtility
 from zope.app.testing import setup
 from zope.app import zapi

Modified: Zope3/branches/jim-call-checkers/src/zope/security/checker.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/security/checker.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/security/checker.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -73,18 +73,54 @@
             # can call ProxyFactory.
             raise TypeError("Tried to use ProxyFactory to change a Proxy's"
                             " checker.")
+        
     if checker is None:
         checker = getattr(object, '__Security_checker__', None)
 
         if checker is None:
             checker = selectChecker(object)
-            if checker is None:
-                return object
 
-    return Proxy(object, checker)
+    try:
+        return checker(object)
+    except TypeError:
+        import warnings
+        warnings.warn(
+            "Non-callable checkers like %s are deprecated and will not be"
+            " supported after 2006." % checker,
+            DeprecationWarning)
+        return Proxy(object, checker)
 
 directlyProvides(ProxyFactory, ISecurityProxyFactory)
 
+def queryChecker(ob, default=None):
+    """Determine the checker for an object
+
+    Return None if no checker is defined.
+
+    >>> class C(object):
+    ...     pass
+
+    >>> c = C()
+    >>> print queryChecker(c)
+    None
+
+    >>> checker1 = Checker({})
+    >>> defineChecker(C, checker1)
+    >>> queryChecker(c) is checker1
+    True
+    >>> checker2 = Checker({})
+    >>> c.__Security_checker__ = checker2
+    >>> queryChecker(c) is checker2
+    True
+    
+    """
+    checker = getattr(ob, '__Security_checker__', None)
+
+    if checker is None:
+        checker = _getChecker(type(ob), default)
+
+    return checker
+
 def canWrite(obj, name):
     """Check whether the interaction may write an attribute named name on obj.
 
@@ -199,13 +235,14 @@
         checker = getattr(value, '__Security_checker__', None)
         if checker is None:
             checker = selectChecker(value)
-            if checker is None:
-                return value
 
-        return Proxy(value, checker)
+        return checker(value)
 
+    def __call__(self, value):
+        return Proxy(value, self)
 
 
+
 # Helper class for __traceback_supplement__
 class TracebackSupplement(object):
 
@@ -335,28 +372,10 @@
     return value is None, then object should not be wrapped in a proxy.
     """
 
-    # We need to be careful here. We might have a proxy, in which case
-    # we can't use the type.  OTOH, we might not be able to use the
-    # __class__ either, since not everything has one.
+    checker = _getChecker(type(object), defaultChecker)
 
-    # TODO: we really need formal proxy introspection
-
-    #if type(object) is Proxy:
-    #    # Is this already a security proxy?
-    #    return None
-
-    checker = _getChecker(type(object), _defaultChecker)
-
-    #checker = _getChecker(getattr(object, '__class__', type(object)),
-    #                      _defaultChecker)
-
-    if checker is NoProxy:
-        return None
-
     while not isinstance(checker, Checker):
         checker = checker(object)
-        if checker is NoProxy or checker is None:
-            return None
 
     return checker
 
@@ -376,8 +395,43 @@
         raise DuplicationError(type_)
     _checkers[type_] = checker
 
-NoProxy = object()
+def undefineChecker(type_):
+    """Undefine a checker for a given type of object
 
+    >>> class C(object):
+    ...     pass
+
+    >>> c = C()
+    >>> print queryChecker(c)
+    None
+
+    >>> checker1 = Checker({})
+    >>> defineChecker(C, checker1)
+    >>> queryChecker(c) is checker1
+    True
+
+    >>> undefineChecker(C)
+    >>> print queryChecker(c)
+    None
+
+    
+    """
+    if not isinstance(type_, (type, types.ClassType, types.ModuleType)):
+        raise TypeError(
+                'type_ must be a type, class or module, not a %s' % type_)
+    del _checkers[type_]
+
+
+class NoProxyChecker(Checker):
+
+    def check(self, object, name):
+        pass
+
+    def __call__(self, object):
+        return object
+
+NoProxy = NoProxyChecker({})
+
 # _checkers is a mapping.
 #
 #  - Keys are types
@@ -390,7 +444,8 @@
 #
 _checkers = {}
 
-_defaultChecker = Checker({})
+defaultChecker = Checker({})
+
 _available_by_default = []
 
 # Get optimized versions
@@ -401,7 +456,7 @@
 else:
     from zope.security._zope_security_checker import _checkers, selectChecker
     from zope.security._zope_security_checker import NoProxy, Checker
-    from zope.security._zope_security_checker import _defaultChecker
+    from zope.security._zope_security_checker import defaultChecker
     from zope.security._zope_security_checker import _available_by_default
     zope.interface.classImplements(Checker, INameBasedChecker)
 
@@ -463,8 +518,10 @@
     Prints verbose debugging information about every performed check to
     sys.stderr.
 
-    If verbosity is set to 1, only displays Unauthorized and Forbidden messages.
-    If verbosity is set to a larger number, displays all messages.
+    If verbosity is set to 1, only displays Unauthorized and Forbidden
+    messages.  If verbosity is set to a larger number, displays all
+    messages.
+
     """
 
     verbosity = 1
@@ -532,7 +589,7 @@
         verbosity = WATCH_CHECKERS
 
 def _instanceChecker(inst):
-    return _checkers.get(inst.__class__, _defaultChecker)
+    return _checkers.get(inst.__class__, defaultChecker)
 
 def moduleChecker(module):
     return _checkers.get(module)
@@ -605,7 +662,7 @@
     _implied=CheckerPublic,
     subscribe=CheckerPublic)
 
-def f():
+def generator_sample():
     yield f
 
 
@@ -642,7 +699,7 @@
     type({}.iterkeys()): _iteratorChecker,
     type({}.itervalues()): _iteratorChecker,
     type(iter(_Sequence())): _iteratorChecker,
-    type(f()): _iteratorChecker,
+    type(generator_sample()): _iteratorChecker,
     type(Interface): InterfaceChecker(
         IInterface,
         __str__=CheckerPublic, _implied=CheckerPublic, subscribe=CheckerPublic,

Modified: Zope3/branches/jim-call-checkers/src/zope/security/tests/test_checker.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/security/tests/test_checker.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/security/tests/test_checker.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -32,6 +32,7 @@
 from zope.security.checker import canWrite, canAccess
 from zope.security.proxy import Proxy
 import types, pickle
+from zope.testing import doctest
 
 class SecurityPolicy(object):
     implements(ISecurityPolicy)
@@ -349,8 +350,8 @@
 
         proxy = ProxyFactory(obj)
         self.assert_(type(proxy) is Proxy)
-        from zope.security.checker import _defaultChecker
-        self.assert_(getChecker(proxy) is _defaultChecker)
+        from zope.security.checker import defaultChecker
+        self.assert_(getChecker(proxy) is defaultChecker)
 
         defineChecker(SomeClass, checker)
 
@@ -544,6 +545,7 @@
         makeSuite(Test),
         makeSuite(TestCheckerPublic),
         makeSuite(TestCombinedChecker),
+        doctest.DocTestSuite('zope.security.checker')
         ))
 
 if __name__=='__main__':

Modified: Zope3/branches/jim-call-checkers/src/zope/security/tests/test_proxy.py
===================================================================
--- Zope3/branches/jim-call-checkers/src/zope/security/tests/test_proxy.py	2005-10-07 17:23:21 UTC (rev 38904)
+++ Zope3/branches/jim-call-checkers/src/zope/security/tests/test_proxy.py	2005-10-07 20:31:20 UTC (rev 38905)
@@ -18,6 +18,7 @@
 
 import unittest
 from zope.security.proxy import getChecker, ProxyFactory, removeSecurityProxy
+from zope.security.proxy import Proxy
 from zope.proxy import ProxyBase as proxy
 
 class Checker(object):
@@ -43,7 +44,11 @@
             return value
         return ProxyFactory(value, self)
 
+    def __call__(self, value):
+        return Proxy(value, self)
+        
 
+
 class Something:
     def __init__(self):
         self.foo = [1,2,3]
@@ -388,6 +393,9 @@
       ...         print 'check_getattr', name
       ...     def proxy(self, object):
       ...         return 1
+      ...     def __call__(self, object):
+      ...         return Proxy(object, self)
+      
       >>> def f():
       ...     pass
       >>> p = ProxyFactory(f, Checker())



More information about the Zope3-Checkins mailing list