Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 22 additions & 29 deletions mitogen/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ def enable_profiling(econtext=None):

def import_module(modname):
"""
Import `module` and return the attribute named `attr`.
Return the module with absolute name `modname`, importing it as necessary.
"""
return __import__(modname, None, None, [''])

Expand Down Expand Up @@ -1319,18 +1319,22 @@ class ImportPolicy(object):
:param blocks:
Prefixes always denied by the responder, only local versions can be
used.

:param unsuitables:
Prefixes unsuitable to be served, e.g. because they're Python stdlib,
platform specific. An optimisation to reduce futile round trips.
"""
def __init__(self, overrides=(), blocks=()):
def __init__(self, overrides=(), blocks=(), unsuitables=()):
self.overrides = set(overrides)
self.blocks = set(blocks)
self._always = set(Importer.ALWAYS_BLACKLIST)
self.unsuitables = set(unsuitables)

def denied(self, fullname):
fullnames = frozenset(module_lineage(fullname))
if self.overrides and not self.overrides.intersection(fullnames):
return ModuleDeniedByOverridesError
if self.blocks.intersection(fullnames): return ModuleDeniedByBlocksError
if self._always.intersection(fullnames): return ModuleUnsuitableError
if self.unsuitables.intersection(fullnames): return ModuleUnsuitableError
return False

def denied_raise(self, fullname):
Expand All @@ -1340,9 +1344,13 @@ def denied_raise(self, fullname):
def overriden(self, fullname):
return bool(self.overrides.intersection(module_lineage(fullname)))

def unsuited(self, fullname):
return bool(self.unsuitables.intersection(module_lineage(fullname)))

def __repr__(self):
args = (type(self).__name__, self.overrides, self.blocks)
return '%s(overrides=%r, blocks=%r)' % args
name = type(self).__name__
args = (name, self.overrides, self.blocks, self.unsuitables)
return '%s(overrides=%r, blocks=%r, unsuitables=%r)' % args


class Importer(object):
Expand Down Expand Up @@ -1381,29 +1389,6 @@ class Importer(object):
'utils',
]

ALWAYS_BLACKLIST = [
# 2.x generates needless imports for 'builtins', while 3.x does the
# same for '__builtin__'. The correct one is built-in, the other always
# a negative round-trip.
'builtins',
'__builtin__',

# On some Python releases (e.g. 3.8, 3.9) the subprocess module tries
# to import of this Windows-only builtin module.
'msvcrt',

# Python 2.x module that was renamed to _thread in 3.x.
# This entry avoids a roundtrip on 2.x -> 3.x.
'thread',

# org.python.core imported by copy, pickle, xml.sax; breaks Jython, but
# very unlikely to trigger a bug report.
'org',
]

if sys.version_info >= (3, 0):
ALWAYS_BLACKLIST += ['cStringIO']

def __init__(self, router, context, core_src, policy):
self._log = logging.getLogger('mitogen.importer')
self._context = context
Expand Down Expand Up @@ -1487,6 +1472,9 @@ def find_module(self, fullname, path=None):
if hasattr(_tls, 'running'):
return None

if self.policy.unsuited(fullname):
return None

_tls.running = True
try:
#_v and self._log.debug('Python requested %r', fullname)
Expand Down Expand Up @@ -1536,6 +1524,10 @@ def find_spec(self, fullname, path, target=None):
if fullname.endswith('.'):
return None

if self.policy.unsuited(fullname):
log.debug('Skipping %s. It is unsuited.')
return None

pkgname, _, modname = fullname.rpartition('.')
if pkgname and modname not in self._present.get(pkgname, ()):
log.debug('Skipping %s. Parent %s has no submodule %s',
Expand Down Expand Up @@ -4205,6 +4197,7 @@ def _setup_importer(self):
policy = ImportPolicy(
self.config['import_overrides'],
self.config['import_blocks'],
self.config['import_unsuitables'],
)
importer = Importer(
self.router,
Expand Down
30 changes: 30 additions & 0 deletions mitogen/imports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,33 @@ def codeobj_imports(co):
* `names`: tuple of names in `from mod import ..`.
"""
return _code_imports(co.co_code, co.co_consts, co.co_names)


def stdlib_module_names(version_info=None):
"""
Return a set of known module names for a Python version.
"""
if version_info is None:
version_info = sys.version_info
if version_info >= (3, 10):
return sys.stdlib_module_names

modname = "%s.stdlibs.py%d%d" % (__name__, version_info[0], version_info[1])
return __import__(modname, None, None, ['']).module_names


def unsuitable_module_names(version_info=None):
"""
Return a set of module names known to be unsuitable for serving by Mitogen.
"""
if version_info is None:
version_info = sys.version_info
names = set([
'org', # Jython, Imported by copy, pickle, & xml.sax.
])
names.update(stdlib_module_names(version_info))
if version_info >= (3, 0):
names.update(stdlib_module_names((2, 7)))
else:
names.update(stdlib_module_names((3, 6)))
return names
Empty file.
Loading