------------------------------------------------------------
revno: 6720
committer: Barry Warsaw <[email protected]>
branch nick: restful
timestamp: Sat 2009-05-02 18:07:38 -0400
message:
  Moving closer now.
  
  * Use the source version of lazr.restful until it's cheeseshopped.
  * IHasGet -> IResolvePathNames
  * path_override -> None; we don't need this
  * Simplify publication.  We don't need anything fancy, except that what sucks
    is that it seems like we need to unwrap the security proxy in callObject()
  * Adaptation to IAbsoluteURL still doesn't work right.
added:
  src/mailman/rest/urls.py
  src/mailman/rest/webservice.py
modified:
  buildout.cfg
  src/mailman/interfaces/rest.py
  src/mailman/rest/configuration.py
  src/mailman/rest/configure.zcml
  src/mailman/rest/publication.py
  src/mailman/rest/root.py
  src/mailman/rest/traverse.py

=== modified file 'buildout.cfg'
--- buildout.cfg        2009-04-02 20:19:00 +0000
+++ buildout.cfg        2009-05-02 22:07:38 +0000
@@ -4,7 +4,7 @@
     tags
     test
 unzip = true
-develop = .
+develop = . /Users/barry/projects/lazr/lazr.restful
 
 [interpreter]
 recipe = zc.recipe.egg

=== modified file 'src/mailman/interfaces/rest.py'
--- src/mailman/interfaces/rest.py      2009-04-02 00:02:49 +0000
+++ src/mailman/interfaces/rest.py      2009-05-02 22:07:38 +0000
@@ -21,7 +21,7 @@
 
 __metaclass__ = type
 __all__ = [
-    'IHasGet',
+    'IResolvePathNames',
     ]
 
 
@@ -29,8 +29,8 @@
 
 
 
-class IHasGet(Interface):
-    """A marker interface objects that implement traversal with get()."""
+class IResolvePathNames(Interface):
+    """A marker interface objects that implement simple traversal."""
 
     def get(name):
         """Traverse to a contained object."""

=== modified file 'src/mailman/rest/configuration.py'
--- src/mailman/rest/configuration.py   2009-04-02 20:44:25 +0000
+++ src/mailman/rest/configuration.py   2009-05-02 22:07:38 +0000
@@ -26,11 +26,12 @@
 
 
 from lazr.restful.interfaces import IWebServiceConfiguration
+from zope.interface import implements
 
+from mailman import version
 from mailman.config import config
 from mailman.rest.publication import AdminWebServicePublication
 from mailman.rest.root import AdminWebServiceRootResource
-from mailman.version import VERSION
 
 
 
@@ -43,7 +44,7 @@
     def view_permission(self):
         return config.webservice.view_permission
 
-    path_override = 'admin'
+    path_override = None
 
     @property
     def use_https(self):
@@ -51,8 +52,8 @@
         return config.webservice.use_https
 
     # This should match the major.minor Mailman version.
-    service_version_uri_prefix = '3.0'
-    code_revision = VERSION
+    service_version_uri_prefix = '{0.MAJOR_REV}.{0.MINOR_REV}'.format(version)
+    code_revision = version.VERSION
 
     @property
     def show_tracebacks(self):

=== modified file 'src/mailman/rest/configure.zcml'
--- src/mailman/rest/configure.zcml     2009-04-02 20:44:25 +0000
+++ src/mailman/rest/configure.zcml     2009-05-02 22:07:38 +0000
@@ -6,16 +6,20 @@
   <include package="zope.component" file="meta.zcml"/>
   <include package="zope.security" file="meta.zcml"/>
   <include package="lazr.restful" file="meta.zcml"/>
-
-  <webservice:register module="mailman.interfaces.rest" />
-
-  <adapter factory="mailman.rest.traverse.Traverse" />
-
-  <adapter factory="mailman.rest.root.AdminWebServiceRootAbsoluteURL" />
+  <include package="lazr.restful" file="configure.zcml"/>
+
+  <webservice:register module="mailman.interfaces.system" />
+
+  <adapter factory="mailman.rest.urls.AbsoluteURLMapper" />
 
   <adapter
     factory="mailman.rest.root.AdminWebServiceRootAbsoluteURL"
     name="absolute_url"
     />
 
+  <utility
+    factory="mailman.rest.configuration.AdminWebServiceConfiguration"
+    provides="lazr.restful.interfaces.IWebServiceConfiguration">
+  </utility>
+
 </configure>

