diff --git a/docs/api.rst b/docs/api.rst index efa9ad9a..510f7072 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -207,12 +207,21 @@ Router Class receive side to the I/O multiplexer. This This method remains public for now while hte design has not yet settled. - .. method:: add_handler (fn, handle=None, persist=None, respondent=None) + .. method:: add_handler (fn, handle=None, persist=True, respondent=None) Invoke `fn(msg)` for each Message sent to `handle` from this context. Unregister after one invocation if `persist` is ``False``. If `handle` is ``None``, a new handle is allocated and returned. + :param int handle: + If not ``None``, an explicit handle to register, usually one of the + ``mitogen.core.*`` constants. If unspecified, a new unused handle + will be allocated. + + :param bool persist: + If ``False``, the handler will be unregistered after a single + message has been received. + :param mitogen.core.Context respondent: Context that messages to this handle are expected to be sent from. If specified, arranges for ``_DEAD`` to be delivered to `fn` when @@ -221,6 +230,9 @@ Router Class In future `respondent` will likely also be used to prevent other contexts from sending messages to the handle. + :return: + `handle`, or if `handle` was ``None``, the newly allocated handle. + .. method:: _async_route(msg, stream=None) Arrange for `msg` to be forwarded towards its destination. If its @@ -335,7 +347,8 @@ Router Class Accepts all parameters accepted by :py:meth:`local`, in addition to: :param str username: - The ``sudo`` username; defaults to ``root`.. + The ``sudo`` username; defaults to ``root``. + :param str sudo_path: Absolute or relative path to ``sudo``. Defaults to ``sudo``. :param str password: @@ -377,20 +390,125 @@ Router Class ``~/.ssh/id_rsa``, or ``~/.ssh/id_dsa``. -Broker Class -============ +Context Class +============= -.. autoclass:: mitogen.master.Broker - :members: - :inherited-members: +.. class:: mitogen.core.Context + Represent a remote context regardless of connection method. -Context Class -------------- + **Note:** This is the somewhat limited core version of the Context class + used by child contexts. The master subclass is documented below this one. + + .. method:: send (msg) + + Arrange for `msg` to be delivered to this context. Updates the + message's `dst_id` prior to routing it via the associated router. + + :param mitogen.core.Message msg: + The message. + + .. method:: send_async (msg, persist=False) + + Arrange for `msg` to be delivered to this context, with replies + delivered to a newly constructed Receiver. Updates the message's + `dst_id` prior to routing it via the associated router and registers a + handle which is placed in the message's `reply_to`. + + :param bool persist: + If ``False``, the handler will be unregistered after a single + message has been received. + + :param mitogen.core.Message msg: + The message. + + :return mitogen.core.Receiver: + Receiver configured to receive any replies sent to the message's + `reply_to` handle. + + .. method:: send_await (msg, deadline=None) + + As with :py:meth:`send_async`, but expect a single reply + (`persist=False`) delivered within `deadline` seconds. + + :param mitogen.core.Message msg: + The message. + + :param float deadline: + If not ``None``, seconds before timing out waiting for a reply. + + :raises mitogen.core.TimeoutError: + No message was received and `deadline` passed. + + +.. class:: mitogen.master.Context + + Extend :py:class:`mitogen.core.Router` with functionality useful to + masters, and child contexts who later become masters. Currently when this + class is required, the target context's router is upgraded at runtime. + + .. method:: call_async (fn, \*args, \*\*kwargs) + + Arrange for the context's ``CALL_FUNCTION`` handle to receive a + message that causes `fn(\*args, \**kwargs)` to be invoked on the + context's main thread. + + :param fn: + A free function in module scope, or a classmethod or staticmethod + of a class directly reachable from module scope: + + .. code-block:: python + + # mymodule.py + + def my_func(): + """A free function reachable as mymodule.my_func""" + + class MyClass: + @staticmethod + def my_staticmethod(): + """Reachable as mymodule.MyClass.my_staticmethod""" + + @classmethod + def my_classmethod(cls): + """Reachable as mymodule.MyClass.my_staticmethod""" + + def my_instancemethod(self): + """Unreachable: requires a class instance!""" + + class MyEmbeddedClass: + @classmethod + def my_classmethod(cls): + """Not directly reachable from module scope!""" + + :param tuple args: + Function arguments, if any. See :ref:`serialization-rules` for + permitted types. + :param dict kwargs: + Function keyword arguments, if any. See :ref:`serialization-rules` + for permitted types. + :return mitogen.core.Receiver: + A receiver configured to receive the result of the invocation: + + .. code-block:: python + + recv = context.call_async(os.check_output, 'ls /tmp/') + try: + print recv.get_data() # Prints output once it is received. + except mitogen.core.CallError, e: + print 'Call failed:', str(e) + + .. method:: call (fn, \*args, \*\*kwargs) + + Equivalent to :py:meth:`call_async(fn, \*args, \**kwargs).get_data() + `. + + :return: + The function's return value. + + :raises mitogen.core.CallError: + An exception was raised in the remote context during execution. -.. autoclass:: mitogen.master.Context - :members: - :inherited-members: Receiver Class @@ -519,6 +637,13 @@ Channel Class to match. Currently this is a manual task. +Broker Class +============ + +.. autoclass:: mitogen.master.Broker + :members: + :inherited-members: + Utility Functions ================= diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 8c4083a6..264fab78 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -5,6 +5,8 @@ Getting Started xxx +.. _serialization-rules: + RPC Serialization Rules ----------------------- diff --git a/docs/howitworks.rst b/docs/howitworks.rst index 363ff043..d2d214af 100644 --- a/docs/howitworks.rst +++ b/docs/howitworks.rst @@ -202,8 +202,8 @@ After all initialization is complete, the slave's main thread sits in a loop reading from a :py:class:`Channel ` connected to the :py:data:`CALL_FUNCTION ` handle. This handle is written to by -:py:meth:`call_with_deadline() ` -and :py:meth:`call() `. +:py:meth:`call() ` +and :py:meth:`call_async() `. Shutdown diff --git a/mitogen/core.py b/mitogen/core.py index e4848c3e..46be09f8 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -711,9 +711,6 @@ class Stream(BasicStream): class Context(object): - """ - Represent a remote context regardless of connection method. - """ remote_name = None def __init__(self, router, context_id, name=None): diff --git a/mitogen/master.py b/mitogen/master.py index b2708fbd..1a8335e8 100644 --- a/mitogen/master.py +++ b/mitogen/master.py @@ -799,7 +799,6 @@ class Context(mitogen.core.Context): ) def call(self, fn, *args, **kwargs): - """Invoke `fn(*args, **kwargs)` in the external context.""" return self.call_async(fn, *args, **kwargs).get_data()