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.
This commit is contained in:
David Wilson 2018-03-24 18:54:59 +05:45
parent 447353ecb8
commit 6a74edce6b
7 changed files with 43 additions and 43 deletions

View File

@ -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.

View File

@ -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

View File

@ -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(),

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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())),)