work on docs

This commit is contained in:
Tobias Oberstein
2014-08-06 01:08:08 +02:00
parent a35a38641c
commit be1c8a1633
6 changed files with 217 additions and 114 deletions

View File

@@ -359,32 +359,33 @@ class ICaller(ISession):
""" """
Call a remote procedure. Call a remote procedure.
This will return a Deferred/Future, that when resolved, provides the actual result. This will return a Deferred/Future, that when resolved, provides the actual result
returned by the called remote procedure.
If the result is a single positional return value, it'll be returned "as-is". If the - If the result is a single positional return value, it'll be returned "as-is".
result contains multiple positional return values or keyword return values,
- If the result contains multiple positional return values or keyword return values,
the result is wrapped in an instance of :class:`autobahn.wamp.types.CallResult`. the result is wrapped in an instance of :class:`autobahn.wamp.types.CallResult`.
If the call fails, the returned Deferred/Future will be rejected with an instance - If the call fails, the returned Deferred/Future will be rejected with an instance
of :class:`autobahn.wamp.exception.ApplicationError`. of :class:`autobahn.wamp.exception.ApplicationError`.
If the *Caller* and *Dealer* implementations support canceling of calls, the call may If ``kwargs`` contains an ``options`` keyword argument that is an instance of
:class:`autobahn.wamp.types.CallOptions`, this will provide specific options for
the call to perform.
When the *Caller* and *Dealer* implementations support canceling of calls, the call may
be canceled by canceling the returned Deferred/Future. be canceled by canceling the returned Deferred/Future.
If ``kwargs`` contains an ``options`` keyword argument that is an instance of :param procedure: The URI of the remote procedure to be called, e.g. ``u"com.myapp.hello"``.
:class:`autobahn.wamp.types.CallOptions`, this will provide :type procedure: unicode
specific options for the call to perform.
:param procedure: The URI of the remote procedure to be called, e.g. ``"com.myapp.hello"``.
:type procedure: str
:param args: Any positional arguments for the call. :param args: Any positional arguments for the call.
:type args: list :type args: list
:param kwargs: Any keyword arguments for the call. :param kwargs: Any keyword arguments for the call.
:type kwargs: dict :type kwargs: dict
:returns: obj -- A Deferred/Future for the call result - :returns: A Deferred/Future for the call result -
an instance of :class:`twisted.internet.defer.Deferred` (when running under Twisted) or :rtype: instance of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
an instance of :class:`asyncio.Future` (when running under asyncio).
""" """
@@ -414,18 +415,21 @@ class IRegistration(object):
Unregister this registration that was previously created from Unregister this registration that was previously created from
:func:`autobahn.wamp.interfaces.ICallee.register`. :func:`autobahn.wamp.interfaces.ICallee.register`.
After a registration has been unregistered, calls won't get routed After a registration has been unregistered successfully, no calls
to the endpoint any more. will be routed to the endpoint anymore.
This will return a Deferred/Future, that when resolved signals Returns an instance of :tx:`twisted.internet.defer.Deferred` (when
successful unregistration. running on **Twisted**) or an instance of :py:class:`asyncio.Future`
(when running on **asyncio**).
If the unregistration fails, the returned Deferred/Future will be rejected - If the unregistration succeeds, the returned Deferred/Future will
*resolve* (with no return value).
- If the unregistration fails, the returned Deferred/Future will be rejected
with an instance of :class:`autobahn.wamp.exception.ApplicationError`. with an instance of :class:`autobahn.wamp.exception.ApplicationError`.
:returns: obj -- A Deferred/Future for the unregistration - :returns: A Deferred/Future for the unregistration
an instance of :class:`twisted.internet.defer.Deferred` (when running under Twisted) :rtype: instance(s) of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
or an instance of :class:`asyncio.Future` (when running under asyncio).
""" """
@@ -438,37 +442,34 @@ class ICallee(ISession):
@abc.abstractmethod @abc.abstractmethod
def register(self, endpoint, procedure = None, options = None): def register(self, endpoint, procedure = None, options = None):
""" """
Register an endpoint for a procedure to (subsequently) receive calls Register a procedure for remote calling.
calling that procedure.
If ``endpoint`` is a callable (function, method or object that implements ``__call__``), When ``endpoint`` is a callable (function, method or object that implements ``__call__``),
then `procedure` must be provided and an instance of then ``procedure`` must be provided and an instance of
:class:`twisted.internet.defer.Deferred` (when running on Twisted) or an instance :tx:`twisted.internet.defer.Deferred` (when running on **Twisted**) or an instance
of :class:`asyncio.Future` (when running on asyncio) is returned. of :py:class:`asyncio.Future` (when running on **asyncio**) is returned.
If the registration succeeds the Deferred/Future will resolve to an object - If the registration *succeeds* the returned Deferred/Future will *resolve* to
that implements :class:`autobahn.wamp.interfaces.Registration`. an object that implements :class:`autobahn.wamp.interfaces.IRegistration`.
If the registration fails the Deferred/Future will reject with an instance - If the registration *fails* the returned Deferred/Future will *reject* with an
of :class:`autobahn.wamp.exception.ApplicationError`. instance of :class:`autobahn.wamp.exception.ApplicationError`.
If ``endpoint`` is an object, then each of the object's methods that are decorated When ``endpoint`` is an object, then each of the object's methods that is decorated
with :func:`autobahn.wamp.register` are registered as procedure endpoints, and a list of with :func:`autobahn.wamp.register` is automatically registered and a list of
Deferreds/Futures is returned that each resolves or rejects as above. Deferreds/Futures is returned that each resolves or rejects as above.
:param endpoint: The endpoint or endpoint object called under the procedure. :param endpoint: The endpoint called under the procedure.
:type endpoint: callable :type endpoint: callable or object
:param procedure: When ``endpoint`` is a single event handler, the URI (or URI pattern) :param procedure: When ``endpoint`` is a callable, the URI (or URI pattern)
of the procedure to register for. When ``endpoint`` is an endpoint of the procedure to register for. When ``endpoint`` is an object,
object, this value is ignored (and should be ``None``). the argument is ignored (and should be ``None``).
:type procedure: str :type procedure: unicode
:param options: Options for registering. :param options: Options for registering.
:type options: An instance of :class:`autobahn.wamp.types.RegisterOptions`. :type options: instance of :class:`autobahn.wamp.types.RegisterOptions`.
:returns: obj -- A (list of) Deferred(s)/Future(s) for the registration(s) - :returns: A registration or a list of registrations (or errors)
instance(s) of :class:`twisted.internet.defer.Deferred` (when :rtype: instance(s) of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
running under Twisted) or instance(s) of :class:`asyncio.Future`
(when running under asyncio).
""" """
@@ -501,26 +502,29 @@ class IPublisher(ISession):
:class:`autobahn.wamp.types.PublishOptions`, this will provide :class:`autobahn.wamp.types.PublishOptions`, this will provide
specific options for the publish to perform. specific options for the publish to perform.
If publication acknowledgement is requested via ``options.acknowledge == True``, .. note::
By default, publications are non-acknowledged and the publication can
fail silently, e.g. because the session is not authorized to publish
to the topic.
When publication acknowledgement is requested via ``options.acknowledge == True``,
this function returns a Deferred/Future: this function returns a Deferred/Future:
- if the publication succeeds the Deferred/Future will resolve to an object - If the publication succeeds the Deferred/Future will resolve to an object
that implements :class:`autobahn.wamp.interfaces.IPublication`. that implements :class:`autobahn.wamp.interfaces.IPublication`.
- if the publication fails the Deferred/Future will reject with an instance - If the publication fails the Deferred/Future will reject with an instance
of :class:`autobahn.wamp.exception.ApplicationError`. of :class:`autobahn.wamp.exception.ApplicationError`.
:param topic: The URI of the topic to publish to, e.g. ``"com.myapp.mytopic1"``. :param topic: The URI of the topic to publish to, e.g. ``u"com.myapp.mytopic1"``.
:type topic: str :type topic: unicode
:param args: Arbitrary application payload for the event (positional arguments). :param args: Arbitrary application payload for the event (positional arguments).
:type args: list :type args: list
:param kwargs: Arbitrary application payload for the event (keyword arguments). :param kwargs: Arbitrary application payload for the event (keyword arguments).
:type kwargs: dict :type kwargs: dict
:returns: obj -- ``None`` for non-acknowledged publications or, :returns: Acknowledgement for acknowledge publications - otherwise nothing.
for acknowledged publications, an instance of :rtype: ``None`` or instance of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
:class:`twisted.internet.defer.Deferred` (when running under Twisted)
or an instance of :class:`asyncio.Future` (when running under asyncio).
""" """
@@ -551,18 +555,21 @@ class ISubscription(object):
Unsubscribe this subscription that was previously created from Unsubscribe this subscription that was previously created from
:func:`autobahn.wamp.interfaces.ISubscriber.subscribe`. :func:`autobahn.wamp.interfaces.ISubscriber.subscribe`.
After a subscription has been unsubscribed, events won't get After a subscription has been unsubscribed successfully, no events
routed to the handler anymore. will be routed to the event handler anymore.
This will return a Deferred/Future, that when resolved signals Returns an instance of :tx:`twisted.internet.defer.Deferred` (when
successful unsubscription. running on **Twisted**) or an instance of :py:class:`asyncio.Future`
(when running on **asyncio**).
If the unsubscription fails, the returned Deferred/Future will be rejected - If the unsubscription succeeds, the returned Deferred/Future will
*resolve* (with no return value).
- If the unsubscription fails, the returned Deferred/Future will *reject*
with an instance of :class:`autobahn.wamp.exception.ApplicationError`. with an instance of :class:`autobahn.wamp.exception.ApplicationError`.
:returns: obj -- A Deferred/Future for the unsubscription - :returns: A Deferred/Future for the unsubscription
an instance of :class:`twisted.internet.defer.Deferred` (when running under Twisted) :rtype: instance(s) of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
or an instance of :class:`asyncio.Future` (when running under asyncio).
""" """
@@ -575,36 +582,34 @@ class ISubscriber(ISession):
@abc.abstractmethod @abc.abstractmethod
def subscribe(self, handler, topic = None, options = None): def subscribe(self, handler, topic = None, options = None):
""" """
Subscribe to a topic and subsequently receive events published to that topic. Subscribe to a topic for receiving events.
If ``handler`` is a callable (function, method or object that implements ``__call__``), When ``handler`` is a callable (function, method or object that implements ``__call__``),
then `topic` must be provided and an instance of then `topic` must be provided and an instance of
:class:`twisted.internet.defer.Deferred` (when running on Twisted) or an instance :tx:`twisted.internet.defer.Deferred` (when running on **Twisted**) or an instance
of :class:`asyncio.Future` (when running on asyncio) is returned. of :class:`asyncio.Future` (when running on **asyncio**) is returned.
If the subscription succeeds the Deferred/Future will resolve to an object - If the subscription succeeds the Deferred/Future will resolve to an object
that implements :class:`autobahn.wamp.interfaces.ISubscription`. that implements :class:`autobahn.wamp.interfaces.ISubscription`.
If the subscription fails the Deferred/Future will reject with an instance - If the subscription fails the Deferred/Future will reject with an instance
of :class:`autobahn.wamp.exception.ApplicationError`. of :class:`autobahn.wamp.exception.ApplicationError`.
If ``handler`` is an object, then each of the object's methods that are decorated When ``handler`` is an object, then each of the object's methods that is decorated
with :func:`autobahn.wamp.subscribe` are subscribed as event handlers, and a list of with :func:`autobahn.wamp.subscribe` is automatically subscribed as event handlers,
Deferreds/Futures is returned that each resolves or rejects as above. and a list of Deferreds/Futures is returned that each resolves or rejects as above.
:param handler: The event handler or handler object to receive events. :param handler: The event handler to receive events.
:type handler: callable or obj :type handler: callable or object
:param topic: When ``handler`` is a single event handler, the URI (or URI pattern) :param topic: When ``handler`` is a callable, the URI (or URI pattern)
of the topic to subscribe to. When ``handler`` is an event handler of the topic to subscribe to. When ``handler`` is an object, this
object, this value is ignored (and should be ``None``). value is ignored (and should be ``None``).
:type topic: str :type topic: unicode
:param options: Options for subscribing. :param options: Options for subscribing.
:type options: An instance of :class:`autobahn.wamp.types.SubscribeOptions`. :type options: An instance of :class:`autobahn.wamp.types.SubscribeOptions`.
:returns: obj -- A (list of) Deferred(s)/Future(s) for the subscription(s) - :returns: A single Deferred/Future or a list of such objects
instance(s) of :class:`twisted.internet.defer.Deferred` (when :rtype: instance(s) of :tx:`twisted.internet.defer.Deferred` / :py:class:`asyncio.Future`
running under Twisted) or instance(s) of :class:`asyncio.Future`
(when running under asyncio).
""" """