=== modified file 'src/mailman/rest/publication.py'
--- src/mailman/rest/publication.py     2009-04-02 23:43:19 +0000
+++ src/mailman/rest/publication.py     2009-05-02 22:07:38 +0000
@@ -28,80 +28,55 @@
 import traceback
 
 from lazr.restful.publisher import WebServicePublicationMixin
-from zope.component import getUtility, queryMultiAdapter
+from zope.component import queryMultiAdapter
 from zope.interface import implements
-from zope.publisher.interfaces import IPublication, IPublishTraverse, NotFound
+from zope.publisher.interfaces import IPublication, NotFound
 from zope.publisher.publish import mapply
-from zope.security.checker import ProxyFactory
 from zope.security.management import endInteraction, newInteraction
 
+from mailman.interfaces.rest import IResolvePathNames
+
 
 
 class Publication:
-    """Very simple implementation of `IPublication`.
-
-    The object pass to the constructor is returned by getApplication().
-    """
+    """Very simple implementation of `IPublication`."""
     implements(IPublication)
 
     def __init__(self, application):
-        """Create the test publication.
-
-        The object at which traversal should start is passed as parameter.
-        """
         self.application = application
 
     def beforeTraversal(self, request):
-        """Sets the request as the current interaction.
-
-        (It also ends any previous interaction, that's convenient when
-        tests don't go through the whole request.)
-        """
-        endInteraction()
-        newInteraction(request)
+        """See `IPublication`."""
+        pass
 
     def getApplication(self, request):
-        """Returns the application passed to the constructor."""
+        """See `IPublication`."""
         return self.application
 
     def callTraversalHooks(self, request, ob):
-        """Does nothing."""
+        """See `IPublication`."""
+        pass
 
     def traverseName(self, request, ob, name):
-        """Traverse by looking at an `IPublishTraverse` adapter.
-
-        The object is security wrapped.
-        """
-        # XXX flacoste 2009/03/06 bug=338831. This is copied from
-        # zope.app.publication.publicationtraverse.PublicationTraverse.
-        # This should really live in zope.publisher, we are copying because
-        # we don't want to depend on zope.app stuff.
-        # Namespace support was dropped.
-        if name == '.':
-            return ob
-
-        if IPublishTraverse.providedBy(ob):
-            ob2 = ob.publishTraverse(request, name)
-        else:
-            # self is marker.
-            adapter = queryMultiAdapter(
-                (ob, request), IPublishTraverse, default=self)
-            if adapter is not self:
-                ob2 = adapter.publishTraverse(request, name)
-            else:
-                raise NotFound(ob, name, request)
-
-        return ProxyFactory(ob2)
+        """See `IPublication`."""
+        missing = object()
+        resolver = IResolvePathNames(ob, missing)
+        if resolver is missing:
+            raise NotFound(ob, name, request)
+        return ob.get(name)
 
     def afterTraversal(self, request, ob):
-        """Does nothing."""
+        pass
 
     def callObject(self, request, ob):
         """Call the object, returning the result."""
+        # XXX Bad hack.
+        from zope.security.proxy import removeSecurityProxy
+        ob = removeSecurityProxy(ob)
         return mapply(ob, request.getPositionalArguments(), request)
 
     def afterCall(self, request, ob):
-        """Does nothing."""
+        pass
 
     def handleException(self, object, request, exc_info, retry_allowed=1):
         """Prints the exception."""

=== modified file 'src/mailman/rest/root.py'
--- src/mailman/rest/root.py    2009-04-02 23:43:19 +0000
+++ src/mailman/rest/root.py    2009-05-02 22:07:38 +0000
@@ -27,6 +27,7 @@
 
 
 from lazr.restful import ServiceRootResource
+from lazr.restful.interfaces import ICollection
 from zope.component import adapts
 from zope.interface import implements
 from zope.publisher.interfaces.browser import IDefaultBrowserLayer
@@ -34,15 +35,12 @@
 
 from mailman.config import config
 from mailman.core.system import system
-from mailman.interfaces.rest import IHasGet
 
 
 
 class AdminWebServiceRootResource(ServiceRootResource):
     """The root of the Mailman RESTful admin web service."""
 
