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.
pull/167/head
David Wilson 6 years ago
parent 447353ecb8
commit 6a74edce6b

@ -732,12 +732,12 @@ Context Class
No message was received and `deadline` passed. No message was received and `deadline` passed.
.. currentmodule:: mitogen.master .. currentmodule:: mitogen.parent
.. class:: Context .. class:: Context
Extend :py:class:`mitogen.core.Router` with functionality useful to 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. class is required, the target context's router is upgraded at runtime.
.. method:: call_async (fn, \*args, \*\*kwargs) .. 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 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 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. multiple use.
:param mitogen.core.Router router: :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 functionality, such as annotating the safety of a Unicode string, or adding
additional methods to a dict. However, cPickle loves to preserve those additional methods to a dict. However, cPickle loves to preserve those
subtypes during serialization, resulting in CallError during :py:meth:`call 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. the data.
This function walks the object graph `obj`, producing a copy with any This function walks the object graph `obj`, producing a copy with any
@ -1139,7 +1139,7 @@ Exceptions
.. class:: CallError (e) .. 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 A copy of the traceback from the external context is appended to the
exception message. 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 reading from a :py:class:`Channel <mitogen.core.Channel>` connected to the
:py:data:`CALL_FUNCTION <mitogen.core.CALL_FUNCTION>` handle. This handle is :py:data:`CALL_FUNCTION <mitogen.core.CALL_FUNCTION>` handle. This handle is
written to by written to by
:py:meth:`call() <mitogen.master.Context.call>` :py:meth:`call() <mitogen.parent.Context.call>`
and :py:meth:`call_async() <mitogen.master.Context.call_async>`. and :py:meth:`call_async() <mitogen.parent.Context.call_async>`.
:py:data:`CALL_FUNCTION <mitogen.core.CALL_FUNCTION>` only accepts requests :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 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)` Receives `(mod_name, class_name, func_name, args, kwargs)`
5-tuples from 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 imports ``mod_name``, then attempts to execute
`class_name.func_name(\*args, \**kwargs)`. `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 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 Sentinel Value

@ -287,7 +287,7 @@ def _fakessh_main(dest_context_id, econtext):
if not args: if not args:
die('fakessh: login mode not supported and no command specified') 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 # 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 # 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) mitogen.parent.upgrade_router(econtext)
context_id = router.allocate_id() 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,) fakessh.name = 'fakessh.%d' % (context_id,)
sock1, sock2 = socket.socketpair() sock1, sock2 = socket.socketpair()
@ -345,8 +345,8 @@ def run(dest, router, args, deadline=None, econtext=None):
fp.write('ExternalContext().main(**%r)\n' % ({ fp.write('ExternalContext().main(**%r)\n' % ({
'parent_ids': parent_ids, 'parent_ids': parent_ids,
'context_id': context_id, 'context_id': context_id,
'debug': router.debug, 'debug': getattr(router, 'debug', False),
'profiling': router.profiling, 'profiling': getattr(router, 'profiling', False),
'log_level': mitogen.parent.get_log_level(), 'log_level': mitogen.parent.get_log_level(),
'in_fd': sock2.fileno(), 'in_fd': sock2.fileno(),
'out_fd': sock2.fileno(), 'out_fd': sock2.fileno(),

@ -641,33 +641,7 @@ class Broker(mitogen.core.Broker):
self._watcher.remove() 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): class Router(mitogen.parent.Router):
context_class = Context
broker_class = Broker broker_class = Broker
debug = False debug = False
profiling = False profiling = False

@ -39,6 +39,7 @@ import termios
import textwrap import textwrap
import threading import threading
import time import time
import types
import zlib import zlib
import mitogen.core import mitogen.core
@ -467,6 +468,31 @@ class ChildIdAllocator(object):
return self.allocate() 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): class RouteMonitor(object):
def __init__(self, router, parent=None): def __init__(self, router, parent=None):
self.router = router self.router = router
@ -556,7 +582,7 @@ class RouteMonitor(object):
class Router(mitogen.core.Router): class Router(mitogen.core.Router):
context_class = mitogen.core.Context context_class = Context
id_allocator = None id_allocator = None
responder = None responder = None

@ -83,7 +83,7 @@ class Listener(mitogen.core.BasicStream):
pid, = struct.unpack('>L', sock.recv(4)) pid, = struct.unpack('>L', sock.recv(4))
context_id = self._router.id_allocator.allocate() 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 = mitogen.core.Stream(self._router, context_id)
stream.accept(sock.fileno(), sock.fileno()) stream.accept(sock.fileno(), sock.fileno())
stream.name = 'unix_client.%d' % (pid,) stream.name = 'unix_client.%d' % (pid,)
@ -111,7 +111,7 @@ def connect(path, broker=None):
stream.accept(sock.fileno(), sock.fileno()) stream.accept(sock.fileno(), sock.fileno())
stream.name = 'unix_listener.%d' % (pid,) stream.name = 'unix_listener.%d' % (pid,)
context = mitogen.master.Context(router, remote_id) context = mitogen.parent.Context(router, remote_id)
router.register(context, stream) router.register(context, stream)
mitogen.core.listen(router.broker, 'shutdown', mitogen.core.listen(router.broker, 'shutdown',

@ -13,7 +13,7 @@ import mitogen.ssh
import mitogen.sudo import mitogen.sudo
router = mitogen.master.Router() router = mitogen.master.Router()
context = mitogen.master.Context(router, 0) context = mitogen.parent.Context(router, 0)
stream = mitogen.ssh.Stream(router, 0, hostname='foo') stream = mitogen.ssh.Stream(router, 0, hostname='foo')
print 'SSH command size: %s' % (len(' '.join(stream.get_boot_command())),) print 'SSH command size: %s' % (len(' '.join(stream.get_boot_command())),)

Loading…
Cancel
Save