View File

@@ -15,3 +15,30 @@ Then, to get help on available build targets, just type
```sh ```sh
make make
``` ```
## Linking to Python objects
To link to a Autobahn class:
```rst
:py:class:`autobahn.websocket.protocol.WebSocketProtocol`
```
To link to a Python stdlib class:
```rst
:py:class:`zipfile.ZipFile`
```
Or to link to Python 2 or Python 3 specifically:
```rst
:py:class:`zipfile.ZipFile <py2:zipfile.ZipFile>`
:py:class:`zipfile.ZipFile <py3:zipfile.ZipFile>`
```
To link to a Twisted class:
```rst
:tx:`twisted.internet.defer.Deferred`
```

View File

@@ -0,0 +1,62 @@
##
## The code in this file is a (slightly modified) version from here:
## https://github.com/twisted/twisted/blob/trunk/docs/_extensions/apilinks.py
##
## It is hence licensed under the Twisted license (essentially BSD less advertising):
## https://github.com/twisted/twisted/blob/trunk/LICENSE
##
"""
Sphinx/docutils extension to create links to pyDoctor documentation using a
RestructuredText interpreted text role that looks like this::
:tx:`python_object_to_link_to <label>`
for example::
:tx:`twisted.internet.defer.Deferred <Deferred>`
The label is optional, hence you can also use
:tx:`twisted.internet.defer.Deferred`
"""
def make_api_link(name, rawtext, text, lineno, inliner,
options={}, content=[]):
from docutils import nodes, utils
# quick, dirty, and ugly...
if '<' in text and '>' in text:
full_name, label = text.split('<')
full_name = full_name.strip()
label = label.strip('>').strip()
else:
full_name = label = text
#get the base url for api links from the config file
env = inliner.document.settings.env
base_url = env.config.apilinks_base_url
# not really sufficient, but just testing...
# ...hmmm, maybe this is good enough after all
ref = ''.join((base_url, full_name, '.html'))
options.update(classes=["tx"])
node = nodes.reference(rawtext, utils.unescape(label), refuri=ref,
**options)
nodes = [node]
sys_msgs = []
return nodes, sys_msgs
# setup function to register the extension
def setup(app):
app.add_config_value('apilinks_base_url',
'http://twistedmatrix.com/documents/current/api/',
'env')
app.add_role('tx', make_api_link)

