|
3 | 3 | # Copyright (c) 2021 Daniël van Noord <[email protected]>
|
4 | 4 | # Copyright (c) 2021 Neil Girdhar <[email protected]>
|
5 | 5 |
|
| 6 | +try: |
| 7 | + import pkg_resources |
| 8 | +except ImportError: |
| 9 | + pkg_resources = None # type: ignore[assignment] |
6 | 10 |
|
7 |
| -from importlib import abc, util |
8 |
| - |
9 |
| -from astroid.const import PY36 |
10 |
| - |
11 |
| - |
12 |
| -def _is_old_setuptools_namespace_package(modname: str) -> bool: |
13 |
| - """Check for old types of setuptools namespace packages. |
14 |
| -
|
15 |
| - See https://setuptools.pypa.io/en/latest/pkg_resources.html and |
16 |
| - https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ |
17 |
| -
|
18 |
| - Because pkg_resources is slow to import we only do so if explicitly necessary. |
19 |
| - """ |
20 |
| - try: |
21 |
| - import pkg_resources # pylint: disable=import-outside-toplevel |
22 |
| - except ImportError: |
23 |
| - return False |
24 | 11 |
|
| 12 | +def is_namespace(modname): |
25 | 13 | return (
|
26 |
| - hasattr(pkg_resources, "_namespace_packages") |
27 |
| - and modname in pkg_resources._namespace_packages # type: ignore[attr-defined] |
28 |
| - ) |
29 |
| - |
30 |
| - |
31 |
| -def is_namespace(modname: str) -> bool: |
32 |
| - """Determine whether we encounter a namespace package.""" |
33 |
| - if PY36: |
34 |
| - # On Python 3.6 an AttributeError is raised when a package |
35 |
| - # is lacking a __path__ attribute and thus is not a |
36 |
| - # package. |
37 |
| - try: |
38 |
| - spec = util.find_spec(modname) |
39 |
| - except (AttributeError, ValueError): |
40 |
| - return _is_old_setuptools_namespace_package(modname) |
41 |
| - else: |
42 |
| - try: |
43 |
| - spec = util.find_spec(modname) |
44 |
| - except ValueError: |
45 |
| - return _is_old_setuptools_namespace_package(modname) |
46 |
| - |
47 |
| - # If there is no spec or origin this is a namespace package |
48 |
| - # See: https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.origin |
49 |
| - # We assume builtin packages are never namespace |
50 |
| - if not spec or not spec.origin or spec.origin == "built-in": |
51 |
| - return False |
52 |
| - |
53 |
| - # If there is no loader the package is namespace |
54 |
| - # See https://docs.python.org/3/library/importlib.html#importlib.abc.PathEntryFinder.find_loader |
55 |
| - if not spec.loader: |
56 |
| - return True |
57 |
| - # This checks for _frozen_importlib.FrozenImporter, which does not inherit from InspectLoader |
58 |
| - if hasattr(spec.loader, "_ORIGIN") and spec.loader._ORIGIN == "frozen": |
59 |
| - return False |
60 |
| - # Other loaders are namespace packages |
61 |
| - if not isinstance(spec.loader, abc.InspectLoader): |
62 |
| - return True |
63 |
| - |
64 |
| - # Lastly we check if the package declares itself a namespace package |
65 |
| - try: |
66 |
| - source = spec.loader.get_source(spec.origin) |
67 |
| - # If the loader can't handle the spec, we're dealing with a namespace package |
68 |
| - except ImportError: |
69 |
| - return False |
70 |
| - return bool( |
71 |
| - source and "pkg_resources" in source and "declare_namespace(__name__)" in source |
| 14 | + pkg_resources is not None |
| 15 | + and hasattr(pkg_resources, "_namespace_packages") |
| 16 | + and modname in pkg_resources._namespace_packages |
72 | 17 | )
|
0 commit comments