[Checkins] SVN: grokcore.rest/trunk/src/grokcore/rest/ checkpoint

Christian Klinger cklinger at novareto.de
Thu Dec 16 05:00:39 EST 2010


Log message for revision 118958:
  checkpoint

Changed:
  U   grokcore.rest/trunk/src/grokcore/rest/configure.zcml
  U   grokcore.rest/trunk/src/grokcore/rest/ftesting.zcml
  U   grokcore.rest/trunk/src/grokcore/rest/ftests/rest/rest.py
  U   grokcore.rest/trunk/src/grokcore/rest/ftests/test_grok_functional.py
  U   grokcore.rest/trunk/src/grokcore/rest/publication.py
  D   grokcore.rest/trunk/src/grokcore/rest/tests/

-=-
Modified: grokcore.rest/trunk/src/grokcore/rest/configure.zcml
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/configure.zcml	2010-12-16 09:58:13 UTC (rev 118957)
+++ grokcore.rest/trunk/src/grokcore/rest/configure.zcml	2010-12-16 10:00:39 UTC (rev 118958)
@@ -12,19 +12,15 @@
       provides="zope.traversing.interfaces.ITraversable"
       name="rest"
       />
-  <!-- this overrides Zope 3's publication factories because they have
-       the same name; we also need to change the priority because of
-       the ZCML discriminator -->
-<!--
+
   <publisher
-      name="BROWSER"
-      factory=".publication.GrokBrowserFactory"
-      methods="GET POST HEAD"
+      name="HTTP"
+      factory=".publication.GrokHTTPFactory"
+      methods="*"
       mimetypes="*"
-      priority="11"
+      priority="1"
       />
--->
-  <!-- need to grok this for some basic REST support -->
+
   <grok:grok package=".rest" />
 
 </configure>

Modified: grokcore.rest/trunk/src/grokcore/rest/ftesting.zcml
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/ftesting.zcml	2010-12-16 09:58:13 UTC (rev 118957)
+++ grokcore.rest/trunk/src/grokcore/rest/ftesting.zcml	2010-12-16 10:00:39 UTC (rev 118958)
@@ -12,15 +12,9 @@
    <include package="grokcore.view" file="publication_security.zcml" />
    <include package="grokcore.rest" />
 
+   <include package="zope.app.http.exception" />
 
-  <browser:defaultView name="index.html" />
-
-<!--
-   <browser:defaultView
-       for="grokcore.content.IContext"
-       name="index"
-       />
--->
-
+   <browser:defaultView name="index.html" />
    <grok:grok package=".ftests" />
+
 </configure>

Modified: grokcore.rest/trunk/src/grokcore/rest/ftests/rest/rest.py
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/ftests/rest/rest.py	2010-12-16 09:58:13 UTC (rev 118957)
+++ grokcore.rest/trunk/src/grokcore/rest/ftests/rest/rest.py	2010-12-16 10:00:39 UTC (rev 118958)
@@ -1,6 +1,16 @@
 """
 Let's examine Grok's REST support.
 
+  >>> from zope.publisher.browser import TestRequest
+  >>> from zope.component import getMultiAdapter
+  >>> from grokcore.rest.rest import GrokMethodNotAllowed
+
+  >>> erview = getMultiAdapter((GrokMethodNotAllowed(None, None), 
+  ...      TestRequest()), name="index.html")
+
+  >>> erview
+  <grokcore.rest.rest.MethodNotAllowedView object at 0...>
+
 Let's create a simple application with REST support::
 
   >>> from grokcore.rest.ftests.rest.rest import MyApp
@@ -52,7 +62,7 @@
   >>> response = http_call('POST', 'http://localhost/++rest++b/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...>,
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...>,
   <zope.publisher.browser.BrowserRequest instance URL=http://localhost/++rest++b/app>
 
 DELETE is also not defined, so we also expect a 405 error::
@@ -60,7 +70,7 @@
   >>> response = http_call('DELETE', 'http://localhost/++rest++b/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...>,
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...>,
   <zope.publisher.http.HTTPRequest instance URL=http://localhost/++rest++b/app>
 
 Let's examine protocol c where no method is allowed::
@@ -68,38 +78,38 @@
   >>> response = http_call('GET', 'http://localhost/++rest++c/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('POST', 'http://localhost/++rest++c/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('PUT', 'http://localhost/++rest++c/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('DELETE', 'http://localhost/++rest++c/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
 
 Let's examine the default protocol d, where nothing should work as well::
 
   >>> response = http_call('GET', 'http://localhost/++rest++d/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('POST', 'http://localhost/++rest++d/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('PUT', 'http://localhost/++rest++d/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
   >>> response = http_call('DELETE', 'http://localhost/++rest++d/app')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyApp object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyApp object at ...
 
 We have added support for GET for the ``alpha`` subobject only, in
 the default rest layer::
@@ -113,7 +123,7 @@
   >>> response = http_call('POST', 'http://localhost/++rest++d/app/alpha')
   Traceback (most recent call last):
     ...
-  GrokMethodNotAllowed: <grok.ftests.rest.rest.MyContent object at ...
+  GrokMethodNotAllowed: <grokcore.rest.ftests.rest.rest.MyContent object at ...
 
 According to the HTTP spec, in case of a 405 Method Not Allowed error,
 the response MUST include an Allow header containing a list of valid

Modified: grokcore.rest/trunk/src/grokcore/rest/ftests/test_grok_functional.py
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/ftests/test_grok_functional.py	2010-12-16 09:58:13 UTC (rev 118957)
+++ grokcore.rest/trunk/src/grokcore/rest/ftests/test_grok_functional.py	2010-12-16 10:00:39 UTC (rev 118958)
@@ -30,7 +30,7 @@
     if data is not None:
         request_string += '\r\n'
         request_string += data
-    return http(request_string, handle_errors=True)
+    return http(request_string, handle_errors=False)
 
 def suiteFromPackage(name):
     files = resource_listdir(__name__, name)

Modified: grokcore.rest/trunk/src/grokcore/rest/publication.py
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/publication.py	2010-12-16 09:58:13 UTC (rev 118957)
+++ grokcore.rest/trunk/src/grokcore/rest/publication.py	2010-12-16 10:00:39 UTC (rev 118958)
@@ -40,32 +40,44 @@
     BrowserFactory, HTTPFactory)
 
 
+class GrokHTTPPublication(ZopePublicationSansProxy, HTTPPublication):
+    """Combines `HTTPPublication` with the Grok sans-proxy mixin.
 
-class GrokBrowserPublication(ZopePublicationSansProxy, BrowserPublication):
-    """Combines `BrowserPublication` 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.
 
-    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
+    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)
 
 
-class GrokBrowserFactory(BrowserFactory):
-    """Returns the classes Grok uses for browser requests and publication.
+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 browser requests.
-    - The publication class that Grok uses to publish to a browser.
+    - 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(GrokBrowserFactory, self).__call__()
-        return request, GrokBrowserPublication
+        request, publication = super(GrokHTTPFactory, self).__call__()
+        return request, GrokHTTPPublication



More information about the checkins mailing list