From 4a9c7d019fdb4a9ebf666bb36eec5082b9cbf332 Mon Sep 17 00:00:00 2001 From: Orion Poplawski Date: Sun, 19 Jul 2020 18:06:30 -0600 Subject: [PATCH] Scan class definitions for import statements. Resolves #682 --- docs/changelog.rst | 1 + mitogen/master.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 407a8c78..9127a9f3 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -24,6 +24,7 @@ Unreleased * :gh:issue:`952` Fix Ansible `--ask-become-pass`, add test coverage * :gh:issue:`957` Fix Ansible exception when executing against 10s of hosts "ValueError: filedescriptor out of range in select()" +* :gh:issue:`682`: mitogen did not deploy class level imports. v0.3.7 (2024-04-08) diff --git a/mitogen/master.py b/mitogen/master.py index b1e0a1de..97f5ca45 100644 --- a/mitogen/master.py +++ b/mitogen/master.py @@ -250,7 +250,9 @@ if mitogen.is_master: mitogen.parent._get_core_source = _get_core_source +BUILD_TUPLE = dis.opname.index('BUILD_TUPLE') LOAD_CONST = dis.opname.index('LOAD_CONST') +LOAD_NAME = dis.opname.index('LOAD_NAME') IMPORT_NAME = dis.opname.index('IMPORT_NAME') @@ -284,7 +286,8 @@ def scan_code_imports(co): """ Given a code object `co`, scan its bytecode yielding any ``IMPORT_NAME`` and associated prior ``LOAD_CONST`` instructions representing an `Import` - statement or `ImportFrom` statement. + statement or `ImportFrom` statement. Also scan class definitions for + imports. :return: Generator producing `(level, modname, namelist)` tuples, where: @@ -307,11 +310,12 @@ def scan_code_imports(co): return if sys.version_info >= (2, 5): - for oparg1, oparg2, (op3, arg3) in izip(opit, opit2, opit3): - if op3 == IMPORT_NAME: - op2, arg2 = oparg2 - op1, arg1 = oparg1 - if op1 == op2 == LOAD_CONST: + for (op1, arg1), (op2, arg2), (op3, arg3) in izip(opit, opit2, opit3): + # Scan defined classes for imports + if op1 == LOAD_NAME and op2 == BUILD_TUPLE and op3 == LOAD_CONST and isinstance(co.co_consts[arg3],types.CodeType): + for level, modname, namelist in scan_code_imports(co.co_consts[arg3]): + yield (level, modname, namelist) + if op3 == IMPORT_NAME and op1 == op2 == LOAD_CONST: yield (co.co_consts[arg1], co.co_names[arg3], co.co_consts[arg2] or ())