Package: dm.zope.rpc
This package implements a middleware
which allows to provide an internet
service (a set of functions made available via the internet)
over multiple rpc protocols with a common (protocol independent) service
implementation.The service functions can be called both via “GET” as well as
“POST” requests. “GET” requests are supported to leverage HTTP caching and to
facilitate debugging. To get the types right, “GET” requests must use theZPublishertype conversion support (or some “GET” support
defined by the rpc protocol itself (as e.g. by the json-rpc protocol)).The rpc protocol can be selected via url components (other means
are implementable as well but not directly supported). Available protocols
are selectable via deployment configuration.This package supports the protocolsreprrpca result format based on Python’s repr – mainly for testing purposes,jsonrpcajsonbased rpc protocol, defined byhttp://json-rpc.org/.This requires thejsonmodule of Python 2.6 (separately installed,
if necessary)xmlrpcthe rpc protocol based on Python’sxmlrpcmodule.This requires the PyPI packagedm.reuseand
(probably)dm.zopepatches.xmlrpc(to control/deactivate
Zope’s builtin xmlrpc support).Forthcoming subpackages will supportsoapbased protocols for
services described by WSDL.ArchitectureAt the package’s core is a protocol handler. Its task is to handle
incoming requests for a specific rpc protocol. To prepare for the
protocol specific serialization of the result, it installs a new
response object. This will handle the result and potential exceptions
in a protocol specific way. In addition, the handler parses a potential
request body and updates theZPublisherargument information
accordingly. Thereafter, “GET” and “POST” requests are (almost) identical.Usually, the protocol handlers for the various protocols are
registered in a Zope Toolkitnamespace. Protocol selection
then can use an url component of the form++namespace++protocol.The protocol handlers in this package derive from a generic
(protocol and configuration independent) class and delegate protocol
and configuration specific operations to a protocol specific mashaller,
which also holds the configuration. The marshaller is either
specified via the handler’smarshallerattribute or obtained
by adaptation of the handler to the.interfaces.IMarshallerinterface.
The function.handler.handlerfactory_from_marshallerfacilitates
the definition of a handler factory which then can be used in the
definition of an adapter.
As a consequence, a specially configured protocol handler
is usually set up by instantiating an appropriately configured
marshaller, passing this marshaller tohandlerfactory_from_marshallerand registering the resulting protocol handler factory as
an adapter (for context and request).The rpc protocols usually support only a limited set of types.
The potentially richer type world used by the service results need
to be mapped to the restricted type set. In addition, the types
delivered by the protocol modules’ deserialization differ. Using
a standardized set of types toward the service
facilitates its implementation.
Therefore, the architecture contains anIDataAdaptercomponent.
It has two methodsnormalize_inandnormalize_outto normalize
the types used in incoming or outgoing values, respectively.
The marshallers look it up via adaptation to.interfaces.IDataAdapter.
The implemented marshallers derive from.adapter.StandardDataAdapter.
It normalizes incoming types tobool,int,float,binary,
a text type (eitherstrorunicode), a date type
(eitherdatetime.dateor Zope’sDateTime.DateTime),
a datetime type (eitherdatetime.datetimeor Zope’sDateTime.DateTime)
and lists and structure wrappers of normalized types.
The structure wrappers support both the mapping api as well as
attribute access; they can be read and written by untrusted code.
Options control which text, date and datetime types are used (see below).
Outgoing types are normalized tobool,int,float,binary,unicode,date,datetimeand lists/dictionaries of normalized
values. Instance objects with anitemsmethod are normalized
to the dicts of (normalized) items; instance objects with an__iter__method are normalized as the list of (normalized) iterated values;
other instance objects are normalized by normalizing their__dict__omitting attributes starting with_(priviate
attributes), an_rpc_typeattribute may be added to convey
the original type. This has the drawback that default (class level
defined) attributes are not taken into account.
You can find details about the standard data adapter inadapter.txtin the subdirectorytests.Text handling is difficult with rpc protocols.
With Python 2.x,stris still often used to represent both text
and binary data while many rpc protocols make a strict distinction
between text and binary data. Therefore, the package defines
a special typebinaryto clearly mark binary data.binaryis derived fromstrand can (usually) be used whereeverstris usable (there are a few exceptions).
An option for the standard data adapter specifies whether
the service usesstrto represent text. In this case, the
protocol text type is mapped tostr(and vice versa) using an encoding
specified via an additional option.
Some rpc protocols (e.g.json) do not support a binary type. In this
case, the module assumes that binary data is coded by the first 256 unicode
codepoints. Thebinarytype implements this assumption.In the Zope [2] world, dates and datetimes pose another ambiguitiy.
Traditionally, Zope uses itsDateTime.DateTimeclass to represent
dates and datetimes. But newer applications may have switched to Python’s
newdateanddatetimetypes. The standard data adapter uses
Python’s types to represent dates and times externally (toward the
protocol) and has an option whether it should convert them to
Zope’sDateTimeinternally (toward the service implementation).ExamplesYou can find simple examples intests.exampleandtests.xmlrpc.exampledemonstrates example zcml registrations to supportjsonrpcandreprrpc,xmlrpcdoes so for thexmlrpcprotocol.The package uses (mostly) the Zope Toolkit component architecture
to combine the various architectural components and
integrate the package into an application. This provides for great
flexibility. Individual components can be easily replaced by
application specific adaptations. Up to now, there are no
documentation or specific examples. You will need to look at
the component sources to find out the possibilities.InstallationThe package expects to be used inside a Zope [2] environment.
However, to facilitate use in a Zope below version 2.12 (the first eggified
Zope 2 version), it does not specify this dependency.In a Zope below 2.12, it might be necessary to set up some
so calledfake-eggs(supported by the buildout recipeplone.recipe.plone2instance) or egg links, e.g. forzope.schema,
andzope.interface, such that these eggs are found inside the
Zope codetree.