|
|
|
@ -266,9 +266,12 @@ def scan_code_imports(co, LOAD_CONST=dis.opname.index('LOAD_CONST'),
|
|
|
|
|
for c in ordit)
|
|
|
|
|
|
|
|
|
|
opit, opit2, opit3 = itertools.tee(opit, 3)
|
|
|
|
|
next(opit2)
|
|
|
|
|
next(opit3)
|
|
|
|
|
next(opit3)
|
|
|
|
|
try:
|
|
|
|
|
next(opit2)
|
|
|
|
|
next(opit3)
|
|
|
|
|
next(opit3)
|
|
|
|
|
except StopIteration:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
for oparg1, oparg2, (op3, arg3) in itertools.izip(opit, opit2, opit3):
|
|
|
|
|
if op3 == IMPORT_NAME:
|
|
|
|
@ -532,6 +535,10 @@ class ModuleFinder(object):
|
|
|
|
|
"""Given an ImportFrom AST node, guess the prefix that should be tacked
|
|
|
|
|
on to an alias name to produce a canonical name. `fullname` is the name
|
|
|
|
|
of the module in which the ImportFrom appears."""
|
|
|
|
|
mod = sys.modules.get(fullname, None)
|
|
|
|
|
if hasattr(mod, '__path__'):
|
|
|
|
|
fullname += '.__init__'
|
|
|
|
|
|
|
|
|
|
if level == 0 or not fullname:
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
|
@ -540,11 +547,11 @@ class ModuleFinder(object):
|
|
|
|
|
# This would be an ImportError in real code.
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
|
|
return '.'.join(bits[:-level]) + '.'
|
|
|
|
|
return '.'.join(bits[:-level])
|
|
|
|
|
|
|
|
|
|
def generate_parent_names(self, fullname):
|
|
|
|
|
while '.' in fullname:
|
|
|
|
|
fullname = fullname[:fullname.rindex('.')]
|
|
|
|
|
fullname, _, _ = fullname.rpartition('.')
|
|
|
|
|
yield fullname
|
|
|
|
|
|
|
|
|
|
def find_related_imports(self, fullname):
|
|
|
|
@ -599,13 +606,14 @@ class ModuleFinder(object):
|
|
|
|
|
stack.extend(set(fullnames).difference(found, stack, [fullname]))
|
|
|
|
|
found.update(fullnames)
|
|
|
|
|
|
|
|
|
|
return found
|
|
|
|
|
return sorted(found)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ModuleResponder(object):
|
|
|
|
|
def __init__(self, router):
|
|
|
|
|
self._router = router
|
|
|
|
|
self._finder = ModuleFinder()
|
|
|
|
|
self._cache = {} # fullname -> pickled
|
|
|
|
|
router.add_handler(self._on_get_module, mitogen.core.GET_MODULE)
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
@ -622,40 +630,78 @@ class ModuleResponder(object):
|
|
|
|
|
return src[:match.start()]
|
|
|
|
|
return src
|
|
|
|
|
|
|
|
|
|
def _build_tuple(self, fullname):
|
|
|
|
|
if fullname in self._cache:
|
|
|
|
|
return self._cache[fullname]
|
|
|
|
|
|
|
|
|
|
path, source, is_pkg = self._finder.get_module_source(fullname)
|
|
|
|
|
if source is None:
|
|
|
|
|
raise ImportError('could not find %r' % (fullname,))
|
|
|
|
|
|
|
|
|
|
if is_pkg:
|
|
|
|
|
pkg_present = get_child_modules(path, fullname)
|
|
|
|
|
LOG.debug('_build_tuple(%r, %r) -> %r',
|
|
|
|
|
path, fullname, pkg_present)
|
|
|
|
|
else:
|
|
|
|
|
pkg_present = None
|
|
|
|
|
|
|
|
|
|
if fullname == '__main__':
|
|
|
|
|
source = self.neutralize_main(source)
|
|
|
|
|
compressed = zlib.compress(source)
|
|
|
|
|
related = list(self._finder.find_related(fullname))
|
|
|
|
|
# 0:fullname 1:pkg_present 2:path 3:compressed 4:related
|
|
|
|
|
tup = fullname, pkg_present, path, compressed, related
|
|
|
|
|
self._cache[fullname] = tup
|
|
|
|
|
return tup
|
|
|
|
|
|
|
|
|
|
def _send_load_module(self, stream, msg, fullname):
|
|
|
|
|
LOG.debug('_send_load_module(%r, %r)', stream, fullname)
|
|
|
|
|
self._router.route(
|
|
|
|
|
mitogen.core.Message.pickled(
|
|
|
|
|
self._build_tuple(fullname),
|
|
|
|
|
dst_id=msg.src_id,
|
|
|
|
|
handle=mitogen.core.LOAD_MODULE,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
stream.sent_modules.add(fullname)
|
|
|
|
|
|
|
|
|
|
def _on_get_module(self, msg):
|
|
|
|
|
LOG.debug('%r.get_module(%r)', self, msg)
|
|
|
|
|
if msg == mitogen.core._DEAD:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
stream = self._router.stream_by_id(msg.src_id)
|
|
|
|
|
fullname = msg.data
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
path, source, is_pkg = self._finder.get_module_source(fullname)
|
|
|
|
|
if source is None:
|
|
|
|
|
raise ImportError('could not find %r' % (fullname,))
|
|
|
|
|
|
|
|
|
|
if is_pkg:
|
|
|
|
|
pkg_present = get_child_modules(path, fullname)
|
|
|
|
|
LOG.debug('get_child_modules(%r, %r) -> %r',
|
|
|
|
|
path, fullname, pkg_present)
|
|
|
|
|
else:
|
|
|
|
|
pkg_present = None
|
|
|
|
|
tup = self._build_tuple(fullname)
|
|
|
|
|
|
|
|
|
|
for name in tup[4]: # related
|
|
|
|
|
if name == fullname:
|
|
|
|
|
# Must be sent last
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
parent_pkg, _, _ = name.partition('.')
|
|
|
|
|
if parent_pkg != fullname and parent_pkg not in stream.sent_packages:
|
|
|
|
|
# Parent hasn't been required, so don't load this guy yet.
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
if name in stream.sent_modules:
|
|
|
|
|
# Submodule has been sent already, skip.
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
self._send_load_module(stream, msg, name)
|
|
|
|
|
|
|
|
|
|
self._send_load_module(stream, msg, fullname)
|
|
|
|
|
if tup[1] is not None:
|
|
|
|
|
# It's a package, record the fact it was sent.
|
|
|
|
|
stream.sent_packages.add(fullname)
|
|
|
|
|
|
|
|
|
|
if fullname == '__main__':
|
|
|
|
|
source = self.neutralize_main(source)
|
|
|
|
|
compressed = zlib.compress(source)
|
|
|
|
|
related = list(self._finder.find_related(fullname))
|
|
|
|
|
self._router.route(
|
|
|
|
|
mitogen.core.Message.pickled(
|
|
|
|
|
(pkg_present, path, compressed, related),
|
|
|
|
|
dst_id=msg.src_id,
|
|
|
|
|
handle=msg.reply_to,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
except Exception:
|
|
|
|
|
LOG.debug('While importing %r', fullname, exc_info=True)
|
|
|
|
|
self._router.route(
|
|
|
|
|
mitogen.core.Message.pickled(
|
|
|
|
|
None,
|
|
|
|
|
(fullname, None, None, None, []),
|
|
|
|
|
dst_id=msg.src_id,
|
|
|
|
|
handle=msg.reply_to,
|
|
|
|
|
)
|
|
|
|
@ -682,41 +728,28 @@ class ModuleForwarder(object):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
fullname = msg.data
|
|
|
|
|
cached = self.importer._cache.get(fullname)
|
|
|
|
|
if cached:
|
|
|
|
|
LOG.debug('%r._on_get_module(): using cached %r', self, fullname)
|
|
|
|
|
self.router.route(
|
|
|
|
|
mitogen.core.Message.pickled(
|
|
|
|
|
cached,
|
|
|
|
|
dst_id=msg.src_id,
|
|
|
|
|
handle=msg.reply_to,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
LOG.debug('%r._on_get_module(): requesting %r', self, fullname)
|
|
|
|
|
self.parent_context.send(
|
|
|
|
|
mitogen.core.Message(
|
|
|
|
|
data=msg.data,
|
|
|
|
|
handle=mitogen.core.GET_MODULE,
|
|
|
|
|
reply_to=self.router.add_handler(
|
|
|
|
|
lambda m: self._on_got_source(m, msg),
|
|
|
|
|
persist=False
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
callback = lambda: self._on_cache_callback(msg, fullname)
|
|
|
|
|
self.importer._request_module(fullname, callback)
|
|
|
|
|
|
|
|
|
|
def _on_got_source(self, msg, original_msg):
|
|
|
|
|
LOG.debug('%r._on_got_source(%r, %r)', self, msg, original_msg)
|
|
|
|
|
fullname = original_msg.data
|
|
|
|
|
self.importer._cache[fullname] = msg.unpickle()
|
|
|
|
|
def _send_one_module(self, msg, tup):
|
|
|
|
|
self.router.route(
|
|
|
|
|
mitogen.core.Message(
|
|
|
|
|
data=msg.data,
|
|
|
|
|
dst_id=original_msg.src_id,
|
|
|
|
|
handle=original_msg.reply_to,
|
|
|
|
|
mitogen.core.Message.pickled(
|
|
|
|
|
tup,
|
|
|
|
|
dst_id=msg.src_id,
|
|
|
|
|
handle=mitogen.core.LOAD_MODULE,
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _on_cache_callback(self, msg, fullname):
|
|
|
|
|
LOG.debug('%r._on_get_module(): sending %r', self, fullname)
|
|
|
|
|
tup = self.importer._cache[fullname]
|
|
|
|
|
if tup is not None:
|
|
|
|
|
for related in tup[4]:
|
|
|
|
|
rtup = self.importer._cache[fullname]
|
|
|
|
|
self._send_one_module(msg, rtup)
|
|
|
|
|
|
|
|
|
|
self._send_one_module(msg, tup)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Stream(mitogen.core.Stream):
|
|
|
|
|
"""
|
|
|
|
@ -731,6 +764,11 @@ class Stream(mitogen.core.Stream):
|
|
|
|
|
#: True to cause context to write /tmp/mitogen.stats.<pid>.<thread>.log.
|
|
|
|
|
profiling = False
|
|
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super(Stream, self).__init__(*args, **kwargs)
|
|
|
|
|
self.sent_modules = set(['mitogen', 'mitogen.core'])
|
|
|
|
|
self.sent_packages = set(['mitogen'])
|
|
|
|
|
|
|
|
|
|
def construct(self, remote_name=None, python_path=None, debug=False,
|
|
|
|
|
profiling=False, **kwargs):
|
|
|
|
|
"""Get the named context running on the local machine, creating it if
|
|
|
|
|