[Checkins] SVN: grok/trunk/ - added xmlrpc
Christian Theune
ct at gocept.com
Wed Oct 18 12:52:50 EDT 2006
Log message for revision 70787:
- added xmlrpc
Changed:
U grok/trunk/TODO.txt
U grok/trunk/src/grok/__init__.py
U grok/trunk/src/grok/_grok.py
U grok/trunk/src/grok/ftests/test_grok_functional.py
A grok/trunk/src/grok/ftests/xmlrpc/
A grok/trunk/src/grok/ftests/xmlrpc/__init__.py
A grok/trunk/src/grok/ftests/xmlrpc/xmlrpc.py
A grok/trunk/src/grok/ftests/xmlrpc_helper.py
U grok/trunk/src/grok/tests/test_grok.py
A grok/trunk/src/grok/tests/xmlrpc/
A grok/trunk/src/grok/tests/xmlrpc/__init__.py
A grok/trunk/src/grok/tests/xmlrpc/nocontext.py
-=-
Modified: grok/trunk/TODO.txt
===================================================================
--- grok/trunk/TODO.txt 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/TODO.txt 2006-10-18 16:52:48 UTC (rev 70787)
@@ -30,8 +30,6 @@
- local registrations (philikon)
-- xml-rpc (theuni)
-
- make it easier to write tests (wosc, faassen)
- grok.App (philikon)
@@ -43,6 +41,10 @@
- error reporting during grokking (provide file/line-number information
on our extrinsically generated errors) (philikon)
+- maybe: transform register_foo() functions that take lists into functions
+ that operate on a single entity and provide a decorator (@iterate) to
+ call the function for each item (theuni)
+
Need to discuss
---------------
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/__init__.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -21,17 +21,22 @@
IObjectCreatedEvent, ObjectCreatedEvent,
IObjectModifiedEvent, ObjectModifiedEvent,
IObjectCopiedEvent, ObjectCopiedEvent)
+
from zope.app.container.contained import (
IObjectAddedEvent, ObjectAddedEvent,
IObjectMovedEvent, ObjectMovedEvent,
IObjectRemovedEvent, ObjectRemovedEvent,
IContainerModifiedEvent, ContainerModifiedEvent)
-from grok._grok import (Model, Adapter, MultiAdapter, View, PageTemplate, Utility,
- grok, context, name, template, templatedir, )
+from grok._grok import Model, Adapter, MultiAdapter, View, XMLRPC
+from grok._grok import PageTemplate, Utility
+
+from grok._grok import grok, context, name, template, templatedir
+
from grok._grok import SubscribeDecorator as subscribe
from grok.error import GrokError, GrokImportError
+# Our __init__ provides the grok API directly so using 'import grok' is enough.
from grok.interfaces import IGrokAPI
from zope.interface import moduleProvides
moduleProvides(IGrokAPI)
Modified: grok/trunk/src/grok/_grok.py
===================================================================
--- grok/trunk/src/grok/_grok.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/_grok.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -15,6 +15,7 @@
"""
import os
import sys
+import inspect
import persistent
from zope import component
@@ -29,10 +30,13 @@
from zope.publisher.interfaces.browser import (IDefaultBrowserLayer,
IBrowserRequest)
from zope.pagetemplate import pagetemplate
+
from zope.app.pagetemplate.engine import TrustedAppPT
from zope.app.publisher.browser import directoryresource
from zope.app.publisher.browser.pagetemplateresource import \
PageTemplateResourceFactory
+from zope.app.publisher.xmlrpc import MethodPublisher
+from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
from grok import util, scan
from grok.error import GrokError, GrokImportError
@@ -41,6 +45,7 @@
TextDirective, InterfaceOrClassDirective,
frame_is_module)
+
AMBIGUOUS_CONTEXT = object()
class Model(persistent.Persistent):
@@ -86,6 +91,12 @@
def before(self):
pass
+
+class XMLRPC(object):
+ pass
+
+
+
class PageTemplate(TrustedAppPT, pagetemplate.PageTemplate):
expand = 0
@@ -140,7 +151,7 @@
raise GrokError("A package can not contain both a 'static' "
"resource directory and a module named "
"'static.py'", module_info.getModule())
-
+
register_static_resources(module_info.dotted_name, resource_path)
for sub_module_info in module_info.getSubModuleInfos():
@@ -149,7 +160,7 @@
def grok_module(module_info):
(models, adapters, multiadapters, utilities,
- views, templates, subscribers) = scan_module(module_info)
+ views, xmlrpc_views, templates, subscribers) = scan_module(module_info)
find_filesystem_templates(module_info, templates)
@@ -160,15 +171,20 @@
register_multiadapters(multiadapters)
register_utilities(utilities)
register_views(context, views, templates)
+ register_xmlrpc(context, xmlrpc_views)
register_unassociated_templates(context, templates)
register_subscribers(subscribers)
+
def scan_module(module_info):
- models = []
- adapters = []
- multiadapters = []
- utilities = []
- views = []
+ components = {
+ Model: [],
+ Adapter: [],
+ MultiAdapter: [],
+ Utility: [],
+ View: [],
+ XMLRPC: []
+ }
templates = TemplateRegistry()
subscribers = module_info.getAnnotation('grok.subscribers', [])
@@ -179,23 +195,20 @@
if not defined_locally(obj, module_info.dotted_name):
continue
- if util.check_subclass(obj, Model):
- models.append(obj)
- elif util.check_subclass(obj, Adapter):
- adapters.append(obj)
- elif util.check_subclass(obj, MultiAdapter):
- multiadapters.append(obj)
- elif util.check_subclass(obj, View):
- views.append(obj)
- elif util.check_subclass(obj, Utility):
- utilities.append(obj)
- elif isinstance(obj, PageTemplate):
+ if isinstance(obj, PageTemplate):
templates.register(name, obj)
obj._annotateGrokInfo(module_info, name, module_info.dotted_name)
+ continue
- return (models, adapters, multiadapters, utilities,
- views, templates, subscribers)
+ for candidate_class, found_list in components.items():
+ if util.check_subclass(obj, candidate_class):
+ found_list.append(obj)
+ break
+ return (components[Model], components[Adapter],
+ components[MultiAdapter], components[Utility],
+ components[View], components[XMLRPC], templates, subscribers)
+
def find_filesystem_templates(module_info, templates):
template_dir_name = module_info.getAnnotation('grok.templatedir', module_info.name)
template_dir = module_info.getResourcePath(template_dir_name)
@@ -321,6 +334,22 @@
name = class_annotation(factory, 'grok.name', '')
component.provideUtility(factory(), name=name)
+def register_xmlrpc(context, views):
+ for view in views:
+ view_context = determine_class_context(view, context)
+ candidates = [getattr(view, name) for name in dir(view)]
+ methods = [c for c in candidates if inspect.ismethod(c)]
+
+ for method in methods:
+ # Make sure that the class inherits MethodPublisher, so that the views
+ # have a location
+ method_view = type(view.__name__, (view, MethodPublisher),
+ {'__call__':method,
+ '__Security_checker__':GrokChecker()})
+ component.provideAdapter(
+ method_view, (view_context, IXMLRPCRequest), interface.Interface,
+ name=method.__name__)
+
def register_views(context, views, templates):
for factory in views:
view_context = determine_class_context(factory, context)
Modified: grok/trunk/src/grok/ftests/test_grok_functional.py
===================================================================
--- grok/trunk/src/grok/ftests/test_grok_functional.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/ftests/test_grok_functional.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -56,7 +56,7 @@
def test_suite():
suite = unittest.TestSuite()
- for name in ['view', 'static']:
+ for name in ['view', 'static', 'xmlrpc']:
suite.addTest(suiteFromPackage(name))
return suite
Added: grok/trunk/src/grok/ftests/xmlrpc/__init__.py
===================================================================
--- grok/trunk/src/grok/ftests/xmlrpc/__init__.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/ftests/xmlrpc/__init__.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -0,0 +1 @@
+# this is a package
Property changes on: grok/trunk/src/grok/ftests/xmlrpc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/ftests/xmlrpc/xmlrpc.py
===================================================================
--- grok/trunk/src/grok/ftests/xmlrpc/xmlrpc.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/ftests/xmlrpc/xmlrpc.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -0,0 +1,29 @@
+"""
+ >>> import grok
+ >>> grok.grok('grok.ftests.xmlrpc.xmlrpc')
+ >>> from grok.ftests.xmlrpc.xmlrpc import Mammoth
+ >>> getRootFolder()["Manfred"] = Mammoth()
+
+ >>> from grok.ftests.xmlrpc_helper import ServerProxy
+
+ >>> server = ServerProxy("http://localhost/")
+ >>> server.Manfred.stomp()
+ 'Manfred stomped.'
+ >>> server.Manfred.dance()
+ "Manfred doesn't like to dance."
+
+"""
+import grok
+
+
+class Mammoth(grok.Model):
+ pass
+
+
+class MammothRPC(grok.XMLRPC):
+
+ def stomp(self):
+ return '%s stomped.' % self.context.__name__
+
+ def dance(self):
+ return '%s doesn\'t like to dance.' % self.context.__name__
Property changes on: grok/trunk/src/grok/ftests/xmlrpc/xmlrpc.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/ftests/xmlrpc_helper.py
===================================================================
--- grok/trunk/src/grok/ftests/xmlrpc_helper.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/ftests/xmlrpc_helper.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -0,0 +1,75 @@
+# XXX This code is duplicated from Zope 3 trunk (future Zope 3.4) as we want to
+# stay compatible with Zope 3.3
+#
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""XMLRPC testing helpers for Zope 3.
+
+$Id$
+"""
+
+import StringIO
+import xmlrpclib
+
+from zope.app.testing.functional import HTTPCaller
+
+
+class ZopeTestTransport(xmlrpclib.Transport):
+ """xmlrpclib transport that delegates to
+ zope.app.testing.functional.HTTPCaller.
+
+ It can be used like a normal transport, including support for basic
+ authentication.
+ """
+
+ verbose = False
+ handleErrors = True
+
+ def request(self, host, handler, request_body, verbose=0):
+ request = "POST %s HTTP/1.0\n" % (handler,)
+ request += "Content-Length: %i\n" % len(request_body)
+ request += "Content-Type: text/xml\n"
+
+ host, extra_headers, x509 = self.get_host_info(host)
+ if extra_headers:
+ request += "Authorization: %s\n" % (dict(extra_headers)["Authorization"],)
+
+ request += "\n" + request_body
+ response = HTTPCaller()(request, handle_errors=self.handleErrors)
+
+ errcode = response.getStatus()
+ errmsg = response.getStatusString()
+ # This is not the same way that the normal transport deals with the headers.
+ headers = response.getHeaders()
+
+ if errcode != 200:
+ raise xmlrpclib.ProtocolError(
+ host + handler,
+ errcode, errmsg,
+ headers
+ )
+
+ return self._parse_response(
+ StringIO.StringIO(response.getBody()), sock=None)
+
+
+def ServerProxy(uri, transport=ZopeTestTransport(), encoding=None,
+ verbose=0, allow_none=0, handleErrors=True):
+ """A factory that creates a server proxy using the ZopeTestTransport
+ by default.
+
+ """
+ if isinstance(transport, ZopeTestTransport):
+ transport.handleErrors = handleErrors
+ return xmlrpclib.ServerProxy(uri, transport, encoding, verbose, allow_none)
Property changes on: grok/trunk/src/grok/ftests/xmlrpc_helper.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/tests/test_grok.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -33,7 +33,7 @@
def test_suite():
suite = unittest.TestSuite()
for name in ['adapter', 'error', 'view', 'security', 'scan',
- 'event', 'zcml', 'static', 'utility']:
+ 'event', 'zcml', 'static', 'utility', 'xmlrpc']:
suite.addTest(suiteFromPackage(name))
return suite
Added: grok/trunk/src/grok/tests/xmlrpc/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/xmlrpc/__init__.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/tests/xmlrpc/__init__.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -0,0 +1 @@
+# this is a package
Property changes on: grok/trunk/src/grok/tests/xmlrpc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
Added: grok/trunk/src/grok/tests/xmlrpc/nocontext.py
===================================================================
--- grok/trunk/src/grok/tests/xmlrpc/nocontext.py 2006-10-18 14:33:55 UTC (rev 70786)
+++ grok/trunk/src/grok/tests/xmlrpc/nocontext.py 2006-10-18 16:52:48 UTC (rev 70787)
@@ -0,0 +1,16 @@
+"""
+
+Context-determination follows the same rules as for adapters. We just check
+whether it's hooked up at all:
+
+ >>> grok.grok(__name__)
+ Traceback (most recent call last):
+ ...
+ GrokError: No module-level context for
+ <class 'grok.tests.xmlrpc.nocontext.HomeRPC'>, please use grok.context.
+
+"""
+import grok
+
+class HomeRPC(grok.XMLRPC):
+ pass
Property changes on: grok/trunk/src/grok/tests/xmlrpc/nocontext.py
___________________________________________________________________
Name: svn:keywords
+ Id Rev Date
Name: svn:eol-style
+ native
More information about the Checkins
mailing list