1.. _xmlrpc:
2
3=======
4XML-RPC
5=======
6
7XML-RPC allows you to expose one or more methods at a particular URL.
8:mod:`pyramid_rpc` uses a view lookup pattern like that in :mod:`pyramid`
9allowing the XML-RPC methods to be located with the rest of your views, or in
10other packages.
11
12Setup
13=====
14
15Use the ``includeme`` via :meth:`pyramid.config.Configurator.include`:
16
17.. code-block:: python
18
19    config.include('pyramid_rpc.xmlrpc')
20
21Once activated, the following happens:
22
23#. The :meth:`pyramid_rpc.xmlrpc.add_xmlrpc_endpoint` directive is added to
24   the ``config`` instance.
25
26#. The :meth:`pyramid_rpc.xmlrpc.add_xmlrpc_method` directive is added to
27   the ``config`` instance.
28
29#. An exception view is registered for :class:`xmlrpclib.Fault` exceptions.
30
31Usage
32=====
33
34After including the ``pyramid_rpc.xmlrpc`` package in your project, you can
35add an :term:`endpoint` for handling incoming requests. After that, attach
36several methods to the endpoint to handle specific functions within your api.
37
38Adding a XML-RPC Endpoint
39--------------------------
40
41An :term:`endpoint` is added via the
42:func:`~pyramid_rpc.xmlrpc.add_xmlrpc_endpoint` directive on the
43``config`` instance.
44
45Example:
46
47.. code-block:: python
48
49    config = Configurator()
50    config.include('pyramid_rpc.xmlrpc')
51    config.add_xmlrpc_endpoint('api', '/api/xmlrpc')
52
53It is possible to add multiple endpoints as well as pass extra arguments to
54:func:`~pyramid_rpc.xmlrpc.add_xmlrpc_endpoint` to handle traversal, which
55can assist in adding security to your RPC API.
56
57Exposing XML-RPC Methods
58-------------------------
59
60Methods on your API are exposed by attaching views to an :term:`endpoint`.
61Methods may be attached via the
62:func:`~pyramid_rpc.xmlrpc.add_xmlrpc_method` which is a thin wrapper
63around Pyramid's :meth:`pyramid.config.Configurator.add_view` method.
64
65Example:
66
67.. code-block:: python
68
69    def say_hello(request, name):
70        return 'Hello, ' + name
71
72    config.add_xmlrpc_method(say_hello, endpoint='api', method='say_hello')
73
74If you prefer, you can use the :func:`~pyramid_rpc.xmlrpc.xmlrpc_method`
75view decorator to declare your methods closer to your actual code.
76Remember when using this lazy configuration technique, it's always necessary
77to call :meth:`pyramid.config.Configurator.scan` from within your setup code.
78
79.. code-block:: python
80
81    from pyramid_rpc.xmlrpc import xmlrpc_method
82
83    @xmlrpc_method(endpoint='api')
84    def say_hello(request, name):
85        return 'Hello, ' + name
86
87    config.scan()
88
89To set the RPC method to something other than the name of the view, specify
90the ``method`` parameter:
91
92.. code-block:: python
93
94    from pyramid_rpc.xmlrpc import xmlrpc_method
95
96    @xmlrpc_method(method='say_hello', endpoint='api')
97    def say_hello_view(request, name):
98        return 'Hello, ' + name
99
100    config.scan()
101
102Because methods are a thin layer around Pyramid's views, it is possible to add
103extra view predicates to the method, as well as ``permission`` requirements.
104
105Custom Renderers
106----------------
107
108By default, responses are rendered using the Python standard library's
109:func:`xmlrpclib.dumps`. This can be changed the same way any renderer is
110changed in Pyramid. See the `Pyramid Renderers
111<http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html>`_
112chapter for extra details.
113
114In addition, the built in renderer allows configuration by passing keyword
115arguments to it. As an example, let's update an :term:`endpoint` to allow
116marshalling ``None`` objects.
117
118.. code-block:: python
119
120    from pyramid_rpc.xmlrpc import XMLRPCRenderer
121
122    config.add_renderer('myxmlrpc', XMLRPCRenderer(allow_none=True))
123    config.add_xmlrpc_endpoint('api', '/api', default_renderer='myxmlrpc')
124
125
126View Mappers
127------------
128
129A view mapper is registered for XML-RPC methods by default which will
130match the arguments from ``request.rpc_args`` to the parameters of the
131view. Optional arguments are allowed and an error will be returned if too
132many or too few arguments are supplied to the view.
133
134This default view mapper may be overridden by setting the
135``default_mapper`` option on :func:`~pyramid_rpc.xmlrpc.add_xmlrpc_endpoint`
136or the ``mapper`` option when using :func:`~pyramid_rpc.xmlrpc.xmlrpc_method`
137or :func:`~pyramid_rpc.xmlrpc.add_xmlrpc_method`.
138
139
140Call Example
141============
142
143Using Python's :mod:`xmlrpclib`, it's simple to instantiate a ``ServerProxy``
144to call the function via an XML-RPC client.
145
146.. code-block:: python
147   :linenos:
148
149   >>> from xmlrpclib import ServerProxy
150   >>> s = ServerProxy('http://localhost:6543/api/xmlrpc')
151   >>> s.say_hello(name='Chris')
152   Hello, Chris
153
154
155.. _xmlrpc_api:
156
157API
158===
159
160.. automodule:: pyramid_rpc.xmlrpc
161
162  .. autofunction:: includeme
163
164  .. autofunction:: add_xmlrpc_endpoint
165
166  .. autofunction:: add_xmlrpc_method
167
168  .. autofunction:: xmlrpc_method
169
170