[Checkins] SVN: grok/trunk/src/grok/publication.py Added module and class docstrings to publication.py.

Brandon Rhodes brandon at rhodesmill.org
Sat Dec 13 08:33:28 EST 2008


Log message for revision 94015:
  Added module and class docstrings to publication.py.
  

Changed:
  U   grok/trunk/src/grok/publication.py

-=-
Modified: grok/trunk/src/grok/publication.py
===================================================================
--- grok/trunk/src/grok/publication.py	2008-12-13 11:13:37 UTC (rev 94014)
+++ grok/trunk/src/grok/publication.py	2008-12-13 13:33:27 UTC (rev 94015)
@@ -11,9 +11,18 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Grok publication objects
+"""Grok publication factories and classes.
+
+These factories, and the publication classes they return, make Grok
+security different from the way that security normal operates during
+Zope publication.  Instead of security proxies being wrapped around
+every object generated during traversal, and then wrapped around the
+final object before it is viewed, only a single security check is done
+when Grok is in charge: a check to see whether the view selected at the
+end of the traversal process is, in fact, permitted to display the
+object.
+
 """
-
 from grok.rest import GrokMethodNotAllowed
 
 from zope import component
@@ -33,7 +42,27 @@
 from grok.components import JSON
 
 class ZopePublicationSansProxy(object):
+    """Grok mixin that makes a publisher remove security proxies.
 
+    This mixin overrides three methods from the `IPublication` interface
+    (defined in `zope.publisher.interfaces`) to alter their security
+    behavior.  The normal Zope machinery wraps a security proxy around
+    the application object returned by `getApplication()`, and around
+    each of the objects returned as `traverseName()` is then called for
+    each URL component.  The versions here strip the security proxy off
+    instead, returning the bare object (unless the object is a non-Grok
+    view, in which case we leave the proxy installed for important
+    security reasons).  Finally, when `callObject()` is asked to render
+    the view, we quickly re-install a security proxy on the object, make
+    sure that the current user is indeed allowed to invoke `__call__()`,
+    then pass the bare object to the rendering machinery.
+
+    The result is that, in place of the elaborate series of security
+    checks made during the processing of a normal Zope request, Grok
+    makes only a single security check: to see if the view can be
+    permissibly rendered or not.
+
+    """
     def getApplication(self, request):
         result = super(ZopePublicationSansProxy, self).getApplication(request)
         return removeSecurityProxy(result)
@@ -58,45 +87,89 @@
 
 
 class GrokBrowserPublication(ZopePublicationSansProxy, BrowserPublication):
+    """Combines `BrowserPublication` with the Grok sans-proxy mixin.
 
+    In addition to the three methods that are overridden by the
+    `ZopePublicationSansProxy`, this class overrides a fourth: the
+    `getDefaultTraversal()` method, which strips the security proxy from
+    the object being returned by the normal method.
+
+    """
     def getDefaultTraversal(self, request, ob):
         obj, path = super(GrokBrowserPublication, self).getDefaultTraversal(
             request, ob)
         return removeSecurityProxy(obj), path
 
-
 class GrokBrowserFactory(BrowserFactory):
+    """Returns the classes Grok uses for browser requests and publication.
 
+    When an instance of this class is called, it returns a 2-element
+    tuple containing:
+
+    - The request class that Grok uses for browser requests.
+    - The publication class that Grok uses to publish to a browser.
+
+    """
     def __call__(self):
         request, publication = super(GrokBrowserFactory, self).__call__()
         return request, GrokBrowserPublication
 
 
 class GrokXMLRPCPublication(ZopePublicationSansProxy, BaseHTTPPublication):
-    pass
+    """Combines `BaseHTTPPublication` with the Grok sans-proxy mixin."""
 
 class GrokXMLRPCFactory(XMLRPCFactory):
+    """Returns the classes Grok uses for browser requests and publication.
 
+    When an instance of this class is called, it returns a 2-element
+    tuple containing:
+
+    - The request class that Grok uses for XML-RPC requests.
+    - The publication class that Grok uses to publish to a XML-RPC.
+
+    """
     def __call__(self):
         request, publication = super(GrokXMLRPCFactory, self).__call__()
         return request, GrokXMLRPCPublication
 
 
 class GrokHTTPPublication(ZopePublicationSansProxy, HTTPPublication):
-   def callObject(self, request, ob):
-       orig = ob
-       if not IHTTPException.providedBy(ob):
-           ob = component.queryMultiAdapter((ob, request),
+    """Combines `HTTPPublication` with the Grok sans-proxy mixin.
+
+    Because `HTTPPublication` provides its own, special `callObject()`
+    implementation, this subclass does the same, providing what is
+    basically the same call (you can verify, in fact, that most of its
+    lines were copied directly from the superclass's version) but with a
+    few extra lines added so that - as with the simpler `callObject()`
+    method in `ZopePublicationSansProxy` - it quickly places a security
+    proxy around the object, makes sure that this HTTP method is
+    permitted, and finally passes the bare object to the view that will
+    render it.
+
+    """
+    def callObject(self, request, ob):
+        orig = ob
+        if not IHTTPException.providedBy(ob):
+            ob = component.queryMultiAdapter((ob, request),
                                             name=request.method)
-           checker = selectChecker(ob)
-           if checker is not None:
-               checker.check(ob, '__call__')
-           ob = getattr(ob, request.method, None)
-           if ob is None:
-               raise GrokMethodNotAllowed(orig, request)
-       return mapply(ob, request.getPositionalArguments(), request)
+            checker = selectChecker(ob)
+            if checker is not None:
+                checker.check(ob, '__call__')
+            ob = getattr(ob, request.method, None)
+            if ob is None:
+                raise GrokMethodNotAllowed(orig, request)
+        return mapply(ob, request.getPositionalArguments(), request)
 
 class GrokHTTPFactory(HTTPFactory):
+    """Returns the classes Grok uses for HTTP requests and publication.
+
+    When an instance of this class is called, it returns a 2-element
+    tuple containing:
+
+    - The request class that Grok uses for HTTP requests.
+    - The publication class that Grok uses to publish to HTTP.
+
+    """
     def __call__(self):
         request, publication = super(GrokHTTPFactory, self).__call__()
         return request, GrokHTTPPublication



More information about the Checkins mailing list