| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7e4cf8e commit a71397f
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1077,7 +1077,7 @@ find and load modules. | |||
| 1077 | 1077 | Name of the place from which the module is loaded, e.g. "builtin" for | |
| 1078 | 1078 | built-in modules and the filename for modules loaded from source. | |
| 1079 | 1079 | Normally "origin" should be set, but it may be ``None`` (the default) | |
| 1080 | - which indicates it is unspecified. | ||
| 1080 | + which indicates it is unspecified (e.g. for namespace packages). | ||
| 1081 | 1081 | ||
| 1082 | 1082 | .. attribute:: submodule_search_locations | |
| 1083 | 1083 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -522,6 +522,18 @@ def _init_module_attrs(spec, module, *, override=False): | |||
| 522 | 522 | ||
| 523 | 523 | loader = _NamespaceLoader.__new__(_NamespaceLoader) | |
| 524 | 524 | loader._path = spec.submodule_search_locations | |
| 525 | + spec.loader = loader | ||
| 526 | + # While the docs say that module.__file__ is not set for | ||
| 527 | + # built-in modules, and the code below will avoid setting it if | ||
| 528 | + # spec.has_location is false, this is incorrect for namespace | ||
| 529 | + # packages. Namespace packages have no location, but their | ||
| 530 | + # __spec__.origin is None, and thus their module.__file__ | ||
| 531 | + # should also be None for consistency. While a bit of a hack, | ||
| 532 | + # this is the best place to ensure this consistency. | ||
| 533 | + # | ||
| 534 | + # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module | ||
| 535 | + # and bpo-32305 | ||
| 536 | + module.__file__ = None | ||
| 525 | 537 | try: | |
| 526 | 538 | module.__loader__ = loader | |
| 527 | 539 | except AttributeError: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1160,9 +1160,9 @@ def find_spec(cls, fullname, path=None, target=None): | |||
| 1160 | 1160 | elif spec.loader is None: | |
| 1161 | 1161 | namespace_path = spec.submodule_search_locations | |
| 1162 | 1162 | if namespace_path: | |
| 1163 | - # We found at least one namespace path. Return a | ||
| 1164 | - # spec which can create the namespace package. | ||
| 1165 | - spec.origin = 'namespace' | ||
| 1163 | + # We found at least one namespace path. Return a spec which | ||
| 1164 | + # can create the namespace package. | ||
| 1165 | + spec.origin = None | ||
| 1166 | 1166 | spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) | |
| 1167 | 1167 | return spec | |
| 1168 | 1168 | else: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -307,6 +307,7 @@ def test_reload_namespace_changed(self): | |||
| 307 | 307 | expected = {'__name__': name, | |
| 308 | 308 | '__package__': name, | |
| 309 | 309 | '__doc__': None, | |
| 310 | + '__file__': None, | ||
| 310 | 311 | } | |
| 311 | 312 | os.mkdir(name) | |
| 312 | 313 | with open(bad_path, 'w') as init_file: | |
@@ -318,8 +319,9 @@ def test_reload_namespace_changed(self): | |||
| 318 | 319 | spec = ns.pop('__spec__') | |
| 319 | 320 | ns.pop('__builtins__', None) # An implementation detail. | |
| 320 | 321 | self.assertEqual(spec.name, name) | |
| 321 | - self.assertIs(spec.loader, None) | ||
| 322 | - self.assertIsNot(loader, None) | ||
| 322 | + self.assertIsNotNone(spec.loader) | ||
| 323 | + self.assertIsNotNone(loader) | ||
| 324 | + self.assertEqual(spec.loader, loader) | ||
| 323 | 325 | self.assertEqual(set(path), | |
| 324 | 326 | set([os.path.dirname(bad_path)])) | |
| 325 | 327 | with self.assertRaises(AttributeError): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -317,5 +317,21 @@ def test_dynamic_path(self): | |||
| 317 | 317 | self.assertEqual(foo.two.attr, 'portion2 foo two') | |
| 318 | 318 | ||
| 319 | 319 | ||
| 320 | + class LoaderTests(NamespacePackageTest): | ||
| 321 | + paths = ['portion1'] | ||
| 322 | + | ||
| 323 | + def test_namespace_loader_consistency(self): | ||
| 324 | + # bpo-32303 | ||
| 325 | + import foo | ||
| 326 | + self.assertEqual(foo.__loader__, foo.__spec__.loader) | ||
| 327 | + self.assertIsNotNone(foo.__loader__) | ||
| 328 | + | ||
| 329 | + def test_namespace_origin_consistency(self): | ||
| 330 | + # bpo-32305 | ||
| 331 | + import foo | ||
| 332 | + self.assertIsNone(foo.__spec__.origin) | ||
| 333 | + self.assertIsNone(foo.__file__) | ||
| 334 | + | ||
| 335 | + | ||
| 320 | 336 | if __name__ == "__main__": | |
| 321 | 337 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + For namespace packages, ensure that both ``__file__`` and | ||
| 2 | + ``__spec__.origin`` are set to None. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments