Commit 6a74edce authored by David Wilson's avatar David Wilson

issue #155: parent: move master.Context into parent.

The Context and Router APIs for constructing children and making
function calls should be available in every parent context, as user code
wants to have access to the same API.
parent 447353ec
......@@ -732,12 +732,12 @@ Context Class
No message was received and `deadline` passed.
.. currentmodule:: mitogen.master
.. currentmodule:: mitogen.parent
.. class:: Context
Extend :py:class:`mitogen.core.Router` with functionality useful to
masters, and child contexts who later become masters. Currently when this
masters, and child contexts who later become parents. Currently when this
class is required, the target context's router is upgraded at runtime.
.. method:: call_async (fn, \*args, \*\*kwargs)
......@@ -820,7 +820,7 @@ Receiver Class
Receivers are used to wait for pickled responses from another context to be
sent to a handle registered in this context. A receiver may be single-use
(as in the case of :py:meth:`mitogen.master.Context.call_async`) or
(as in the case of :py:meth:`mitogen.parent.Context.call_async`) or
multiple use.
:param mitogen.core.Router router:
......@@ -1057,7 +1057,7 @@ A random assortment of utility functions useful on masters and children.
functionality, such as annotating the safety of a Unicode string, or adding
additional methods to a dict. However, cPickle loves to preserve those
subtypes during serialization, resulting in CallError during :py:meth:`call
<mitogen.master.Context.call>` in the target when it tries to deserialize
<mitogen.parent.Context.call>` in the target when it tries to deserialize
the data.
This function walks the object graph `obj`, producing a copy with any
......@@ -1139,7 +1139,7 @@ Exceptions
.. class:: CallError (e)
Raised when :py:meth:`Context.call() <mitogen.master.Context.call>` fails.
Raised when :py:meth:`Context.call() <mitogen.parent.Context.call>` fails.
A copy of the traceback from the external context is appended to the
exception message.
......
......@@ -206,8 +206,8 @@ After all initialization is complete, the child's main thread sits in a loop
reading from a :py:class:`Channel <mitogen.core.Channel>` connected to the
:py:data:`CALL_FUNCTION <mitogen.core.CALL_FUNCTION>` handle. This handle is
written to by
:py:meth:`call() <mitogen.master.Context.call>`
and :py:meth:`call_async() <mitogen.master.Context.call_async>`.
:py:meth:`call() <mitogen.parent.Context.call>`
and :py:meth:`call_async() <mitogen.parent.Context.call_async>`.
:py:data:`CALL_FUNCTION <mitogen.core.CALL_FUNCTION>` only accepts requests
from the context IDs listed in :py:data:`mitogen.parent_ids`, forming a chain
......@@ -369,7 +369,7 @@ Children listen on the following handles:
Receives `(mod_name, class_name, func_name, args, kwargs)`
5-tuples from
:py:meth:`call_async() <mitogen.master.Context.call_async>`,
:py:meth:`call_async() <mitogen.parent.Context.call_async>`,
imports ``mod_name``, then attempts to execute
`class_name.func_name(\*args, \**kwargs)`.
......@@ -430,7 +430,7 @@ also listen on the following handles:
Additional handles are created to receive the result of every function call
triggered by :py:meth:`call_async() <mitogen.master.Context.call_async>`.
triggered by :py:meth:`call_async() <mitogen.parent.Context.call_async>`.
Sentinel Value
......
......@@ -287,7 +287,7 @@ def _fakessh_main(dest_context_id, econtext):
if not args:
die('fakessh: login mode not supported and no command specified')
dest = mitogen.master.Context(econtext.router, dest_context_id)
dest = mitogen.parent.Context(econtext.router, dest_context_id)
# Even though SSH receives an argument vector, it still cats the vector
# together before sending to the server, the server just uses /bin/sh -c to
......@@ -318,7 +318,7 @@ def run(dest, router, args, deadline=None, econtext=None):
mitogen.parent.upgrade_router(econtext)
context_id = router.allocate_id()
fakessh = mitogen.master.Context(router, context_id)
fakessh = mitogen.parent.Context(router, context_id)
fakessh.name = 'fakessh.%d' % (context_id,)
sock1, sock2 = socket.socketpair()
......@@ -345,8 +345,8 @@ def run(dest, router, args, deadline=None, econtext=None):
fp.write('ExternalContext().main(**%r)\n' % ({
'parent_ids': parent_ids,
'context_id': context_id,
'debug': router.debug,
'profiling': router.profiling,
'debug': getattr(router, 'debug', False),
'profiling': getattr(router, 'profiling', False),
'log_level': mitogen.parent.get_log_level(),
'in_fd': sock2.fileno(),
'out_fd': sock2.fileno(),
......
......@@ -641,33 +641,7 @@ class Broker(mitogen.core.Broker):
self._watcher.remove()
class Context(mitogen.core.Context):
via = None
def call_async(self, fn, *args, **kwargs):
LOG.debug('%r.call_async(%r, *%r, **%r)',
self, fn, args, kwargs)
if isinstance(fn, types.MethodType) and \
isinstance(fn.im_self, (type, types.ClassType)):
klass = fn.im_self.__name__
else:
klass = None
return self.send_async(
mitogen.core.Message.pickled(
(fn.__module__, klass, fn.__name__, args, kwargs),
handle=mitogen.core.CALL_FUNCTION,
)
)
def call(self, fn, *args, **kwargs):
receiver = self.call_async(fn, *args, **kwargs)
return receiver.get().unpickle(throw_dead=False)
class Router(mitogen.parent.Router):
context_class = Context
broker_class = Broker
debug = False
profiling = False
......
......@@ -39,6 +39,7 @@ import termios
import textwrap
import threading
import time
import types
import zlib
import mitogen.core
......@@ -467,6 +468,31 @@ class ChildIdAllocator(object):
return self.allocate()
class Context(mitogen.core.Context):
via = None
def call_async(self, fn, *args, **kwargs):
LOG.debug('%r.call_async(%r, *%r, **%r)',
self, fn, args, kwargs)
if isinstance(fn, types.MethodType) and \
isinstance(fn.im_self, (type, types.ClassType)):
klass = fn.im_self.__name__
else:
klass = None
return self.send_async(
mitogen.core.Message.pickled(
(fn.__module__, klass, fn.__name__, args, kwargs),
handle=mitogen.core.CALL_FUNCTION,
)
)
def call(self, fn, *args, **kwargs):
receiver = self.call_async(fn, *args, **kwargs)
return receiver.get().unpickle(throw_dead=False)
class RouteMonitor(object):
def __init__(self, router, parent=None):
self.router = router
......@@ -556,7 +582,7 @@ class RouteMonitor(object):
class Router(mitogen.core.Router):
context_class = mitogen.core.Context
context_class = Context
id_allocator = None
responder = None
......
......@@ -83,7 +83,7 @@ class Listener(mitogen.core.BasicStream):
pid, = struct.unpack('>L', sock.recv(4))
context_id = self._router.id_allocator.allocate()
context = mitogen.master.Context(self._router, context_id)
context = mitogen.parent.Context(self._router, context_id)
stream = mitogen.core.Stream(self._router, context_id)
stream.accept(sock.fileno(), sock.fileno())
stream.name = 'unix_client.%d' % (pid,)
......@@ -111,7 +111,7 @@ def connect(path, broker=None):
stream.accept(sock.fileno(), sock.fileno())
stream.name = 'unix_listener.%d' % (pid,)
context = mitogen.master.Context(router, remote_id)
context = mitogen.parent.Context(router, remote_id)
router.register(context, stream)
mitogen.core.listen(router.broker, 'shutdown',
......
......@@ -13,7 +13,7 @@ import mitogen.ssh
import mitogen.sudo
router = mitogen.master.Router()
context = mitogen.master.Context(router, 0)
context = mitogen.parent.Context(router, 0)
stream = mitogen.ssh.Stream(router, 0, hostname='foo')
print 'SSH command size: %s' % (len(' '.join(stream.get_boot_command())),)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment