diff --git a/isort/settings.py b/isort/settings.py index 1ce832299..9c6bc3b24 100644 --- a/isort/settings.py +++ b/isort/settings.py @@ -46,6 +46,11 @@ from .wrap_modes import from_string as wrap_mode_from_string if TYPE_CHECKING: + if sys.version_info < (3, 10): # pragma: no cover + EntryPoints = Any + else: + from importlib.metadata import EntryPoints + tomllib: Any else: if sys.version_info >= (3, 11): @@ -356,9 +361,7 @@ def __init__( profile: Dict[str, Any] = {} if profile_name: if profile_name not in profiles: - import pkg_resources - - for plugin in pkg_resources.iter_entry_points("isort.profiles"): + for plugin in entry_points(group="isort.profiles"): profiles.setdefault(plugin.name, plugin.load()) if profile_name not in profiles: @@ -473,9 +476,7 @@ def __init__( combined_config["src_paths"] = tuple(src_paths) if "formatter" in combined_config: - import pkg_resources - - for plugin in pkg_resources.iter_entry_points("isort.formatters"): + for plugin in entry_points(group="isort.formatters"): if plugin.name == combined_config["formatter"]: combined_config["formatting_function"] = plugin.load() break @@ -715,9 +716,7 @@ def sorting_function(self) -> Callable[..., List[str]]: self._sorting_function = sorted else: available_sort_orders = ["natural", "native"] - import pkg_resources - - for sort_plugin in pkg_resources.iter_entry_points("isort.sort_function"): + for sort_plugin in entry_points(group="isort.sort_function"): available_sort_orders.append(sort_plugin.name) if sort_plugin.name == self.sort_order: self._sorting_function = sort_plugin.load() @@ -938,4 +937,17 @@ def _as_bool(value: str) -> bool: raise ValueError(f"invalid truth value {value}") +def entry_points(group: str) -> "EntryPoints": + """Call entry_point after lazy loading it. + + TODO: The reason for lazy loading here are unknown. + """ + if sys.version_info < (3, 10): # pragma: no cover + from importlib_metadata import entry_points + else: + from importlib.metadata import entry_points + + return entry_points(group=group) + + DEFAULT_CONFIG = Config() diff --git a/pyproject.toml b/pyproject.toml index 6614569fa..9152b2045 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,13 @@ include = [ ] requires-python = ">=3.9.0" -dependencies = [] +dependencies = [ + # we only need the entry_points() function, which appeared in the stdlib + # in Python 3.10. + # importlib_metadata 4.6 is the version matching stdlib 3.10 + # See grid at https://pypi.org/project/importlib-metadata/ + "importlib_metadata >= 4.6.0; python_version < '3.10'", +] [project.urls] Homepage = "https://pycqa.github.io/isort/index.html" @@ -174,6 +180,10 @@ allow_untyped_defs = true allow_incomplete_defs = true allow_untyped_calls = true +[[tool.mypy.overrides]] +module = "importlib_metadata.*" +ignore_missing_imports = true + [tool.ruff] line-length = 100 lint.select = [ diff --git a/tests/unit/test_regressions.py b/tests/unit/test_regressions.py index 4180f81c0..1d97fa5a2 100644 --- a/tests/unit/test_regressions.py +++ b/tests/unit/test_regressions.py @@ -1875,11 +1875,7 @@ class Bar: def test_isort_should_produce_the_same_code_on_subsequent_runs_issue_1799(tmpdir): code = """import sys -if sys.version_info[:2] >= (3, 8): - # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8` - from importlib.metadata import PackageNotFoundError, version # pragma: no cover -else: - from importlib_metadata import PackageNotFoundError, version # pragma: no cover +from importlib.metadata import PackageNotFoundError, version """ config_file = tmpdir.join(".isort.cfg") config_file.write(