@@ -457,6 +457,62 @@ def test_lazy_submodule_stored_in_parent_dict(self):
457457 self .assertIs (pkg .__dict__ ["bar" ], sys .modules ["test.test_lazy_import.data.pkg.bar" ])
458458 self .assertIn ("BAR_MODULE_LOADED" , out .getvalue ())
459459
460+ @support .requires_subprocess ()
461+ def test_lazy_submodule_missing_from_sys_modules_raises_key_error (self ):
462+ """A sys.modules race after import should surface the hard error."""
463+ code = textwrap .dedent ("""
464+ import os
465+ import sys
466+ import tempfile
467+
468+ class HidingModules(dict):
469+ hide = False
470+ hide_name = None
471+
472+ def __getitem__(self, name):
473+ if self.hide and name == self.hide_name:
474+ raise KeyError(name)
475+ return super().__getitem__(name)
476+
477+ with tempfile.TemporaryDirectory() as tmpdir:
478+ pkg_dir = os.path.join(tmpdir, "lazy_sysmodules_pkg")
479+ os.mkdir(pkg_dir)
480+ with open(os.path.join(pkg_dir, "__init__.py"), "w", encoding="utf-8") as f:
481+ f.write("")
482+ with open(os.path.join(pkg_dir, "sub.py"), "w", encoding="utf-8") as f:
483+ f.write("VALUE = 42\\ n")
484+
485+ original_modules = sys.modules
486+ modules = HidingModules(original_modules)
487+ sys.modules = modules
488+ sys.path.insert(0, tmpdir)
489+ try:
490+ lazy import lazy_sysmodules_pkg.sub
491+ modules.hide_name = "lazy_sysmodules_pkg.sub"
492+ modules.hide = True
493+
494+ try:
495+ lazy_sysmodules_pkg.sub
496+ except KeyError as exc:
497+ assert exc.args == ("lazy_sysmodules_pkg.sub",), exc
498+ else:
499+ raise AssertionError("KeyError was not raised")
500+ finally:
501+ sys.path.remove(tmpdir)
502+ sys.modules = original_modules
503+ for name in ("lazy_sysmodules_pkg", "lazy_sysmodules_pkg.sub"):
504+ sys.modules.pop(name, None)
505+
506+ print("OK")
507+ """ )
508+ result = subprocess .run (
509+ [sys .executable , "-c" , code ],
510+ capture_output = True ,
511+ text = True
512+ )
513+ self .assertEqual (result .returncode , 0 , f"stdout: { result .stdout } , stderr: { result .stderr } " )
514+ self .assertIn ("OK" , result .stdout )
515+
460516 def test_lazy_import_pkg_cross_import (self ):
461517 """Cross-imports within package should preserve lazy imports."""
462518 import test .test_lazy_import .data .pkg .c
0 commit comments