Skip to content

Commit 31d8972

Browse files
agronholmjaraco
andauthored
Replaced all uses of distutils with setuptools (#428)
Distutils has been deprecated and will be removed in Python 3.12. This changeset replaces distutils logging with similar logging functionality from setuptools (when ready), and if not available, provides a replacement of its own. Co-authored-by: Jason R. Coombs <[email protected]>
1 parent afc0d5e commit 31d8972

File tree

9 files changed

+79
-48
lines changed

9 files changed

+79
-48
lines changed

docs/news.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Release Notes
55

66
- Dropped support for Python < 3.7
77
- Updated vendored ``packaging`` to 21.3
8+
- Replaced all uses of ``distutils`` with ``setuptools``
89

910
**0.37.1 (2021-12-22)**
1011

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ package_dir=
3131
= src
3232
packages = find:
3333
python_requires = >=3.7
34-
setup_requires = setuptools >= 45.2.0
34+
install_requires = setuptools >= 45.2.0
3535
zip_safe = False
3636

3737
[options.packages.find]

src/wheel/_setuptools_logging.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# copied from setuptools.logging, omitting monkeypatching
2+
from __future__ import annotations
3+
4+
import logging
5+
import sys
6+
7+
8+
def _not_warning(record):
9+
return record.levelno < logging.WARNING
10+
11+
12+
def configure():
13+
"""
14+
Configure logging to emit warning and above to stderr
15+
and everything else to stdout. This behavior is provided
16+
for compatibility with distutils.log but may change in
17+
the future.
18+
"""
19+
err_handler = logging.StreamHandler()
20+
err_handler.setLevel(logging.WARNING)
21+
out_handler = logging.StreamHandler(sys.stdout)
22+
out_handler.addFilter(_not_warning)
23+
handlers = err_handler, out_handler
24+
logging.basicConfig(
25+
format="{message}", style="{", handlers=handlers, level=logging.DEBUG
26+
)

src/wheel/bdist_wheel.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@
66

77
from __future__ import annotations
88

9-
import distutils
109
import os
1110
import re
1211
import shutil
1312
import stat
1413
import sys
14+
import sysconfig
1515
import warnings
1616
from collections import OrderedDict
17-
from distutils import log as logger
18-
from distutils.core import Command
1917
from email.generator import BytesGenerator, Generator
2018
from glob import iglob
2119
from io import BytesIO
@@ -24,10 +22,12 @@
2422
from zipfile import ZIP_DEFLATED, ZIP_STORED
2523

2624
import pkg_resources
25+
from setuptools import Command
2726

2827
from . import __version__ as wheel_version
2928
from .macosx_libfile import calculate_macosx_platform_tag
3029
from .metadata import pkginfo_to_metadata
30+
from .util import log
3131
from .vendored.packaging import tags
3232
from .wheelfile import WheelFile
3333

@@ -43,14 +43,14 @@ def python_tag():
4343

4444
def get_platform(archive_root):
4545
"""Return our platform name 'win32', 'linux_x86_64'"""
46-
# XXX remove distutils dependency
47-
result = distutils.util.get_platform()
46+
result = sysconfig.get_platform()
4847
if result.startswith("macosx") and archive_root is not None:
4948
result = calculate_macosx_platform_tag(archive_root, result)
50-
if result == "linux_x86_64" and sys.maxsize == 2147483647:
49+
elif result == "linux-x86_64" and sys.maxsize == 2147483647:
5150
# pip pull request #3497
52-
result = "linux_i686"
53-
return result
51+
result = "linux-i686"
52+
53+
return result.replace("-", "_")
5454

5555

5656
def get_flag(var, fallback, expected=True, warn=True):
@@ -238,7 +238,9 @@ def finalize_options(self):
238238
wheel = self.distribution.get_option_dict("wheel")
239239
if "universal" in wheel:
240240
# please don't define this in your global configs
241-
logger.warn("The [wheel] section is deprecated. Use [bdist_wheel] instead.")
241+
log.warning(
242+
"The [wheel] section is deprecated. Use [bdist_wheel] instead.",
243+
)
242244
val = wheel["universal"][1].strip()
243245
if val.lower() in ("1", "true", "yes"):
244246
self.universal = True
@@ -353,7 +355,7 @@ def run(self):
353355
basedir_observed,
354356
)
355357

356-
logger.info("installing to %s", self.bdist_dir)
358+
log.info(f"installing to {self.bdist_dir}")
357359

358360
self.run_command("install")
359361

@@ -394,7 +396,7 @@ def run(self):
394396
)
395397

396398
if not self.keep_temp:
397-
logger.info("removing %s", self.bdist_dir)
399+
log.info(f"removing {self.bdist_dir}")
398400
if not self.dry_run:
399401
rmtree(self.bdist_dir, onerror=remove_readonly)
400402

