Skip to content

Commit cd5c8a0

Browse files
Merge pull request #1130 from RonnyPfannschmidt/fix-1013-importlib-dedup
use importlib_metadata on python <3.10 resolves duplicate finding of certain distributions
2 parents 1f7abea + 0a07be8 commit cd5c8a0

File tree

6 files changed

+39
-45
lines changed

6 files changed

+39
-45
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22

3-
## v8.2.1
3+
## v8.3.0
4+
5+
### Fixed
6+
7+
- fix #1013: use modern importlib_metadata in all cases to dedup distribution objects that must shadow based on pythonpath priority
8+
starting with python 3.10 this is part of python itself
9+
10+
## v8.2.1 (yanked due to legacy python issues)
411

512
### Fixed
613

pyproject.toml

+15-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ build-backend = "_own_version_helper:build_meta"
55
requires = [
66
"setuptools>=61",
77
'tomli<=2.0.2; python_version < "3.11"',
8+
'importlib-metadata>=4.6; python_version < "3.10"',
89
]
910
backend-path = [
1011
".",
@@ -43,9 +44,10 @@ dynamic = [
4344
dependencies = [
4445
"packaging>=20",
4546
# https://github.com/pypa/setuptools-scm/issues/1112 - re-pin in a breaking release
46-
"setuptools", # >=61",
47+
"setuptools", # >= 61",
4748
'tomli>=1; python_version < "3.11"',
4849
'typing-extensions; python_version < "3.10"',
50+
'importlib-metadata>=4.6; python_version < "3.10"',
4951
]
5052
[project.optional-dependencies]
5153
docs = [
@@ -69,38 +71,49 @@ test = [
6971
]
7072
toml = [
7173
]
74+
7275
[project.urls]
7376
documentation = "https://setuptools-scm.readthedocs.io/"
7477
repository = "https://github.com/pypa/setuptools-scm/"
78+
7579
[project.entry-points."distutils.setup_keywords"]
7680
use_scm_version = "setuptools_scm._integration.setuptools:version_keyword"
81+
7782
[project.entry-points."pipx.run"]
7883
setuptools-scm = "setuptools_scm._cli:main"
7984
setuptools_scm = "setuptools_scm._cli:main"
85+
8086
[project.entry-points."setuptools.file_finders"]
8187
setuptools_scm = "setuptools_scm._file_finders:find_files"
88+
8289
[project.entry-points."setuptools.finalize_distribution_options"]
8390
setuptools_scm = "setuptools_scm._integration.setuptools:infer_version"
91+
8492
[project.entry-points."setuptools_scm.files_command"]
8593
".git" = "setuptools_scm._file_finders.git:git_find_files"
8694
".hg" = "setuptools_scm._file_finders.hg:hg_find_files"
95+
8796
[project.entry-points."setuptools_scm.files_command_fallback"]
8897
".git_archival.txt" = "setuptools_scm._file_finders.git:git_archive_find_files"
8998
".hg_archival.txt" = "setuptools_scm._file_finders.hg:hg_archive_find_files"
99+
90100
[project.entry-points."setuptools_scm.local_scheme"]
91101
dirty-tag = "setuptools_scm.version:get_local_dirty_tag"
92102
no-local-version = "setuptools_scm.version:get_no_local_node"
93103
node-and-date = "setuptools_scm.version:get_local_node_and_date"
94104
node-and-timestamp = "setuptools_scm.version:get_local_node_and_timestamp"
105+
95106
[project.entry-points."setuptools_scm.parse_scm"]
96107
".git" = "setuptools_scm.git:parse"
97108
".hg" = "setuptools_scm.hg:parse"
109+
98110
[project.entry-points."setuptools_scm.parse_scm_fallback"]
99111
".git_archival.txt" = "setuptools_scm.git:parse_archival"
100112
".hg_archival.txt" = "setuptools_scm.hg:parse_archival"
101113
PKG-INFO = "setuptools_scm.fallbacks:parse_pkginfo"
102114
"pyproject.toml" = "setuptools_scm.fallbacks:fallback_version"
103115
"setup.py" = "setuptools_scm.fallbacks:fallback_version"
116+
104117
[project.entry-points."setuptools_scm.version_scheme"]
105118
"calver-by-date" = "setuptools_scm.version:calver_by_date"
106119
"guess-next-dev" = "setuptools_scm.version:guess_next_dev_version"
@@ -133,7 +146,7 @@ order-by-type = true
133146
ignore = ["PP305", "GH103", "GH212", "MY100", "PC111", "PC160", "PC170", "PC180", "PC901"]
134147

135148
[tool.pytest.ini_options]
136-
minversion = "7"
149+
minversion = "8"
137150
testpaths = ["testing"]
138151
filterwarnings = [
139152
"error",

src/setuptools_scm/_entrypoints.py

+5-30
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,12 @@
1717
from ._config import Configuration
1818
from ._config import ParseFunction
1919

20-
21-
from importlib.metadata import EntryPoint as EntryPoint
22-
2320
if sys.version_info[:2] < (3, 10):
24-
from importlib.metadata import entry_points as legacy_entry_points
25-
26-
class EntryPoints:
27-
_groupdata: list[EntryPoint]
28-
29-
def __init__(self, groupdata: list[EntryPoint]) -> None:
30-
self._groupdata = groupdata
31-
32-
def select(self, name: str) -> EntryPoints:
33-
return EntryPoints([x for x in self._groupdata if x.name == name])
34-
35-
def __iter__(self) -> Iterator[EntryPoint]:
36-
return iter(self._groupdata)
37-
38-
def entry_points(group: str) -> EntryPoints:
39-
return EntryPoints(legacy_entry_points()[group])
40-
21+
from importlib_metadata import EntryPoint as EntryPoint
22+
from importlib_metadata import entry_points as entry_points
4123
else:
42-
from importlib.metadata import EntryPoints
43-
from importlib.metadata import entry_points
24+
from importlib.metadata import EntryPoint as EntryPoint
25+
from importlib.metadata import entry_points as entry_points
4426

4527

4628
log = _log.log.getChild("entrypoints")
@@ -61,15 +43,8 @@ def version_from_entrypoint(
6143
return None
6244

6345

64-
def iter_entry_points(group: str, name: str | None = None) -> Iterator[EntryPoint]:
65-
eps: EntryPoints = entry_points(group=group)
66-
res = eps if name is None else eps.select(name=name)
67-
68-
return iter(res)
69-
70-
7146
def _get_ep(group: str, name: str) -> Any | None:
72-
for ep in iter_entry_points(group, name):
47+
for ep in entry_points(group=group, name=name):
7348
log.debug("ep found: %s", ep.name)
7449
return ep.load()
7550
return None

src/setuptools_scm/_file_finders/__init__.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
from __future__ import annotations
22

3-
import itertools
43
import os
54

65
from typing import TYPE_CHECKING
76
from typing import Callable
87

98
from .. import _log
109
from .. import _types as _t
11-
from .._entrypoints import iter_entry_points
10+
from .._entrypoints import EntryPoint
11+
from .._entrypoints import entry_points
1212
from .pathtools import norm_real
1313

1414
if TYPE_CHECKING:
@@ -102,10 +102,11 @@ def is_toplevel_acceptable(toplevel: str | None) -> TypeGuard[str]:
102102

103103

104104
def find_files(path: _t.PathT = "") -> list[str]:
105-
for ep in itertools.chain(
106-
iter_entry_points("setuptools_scm.files_command"),
107-
iter_entry_points("setuptools_scm.files_command_fallback"),
108-
):
105+
eps: list[EntryPoint] = [
106+
*entry_points(group="setuptools_scm.files_command"),
107+
*entry_points(group="setuptools_scm.files_command_fallback"),
108+
]
109+
for ep in eps:
109110
command: Callable[[_t.PathT], list[str]] = ep.load()
110111
res: list[str] = command(path)
111112
if res:

src/setuptools_scm/discover.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,9 @@ def iter_matching_entrypoints(
5858
"""
5959

6060
log.debug("looking for ep %s in %s", entrypoint, root)
61-
from ._entrypoints import iter_entry_points
6261

6362
for wd in walk_potential_roots(root, config.search_parent_directories):
64-
for ep in iter_entry_points(entrypoint):
63+
for ep in _entrypoints.entry_points(group=entrypoint):
6564
if ep.value in _BLOCKED_EP_TARGETS:
6665
continue
6766
if match_entrypoint(wd, ep.name):

src/setuptools_scm/version.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,10 @@ def callable_or_entrypoint(group: str, callable_or_name: str | Any) -> Any:
8282

8383
if callable(callable_or_name):
8484
return callable_or_name
85-
from ._entrypoints import iter_entry_points
8685

87-
for ep in iter_entry_points(group, callable_or_name):
88-
log.debug("ep found: %s", ep.name)
89-
return ep.load()
86+
from ._entrypoints import _get_ep
87+
88+
return _get_ep(group, callable_or_name)
9089

9190

9291
def tag_to_version(

0 commit comments

Comments
 (0)