Skip to content

Commit db584bd

Browse files
authored
bpo-42955: Add sys.modules_names (pythonGH-24238)
Add sys.module_names, containing the list of the standard library module names.
1 parent 879986d commit db584bd

File tree

10 files changed

+303
-273
lines changed

10 files changed

+303
-273
lines changed

Doc/library/sys.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,12 @@ always available.
153153

154154
.. data:: builtin_module_names
155155

156-
A tuple of strings giving the names of all modules that are compiled into this
156+
A tuple of strings containing the names of all modules that are compiled into this
157157
Python interpreter. (This information is not available in any other way ---
158158
``modules.keys()`` only lists the imported modules.)
159159

160+
See also the :attr:`sys.module_names` list.
161+
160162

161163
.. function:: call_tracing(func, args)
162164

@@ -1060,6 +1062,24 @@ always available.
10601062
This is still called as a fallback if a :data:`meta_path` entry doesn't
10611063
have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
10621064

1065+
.. data:: module_names
1066+
1067+
A frozenset of strings containing the names of standard library modules.
1068+
1069+
It is the same on all platforms. Modules which are not available on
1070+
some platforms and modules disabled at Python build are also listed.
1071+
All module kinds are listed: pure Python, built-in, frozen and extension
1072+
modules. Test modules are excluded.
1073+
1074+
For packages, only sub-packages are listed, not sub-modules. For example,
1075+
``concurrent`` package and ``concurrent.futures`` sub-package are listed,
1076+
but not ``concurrent.futures.base`` sub-module.
1077+
1078+
See also the :attr:`sys.builtin_module_names` list.
1079+
1080+
.. versionchanged:: 3.10
1081+
1082+
10631083
.. data:: modules
10641084

10651085
This is a dictionary that maps module names to modules which have already been

Doc/whatsnew/3.10.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ Add :data:`sys.orig_argv` attribute: the list of the original command line
396396
arguments passed to the Python executable.
397397
(Contributed by Victor Stinner in :issue:`23427`.)
398398
399+
Add :data:`sys.module_names`, containing the list of the standard library
400+
module names.
401+
(Contributed by Victor Stinner in :issue:`42955`.)
402+
399403
threading
400404
---------
401405

Lib/test/test_capi.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,23 @@ def check_fatal_error(self, code, expected, not_expected=()):
569569
self.assertEqual(len(modules), total)
570570

571571
def test_fatal_error(self):
572+
# By default, stdlib extension modules are ignored,
573+
# but not test modules.
572574
expected = ('_testcapi',)
573-
not_expected = ('sys', 'builtins', '_imp', '_thread', '_weakref',
574-
'_io', 'marshal', '_signal', '_abc')
575-
code = 'import _testcapi; _testcapi.fatal_error(b"MESSAGE")'
575+
not_expected = ('sys',)
576+
code = 'import _testcapi, sys; _testcapi.fatal_error(b"MESSAGE")'
576577
self.check_fatal_error(code, expected, not_expected)
577578

579+
# Mark _testcapi as stdlib module, but not sys
580+
expected = ('sys',)
581+
not_expected = ('_testcapi',)
582+
code = textwrap.dedent('''
583+
import _testcapi, sys
584+
sys.module_names = frozenset({"_testcapi"})
585+
_testcapi.fatal_error(b"MESSAGE")
586+
''')
587+
self.check_fatal_error(code, expected)
588+
578589

579590
class TestPendingCalls(unittest.TestCase):
580591

Lib/test/test_faulthandler.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,9 @@ def test_disable(self):
334334
def test_dump_ext_modules(self):
335335
code = """
336336
import faulthandler
337-
# _testcapi is a test module and not considered as a stdlib module
338-
import _testcapi
337+
import sys
338+
# Don't filter stdlib module names
339+
sys.module_names = frozenset()
339340
faulthandler.enable()
340341
faulthandler._sigsegv()
341342
"""
@@ -346,7 +347,8 @@ def test_dump_ext_modules(self):
346347
if not match:
347348
self.fail(f"Cannot find 'Extension modules:' in {stderr!r}")
348349
modules = set(match.group(1).strip().split(', '))
349-
self.assertIn('_testcapi', modules)
350+
for name in ('sys', 'faulthandler'):
351+
self.assertIn(name, modules)
350352

351353
def test_is_enabled(self):
352354
orig_stderr = sys.stderr

Lib/test/test_sys.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,11 @@ def test_orig_argv(self):
986986
self.assertEqual(proc.stdout.rstrip().splitlines(), expected,
987987
proc)
988988

989+
def test_module_names(self):
990+
self.assertIsInstance(sys.module_names, frozenset)
991+
for name in sys.module_names:
992+
self.assertIsInstance(name, str)
993+
989994

990995
@test.support.cpython_only
991996
class UnraisableHookTest(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :data:`sys.module_names`, containing the list of the standard library
2+
module names. Patch by Victor Stinner.

0 commit comments

Comments
 (0)