Skip to content

Commit efde8e5

Browse files
committed
Replace deprecated pkg_resources and pin setuptools
setuptools v82.0.0 removed the deprecated pkg_resources. Our Dockerfile installs the most recent version of build tools, including setuptools, which breaks tests. We can fix the tests to use importlib instead of pkg_resources. However, we still can't just install the latest setuptools, because various packages also depend on a version that still includes pkg_resources, so we pin it to <82.0.0.
1 parent 61e9fd3 commit efde8e5

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ RUN python3 -m venv /opt/venv
3636
# "activate" the venv
3737
ENV VIRTUAL_ENV=/opt/venv/ PATH="/opt/venv/bin:$PATH"
3838
# We ensure up-to-date build tools (which why we ignore DL3013)
39+
# Pin setuptools to <82.0.0 (which removed pkg_resources, which some dependencies require)
3940
# hadolint ignore=DL3013,DL3042
40-
RUN --mount=type=cache,target=/root/.cache python -m pip install -U pip setuptools wheel pip-tools
41+
RUN --mount=type=cache,target=/root/.cache python -m pip install -U pip wheel pip-tools "setuptools<82.0.0"
4142

4243

4344
#################################################

tests/test_import.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import os
2-
import subprocess
2+
import re
3+
34
from importlib import import_module
45
from pathlib import Path
5-
import re
6+
from importlib.metadata import distribution
7+
68

79
import pytest
8-
from pkg_resources import Requirement, get_provider
910

1011

1112
# packages that have no way to detect their importable name
@@ -15,33 +16,42 @@
1516
"qtpy": None, # required dependency of jupyter-lab
1617
}
1718

19+
1820
def get_module_names(pkg_name):
19-
"""Load pkg metadata to find out its importable module name(s)."""
21+
"""Load distribution to find out its importable module name(s)."""
2022
# remove any extras
21-
pkg_name = re.sub(r'\[.*\]', '', pkg_name)
23+
pkg_name = re.sub(r"\[.*\]", "", pkg_name)
2224
modules = set()
23-
provider = get_provider(Requirement.parse(pkg_name))
2425
# top level package name is typically all we need
26+
dist = distribution(pkg_name)
2527
if pkg_name in BAD_PACKAGES:
2628
name = BAD_PACKAGES[pkg_name]
27-
if name is None: # unimportably package
29+
if name is None: # unimportable package
2830
return []
2931
modules.add(BAD_PACKAGES[pkg_name])
30-
elif provider.has_metadata("top_level.txt"):
31-
first_line = list(provider.get_metadata_lines("top_level.txt"))[0]
32-
modules.add(first_line)
32+
elif top_level_names := dist.read_text("top_level.txt"):
33+
# Find the first non-_ prefixed module
34+
if first_public_name := next(
35+
(
36+
name
37+
for name in top_level_names.strip().split("\n")
38+
if not name.startswith("_")
39+
),
40+
None,
41+
):
42+
modules.add(first_public_name)
3343
else:
3444
# badly packaged dependency, make an educated guess
3545
name = pkg_name
3646
if pkg_name.endswith("-cffi"):
3747
name = pkg_name[:-5]
3848
elif pkg_name.endswith("-py"):
3949
name = pkg_name[:-3]
40-
50+
4151
modules.add(name.replace("-", "_"))
4252

43-
if provider.has_metadata("namespace_packages.txt"):
44-
modules |= set(provider.get_metadata_lines("namespace_packages.txt"))
53+
if namespace_packages := dist.read_text("namespace_packages.txt"):
54+
modules |= set(namespace_packages.strip().split("\n"))
4555

4656
# _ prefixed modules are typically C modules and not directly importable
4757
return [n for n in modules if n[0] != "_"]

0 commit comments

Comments
 (0)