@@ -418,7 +420,7 @@ def write_wheelfile(
418420
msg["Tag"] = "-".join((impl, abi, plat))
419421

420422
wheelfile_path = os.path.join(wheelfile_base, "WHEEL")
421-
logger.info("creating %s", wheelfile_path)
423+
log.info(f"creating {wheelfile_path}")
422424
buffer = BytesIO()
423425
BytesGenerator(buffer, maxheaderlen=0).flatten(msg)
424426
with open(wheelfile_path, "wb") as f:
@@ -453,14 +455,14 @@ def license_paths(self):
453455
for pattern in patterns:
454456
for path in iglob(pattern):
455457
if path.endswith("~"):
456-
logger.debug(
457-
'ignoring license file "%s" as it looks like a backup', path
458+
log.debug(
459+
f'ignoring license file "{path}" as it looks like a ' f"backup"
458460
)
459461
continue
460462

461463
if path not in files and os.path.isfile(path):
462-
logger.info(
463-
'adding license file "%s" (matched pattern "%s")', path, pattern
464+
log.info(
465+
f'adding license file "{path}" (matched pattern "{pattern}")'
464466
)
465467
files.add(path)
466468

src/wheel/cli/__init__.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@
99
import sys
1010

1111

12-
def require_pkgresources(name):
13-
try:
14-
import pkg_resources # noqa: F401
15-
except ImportError:
16-
raise RuntimeError(f"'{name}' needs pkg_resources (part of setuptools).")
17-
18-
1912
class WheelError(Exception):
2013
pass
2114

src/wheel/cli/convert.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
import shutil
66
import tempfile
77
import zipfile
8-
from distutils import dist
98
from glob import iglob
109

10+
from setuptools.dist import Distribution
11+
1112
from ..bdist_wheel import bdist_wheel
1213
from ..wheelfile import WheelFile
13-
from . import WheelError, require_pkgresources
14+
from . import WheelError
1415

1516
egg_info_re = re.compile(
1617
r"""
@@ -70,9 +71,9 @@ def egg2wheel(egg_path: str, dest_dir: str):
7071

7172
root_is_purelib = egg_info["arch"] is None
7273
if root_is_purelib:
73-
bw = bdist_wheel(dist.Distribution())
74+
bw = bdist_wheel(Distribution())
7475
else:
75-
bw = _bdist_wheel_tag(dist.Distribution())
76+
bw = _bdist_wheel_tag(Distribution())
7677

7778
bw.root_is_pure = root_is_purelib
7879
bw.python_tag = pyver
@@ -229,9 +230,9 @@ def wininst2wheel(path, dest_dir):
229230
pyver = pyver.replace("py", "cp")
230231
wheel_name = "-".join((dist_info, pyver, abi, arch))
231232
if root_is_purelib:
232-
bw = bdist_wheel(dist.Distribution())
233+
bw = bdist_wheel(Distribution())
233234
else:
234-
bw = _bdist_wheel_tag(dist.Distribution())
235+
bw = _bdist_wheel_tag(Distribution())
235236

236237
bw.root_is_pure = root_is_purelib
237238
bw.python_tag = pyver
@@ -254,9 +255,6 @@ def wininst2wheel(path, dest_dir):
254255

255256

256257
def convert(files, dest_dir, verbose):
257-
# Only support wheel convert if pkg_resources is present
258-
require_pkgresources("wheel convert")
259-
260258
for pat in files:
261259
for installer in iglob(pat):
262260
if os.path.splitext(installer)[1] == ".egg":

src/wheel/util.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
from __future__ import annotations
22

33
import base64
4+
import logging
5+
6+
log = logging.getLogger("wheel")
7+
8+
# ensure Python logging is configured
9+
try:
10+
__import__("setuptools.logging")
11+
except ImportError:
12+
# setuptools < ??
13+
from . import _setuptools_logging
14+
15+
_setuptools_logging.configure()
416

517

618
def urlsafe_b64encode(data: bytes) -> bytes:

src/wheel/wheelfile.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
import stat
88
import time
99
from collections import OrderedDict
10-
from distutils import log as logger
1110
from io import StringIO, TextIOWrapper
1211
from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
1312

1413
from wheel.cli import WheelError
15-
from wheel.util import urlsafe_b64decode, urlsafe_b64encode
14+
from wheel.util import log, urlsafe_b64decode, urlsafe_b64encode
1615

1716
# Non-greedy matching of an optional build number may be too clever (more
1817
# invalid wheel filenames will match). Separate regex for .dist-info?
@@ -118,7 +117,7 @@ def _update_crc(newdata):
118117
return ef
119118

120119
def write_files(self, base_dir):
121-
logger.info("creating '%s' and adding '%s' to it", self.filename, base_dir)
120+
log.info(f"creating '{self.filename}' and adding '{base_dir}' to it")
122121
deferred = []
123122
for root, dirnames, filenames in os.walk(base_dir):
124123
# Sort the directory names so that `os.walk` will walk them in a
@@ -161,7 +160,7 @@ def writestr(self, zinfo_or_arcname, data, compress_type=None):
161160
if isinstance(zinfo_or_arcname, ZipInfo)
162161
else zinfo_or_arcname
163162
)
164-
logger.info("adding '%s'", fname)
163+
log.info(f"adding '{fname}'")
165164
if fname != self.record_path:
166165
hash_ = self._default_algorithm(data)
167166
self._file_hashes[fname] = (

tests/test_macosx_libfile.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from __future__ import annotations
22

3-
import distutils.util
43
import os
54
import sys
5+
import sysconfig
66

77
from wheel.bdist_wheel import get_platform
88
from wheel.macosx_libfile import extract_macosx_min_system_version
@@ -52,15 +52,15 @@ def test_simple(self, monkeypatch):
5252
dirname = os.path.dirname(__file__)
5353
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
5454
monkeypatch.setattr(
55-
distutils.util, "get_platform", return_factory("macosx-11.0-x86_64")
55+
sysconfig, "get_platform", return_factory("macosx-11.0-x86_64")
5656
)
5757
assert get_platform(dylib_dir) == "macosx_11_0_x86_64"
5858

5959
def test_version_bump(self, monkeypatch, capsys):
6060
dirname = os.path.dirname(__file__)
6161
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
6262
monkeypatch.setattr(
63-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
63+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
6464
)
6565
assert get_platform(dylib_dir) == "macosx_11_0_x86_64"
6666
captured = capsys.readouterr()
@@ -72,7 +72,7 @@ def test_information_about_problematic_files_python_version(
7272
dirname = os.path.dirname(__file__)
7373
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
7474
monkeypatch.setattr(
75-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
75+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
7676
)
7777
monkeypatch.setattr(
7878
os,
@@ -95,7 +95,7 @@ def test_information_about_problematic_files_env_variable(
9595
dirname = os.path.dirname(__file__)
9696
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
9797
monkeypatch.setattr(
98-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
98+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
9999
)
100100
monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "10.8")
101101
monkeypatch.setattr(
@@ -115,7 +115,7 @@ def test_bump_platform_tag_by_env_variable(self, monkeypatch, capsys):
115115
dirname = os.path.dirname(__file__)
116116
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
117117
monkeypatch.setattr(
118-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
118+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
119119
)
120120
monkeypatch.setattr(
121121
os,
@@ -134,7 +134,7 @@ def test_bugfix_release_platform_tag(self, monkeypatch, capsys):
134134
dirname = os.path.dirname(__file__)
135135
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
136136
monkeypatch.setattr(
137-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
137+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
138138
)
139139
monkeypatch.setattr(
140140
os,
@@ -165,7 +165,7 @@ def test_warning_on_to_low_env_variable(self, monkeypatch, capsys):
165165
dirname = os.path.dirname(__file__)
166166
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
167167
monkeypatch.setattr(
168-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
168+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
169169
)
170170
monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "10.8")
171171
monkeypatch.setattr(
@@ -186,7 +186,7 @@ def test_get_platform_bigsur_env(self, monkeypatch):
186186
dirname = os.path.dirname(__file__)
187187
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
188188
monkeypatch.setattr(
189-
distutils.util, "get_platform", return_factory("macosx-10.9-x86_64")
189+
sysconfig, "get_platform", return_factory("macosx-10.9-x86_64")
190190
)
191191
monkeypatch.setenv("MACOSX_DEPLOYMENT_TARGET", "11")
192192
monkeypatch.setattr(
@@ -202,7 +202,7 @@ def test_get_platform_bigsur_platform(self, monkeypatch):
202202
dirname = os.path.dirname(__file__)
203203
dylib_dir = os.path.join(dirname, "testdata", "macosx_minimal_system_version")
204204
monkeypatch.setattr(
205-
distutils.util, "get_platform", return_factory("macosx-11-x86_64")
205+
sysconfig, "get_platform", return_factory("macosx-11-x86_64")
206206
)
207207
monkeypatch.setattr(
208208
os,
@@ -215,6 +215,6 @@ def test_get_platform_bigsur_platform(self, monkeypatch):
215215

216216

217217
def test_get_platform_linux(monkeypatch):
218-
monkeypatch.setattr(distutils.util, "get_platform", return_factory("linux_x86_64"))
218+
monkeypatch.setattr(sysconfig, "get_platform", return_factory("linux-x86_64"))
219219
monkeypatch.setattr(sys, "maxsize", 2147483647)
220220
assert get_platform(None) == "linux_i686"

0 commit comments

Comments
 (0)