diff --git a/changelog.d/2925.change.rst b/changelog.d/2925.change.rst new file mode 100644 index 0000000000..c28f29cd1e --- /dev/null +++ b/changelog.d/2925.change.rst @@ -0,0 +1 @@ +Merge with pypa/distutils@92082ee42c including introduction of deprecation warning on Version classes. diff --git a/setuptools/_distutils/command/build_ext.py b/setuptools/_distutils/command/build_ext.py index 22628baf90..181671bf19 100644 --- a/setuptools/_distutils/command/build_ext.py +++ b/setuptools/_distutils/command/build_ext.py @@ -202,9 +202,7 @@ def finalize_options(self): # Append the source distribution include and library directories, # this allows distutils on windows to work in the source tree self.include_dirs.append(os.path.dirname(get_config_h_filename())) - _sys_home = getattr(sys, '_home', None) - if _sys_home: - self.library_dirs.append(_sys_home) + self.library_dirs.append(sys.base_exec_prefix) # Use the .lib files for the correct architecture if self.plat_name == 'win32': diff --git a/setuptools/_distutils/cygwinccompiler.py b/setuptools/_distutils/cygwinccompiler.py index f80ca62287..ad6cc44b08 100644 --- a/setuptools/_distutils/cygwinccompiler.py +++ b/setuptools/_distutils/cygwinccompiler.py @@ -53,6 +53,7 @@ from subprocess import Popen, PIPE, check_output import re +import distutils.version from distutils.unixccompiler import UnixCCompiler from distutils.file_util import write_file from distutils.errors import (DistutilsExecError, CCompilerError, @@ -405,9 +406,10 @@ def _find_exe_version(cmd): result = RE_VERSION.search(out_string) if result is None: return None - # LooseVersion works with strings - # so we need to decode our bytes - return LooseVersion(result.group(1).decode()) + # LooseVersion works with strings; decode + ver_str = result.group(1).decode() + with distutils.version.suppress_known_deprecation(): + return LooseVersion(ver_str) def get_versions(): """ Try to find out the versions of gcc, ld and dllwrap. diff --git a/setuptools/_distutils/tests/test_version.py b/setuptools/_distutils/tests/test_version.py index 8671cd2fc5..d50cca1fc0 100644 --- a/setuptools/_distutils/tests/test_version.py +++ b/setuptools/_distutils/tests/test_version.py @@ -1,11 +1,19 @@ """Tests for distutils.version.""" import unittest +import distutils from distutils.version import LooseVersion from distutils.version import StrictVersion from test.support import run_unittest class VersionTestCase(unittest.TestCase): + def setUp(self): + self.ctx = distutils.version.suppress_known_deprecation() + self.ctx.__enter__() + + def tearDown(self): + self.ctx.__exit__(None, None, None) + def test_prerelease(self): version = StrictVersion('1.2.3a1') self.assertEqual(version.version, (1, 2, 3)) diff --git a/setuptools/_distutils/version.py b/setuptools/_distutils/version.py index c33bebaed2..35e181dbb6 100644 --- a/setuptools/_distutils/version.py +++ b/setuptools/_distutils/version.py @@ -27,6 +27,20 @@ """ import re +import warnings +import contextlib + + +@contextlib.contextmanager +def suppress_known_deprecation(): + with warnings.catch_warnings(record=True) as ctx: + warnings.filterwarnings( + action='default', + category=DeprecationWarning, + message="distutils Version classes are deprecated.", + ) + yield ctx + class Version: """Abstract base class for version numbering classes. Just provides @@ -36,6 +50,12 @@ class Version: """ def __init__ (self, vstring=None): + warnings.warn( + "distutils Version classes are deprecated. " + "Use packaging.version instead.", + DeprecationWarning, + stacklevel=2, + ) if vstring: self.parse(vstring) @@ -165,7 +185,8 @@ def __str__ (self): def _cmp (self, other): if isinstance(other, str): - other = StrictVersion(other) + with suppress_known_deprecation(): + other = StrictVersion(other) elif not isinstance(other, StrictVersion): return NotImplemented @@ -301,11 +322,6 @@ class LooseVersion (Version): component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) - def __init__ (self, vstring=None): - if vstring: - self.parse(vstring) - - def parse (self, vstring): # I've given up on thinking I can reconstruct the version string # from the parsed tuple -- so I just store the string here for diff --git a/setuptools/_distutils/versionpredicate.py b/setuptools/_distutils/versionpredicate.py index 062c98f248..55f25d91ae 100644 --- a/setuptools/_distutils/versionpredicate.py +++ b/setuptools/_distutils/versionpredicate.py @@ -23,7 +23,9 @@ def splitUp(pred): if not res: raise ValueError("bad package restriction syntax: %r" % pred) comp, verStr = res.groups() - return (comp, distutils.version.StrictVersion(verStr)) + with distutils.version.suppress_known_deprecation(): + other = distutils.version.StrictVersion(verStr) + return (comp, other) compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq, ">": operator.gt, ">=": operator.ge, "!=": operator.ne} @@ -162,5 +164,6 @@ def split_provision(value): raise ValueError("illegal provides specification: %r" % value) ver = m.group(2) or None if ver: - ver = distutils.version.StrictVersion(ver) + with distutils.version.suppress_known_deprecation(): + ver = distutils.version.StrictVersion(ver) return m.group(1), ver diff --git a/setuptools/depends.py b/setuptools/depends.py index 8be6928a31..adffd12db8 100644 --- a/setuptools/depends.py +++ b/setuptools/depends.py @@ -2,7 +2,8 @@ import marshal import contextlib import dis -from distutils.version import StrictVersion + +from setuptools.extern.packaging import version from ._imp import find_module, PY_COMPILED, PY_FROZEN, PY_SOURCE from . import _imp @@ -21,7 +22,7 @@ def __init__( attribute=None, format=None): if format is None and requested_version is not None: - format = StrictVersion + format = version.Version if format is not None: requested_version = format(requested_version) @@ -40,7 +41,7 @@ def full_name(self): def version_ok(self, version): """Is 'version' sufficiently up-to-date?""" return self.attribute is None or self.format is None or \ - str(version) != "unknown" and version >= self.requested_version + str(version) != "unknown" and self.format(version) >= self.requested_version def get_version(self, paths=None, default="unknown"): """Get version number of installed module, 'None', or 'default' @@ -78,7 +79,7 @@ def is_current(self, paths=None): version = self.get_version(paths) if version is None: return False - return self.version_ok(version) + return self.version_ok(str(version)) def maybe_close(f): diff --git a/setuptools/dist.py b/setuptools/dist.py index 74afa98fd6..37a10d1dcd 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -25,7 +25,6 @@ from distutils.errors import DistutilsOptionError, DistutilsSetupError from distutils.util import rfc822_escape -from distutils.version import StrictVersion from setuptools.extern import packaging from setuptools.extern import ordered_set @@ -39,6 +38,7 @@ from setuptools.monkey import get_unpatched from setuptools.config import parse_configuration import pkg_resources +from setuptools.extern.packaging import version if TYPE_CHECKING: from email.message import Message @@ -55,7 +55,7 @@ def _get_unpatched(cls): def get_metadata_version(self): mv = getattr(self, 'metadata_version', None) if mv is None: - mv = StrictVersion('2.1') + mv = version.Version('2.1') self.metadata_version = mv return mv @@ -103,7 +103,7 @@ def read_pkg_file(self, file): """Reads the metadata values from a file object.""" msg = message_from_file(file) - self.metadata_version = StrictVersion(msg['metadata-version']) + self.metadata_version = version.Version(msg['metadata-version']) self.name = _read_field_from_msg(msg, 'name') self.version = _read_field_from_msg(msg, 'version') self.description = _read_field_from_msg(msg, 'summary') @@ -121,7 +121,10 @@ def read_pkg_file(self, file): self.download_url = None self.long_description = _read_field_unescaped_from_msg(msg, 'description') - if self.long_description is None and self.metadata_version >= StrictVersion('2.1'): + if ( + self.long_description is None and + self.metadata_version >= version.Version('2.1') + ): self.long_description = _read_payload_from_msg(msg) self.description = _read_field_from_msg(msg, 'summary') @@ -132,7 +135,7 @@ def read_pkg_file(self, file): self.classifiers = _read_list_from_msg(msg, 'classifier') # PEP 314 - these fields only exist in 1.1 - if self.metadata_version == StrictVersion('1.1'): + if self.metadata_version == version.Version('1.1'): self.requires = _read_list_from_msg(msg, 'requires') self.provides = _read_list_from_msg(msg, 'provides') self.obsoletes = _read_list_from_msg(msg, 'obsoletes') diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index 42f8e18bef..3609ab5ed8 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -7,10 +7,11 @@ from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsSetupError from distutils.core import Extension -from distutils.version import LooseVersion import pytest +from setuptools.extern.packaging import version + import setuptools import setuptools.dist import setuptools.depends as dep @@ -84,12 +85,12 @@ def testRequire(self): assert req.name == 'Json' assert req.module == 'json' - assert req.requested_version == '1.0.3' + assert req.requested_version == version.Version('1.0.3') assert req.attribute == '__version__' assert req.full_name() == 'Json-1.0.3' from json import __version__ - assert req.get_version() == __version__ + assert str(req.get_version()) == __version__ assert req.version_ok('1.0.9') assert not req.version_ok('0.9.1') assert not req.version_ok('unknown') @@ -97,11 +98,6 @@ def testRequire(self): assert req.is_present() assert req.is_current() - req = Require('Json 3000', '03000', 'json', format=LooseVersion) - assert req.is_present() - assert not req.is_current() - assert not req.version_ok('unknown') - req = Require('Do-what-I-mean', '1.0', 'd-w-i-m') assert not req.is_present() assert not req.is_current()