Skip to content

Commit 8c8aada

Browse files
committed
mitogen: Delegate modules in ModulePolicy.unsuitables to Python's importers
These are not modules that Mitogen should block import of., the previous name Importer.ALWAYS_BLACKLIST was a misnomer. It conflated their unsuitablility for serving by Mitogen with the concept of modules that should be blocked from import. Mitogen should have no opinion about whether they're imported from a local source. It is attempting to handle their import with Mitogen that we wish to avoid. With this cStringIO (& probably other platform/version specific modules) can be included regardless.
1 parent 91bf9c3 commit 8c8aada

4 files changed

Lines changed: 28 additions & 5 deletions

File tree

docs/changelog.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ In progress (unreleased)
2525
module overrides and blocks. Improve error messages for denied modules.
2626
* :gh:issue:`1451` :mod:`mitogen`: Move ``Importer.ALWAYS_BLACKLIST``
2727
to :attr:`mitogen.core.ImportPolicy.unsuitables`
28+
* :gh:issue:`1451` :mod:`mitogen`: Always delegate modules in
29+
:attr:`mitogen.core.ImportPolicy.unsuitables` to Python's own importers
2830

2931

3032
v0.3.41 (2026-02-10)

mitogen/core.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1323,11 +1323,11 @@ class ImportPolicy(object):
13231323
unsuitables = set([
13241324
'__builtin__', # Python 2.x built-in Imported as __builtins__.
13251325
'builtins', # Python 3.x built-in. Imported as __builtins__.
1326+
'cStringIO', # Python 2.x extension
13261327
'msvcrt', # Windows only. Imported by subprocess in some versions.
13271328
'org', # Jython only. Imported by copy, pickle, & xml.sax.
13281329
'thread', # Python 2.x built-in. Renamed to _thread in 3.x
13291330
])
1330-
if sys.version_info >= (3, 0): unsuitables.add('cStringIO')
13311331

13321332
def __init__(self, overrides=(), blocks=()):
13331333
self.overrides = set(overrides)
@@ -1348,6 +1348,9 @@ def denied_raise(self, fullname):
13481348
def overriden(self, fullname):
13491349
return bool(self.overrides.intersection(module_lineage(fullname)))
13501350

1351+
def unsuited(self, fullname):
1352+
return bool(self.unsuitables.intersection(module_lineage(fullname)))
1353+
13511354
def __repr__(self):
13521355
args = (type(self).__name__, self.overrides, self.blocks)
13531356
return '%s(overrides=%r, blocks=%r)' % args
@@ -1472,6 +1475,9 @@ def find_module(self, fullname, path=None):
14721475
if hasattr(_tls, 'running'):
14731476
return None
14741477

1478+
if self.policy.unsuited(fullname):
1479+
return None
1480+
14751481
_tls.running = True
14761482
try:
14771483
#_v and self._log.debug('Python requested %r', fullname)
@@ -1521,6 +1527,10 @@ def find_spec(self, fullname, path, target=None):
15211527
if fullname.endswith('.'):
15221528
return None
15231529

1530+
if self.policy.unsuited(fullname):
1531+
log.debug('Skipping %s. It is unsuited.')
1532+
return None
1533+
15241534
pkgname, _, modname = fullname.rpartition('.')
15251535
if pkgname and modname not in self._present.get(pkgname, ()):
15261536
log.debug('Skipping %s. Parent %s has no submodule %s',

tests/importer_test.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ImporterMixin(testlib.RouterMixin):
2323
def setUp(self):
2424
super(ImporterMixin, self).setUp()
2525
self.context = mock.Mock()
26-
self.policy = mock.Mock()
26+
self.policy = mitogen.core.ImportPolicy()
2727
self.importer = mitogen.core.Importer(self.router, self.context, '', self.policy)
2828

2929
# TODO: this is a horrendous hack. Without it, we can't deliver a
@@ -309,6 +309,16 @@ def test_overrides_and_blocks(self):
309309
self.assertTrue(policy.denied('__builtin__'))
310310
self.assertTrue(policy.denied('builtins'))
311311

312+
def test_unsuited(self):
313+
policy = mitogen.core.ImportPolicy(
314+
overrides=['pkg'],
315+
blocks=['pkg'],
316+
)
317+
self.assertTrue(policy.unsuited('__builtin__'))
318+
self.assertTrue(policy.unsuited('builtins'))
319+
self.assertFalse(policy.unsuited('pkg'))
320+
self.assertFalse(policy.unsuited('otherpkg'))
321+
312322

313323
class Python24LineCacheTest(testlib.TestCase):
314324
# TODO: mitogen.core.Importer._update_linecache()

tests/responder_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
except ImportError:
99
import mock
1010

11+
import mitogen.core
1112
import mitogen.master
1213
import testlib
1314

@@ -20,7 +21,7 @@ class NeutralizeMainTest(testlib.RouterMixin, testlib.TestCase):
2021

2122
def call(self, *args, **kwargs):
2223
router = mock.Mock()
23-
policy = mock.Mock()
24+
policy = mitogen.core.ImportPolicy()
2425
return self.klass(router, policy).neutralize_main(*args, **kwargs)
2526

2627
def test_missing_exec_guard(self):
@@ -120,7 +121,7 @@ def test_obviously_missing(self):
120121
)
121122
msg.router = router
122123

123-
policy = mock.Mock()
124+
policy = mitogen.core.ImportPolicy()
124125
responder = mitogen.master.ModuleResponder(router, policy)
125126
responder._on_get_module(msg)
126127
self.assertEqual(1, len(router._async_route.mock_calls))
@@ -159,7 +160,7 @@ def test_ansible_six_messed_up_path(self):
159160
)
160161
msg.router = router
161162

162-
policy = mock.Mock()
163+
policy = mitogen.core.ImportPolicy()
163164
responder = mitogen.master.ModuleResponder(router, policy)
164165
responder._on_get_module(msg)
165166
self.assertEqual(1, len(router._async_route.mock_calls))

0 commit comments

Comments
 (0)