[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