View File

@@ -6,11 +6,15 @@ body {
background-color: #fff; background-color: #fff;
} }
code, kbd, pre, samp, span.pre { code, kbd, pre, samp, span.pre, a.tx {
font-family: 'Source Code Pro', Consolas, Menlo, monospace; font-family: 'Source Code Pro', Consolas, Menlo, monospace;
font-size: 13px; font-size: 13px;
} }
a.tx, a.tx:visited {
font-weight: bold;
}
/* scrolling for both code with and without line numbers */ /* scrolling for both code with and without line numbers */
[class^="highlight-"], [class^="highlight-"],
[class*=" highlight-"] { [class*=" highlight-"] {

View File

@@ -1,15 +1,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os import os
import sys
import sphinx_bootstrap_theme import sphinx_bootstrap_theme
sys.path.insert(0, os.path.abspath('./_extensions'))
sys.path.insert(0, os.path.abspath('../autobahn'))
extensions = [ extensions = [
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx.ext.doctest', 'sphinx.ext.doctest',
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'sphinx.ext.viewcode', 'sphinx.ext.viewcode',
'sphinx.ext.ifconfig', 'sphinx.ext.ifconfig',
'sphinxcontrib.spelling' 'sphinxcontrib.spelling',
'txsphinx'
] ]
spelling_lang = 'en_US' spelling_lang = 'en_US'
@@ -231,8 +236,9 @@ htmlhelp_basename = 'AutobahnPython'
# http://sphinx-doc.org/ext/intersphinx.html # http://sphinx-doc.org/ext/intersphinx.html
intersphinx_mapping = { intersphinx_mapping = {
'py': ('http://docs.python.org/', None), 'py2': ('http://docs.python.org/2', None),
#'twisted': ('http://twistedmatrix.com/documents/current/api/', None), 'py3': ('http://docs.python.org/3', None),
'six': ('https://pythonhosted.org/six/', None),
} }
rst_epilog = """ rst_epilog = """

View File

@@ -50,7 +50,7 @@ When using **Twisted**, you derive from :class:`autobahn.twisted.wamp.Applicatio
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
whereas when you are using **asyncio**, you derive from :class:`autobahn.asyncio.wamp.ApplicationSession` whereas when you are using **asyncio**, you derive from :class:`autobahn.asyncio.wamp.ApplicationSession`
@@ -62,7 +62,7 @@ whereas when you are using **asyncio**, you derive from :class:`autobahn.asyncio
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
As can be seen, the only difference between Twisted and asyncio is the import (line 1). The rest of the code is identical. As can be seen, the only difference between Twisted and asyncio is the import (line 1). The rest of the code is identical.
@@ -131,14 +131,10 @@ The *Caller* and *Callee* will usually run application code, while the *Dealer*
Registering Procedures Registering Procedures
...................... ......................
To make a procedure available for remote calling, the procedure needs to be *registered*. To make a procedure available for remote calling, the procedure needs to be *registered*. Registering a procedure is done by calling :func:`autobahn.wamp.interfaces.ICallee.register` from a session.
Registering a procedure is done by calling :func:`autobahn.wamp.interfaces.ICallee.register`.
Here is an example using **Twisted** Here is an example using **Twisted**
Twisted
.. code-block:: python .. code-block:: python
:linenos: :linenos:
:emphasize-lines: 14 :emphasize-lines: 14
@@ -150,7 +146,7 @@ Twisted
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
def add2(x, y): def add2(x, y):
return x + y return x + y
@@ -161,11 +157,17 @@ Twisted
except Exception as e: except Exception as e:
print("could not register procedure: {0}".format(e)) print("could not register procedure: {0}".format(e))
The procedure ``add2`` is registered (line 14) under the URI ``com.myapp.add2``. When the registration succeeds, callers will immediately be able to call the procedure using the URI under which it was registered (``com.myapp.add2``). The procedure ``add2`` is registered (line 14) under the URI ``u"com.myapp.add2"`` immediately in the ``onJoin`` callback which fires when the session has connected to a *Router* and joined a *Realm*.
The same code for **asyncio** looks like this .. tip::
asyncio You can register *local* functions like in above example, *global* functions as well as *methods* on class instances. Further, procedures can also be automatically registered using *decorators* (see :ref:`registering-procedure-using-decorators`)
When the registration succeeds, authorized callers will immediately be able to call the procedure (see :ref:`calling-procedures`) using the URI under which it was registered (``u"com.myapp.add2"``).
A registration may also fail, e.g. when a procedure is already registered under the given URI or when the session is not authorized to register procedures.
Using **asyncio**, the example looks like this
.. code-block:: python .. code-block:: python
:linenos: :linenos:
@@ -178,7 +180,7 @@ asyncio
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
def add2(x, y): def add2(x, y):
return x + y return x + y
@@ -189,9 +191,10 @@ asyncio
except Exception as e: except Exception as e:
print("could not register procedure: {0}".format(e)) print("could not register procedure: {0}".format(e))
The differences to Twisted are: The differences compared with the Twisted variant are:
* the import (as with the previous examples) * the ``import`` of ``ApplicationSession``
* the use of ``@coroutine`` to decorate co-routines
* the use of ``yield from`` instead of ``yield`` * the use of ``yield from`` instead of ``yield``
@@ -204,8 +207,6 @@ Calling a procedure (that has been previously registered) is done using :func:`a
Here is how you would call the procedure ``add2`` that we registered in :ref:`registering-procedures` under URI ``com.myapp.add2`` in **Twisted** Here is how you would call the procedure ``add2`` that we registered in :ref:`registering-procedures` under URI ``com.myapp.add2`` in **Twisted**
Twisted
.. code-block:: python .. code-block:: python
:linenos: :linenos:
:emphasize-lines: 11 :emphasize-lines: 11
@@ -217,7 +218,7 @@ Twisted
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
try: try:
res = yield self.call(u'com.myapp.add2', 2, 3) res = yield self.call(u'com.myapp.add2', 2, 3)
@@ -227,8 +228,6 @@ Twisted
And here is the same done on **asyncio** And here is the same done on **asyncio**
asyncio
.. code-block:: python .. code-block:: python
:linenos: :linenos:
:emphasize-lines: 11 :emphasize-lines: 11
@@ -240,7 +239,7 @@ asyncio
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
try: try:
res = yield from self.call(u'com.myapp.add2', 2, 3) res = yield from self.call(u'com.myapp.add2', 2, 3)
@@ -289,7 +288,7 @@ Here is a **Twisted** example
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
def oncounter(count): def oncounter(count):
print("event received: {0}", count) print("event received: {0}", count)
@@ -319,7 +318,7 @@ The corresponding **asyncio** code looks like this
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
def oncounter(count): def oncounter(count):
print("event received: {0}", count) print("event received: {0}", count)
@@ -356,7 +355,7 @@ Here is a **Twisted** example that will publish an event to topic ``u'com.myapp.
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
counter = 0 counter = 0
while True: while True:
@@ -378,7 +377,7 @@ The corresponding **asyncio** code looks like this
class MyComponent(ApplicationSession): class MyComponent(ApplicationSession):
def onJoin(self, details): def onJoin(self, details):
print("session established") print("session ready")
counter = 0 counter = 0
while True: while True: