[Zope3-checkins] SVN: Zope3/branches/ZopeX3-3.0/ Made a number of related changes:

Jim Fulton jim at zope.com
Fri Aug 27 16:13:49 EDT 2004


Log message for revision 27307:
  Made a number of related changes:
  
  - Finished the README.txt, explaining how to create named XML-RPC
    views.
  
  - Moved MethodPublisher to zope.app.publisher.xmlrpc
  
  - Now subclasses Location, so that it can acquire security grants
  
  - Now provides traversal via an adapter so that attribute accesses
      are mediated by security.
  
  - MethodPublisher is now pretty much configuration, so needs no unit
      tests.  (It is tested vie README.txt.)
  
  - Got rid of DefaultPublisher, which was only used (and isn't used any
    more) by MethodPublisher.
  


Changed:
  U   Zope3/branches/ZopeX3-3.0/releases/ZopeX3/DEPENDENCIES.cfg
  U   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/configure.zcml
  U   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt
  U   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/__init__.py
  A   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/configure.zcml
  U   Zope3/branches/ZopeX3-3.0/src/zope/publisher/http.py
  D   Zope3/branches/ZopeX3-3.0/src/zope/publisher/tests/test_xmlrpcmethodpublisher.py
  U   Zope3/branches/ZopeX3-3.0/src/zope/publisher/xmlrpc.py


-=-
Modified: Zope3/branches/ZopeX3-3.0/releases/ZopeX3/DEPENDENCIES.cfg
===================================================================
--- Zope3/branches/ZopeX3-3.0/releases/ZopeX3/DEPENDENCIES.cfg	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/releases/ZopeX3/DEPENDENCIES.cfg	2004-08-27 20:13:49 UTC (rev 27307)
@@ -22,5 +22,4 @@
 zope.app.sqlscript
 zope.app.tree
 zope.app.undo
-zope.app.xmlrpc
 zope.app.zptpage

Modified: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/configure.zcml
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/configure.zcml	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/configure.zcml	2004-08-27 20:13:49 UTC (rev 27307)
@@ -1,5 +1,6 @@
 <configure xmlns='http://namespaces.zope.org/zope' >
   <include package=".browser" />
+  <include package=".xmlrpc" />
   <include file="http.zcml" />
 
   <interface

Modified: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt	2004-08-27 20:13:49 UTC (rev 27307)
@@ -124,13 +124,119 @@
   <BLANKLINE>
 
 
-Now let's look at views that have their own methods.  Views that have
-their own methods have names that appear in URLs and they get
-traversed to get to their methods, as in::
+Now let's look at views that have their own methods or other
+subobjects.  Views that have their own methods have names that appear
+in URLs and they get traversed to get to their methods, as in::
 
    .../somefolder/listing/contents
 
 To make this possible, the view has to support traversal, so that,
-when it is traversed, it traverses to it's attributes.
+when it is traversed, it traverses to it's attributes.  To supplot
+traversal, you can implement or provide an adapter to
+`zope.publisher.interfaces.IPublishTraverse`. It's actually better to
+provide an adapter so that accesses to attributes during traversal are
+mediated by the security machinery.  (Object methods are always bound
+to unproxied objects, but adapters are bound to proxied objects unless
+they are trusted adapters.)
 
-XXX: need to finish
+The 'zope.app.publisher.xmlrpc' package provides a base class,
+`MethodPublisher`,  that provides the necessary traversal support.  In
+particulat, it has an adapter that simply traverses to attributes. 
+
+If an XML-RPC view isn't going to be public, then it also has to
+implement 'zope.app.location.ILocation' so that security grants can be
+acquired for it, at least with Zope's default security policy. The
+`MethodPublisher` class does that too.
+
+Let's modify our view class to use `MethodPublisher`:
+
+  >>> from zope.app.publisher.xmlrpc import MethodPublisher
+
+  >>> class FolderListing(MethodPublisher):
+  ...
+  ...     def contents(self):
+  ...         return list(self.context.keys())
+
+Note that `MethodPublisher` also provides a suitable `__init__`
+method, so we don't need one any more.  This time, we'll register it
+as as a named view:
+
+  >>> ignored = xmlconfig.string("""
+  ... <configure 
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
+  ...     >
+  ...   <!-- We only need to do this include in this example, 
+  ...        Normally the include has already been done for us. -->
+  ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
+  ...
+  ...   <xmlrpc:view
+  ...       name="listing"
+  ...       for="zope.app.folder.folder.IFolder"
+  ...       methods="contents"
+  ...       class="zope.app.publisher.xmlrpc.README.FolderListing"
+  ...       permission="zope.ManageContent"
+  ...       />
+  ... </configure>
+  ... """)
+
+Now, when we access the `contents`, we do so through the listing view:
+
+  >>> print http(r"""
+  ... POST /listing/ HTTP/1.0
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... 
+  ... <?xml version='1.0'?>
+  ... <methodCall>
+  ... <methodName>contents</methodName>
+  ... <params>
+  ... </params>
+  ... </methodCall>
+  ... """, handle_errors=False)
+  HTTP/1.0 200 Ok
+  Content-Length: 208
+  Content-Type: text/xml;charset=utf-8
+  <BLANKLINE>
+  <?xml version='1.0'?>
+  <methodResponse>
+  <params>
+  <param>
+  <value><array><data>
+  <value><string>f1</string></value>
+  <value><string>f2</string></value>
+  </data></array></value>
+  </param>
+  </params>
+  </methodResponse>
+  <BLANKLINE>
+
+as before, we will get an error if we don't supply credentials:
+
+  >>> print http(r"""
+  ... POST /listing/ HTTP/1.0
+  ... Content-Length: 102
+  ... Content-Type: text/xml
+  ... 
+  ... <?xml version='1.0'?>
+  ... <methodCall>
+  ... <methodName>contents</methodName>
+  ... <params>
+  ... </params>
+  ... </methodCall>
+  ... """)
+  HTTP/1.0 401 Unauthorized
+  Content-Length: 126
+  Content-Type: text/xml;charset=utf-8
+  Www-Authenticate: basic realm='Zope'
+  <BLANKLINE>
+  <?xml version='1.0'?>
+  <methodResponse>
+  <params>
+  <param>
+  <value><string></string></value>
+  </param>
+  </params>
+  </methodResponse>
+  <BLANKLINE>

Modified: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/__init__.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/__init__.py	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/__init__.py	2004-08-27 20:13:49 UTC (rev 27307)
@@ -17,15 +17,40 @@
 
 $Id$
 """
-from zope.interface import implements
-from zope.app.publisher.interfaces.xmlrpc import IXMLRPCView
+import zope.interface
+import zope.app.location
+import zope.app.publisher.interfaces.xmlrpc
 
 class XMLRPCView(object):
     """A base XML-RPC view that can be used as mix-in for XML-RPC views.""" 
 
-    implements(IXMLRPCView)
+    zope.interface.implements(zope.app.publisher.interfaces.xmlrpc.IXMLRPCView)
 
     def __init__(self, context, request):
         self.context = context
         self.request = request
 
+
+class IMethodPublisher(zope.interface.Interface):
+    """Marker interface for an object that wants to publish methods
+    """
+
+class MethodPublisher(XMLRPCView, zope.app.location.Location):
+    """Base class for very simple XML-RPC views that publish methods
+
+    This class is meant to be more of an example than a standard base class. 
+
+    This example is explained in the README.txt file for this package
+    """
+
+    zope.interface.implements(IMethodPublisher)
+
+class MethodTraverser(object):
+
+    __used_for__ = IMethodPublisher
+
+    def __init__(self, context, request):
+        self.context = context
+        
+    def publishTraverse(self, request, name):
+        return getattr(self.context, name)

Copied: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/configure.zcml (from rev 27304, Zope3/branches/ZopeX3-3.0/src/zope/app/xmlrpc/configure.zcml)
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/xmlrpc/configure.zcml	2004-08-27 18:20:43 UTC (rev 27304)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/configure.zcml	2004-08-27 20:13:49 UTC (rev 27307)
@@ -0,0 +1,38 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
+    >
+
+  <view 
+      for="zope.interface.Interface"
+      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
+      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
+      factory="zope.app.publication.traversers.SimpleComponentTraverser"
+      permission="zope.Public"
+      />
+
+  <view 
+      for="zope.app.container.interfaces.IItemContainer"
+      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
+      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
+      factory="zope.app.container.traversal.ItemTraverser"
+      permission="zope.Public"
+      />
+
+  <view 
+      for="zope.app.container.interfaces.IReadContainer"
+      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
+      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
+      factory="zope.app.container.traversal.ContainerTraverser"
+      permission="zope.Public"
+      />
+
+  <view 
+      for=".IMethodPublisher"
+      type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
+      provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
+      factory=".MethodTraverser"
+      permission="zope.Public"
+      />
+
+</configure>

Modified: Zope3/branches/ZopeX3-3.0/src/zope/publisher/http.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/publisher/http.py	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/publisher/http.py	2004-08-27 20:13:49 UTC (rev 27307)
@@ -928,14 +928,6 @@
         return text
 
 
-class DefaultPublisher(object):
-    implements(IHTTPPublisher)
-
-    def publishTraverse(self, request, name):
-        'See IHTTPPublisher'
-
-        return getattr(self, name)
-
 def sort_charsets(x, y):
     if y[1] == 'utf-8':
         return 1

Deleted: Zope3/branches/ZopeX3-3.0/src/zope/publisher/tests/test_xmlrpcmethodpublisher.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/publisher/tests/test_xmlrpcmethodpublisher.py	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/publisher/tests/test_xmlrpcmethodpublisher.py	2004-08-27 20:13:49 UTC (rev 27307)
@@ -1,62 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""XML-RPC Method Publisher tests
-
-$Id$
-"""
-import unittest
-
-from zope.publisher.xmlrpc import MethodPublisher, TestRequest
-from zope.publisher.interfaces.xmlrpc import IXMLRPCPublisher
-
-from zope.interface.verify import verifyClass
-from zope.interface import implementedBy
-
-class ContentStub(object):
-    pass
-
-class Presentation(MethodPublisher):
-    index = 'index'
-    action = 'action'
-    foo = 'foo'
-
-
-class TestMethodPublisher(unittest.TestCase):
-    def setUp(self):
-        self.pres = Presentation(ContentStub(), TestRequest())
-
-    def testImplementsIXMLRPCPublisher(self):
-        self.failUnless(IXMLRPCPublisher.providedBy(self.pres))
-
-    def testInterfacesVerify(self):
-        for interface in implementedBy(Presentation):
-            verifyClass(interface, Presentation)
-
-    def testXMLRPCTraverseIndex(self):
-        self.assertEquals(self.pres.publishTraverse(None, 'index'), 'index')
-
-    def testXMLRPCTraverseAction(self):
-        self.assertEquals(self.pres.publishTraverse(None, 'action'), 'action')
-
-    def testXMLRPCTraverseNotFound(self):
-        self.failUnlessRaises(AttributeError, self.pres.publishTraverse,
-            None, 'bar')
-
-
-def test_suite():
-    loader = unittest.TestLoader()
-    return loader.loadTestsFromTestCase(TestMethodPublisher)
-
-if __name__ == '__main__':
-    unittest.TextTestRunner().run(test_suite())

Modified: Zope3/branches/ZopeX3-3.0/src/zope/publisher/xmlrpc.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/publisher/xmlrpc.py	2004-08-27 20:13:46 UTC (rev 27306)
+++ Zope3/branches/ZopeX3-3.0/src/zope/publisher/xmlrpc.py	2004-08-27 20:13:49 UTC (rev 27307)
@@ -13,7 +13,7 @@
 ##############################################################################
 """XML-RPC Publisher
 
-This module contains the MethodPublisher, XMLRPCRequest and XMLRPCResponse
+This module contains the XMLRPCRequest and XMLRPCResponse
 
 $Id$
 """
@@ -26,21 +26,8 @@
 from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
 
 from zope.publisher.http import HTTPRequest, HTTPResponse
-from zope.publisher.http import DefaultPublisher
 from zope.proxy import removeAllProxies
 
-
-class MethodPublisher(DefaultPublisher):
-    """Simple XML-RPC publisher that is identical to the HTTP Default Publisher
-       except that it implements the IXMLRPCPublisher interface."""
-
-    implements(IXMLRPCPublisher)
-
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-
 class XMLRPCRequest(HTTPRequest):
     implements(IXMLRPCRequest)
 



More information about the Zope3-Checkins mailing list