gh-131290: ensure that test files can be executed as standalone scripts (#131371)

---------

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Maksim 2025-04-12 10:46:19 +03:00 committed by GitHub
parent 2aab2db146
commit 292a7248cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 39 additions and 8 deletions

View File

@ -297,4 +297,6 @@ def load_tests(loader, tests, pattern):
if __name__ == "__main__": if __name__ == "__main__":
# set __name__ to match doctest expectations
__name__ = "test.test_metaclass"
unittest.main() unittest.main()

View File

@ -3,7 +3,9 @@
Nick Mathewson Nick Mathewson
''' '''
import importlib.machinery
import sys import sys
from contextlib import contextmanager
from textwrap import dedent from textwrap import dedent
from types import FunctionType, MethodType, BuiltinFunctionType from types import FunctionType, MethodType, BuiltinFunctionType
import pyclbr import pyclbr
@ -22,6 +24,29 @@
# is imperfect (as designed), testModule is called with a set of # is imperfect (as designed), testModule is called with a set of
# members to ignore. # members to ignore.
@contextmanager
def temporary_main_spec():
"""
A context manager that temporarily sets the `__spec__` attribute
of the `__main__` module if it's missing.
"""
main_mod = sys.modules.get("__main__")
if main_mod is None:
yield # Do nothing if __main__ is not present
return
original_spec = getattr(main_mod, "__spec__", None)
if original_spec is None:
main_mod.__spec__ = importlib.machinery.ModuleSpec(
name="__main__", loader=None, origin="built-in"
)
try:
yield
finally:
main_mod.__spec__ = original_spec
class PyclbrTest(TestCase): class PyclbrTest(TestCase):
def assertListEq(self, l1, l2, ignore): def assertListEq(self, l1, l2, ignore):
@ -145,6 +170,7 @@ def test_easy(self):
self.checkModule('pyclbr') self.checkModule('pyclbr')
# XXX: Metaclasses are not supported # XXX: Metaclasses are not supported
# self.checkModule('ast') # self.checkModule('ast')
with temporary_main_spec():
self.checkModule('doctest', ignore=("TestResults", "_SpoofOut", self.checkModule('doctest', ignore=("TestResults", "_SpoofOut",
"DocTestCase", '_DocTestSuite')) "DocTestCase", '_DocTestSuite'))
self.checkModule('difflib', ignore=("Match",)) self.checkModule('difflib', ignore=("Match",))
@ -223,6 +249,7 @@ def test_others(self):
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning) warnings.simplefilter('ignore', DeprecationWarning)
cm('sre_parse', ignore=('dump', 'groups', 'pos')) # from sre_constants import *; property cm('sre_parse', ignore=('dump', 'groups', 'pos')) # from sre_constants import *; property
with temporary_main_spec():
cm( cm(
'pdb', 'pdb',
# pyclbr does not handle elegantly `typing` or properties # pyclbr does not handle elegantly `typing` or properties

View File

@ -2546,4 +2546,5 @@ def test_test_result_get_state(self):
if __name__ == '__main__': if __name__ == '__main__':
setup.setup_process()
unittest.main() unittest.main()

View File

@ -0,0 +1 @@
Tests in :file:`Lib/test` can now be correctly executed as standalone scripts.