gh-65961: Do not rely solely on __cached__ (GH-97990)

Make sure `__spec__.cached` (at minimum) can be used.
This commit is contained in:
Brett Cannon 2022-10-06 15:40:22 -07:00 committed by GitHub
parent f8edc6ff53
commit e1c4d56fdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 130 additions and 35 deletions

View file

@ -0,0 +1,71 @@
"""Tests for helper functions used by import.c ."""
from importlib import _bootstrap_external, machinery
import os.path
import unittest
from .. import util
class FixUpModuleTests:
def test_no_loader_but_spec(self):
loader = object()
name = "hello"
path = "hello.py"
spec = machinery.ModuleSpec(name, loader)
ns = {"__spec__": spec}
_bootstrap_external._fix_up_module(ns, name, path)
expected = {"__spec__": spec, "__loader__": loader, "__file__": path,
"__cached__": None}
self.assertEqual(ns, expected)
def test_no_loader_no_spec_but_sourceless(self):
name = "hello"
path = "hello.py"
ns = {}
_bootstrap_external._fix_up_module(ns, name, path, path)
expected = {"__file__": path, "__cached__": path}
for key, val in expected.items():
with self.subTest(f"{key}: {val}"):
self.assertEqual(ns[key], val)
spec = ns["__spec__"]
self.assertIsInstance(spec, machinery.ModuleSpec)
self.assertEqual(spec.name, name)
self.assertEqual(spec.origin, os.path.abspath(path))
self.assertEqual(spec.cached, os.path.abspath(path))
self.assertIsInstance(spec.loader, machinery.SourcelessFileLoader)
self.assertEqual(spec.loader.name, name)
self.assertEqual(spec.loader.path, path)
self.assertEqual(spec.loader, ns["__loader__"])
def test_no_loader_no_spec_but_source(self):
name = "hello"
path = "hello.py"
ns = {}
_bootstrap_external._fix_up_module(ns, name, path)
expected = {"__file__": path, "__cached__": None}
for key, val in expected.items():
with self.subTest(f"{key}: {val}"):
self.assertEqual(ns[key], val)
spec = ns["__spec__"]
self.assertIsInstance(spec, machinery.ModuleSpec)
self.assertEqual(spec.name, name)
self.assertEqual(spec.origin, os.path.abspath(path))
self.assertIsInstance(spec.loader, machinery.SourceFileLoader)
self.assertEqual(spec.loader.name, name)
self.assertEqual(spec.loader.path, path)
self.assertEqual(spec.loader, ns["__loader__"])
FrozenFixUpModuleTests, SourceFixUpModuleTests = util.test_both(FixUpModuleTests)
if __name__ == "__main__":
unittest.main()

View file

@ -4358,8 +4358,11 @@ class TestMain(unittest.TestCase):
'unittest', '--details')
output = out.decode()
# Just a quick sanity check on the output
self.assertIn(module.__spec__.name, output)
self.assertIn(module.__name__, output)
self.assertIn(module.__spec__.origin, output)
self.assertIn(module.__file__, output)
self.assertIn(module.__spec__.cached, output)
self.assertIn(module.__cached__, output)
self.assertEqual(err, b'')

View file

@ -702,7 +702,7 @@ class PydocDocTest(unittest.TestCase):
def test_synopsis_sourceless(self):
os = import_helper.import_fresh_module('os')
expected = os.__doc__.splitlines()[0]
filename = os.__cached__
filename = os.__spec__.cached
synopsis = pydoc.synopsis(filename)
self.assertEqual(synopsis, expected)