-    implements(IHasGet)
-
     def get(self, name):
         """See `IHasGet`."""
         top_level = {

=== modified file 'src/mailman/rest/traverse.py'
--- src/mailman/rest/traverse.py        2009-04-02 20:44:25 +0000
+++ src/mailman/rest/traverse.py        2009-05-02 22:07:38 +0000
@@ -40,7 +40,6 @@
     """An implementation of `IPublishTraverse` that uses the get() method."""
 
     implements(IPublishTraverse)
-    adapts(IHasGet, IDefaultBrowserLayer)
 
     def __init__(self, context, request):
         self.context = context

=== added file 'src/mailman/rest/urls.py'
--- src/mailman/rest/urls.py    1970-01-01 00:00:00 +0000
+++ src/mailman/rest/urls.py    2009-05-02 22:07:38 +0000
@@ -0,0 +1,53 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Module stuff."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+    'AbsoluteURLMapper',
+    ]
+
+
+from zope.component import adapts
+from zope.interface import implements, Interface
+from zope.traversing.browser.interfaces import IAbsoluteURL
+
+
+
+class AbsoluteURLMapper:
+    """Generic absolute url mapper."""
+
+    implements(IAbsoluteURL)
+    adapts(Interface, IAbsoluteURL)
+
+    def __init__(self, context, request):
+        """Initialize with respect to a context and request."""
+        # Avoid circular imports.
+        from mailman.rest.configuration import AdminWebServiceConfiguration
+        self.webservice_config = AdminWebServiceConfiguration()
+        self.version = webservice_config.service_version_uri_prefix
+        self.schema = ('https' if self.webservice_config.use_https else 'http')
+        self.hostname = config.webservice.hostname
+
+    def __str__(self):
+        """Return the semi-hard-coded URL to the service root."""
+        return '{0.schema}://{0.hostname}/{0.version}'.format(self)
+
+    __call__ = __str__

=== added file 'src/mailman/rest/webservice.py'
--- src/mailman/rest/webservice.py      1970-01-01 00:00:00 +0000
+++ src/mailman/rest/webservice.py      2009-05-02 22:07:38 +0000
@@ -0,0 +1,88 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.
+
+"""Module stuff."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+    'AdminWebServiceApplication',
+    'AdminWebServiceRequest',
+    'start',
+    ]
+
+
+from wsgiref.simple_server import make_server
+
+from lazr.restful.publisher import WebServiceRequestTraversal
+from pkg_resources import resource_string
+from zope.configuration import xmlconfig
+from zope.interface import implements
+from zope.publisher.browser import BrowserRequest
+from zope.publisher.publish import publish
+
+from mailman.core.system import system
+from mailman.interfaces.rest import IResolvePathNames
+from mailman.rest.publication import AdminWebServicePublication
+
+
+
+class AdminWebServiceRequest(WebServiceRequestTraversal, BrowserRequest):
+    """A request for the admin REST interface."""
+
+
+class AdminWebServiceApplication:
+    """A WSGI application for the admin REST interface."""
+
+    implements(IResolvePathNames)
+
+    def __init__(self, environ, start_response):
+        # Create the request based on the HTTP method used.
+        method = environ.get('REQUEST_METHOD', 'GET').upper()
+        request = AdminWebServiceRequest(environ['wsgi.input'], environ)
+        request.setPublication(AdminWebServicePublication(self))
+        # Support post-mortem debugging.
+        handle_errors = environ.get('wsgi.handleErrors', True)
+        # The request returned by the publisher may in fact be different than
+        # the one passed in.
+        request = publish(request, handle_errors=handle_errors)
+        # Start the WSGI server response.
+        response = request.response
+        start_response(response.getStatusString(), response.getHeaders())
+        # Return the result body iterable.
+        return response.consumeBodyIter()
+
+    def get(self, name):
+        """Maps root names to resources."""
+        top_level = dict(
+            sys=system,
+            )
+        return top_level.get(name)
+
+
+
+def start():
+    """Start the WSGI admin REST service."""
+    zcml = resource_string('mailman.rest', 'configure.zcml')
+    xmlconfig.string(zcml)
+    server = make_server('', 8001, AdminWebServiceApplication)
+    return server
+
+
+if __name__ == '__main__':
+    start().serve_forever()



--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0

Your team Mailman Checkins is subscribed to branch lp:mailman.
To unsubscribe from this branch go to 
https://code.launchpad.net/~mailman-coders/mailman/3.0/+edit-subscription.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to