1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
"""Tests for helper functions used by import.c ."""
from importlib import _bootstrap_external, machinery
import os.path
from types import ModuleType, SimpleNamespace
import unittest
import warnings
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)
class TestBlessMyLoader(unittest.TestCase):
# GH#86298 is part of the migration away from module attributes and toward
# __spec__ attributes. There are several cases to test here. This will
# have to change in Python 3.14 when we actually remove/ignore __loader__
# in favor of requiring __spec__.loader.
def test_gh86298_no_loader_and_no_spec(self):
bar = ModuleType('bar')
del bar.__loader__
del bar.__spec__
# 2022-10-06(warsaw): For backward compatibility with the
# implementation in _warnings.c, this can't raise an
# AttributeError. See _bless_my_loader() in _bootstrap_external.py
# If working with a module:
## self.assertRaises(
## AttributeError, _bootstrap_external._bless_my_loader,
## bar.__dict__)
self.assertIsNone(_bootstrap_external._bless_my_loader(bar.__dict__))
def test_gh86298_loader_is_none_and_no_spec(self):
bar = ModuleType('bar')
bar.__loader__ = None
del bar.__spec__
# 2022-10-06(warsaw): For backward compatibility with the
# implementation in _warnings.c, this can't raise an
# AttributeError. See _bless_my_loader() in _bootstrap_external.py
# If working with a module:
## self.assertRaises(
## AttributeError, _bootstrap_external._bless_my_loader,
## bar.__dict__)
self.assertIsNone(_bootstrap_external._bless_my_loader(bar.__dict__))
def test_gh86298_no_loader_and_spec_is_none(self):
bar = ModuleType('bar')
del bar.__loader__
bar.__spec__ = None
self.assertRaises(
ValueError,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_loader_is_none_and_spec_is_none(self):
bar = ModuleType('bar')
bar.__loader__ = None
bar.__spec__ = None
self.assertRaises(
ValueError,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_loader_is_none_and_spec_loader_is_none(self):
bar = ModuleType('bar')
bar.__loader__ = None
bar.__spec__ = SimpleNamespace(loader=None)
self.assertRaises(
ValueError,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_no_spec(self):
bar = ModuleType('bar')
bar.__loader__ = object()
del bar.__spec__
with warnings.catch_warnings():
self.assertWarns(
DeprecationWarning,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_spec_is_none(self):
bar = ModuleType('bar')
bar.__loader__ = object()
bar.__spec__ = None
with warnings.catch_warnings():
self.assertWarns(
DeprecationWarning,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_no_spec_loader(self):
bar = ModuleType('bar')
bar.__loader__ = object()
bar.__spec__ = SimpleNamespace()
with warnings.catch_warnings():
self.assertWarns(
DeprecationWarning,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_loader_and_spec_loader_disagree(self):
bar = ModuleType('bar')
bar.__loader__ = object()
bar.__spec__ = SimpleNamespace(loader=object())
with warnings.catch_warnings():
self.assertWarns(
DeprecationWarning,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_no_loader_and_no_spec_loader(self):
bar = ModuleType('bar')
del bar.__loader__
bar.__spec__ = SimpleNamespace()
self.assertRaises(
AttributeError,
_bootstrap_external._bless_my_loader, bar.__dict__)
def test_gh86298_no_loader_with_spec_loader_okay(self):
bar = ModuleType('bar')
del bar.__loader__
loader = object()
bar.__spec__ = SimpleNamespace(loader=loader)
self.assertEqual(
_bootstrap_external._bless_my_loader(bar.__dict__),
loader)
if __name__ == "__main__":
unittest.main()
|