(mod_name, error=ImportError)
| 102 | |
| 103 | # Helper to get the full name, spec and code for a module |
| 104 | def _get_module_details(mod_name, error=ImportError): |
| 105 | if mod_name.startswith("."): |
| 106 | raise error("Relative module names not supported") |
| 107 | pkg_name, _, _ = mod_name.rpartition(".") |
| 108 | if pkg_name: |
| 109 | # Try importing the parent to avoid catching initialization errors |
| 110 | try: |
| 111 | __import__(pkg_name) |
| 112 | except ImportError as e: |
| 113 | # If the parent or higher ancestor package is missing, let the |
| 114 | # error be raised by find_spec() below and then be caught. But do |
| 115 | # not allow other errors to be caught. |
| 116 | if e.name is None or (e.name != pkg_name and |
| 117 | not pkg_name.startswith(e.name + ".")): |
| 118 | raise |
| 119 | # Warn if the module has already been imported under its normal name |
| 120 | existing = sys.modules.get(mod_name) |
| 121 | if existing is not None and not hasattr(existing, "__path__"): |
| 122 | from warnings import warn |
| 123 | msg = "{mod_name!r} found in sys.modules after import of " \ |
| 124 | "package {pkg_name!r}, but prior to execution of " \ |
| 125 | "{mod_name!r}; this may result in unpredictable " \ |
| 126 | "behaviour".format(mod_name=mod_name, pkg_name=pkg_name) |
| 127 | warn(RuntimeWarning(msg)) |
| 128 | |
| 129 | try: |
| 130 | spec = importlib.util.find_spec(mod_name) |
| 131 | except (ImportError, AttributeError, TypeError, ValueError) as ex: |
| 132 | # This hack fixes an impedance mismatch between pkgutil and |
| 133 | # importlib, where the latter raises other errors for cases where |
| 134 | # pkgutil previously raised ImportError |
| 135 | msg = "Error while finding module specification for {!r} ({}: {})" |
| 136 | if mod_name.endswith(".py"): |
| 137 | msg += (f". Try using '{mod_name[:-3]}' instead of " |
| 138 | f"'{mod_name}' as the module name.") |
| 139 | raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex |
| 140 | if spec is None: |
| 141 | raise error("No module named %s" % mod_name) |
| 142 | if spec.submodule_search_locations is not None: |
| 143 | if mod_name == "__main__" or mod_name.endswith(".__main__"): |
| 144 | raise error("Cannot use package as __main__ module") |
| 145 | try: |
| 146 | pkg_main_name = mod_name + ".__main__" |
| 147 | return _get_module_details(pkg_main_name, error) |
| 148 | except error as e: |
| 149 | if mod_name not in sys.modules: |
| 150 | raise # No module loaded; being a package is irrelevant |
| 151 | raise error(("%s; %r is a package and cannot " + |
| 152 | "be directly executed") %(e, mod_name)) |
| 153 | loader = spec.loader |
| 154 | if loader is None: |
| 155 | raise error("%r is a namespace package and cannot be executed" |
| 156 | % mod_name) |
| 157 | try: |
| 158 | code = loader.get_code(mod_name) |
| 159 | except ImportError as e: |
| 160 | raise error(format(e)) from e |
| 161 | if code is None: |
no test coverage detected
searching dependent graphs…