summaryrefslogtreecommitdiff
path: root/setuptools/_distutils
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2022-05-09 10:42:04 -0400
committerJason R. Coombs <jaraco@jaraco.com>2022-05-09 10:42:56 -0400
commit9116c7eb52504bec77d26881d2c28e427dc52143 (patch)
tree6becb88401eb15bdff6fc924211894e6d9c277d1 /setuptools/_distutils
parent8d12d6196c369c7cf0164a1202e968dd68a2cb6c (diff)
parente009a87b5578cb16099b697ba8395c8f6bdd70f3 (diff)
downloadpython-setuptools-git-debt/remove-easy-install.tar.gz
Merge branch 'main' into debt/remove-easy-installdebt/remove-easy-install
Diffstat (limited to 'setuptools/_distutils')
-rw-r--r--setuptools/_distutils/_collections.py56
-rw-r--r--setuptools/_distutils/_macos_compat.py12
-rw-r--r--setuptools/_distutils/_msvccompiler.py4
-rw-r--r--setuptools/_distutils/bcppcompiler.py2
-rw-r--r--setuptools/_distutils/command/bdist_msi.py2
-rw-r--r--setuptools/_distutils/command/build.py3
-rw-r--r--setuptools/_distutils/command/build_ext.py4
-rw-r--r--setuptools/_distutils/command/build_scripts.py216
-rw-r--r--setuptools/_distutils/command/check.py42
-rw-r--r--setuptools/_distutils/command/install.py155
-rw-r--r--setuptools/_distutils/cygwinccompiler.py147
-rw-r--r--setuptools/_distutils/log.py6
-rw-r--r--setuptools/_distutils/msvc9compiler.py6
-rw-r--r--setuptools/_distutils/msvccompiler.py2
-rw-r--r--setuptools/_distutils/py39compat.py21
-rw-r--r--setuptools/_distutils/spawn.py2
-rw-r--r--setuptools/_distutils/sysconfig.py177
-rw-r--r--setuptools/_distutils/tests/py38compat.py9
-rw-r--r--setuptools/_distutils/tests/test_archive_util.py14
-rw-r--r--setuptools/_distutils/tests/test_bdist.py2
-rw-r--r--setuptools/_distutils/tests/test_bdist_dumb.py2
-rw-r--r--setuptools/_distutils/tests/test_bdist_msi.py2
-rw-r--r--setuptools/_distutils/tests/test_bdist_rpm.py11
-rw-r--r--setuptools/_distutils/tests/test_bdist_wininst.py2
-rw-r--r--setuptools/_distutils/tests/test_build.py8
-rw-r--r--setuptools/_distutils/tests/test_build_clib.py2
-rw-r--r--setuptools/_distutils/tests/test_build_ext.py12
-rw-r--r--setuptools/_distutils/tests/test_build_py.py2
-rw-r--r--setuptools/_distutils/tests/test_build_scripts.py2
-rw-r--r--setuptools/_distutils/tests/test_check.py24
-rw-r--r--setuptools/_distutils/tests/test_clean.py2
-rw-r--r--setuptools/_distutils/tests/test_cmd.py2
-rw-r--r--setuptools/_distutils/tests/test_config.py4
-rw-r--r--setuptools/_distutils/tests/test_config_cmd.py2
-rw-r--r--setuptools/_distutils/tests/test_core.py2
-rw-r--r--setuptools/_distutils/tests/test_cygwinccompiler.py65
-rw-r--r--setuptools/_distutils/tests/test_dep_util.py2
-rw-r--r--setuptools/_distutils/tests/test_dir_util.py2
-rw-r--r--setuptools/_distutils/tests/test_dist.py4
-rw-r--r--setuptools/_distutils/tests/test_extension.py2
-rw-r--r--setuptools/_distutils/tests/test_file_util.py2
-rw-r--r--setuptools/_distutils/tests/test_filelist.py4
-rw-r--r--setuptools/_distutils/tests/test_install.py24
-rw-r--r--setuptools/_distutils/tests/test_install_data.py2
-rw-r--r--setuptools/_distutils/tests/test_install_headers.py2
-rw-r--r--setuptools/_distutils/tests/test_install_lib.py2
-rw-r--r--setuptools/_distutils/tests/test_install_scripts.py2
-rw-r--r--setuptools/_distutils/tests/test_log.py2
-rw-r--r--setuptools/_distutils/tests/test_msvc9compiler.py2
-rw-r--r--setuptools/_distutils/tests/test_msvccompiler.py4
-rw-r--r--setuptools/_distutils/tests/test_register.py2
-rw-r--r--setuptools/_distutils/tests/test_sdist.py13
-rw-r--r--setuptools/_distutils/tests/test_spawn.py2
-rw-r--r--setuptools/_distutils/tests/test_sysconfig.py27
-rw-r--r--setuptools/_distutils/tests/test_text_file.py2
-rw-r--r--setuptools/_distutils/tests/test_unixccompiler.py46
-rw-r--r--setuptools/_distutils/tests/test_upload.py2
-rw-r--r--setuptools/_distutils/tests/test_util.py127
-rw-r--r--setuptools/_distutils/tests/test_version.py10
-rw-r--r--setuptools/_distutils/tests/unix_compat.py16
-rw-r--r--setuptools/_distutils/unixccompiler.py111
-rw-r--r--setuptools/_distutils/util.py98
-rw-r--r--setuptools/_distutils/version.py28
-rw-r--r--setuptools/_distutils/versionpredicate.py7
64 files changed, 794 insertions, 779 deletions
diff --git a/setuptools/_distutils/_collections.py b/setuptools/_distutils/_collections.py
new file mode 100644
index 00000000..98fce800
--- /dev/null
+++ b/setuptools/_distutils/_collections.py
@@ -0,0 +1,56 @@
+import collections
+import itertools
+
+
+# from jaraco.collections 3.5.1
+class DictStack(list, collections.abc.Mapping):
+ """
+ A stack of dictionaries that behaves as a view on those dictionaries,
+ giving preference to the last.
+
+ >>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
+ >>> stack['a']
+ 2
+ >>> stack['b']
+ 2
+ >>> stack['c']
+ 2
+ >>> len(stack)
+ 3
+ >>> stack.push(dict(a=3))
+ >>> stack['a']
+ 3
+ >>> set(stack.keys()) == set(['a', 'b', 'c'])
+ True
+ >>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)])
+ True
+ >>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2)
+ True
+ >>> d = stack.pop()
+ >>> stack['a']
+ 2
+ >>> d = stack.pop()
+ >>> stack['a']
+ 1
+ >>> stack.get('b', None)
+ >>> 'c' in stack
+ True
+ """
+
+ def __iter__(self):
+ dicts = list.__iter__(self)
+ return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
+
+ def __getitem__(self, key):
+ for scope in reversed(tuple(list.__iter__(self))):
+ if key in scope:
+ return scope[key]
+ raise KeyError(key)
+
+ push = list.append
+
+ def __contains__(self, other):
+ return collections.abc.Mapping.__contains__(self, other)
+
+ def __len__(self):
+ return len(list(iter(self)))
diff --git a/setuptools/_distutils/_macos_compat.py b/setuptools/_distutils/_macos_compat.py
new file mode 100644
index 00000000..17769e91
--- /dev/null
+++ b/setuptools/_distutils/_macos_compat.py
@@ -0,0 +1,12 @@
+import sys
+import importlib
+
+
+def bypass_compiler_fixup(cmd, args):
+ return cmd
+
+
+if sys.platform == 'darwin':
+ compiler_fixup = importlib.import_module('_osx_support').compiler_fixup
+else:
+ compiler_fixup = bypass_compiler_fixup
diff --git a/setuptools/_distutils/_msvccompiler.py b/setuptools/_distutils/_msvccompiler.py
index b7a06082..f2f801c5 100644
--- a/setuptools/_distutils/_msvccompiler.py
+++ b/setuptools/_distutils/_msvccompiler.py
@@ -203,7 +203,7 @@ class MSVCCompiler(CCompiler) :
def __init__(self, verbose=0, dry_run=0, force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
+ super().__init__(verbose, dry_run, force)
# target platform (.plat_name is consistent with 'bdist')
self.plat_name = None
self.initialized = False
@@ -527,7 +527,7 @@ class MSVCCompiler(CCompiler) :
return
warnings.warn(
"Fallback spawn triggered. Please update distutils monkeypatch.")
- with unittest.mock.patch('os.environ', env):
+ with unittest.mock.patch.dict('os.environ', env):
bag.value = super().spawn(cmd)
# -- Miscellaneous methods -----------------------------------------
diff --git a/setuptools/_distutils/bcppcompiler.py b/setuptools/_distutils/bcppcompiler.py
index 071fea5d..2eb6d2e9 100644
--- a/setuptools/_distutils/bcppcompiler.py
+++ b/setuptools/_distutils/bcppcompiler.py
@@ -55,7 +55,7 @@ class BCPPCompiler(CCompiler) :
dry_run=0,
force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
+ super().__init__(verbose, dry_run, force)
# These executables are assumed to all be in the path.
# Borland doesn't seem to use any special registry settings to
diff --git a/setuptools/_distutils/command/bdist_msi.py b/setuptools/_distutils/command/bdist_msi.py
index 0863a188..15259532 100644
--- a/setuptools/_distutils/command/bdist_msi.py
+++ b/setuptools/_distutils/command/bdist_msi.py
@@ -27,7 +27,7 @@ class PyDialog(Dialog):
def __init__(self, *args, **kw):
"""Dialog(database, name, x, y, w, h, attributes, title, first,
default, cancel, bitmap=true)"""
- Dialog.__init__(self, *args)
+ super().__init__(*args)
ruler = self.h - 36
bmwidth = 152*ruler/328
#if kw.get("bitmap", True):
diff --git a/setuptools/_distutils/command/build.py b/setuptools/_distutils/command/build.py
index 4355a632..9606b81a 100644
--- a/setuptools/_distutils/command/build.py
+++ b/setuptools/_distutils/command/build.py
@@ -81,7 +81,8 @@ class build(Command):
"--plat-name only supported on Windows (try "
"using './configure --help' on your platform)")
- plat_specifier = ".%s-%d.%d" % (self.plat_name, *sys.version_info[:2])
+ plat_specifier = ".%s-%s" % (self.plat_name,
+ sys.implementation.cache_tag)
# Make it so Python 2.x and Python 2.x with --with-pydebug don't
# share the same build directories. Doing so confuses the build
diff --git a/setuptools/_distutils/command/build_ext.py b/setuptools/_distutils/command/build_ext.py
index 22628baf..181671bf 100644
--- a/setuptools/_distutils/command/build_ext.py
+++ b/setuptools/_distutils/command/build_ext.py
@@ -202,9 +202,7 @@ class build_ext(Command):
# 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/command/build_scripts.py b/setuptools/_distutils/command/build_scripts.py
index e3312cf0..e56511da 100644
--- a/setuptools/_distutils/command/build_scripts.py
+++ b/setuptools/_distutils/command/build_scripts.py
@@ -2,7 +2,8 @@
Implements the Distutils 'build_scripts' command."""
-import os, re
+import os
+import re
from stat import ST_MODE
from distutils import sysconfig
from distutils.core import Command
@@ -11,8 +12,14 @@ from distutils.util import convert_path
from distutils import log
import tokenize
-# check if Python is called on the first line with this expression
-first_line_re = re.compile(b'^#!.*python[0-9.]*([ \t].*)?$')
+shebang_pattern = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
+"""
+Pattern matching a Python interpreter indicated in first line of a script.
+"""
+
+# for Setuptools compatibility
+first_line_re = shebang_pattern
+
class build_scripts(Command):
@@ -26,13 +33,11 @@ class build_scripts(Command):
boolean_options = ['force']
-
def initialize_options(self):
self.build_dir = None
self.scripts = None
self.force = None
self.executable = None
- self.outfiles = None
def finalize_options(self):
self.set_undefined_options('build',
@@ -49,104 +54,117 @@ class build_scripts(Command):
return
self.copy_scripts()
-
def copy_scripts(self):
- r"""Copy each script listed in 'self.scripts'; if it's marked as a
- Python script in the Unix way (first line matches 'first_line_re',
- ie. starts with "\#!" and contains "python"), then adjust the first
- line to refer to the current Python interpreter as we copy.
+ """
+ Copy each script listed in ``self.scripts``.
+
+ If a script is marked as a Python script (first line matches
+ 'shebang_pattern', i.e. starts with ``#!`` and contains
+ "python"), then adjust in the copy the first line to refer to
+ the current Python interpreter.
"""
self.mkpath(self.build_dir)
outfiles = []
updated_files = []
for script in self.scripts:
- adjust = False
- script = convert_path(script)
- outfile = os.path.join(self.build_dir, os.path.basename(script))
- outfiles.append(outfile)
-
- if not self.force and not newer(script, outfile):
- log.debug("not copying %s (up-to-date)", script)
- continue
-
- # Always open the file, but ignore failures in dry-run mode --
- # that way, we'll get accurate feedback if we can read the
- # script.
- try:
- f = open(script, "rb")
- except OSError:
- if not self.dry_run:
- raise
- f = None
- else:
- encoding, lines = tokenize.detect_encoding(f.readline)
- f.seek(0)
- first_line = f.readline()
- if not first_line:
- self.warn("%s is an empty file (skipping)" % script)
- continue
-
- match = first_line_re.match(first_line)
- if match:
- adjust = True
- post_interp = match.group(1) or b''
-
- if adjust:
- log.info("copying and adjusting %s -> %s", script,
- self.build_dir)
- updated_files.append(outfile)
- if not self.dry_run:
- if not sysconfig.python_build:
- executable = self.executable
- else:
- executable = os.path.join(
- sysconfig.get_config_var("BINDIR"),
- "python%s%s" % (sysconfig.get_config_var("VERSION"),
- sysconfig.get_config_var("EXE")))
- executable = os.fsencode(executable)
- shebang = b"#!" + executable + post_interp + b"\n"
- # Python parser starts to read a script using UTF-8 until
- # it gets a #coding:xxx cookie. The shebang has to be the
- # first line of a file, the #coding:xxx cookie cannot be
- # written before. So the shebang has to be decodable from
- # UTF-8.
- try:
- shebang.decode('utf-8')
- except UnicodeDecodeError:
- raise ValueError(
- "The shebang ({!r}) is not decodable "
- "from utf-8".format(shebang))
- # If the script is encoded to a custom encoding (use a
- # #coding:xxx cookie), the shebang has to be decodable from
- # the script encoding too.
- try:
- shebang.decode(encoding)
- except UnicodeDecodeError:
- raise ValueError(
- "The shebang ({!r}) is not decodable "
- "from the script encoding ({})"
- .format(shebang, encoding))
- with open(outfile, "wb") as outf:
- outf.write(shebang)
- outf.writelines(f.readlines())
- if f:
- f.close()
- else:
- if f:
- f.close()
- updated_files.append(outfile)
- self.copy_file(script, outfile)
-
- if os.name == 'posix':
- for file in outfiles:
- if self.dry_run:
- log.info("changing mode of %s", file)
- else:
- oldmode = os.stat(file)[ST_MODE] & 0o7777
- newmode = (oldmode | 0o555) & 0o7777
- if newmode != oldmode:
- log.info("changing mode of %s from %o to %o",
- file, oldmode, newmode)
- os.chmod(file, newmode)
- # XXX should we modify self.outfiles?
+ self._copy_script(script, outfiles, updated_files)
+
+ self._change_modes(outfiles)
+
return outfiles, updated_files
+
+ def _copy_script(self, script, outfiles, updated_files):
+ shebang_match = None
+ script = convert_path(script)
+ outfile = os.path.join(self.build_dir, os.path.basename(script))
+ outfiles.append(outfile)
+
+ if not self.force and not newer(script, outfile):
+ log.debug("not copying %s (up-to-date)", script)
+ return
+
+ # Always open the file, but ignore failures in dry-run mode
+ # in order to attempt to copy directly.
+ try:
+ f = tokenize.open(script)
+ except OSError:
+ if not self.dry_run:
+ raise
+ f = None
+ else:
+ first_line = f.readline()
+ if not first_line:
+ self.warn("%s is an empty file (skipping)" % script)
+ return
+
+ shebang_match = shebang_pattern.match(first_line)
+
+ updated_files.append(outfile)
+ if shebang_match:
+ log.info("copying and adjusting %s -> %s", script,
+ self.build_dir)
+ if not self.dry_run:
+ if not sysconfig.python_build:
+ executable = self.executable
+ else:
+ executable = os.path.join(
+ sysconfig.get_config_var("BINDIR"),
+ "python%s%s" % (
+ sysconfig.get_config_var("VERSION"),
+ sysconfig.get_config_var("EXE")))
+ post_interp = shebang_match.group(1) or ''
+ shebang = "#!" + executable + post_interp + "\n"
+ self._validate_shebang(shebang, f.encoding)
+ with open(outfile, "w", encoding=f.encoding) as outf:
+ outf.write(shebang)
+ outf.writelines(f.readlines())
+ if f:
+ f.close()
+ else:
+ if f:
+ f.close()
+ self.copy_file(script, outfile)
+
+ def _change_modes(self, outfiles):
+ if os.name != 'posix':
+ return
+
+ for file in outfiles:
+ self._change_mode(file)
+
+ def _change_mode(self, file):
+ if self.dry_run:
+ log.info("changing mode of %s", file)
+ return
+
+ oldmode = os.stat(file)[ST_MODE] & 0o7777
+ newmode = (oldmode | 0o555) & 0o7777
+ if newmode != oldmode:
+ log.info("changing mode of %s from %o to %o",
+ file, oldmode, newmode)
+ os.chmod(file, newmode)
+
+ @staticmethod
+ def _validate_shebang(shebang, encoding):
+ # Python parser starts to read a script using UTF-8 until
+ # it gets a #coding:xxx cookie. The shebang has to be the
+ # first line of a file, the #coding:xxx cookie cannot be
+ # written before. So the shebang has to be encodable to
+ # UTF-8.
+ try:
+ shebang.encode('utf-8')
+ except UnicodeEncodeError:
+ raise ValueError(
+ "The shebang ({!r}) is not encodable "
+ "to utf-8".format(shebang))
+
+ # If the script is encoded to a custom encoding (use a
+ # #coding:xxx cookie), the shebang has to be encodable to
+ # the script encoding too.
+ try:
+ shebang.encode(encoding)
+ except UnicodeEncodeError:
+ raise ValueError(
+ "The shebang ({!r}) is not encodable "
+ "to the script encoding ({})"
+ .format(shebang, encoding))
diff --git a/setuptools/_distutils/command/check.py b/setuptools/_distutils/command/check.py
index ada25006..af311ca9 100644
--- a/setuptools/_distutils/command/check.py
+++ b/setuptools/_distutils/command/check.py
@@ -2,6 +2,8 @@
Implements the Distutils 'check' command.
"""
+from email.utils import getaddresses
+
from distutils.core import Command
from distutils.errors import DistutilsSetupError
@@ -17,7 +19,7 @@ try:
def __init__(self, source, report_level, halt_level, stream=None,
debug=0, encoding='ascii', error_handler='replace'):
self.messages = []
- Reporter.__init__(self, source, report_level, halt_level, stream,
+ super().__init__(source, report_level, halt_level, stream,
debug, encoding, error_handler)
def system_message(self, level, message, *children, **kwargs):
@@ -96,19 +98,39 @@ class check(Command):
if missing:
self.warn("missing required meta-data: %s" % ', '.join(missing))
- if metadata.author:
- if not metadata.author_email:
- self.warn("missing meta-data: if 'author' supplied, " +
- "'author_email' should be supplied too")
- elif metadata.maintainer:
- if not metadata.maintainer_email:
- self.warn("missing meta-data: if 'maintainer' supplied, " +
- "'maintainer_email' should be supplied too")
- else:
+ if not (
+ self._check_contact("author", metadata) or
+ self._check_contact("maintainer", metadata)
+ ):
self.warn("missing meta-data: either (author and author_email) " +
"or (maintainer and maintainer_email) " +
"should be supplied")
+ def _check_contact(self, kind, metadata):
+ """
+ Returns True if the contact's name is specified and False otherwise.
+ This function will warn if the contact's email is not specified.
+ """
+ name = getattr(metadata, kind) or ''
+ email = getattr(metadata, kind + '_email') or ''
+
+ msg = ("missing meta-data: if '{}' supplied, " +
+ "'{}' should be supplied too")
+
+ if name and email:
+ return True
+
+ if name:
+ self.warn(msg.format(kind, kind + '_email'))
+ return True
+
+ addresses = [(alias, addr) for alias, addr in getaddresses([email])]
+ if any(alias and addr for alias, addr in addresses):
+ # The contact's name can be encoded in the email: `Name <email>`
+ return True
+
+ return False
+
def check_restructuredtext(self):
"""Checks if the long string fields are reST-compliant."""
data = self.distribution.get_long_description()
diff --git a/setuptools/_distutils/command/install.py b/setuptools/_distutils/command/install.py
index c756b6db..41c17d8a 100644
--- a/setuptools/_distutils/command/install.py
+++ b/setuptools/_distutils/command/install.py
@@ -17,6 +17,7 @@ from distutils.file_util import write_file
from distutils.util import convert_path, subst_vars, change_root
from distutils.util import get_platform
from distutils.errors import DistutilsOptionError
+from .. import _collections
from site import USER_BASE
from site import USER_SITE
@@ -67,8 +68,8 @@ if HAS_USER_SITE:
INSTALL_SCHEMES['nt_user'] = {
'purelib': '{usersite}',
'platlib': '{usersite}',
- 'headers': '{userbase}/{implementation}{py_version_nodot}/Include/{dist_name}',
- 'scripts': '{userbase}/{implementation}{py_version_nodot}/Scripts',
+ 'headers': '{userbase}/{implementation}{py_version_nodot_plat}/Include/{dist_name}',
+ 'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts',
'data' : '{userbase}',
}
@@ -118,6 +119,65 @@ def _get_implementation():
return 'Python'
+def _select_scheme(ob, name):
+ scheme = _inject_headers(name, _load_scheme(_resolve_scheme(name)))
+ vars(ob).update(_remove_set(ob, _scheme_attrs(scheme)))
+
+
+def _remove_set(ob, attrs):
+ """
+ Include only attrs that are None in ob.
+ """
+ return {
+ key: value
+ for key, value in attrs.items()
+ if getattr(ob, key) is None
+ }
+
+
+def _resolve_scheme(name):
+ os_name, sep, key = name.partition('_')
+ try:
+ resolved = sysconfig.get_preferred_scheme(key)
+ except Exception:
+ resolved = _pypy_hack(name)
+ return resolved
+
+
+def _load_scheme(name):
+ return _load_schemes()[name]
+
+
+def _inject_headers(name, scheme):
+ """
+ Given a scheme name and the resolved scheme,
+ if the scheme does not include headers, resolve
+ the fallback scheme for the name and use headers
+ from it. pypa/distutils#88
+ """
+ # Bypass the preferred scheme, which may not
+ # have defined headers.
+ fallback = _load_scheme(_pypy_hack(name))
+ scheme.setdefault('headers', fallback['headers'])
+ return scheme
+
+
+def _scheme_attrs(scheme):
+ """Resolve install directories by applying the install schemes."""
+ return {
+ f'install_{key}': scheme[key]
+ for key in SCHEME_KEYS
+ }
+
+
+def _pypy_hack(name):
+ PY37 = sys.version_info < (3, 8)
+ old_pypy = hasattr(sys, 'pypy_version_info') and PY37
+ prefix = not name.endswith(('_user', '_home'))
+ pypy_name = 'pypy' + '_nt' * (os.name == 'nt')
+ return pypy_name if old_pypy and prefix else name
+
+
class install(Command):
description = "install everything from build directory"
@@ -335,25 +395,35 @@ class install(Command):
except AttributeError:
# sys.abiflags may not be defined on all platforms.
abiflags = ''
- self.config_vars = {'dist_name': self.distribution.get_name(),
- 'dist_version': self.distribution.get_version(),
- 'dist_fullname': self.distribution.get_fullname(),
- 'py_version': py_version,
- 'py_version_short': '%d.%d' % sys.version_info[:2],
- 'py_version_nodot': '%d%d' % sys.version_info[:2],
- 'sys_prefix': prefix,
- 'prefix': prefix,
- 'sys_exec_prefix': exec_prefix,
- 'exec_prefix': exec_prefix,
- 'abiflags': abiflags,
- 'platlibdir': getattr(sys, 'platlibdir', 'lib'),
- 'implementation_lower': _get_implementation().lower(),
- 'implementation': _get_implementation(),
- }
+ local_vars = {
+ 'dist_name': self.distribution.get_name(),
+ 'dist_version': self.distribution.get_version(),
+ 'dist_fullname': self.distribution.get_fullname(),
+ 'py_version': py_version,
+ 'py_version_short': '%d.%d' % sys.version_info[:2],
+ 'py_version_nodot': '%d%d' % sys.version_info[:2],
+ 'sys_prefix': prefix,
+ 'prefix': prefix,
+ 'sys_exec_prefix': exec_prefix,
+ 'exec_prefix': exec_prefix,
+ 'abiflags': abiflags,
+ 'platlibdir': getattr(sys, 'platlibdir', 'lib'),
+ 'implementation_lower': _get_implementation().lower(),
+ 'implementation': _get_implementation(),
+ }
+
+ # vars for compatibility on older Pythons
+ compat_vars = dict(
+ # Python 3.9 and earlier
+ py_version_nodot_plat=getattr(sys, 'winver', '').replace('.', ''),
+ )
if HAS_USER_SITE:
- self.config_vars['userbase'] = self.install_userbase
- self.config_vars['usersite'] = self.install_usersite
+ local_vars['userbase'] = self.install_userbase
+ local_vars['usersite'] = self.install_usersite
+
+ self.config_vars = _collections.DictStack(
+ [compat_vars, sysconfig.get_config_vars(), local_vars])
self.expand_basedirs()
@@ -361,15 +431,13 @@ class install(Command):
# Now define config vars for the base directories so we can expand
# everything else.
- self.config_vars['base'] = self.install_base
- self.config_vars['platbase'] = self.install_platbase
- self.config_vars['installed_base'] = (
- sysconfig.get_config_vars()['installed_base'])
+ local_vars['base'] = self.install_base
+ local_vars['platbase'] = self.install_platbase
if DEBUG:
from pprint import pprint
print("config vars:")
- pprint(self.config_vars)
+ pprint(dict(self.config_vars))
# Expand "~" and configuration variables in the installation
# directories.
@@ -445,12 +513,17 @@ class install(Command):
def finalize_unix(self):
"""Finalizes options for posix platforms."""
if self.install_base is not None or self.install_platbase is not None:
- if ((self.install_lib is None and
- self.install_purelib is None and
- self.install_platlib is None) or
+ incomplete_scheme = (
+ (
+ self.install_lib is None and
+ self.install_purelib is None and
+ self.install_platlib is None
+ ) or
self.install_headers is None or
self.install_scripts is None or
- self.install_data is None):
+ self.install_data is None
+ )
+ if incomplete_scheme:
raise DistutilsOptionError(
"install-base or install-platbase supplied, but "
"installation scheme is incomplete")
@@ -471,8 +544,13 @@ class install(Command):
raise DistutilsOptionError(
"must not supply exec-prefix without prefix")
- self.prefix = os.path.normpath(sys.prefix)
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
+ # Allow Fedora to add components to the prefix
+ _prefix_addition = getattr(sysconfig, '_prefix_addition', "")
+
+ self.prefix = (
+ os.path.normpath(sys.prefix) + _prefix_addition)
+ self.exec_prefix = (
+ os.path.normpath(sys.exec_prefix) + _prefix_addition)
else:
if self.exec_prefix is None:
@@ -505,20 +583,7 @@ class install(Command):
"I don't know how to install stuff on '%s'" % os.name)
def select_scheme(self, name):
- """Sets the install directories by applying the install schemes."""
- # it's the caller's problem if they supply a bad name!
- if (hasattr(sys, 'pypy_version_info') and
- sys.version_info < (3, 8) and
- not name.endswith(('_user', '_home'))):
- if os.name == 'nt':
- name = 'pypy_nt'
- else:
- name = 'pypy'
- scheme = _load_schemes()[name]
- for key in SCHEME_KEYS:
- attrname = 'install_' + key
- if getattr(self, attrname) is None:
- setattr(self, attrname, scheme[key])
+ _select_scheme(self, name)
def _expand_attrs(self, attrs):
for attr in attrs:
@@ -592,7 +657,7 @@ class install(Command):
return
home = convert_path(os.path.expanduser("~"))
for name, path in self.config_vars.items():
- if path.startswith(home) and not os.path.isdir(path):
+ if str(path).startswith(home) and not os.path.isdir(path):
self.debug_print("os.makedirs('%s', 0o700)" % path)
os.makedirs(path, 0o700)
diff --git a/setuptools/_distutils/cygwinccompiler.py b/setuptools/_distutils/cygwinccompiler.py
index f80ca622..c5c86d8f 100644
--- a/setuptools/_distutils/cygwinccompiler.py
+++ b/setuptools/_distutils/cygwinccompiler.py
@@ -50,15 +50,15 @@ cygwin in no-cygwin mode).
import os
import sys
import copy
-from subprocess import Popen, PIPE, check_output
-import re
+import shlex
+import warnings
+from subprocess import check_output
from distutils.unixccompiler import UnixCCompiler
from distutils.file_util import write_file
from distutils.errors import (DistutilsExecError, CCompilerError,
CompileError, UnknownFileError)
-from distutils.version import LooseVersion
-from distutils.spawn import find_executable
+from distutils.version import LooseVersion, suppress_known_deprecation
def get_msvcr():
"""Include the appropriate MSVC runtime library if Python was built
@@ -108,7 +108,7 @@ class CygwinCCompiler(UnixCCompiler):
def __init__(self, verbose=0, dry_run=0, force=0):
- UnixCCompiler.__init__(self, verbose, dry_run, force)
+ super().__init__(verbose, dry_run, force)
status, details = check_config_h()
self.debug_print("Python's GCC status: %s (details: %s)" %
@@ -123,33 +123,8 @@ class CygwinCCompiler(UnixCCompiler):
self.cc = os.environ.get('CC', 'gcc')
self.cxx = os.environ.get('CXX', 'g++')
- if ('gcc' in self.cc): # Start gcc workaround
- self.gcc_version, self.ld_version, self.dllwrap_version = \
- get_versions()
- self.debug_print(self.compiler_type + ": gcc %s, ld %s, dllwrap %s\n" %
- (self.gcc_version,
- self.ld_version,
- self.dllwrap_version) )
-
- # ld_version >= "2.10.90" and < "2.13" should also be able to use
- # gcc -mdll instead of dllwrap
- # Older dllwraps had own version numbers, newer ones use the
- # same as the rest of binutils ( also ld )
- # dllwrap 2.10.90 is buggy
- if self.ld_version >= "2.10.90":
- self.linker_dll = self.cc
- else:
- self.linker_dll = "dllwrap"
-
- # ld_version >= "2.13" support -shared so use it instead of
- # -mdll -static
- if self.ld_version >= "2.13":
- shared_option = "-shared"
- else:
- shared_option = "-mdll -static"
- else: # Assume linker is up to date
- self.linker_dll = self.cc
- shared_option = "-shared"
+ self.linker_dll = self.cc
+ shared_option = "-shared"
self.set_executables(compiler='%s -mcygwin -O -Wall' % self.cc,
compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc,
@@ -158,17 +133,24 @@ class CygwinCCompiler(UnixCCompiler):
linker_so=('%s -mcygwin %s' %
(self.linker_dll, shared_option)))
- # cygwin and mingw32 need different sets of libraries
- if ('gcc' in self.cc and self.gcc_version == "2.91.57"):
- # cygwin shouldn't need msvcrt, but without the dlls will crash
- # (gcc version 2.91.57) -- perhaps something about initialization
- self.dll_libraries=["msvcrt"]
- self.warn(
- "Consider upgrading to a newer version of gcc")
- else:
- # Include the appropriate MSVC runtime library if Python was built
- # with MSVC 7.0 or later.
- self.dll_libraries = get_msvcr()
+ # Include the appropriate MSVC runtime library if Python was built
+ # with MSVC 7.0 or later.
+ self.dll_libraries = get_msvcr()
+
+ @property
+ def gcc_version(self):
+ # Older numpy dependend on this existing to check for ancient
+ # gcc versions. This doesn't make much sense with clang etc so
+ # just hardcode to something recent.
+ # https://github.com/numpy/numpy/pull/20333
+ warnings.warn(
+ "gcc_version attribute of CygwinCCompiler is deprecated. "
+ "Instead of returning actual gcc version a fixed value 11.2.0 is returned.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ with suppress_known_deprecation():
+ return LooseVersion("11.2.0")
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
"""Compiles the source by spawning GCC and windres if needed."""
@@ -230,24 +212,17 @@ class CygwinCCompiler(UnixCCompiler):
# next add options for def-file and to creating import libraries
- # dllwrap uses different options than gcc/ld
- if self.linker_dll == "dllwrap":
- extra_preargs.extend(["--output-lib", lib_file])
- # for dllwrap we have to use a special option
- extra_preargs.extend(["--def", def_file])
- # we use gcc/ld here and can be sure ld is >= 2.9.10
- else:
- # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
- #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
- # for gcc/ld the def-file is specified as any object files
- objects.append(def_file)
+ # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
+ #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
+ # for gcc/ld the def-file is specified as any object files
+ objects.append(def_file)
#end: if ((export_symbols is not None) and
# (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
# who wants symbols and a many times larger output file
# should explicitly switch the debug mode on
- # otherwise we let dllwrap/ld strip the output file
+ # otherwise we let ld strip the output file
# (On my machine: 10KiB < stripped_file < ??100KiB
# unstripped_file = stripped_file + XXX KiB
# ( XXX=254 for a typical python extension))
@@ -293,21 +268,9 @@ class Mingw32CCompiler(CygwinCCompiler):
def __init__(self, verbose=0, dry_run=0, force=0):
- CygwinCCompiler.__init__ (self, verbose, dry_run, force)
-
- # ld_version >= "2.13" support -shared so use it instead of
- # -mdll -static
- if ('gcc' in self.cc and self.ld_version < "2.13"):
- shared_option = "-mdll -static"
- else:
- shared_option = "-shared"
+ super().__init__ (verbose, dry_run, force)
- # A real mingw32 doesn't need to specify a different entry point,
- # but cygwin 2.91.57 in no-cygwin-mode needs it.
- if ('gcc' in self.cc and self.gcc_version <= "2.91.57"):
- entry_point = '--entry _DllMain@12'
- else:
- entry_point = ''
+ shared_option = "-shared"
if is_cygwincc(self.cc):
raise CCompilerError(
@@ -317,9 +280,9 @@ class Mingw32CCompiler(CygwinCCompiler):
compiler_so='%s -mdll -O -Wall' % self.cc,
compiler_cxx='%s -O -Wall' % self.cxx,
linker_exe='%s' % self.cc,
- linker_so='%s %s %s'
- % (self.linker_dll, shared_option,
- entry_point))
+ linker_so='%s %s'
+ % (self.linker_dll, shared_option))
+
# Maybe we should also append -mthreads, but then the finished
# dlls need another dll (mingwm10.dll see Mingw32 docs)
# (-mthreads: Support thread-safe exception handling on `Mingw32')
@@ -386,38 +349,14 @@ def check_config_h():
return (CONFIG_H_UNCERTAIN,
"couldn't read '%s': %s" % (fn, exc.strerror))
-RE_VERSION = re.compile(br'(\d+\.\d+(\.\d+)*)')
-
-def _find_exe_version(cmd):
- """Find the version of an executable by running `cmd` in the shell.
-
- If the command is not found, or the output does not match
- `RE_VERSION`, returns None.
- """
- executable = cmd.split()[0]
- if find_executable(executable) is None:
- return None
- out = Popen(cmd, shell=True, stdout=PIPE).stdout
- try:
- out_string = out.read()
- finally:
- out.close()
- 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())
-
-def get_versions():
- """ Try to find out the versions of gcc, ld and dllwrap.
-
- If not possible it returns None for it.
- """
- commands = ['gcc -dumpversion', 'ld -v', 'dllwrap --version']
- return tuple([_find_exe_version(cmd) for cmd in commands])
-
def is_cygwincc(cc):
'''Try to determine if the compiler that would be used is from cygwin.'''
- out_string = check_output([cc, '-dumpmachine'])
+ out_string = check_output(shlex.split(cc) + ['-dumpmachine'])
return out_string.strip().endswith(b'cygwin')
+
+
+get_versions = None
+"""
+A stand-in for the previous get_versions() function to prevent failures
+when monkeypatched. See pypa/setuptools#2969.
+"""
diff --git a/setuptools/_distutils/log.py b/setuptools/_distutils/log.py
index 8ef6b28e..a68b156b 100644
--- a/setuptools/_distutils/log.py
+++ b/setuptools/_distutils/log.py
@@ -3,13 +3,14 @@
# The class here is styled after PEP 282 so that it could later be
# replaced with a standard Python logging implementation.
+import sys
+
DEBUG = 1
INFO = 2
WARN = 3
ERROR = 4
FATAL = 5
-import sys
class Log:
@@ -54,6 +55,7 @@ class Log:
def fatal(self, msg, *args):
self._log(FATAL, msg, args)
+
_global_log = Log()
log = _global_log.log
debug = _global_log.debug
@@ -62,12 +64,14 @@ warn = _global_log.warn
error = _global_log.error
fatal = _global_log.fatal
+
def set_threshold(level):
# return the old threshold for use from tests
old = _global_log.threshold
_global_log.threshold = level
return old
+
def set_verbosity(v):
if v <= 0:
set_threshold(WARN)
diff --git a/setuptools/_distutils/msvc9compiler.py b/setuptools/_distutils/msvc9compiler.py
index a1b3b02f..6b627383 100644
--- a/setuptools/_distutils/msvc9compiler.py
+++ b/setuptools/_distutils/msvc9compiler.py
@@ -291,8 +291,6 @@ def query_vcvarsall(version, arch="x86"):
# More globals
VERSION = get_build_version()
-if VERSION < 8.0:
- raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
# MACROS = MacroExpander(VERSION)
class MSVCCompiler(CCompiler) :
@@ -326,7 +324,7 @@ class MSVCCompiler(CCompiler) :
exe_extension = '.exe'
def __init__(self, verbose=0, dry_run=0, force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
+ super().__init__(verbose, dry_run, force)
self.__version = VERSION
self.__root = r"Software\Microsoft\VisualStudio"
# self.__macros = MACROS
@@ -339,6 +337,8 @@ class MSVCCompiler(CCompiler) :
def initialize(self, plat_name=None):
# multi-init means we would need to check platform same each time...
assert not self.initialized, "don't init multiple times"
+ if self.__version < 8.0:
+ raise DistutilsPlatformError("VC %0.1f is not supported by this module" % self.__version)
if plat_name is None:
plat_name = get_platform()
# sanity check for platforms to prevent obscure errors later.
diff --git a/setuptools/_distutils/msvccompiler.py b/setuptools/_distutils/msvccompiler.py
index 2d447b85..e1367b89 100644
--- a/setuptools/_distutils/msvccompiler.py
+++ b/setuptools/_distutils/msvccompiler.py
@@ -228,7 +228,7 @@ class MSVCCompiler(CCompiler) :
exe_extension = '.exe'
def __init__(self, verbose=0, dry_run=0, force=0):
- CCompiler.__init__ (self, verbose, dry_run, force)
+ super().__init__(verbose, dry_run, force)
self.__version = get_build_version()
self.__arch = get_build_architecture()
if self.__arch == "Intel":
diff --git a/setuptools/_distutils/py39compat.py b/setuptools/_distutils/py39compat.py
new file mode 100644
index 00000000..9de95013
--- /dev/null
+++ b/setuptools/_distutils/py39compat.py
@@ -0,0 +1,21 @@
+import sys
+import platform
+
+
+def add_ext_suffix_39(vars):
+ """
+ Ensure vars contains 'EXT_SUFFIX'. pypa/distutils#130
+ """
+ import _imp
+ ext_suffix = _imp.extension_suffixes()[0]
+ vars.update(
+ EXT_SUFFIX=ext_suffix,
+ # sysconfig sets SO to match EXT_SUFFIX, so maintain
+ # that expectation.
+ # https://github.com/python/cpython/blob/785cc6770588de087d09e89a69110af2542be208/Lib/sysconfig.py#L671-L673
+ SO=ext_suffix,
+ )
+
+
+needs_ext_suffix = sys.version_info < (3, 10) and platform.system() == 'Windows'
+add_ext_suffix = add_ext_suffix_39 if needs_ext_suffix else lambda vars: None
diff --git a/setuptools/_distutils/spawn.py b/setuptools/_distutils/spawn.py
index 6e1c89f1..b2d10e39 100644
--- a/setuptools/_distutils/spawn.py
+++ b/setuptools/_distutils/spawn.py
@@ -10,7 +10,7 @@ import sys
import os
import subprocess
-from distutils.errors import DistutilsPlatformError, DistutilsExecError
+from distutils.errors import DistutilsExecError
from distutils.debug import DEBUG
from distutils import log
diff --git a/setuptools/_distutils/sysconfig.py b/setuptools/_distutils/sysconfig.py
index d36d94f7..55a42e16 100644
--- a/setuptools/_distutils/sysconfig.py
+++ b/setuptools/_distutils/sysconfig.py
@@ -9,12 +9,13 @@ Written by: Fred L. Drake, Jr.
Email: <fdrake@acm.org>
"""
-import _imp
import os
import re
import sys
+import sysconfig
from .errors import DistutilsPlatformError
+from . import py39compat
IS_PYPY = '__pypy__' in sys.builtin_module_names
@@ -47,6 +48,7 @@ def _is_python_source_dir(d):
return True
return False
+
_sys_home = getattr(sys, '_home', None)
if os.name == 'nt':
@@ -58,11 +60,13 @@ if os.name == 'nt':
project_base = _fix_pcbuild(project_base)
_sys_home = _fix_pcbuild(_sys_home)
+
def _python_build():
if _sys_home:
return _is_python_source_dir(_sys_home)
return _is_python_source_dir(project_base)
+
python_build = _python_build()
@@ -78,6 +82,7 @@ except AttributeError:
# this attribute, which is fine.
pass
+
def get_python_version():
"""Return a string containing the major and minor Python version,
leaving off the patchlevel. Sample return values could be '1.5'
@@ -191,7 +196,6 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
"on platform '%s'" % os.name)
-
def customize_compiler(compiler):
"""Do any platform-specific customization of a CCompiler instance.
@@ -216,8 +220,9 @@ def customize_compiler(compiler):
_config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
(cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
- get_config_vars('CC', 'CXX', 'CFLAGS',
- 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
+ get_config_vars(
+ 'CC', 'CXX', 'CFLAGS',
+ 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
if 'CC' in os.environ:
newcc = os.environ['CC']
@@ -274,31 +279,14 @@ def get_config_h_filename():
inc_dir = os.path.join(_sys_home or project_base, "PC")
else:
inc_dir = _sys_home or project_base
+ return os.path.join(inc_dir, 'pyconfig.h')
else:
- inc_dir = get_python_inc(plat_specific=1)
-
- return os.path.join(inc_dir, 'pyconfig.h')
-
-
-# Allow this value to be patched by pkgsrc. Ref pypa/distutils#16.
-_makefile_tmpl = 'config-{python_ver}{build_flags}{multiarch}'
+ return sysconfig.get_config_h_filename()
def get_makefile_filename():
"""Return full pathname of installed Makefile from the Python build."""
- if python_build:
- return os.path.join(_sys_home or project_base, "Makefile")
- lib_dir = get_python_lib(plat_specific=0, standard_lib=1)
- multiarch = (
- '-%s' % sys.implementation._multiarch
- if hasattr(sys.implementation, '_multiarch') else ''
- )
- config_file = _makefile_tmpl.format(
- python_ver=get_python_version(),
- build_flags=build_flags,
- multiarch=multiarch,
- )
- return os.path.join(lib_dir, config_file, 'Makefile')
+ return sysconfig.get_makefile_filename()
def parse_config_h(fp, g=None):
@@ -308,26 +296,7 @@ def parse_config_h(fp, g=None):
optional dictionary is passed in as the second argument, it is
used instead of a new dictionary.
"""
- if g is None:
- g = {}
- define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
- undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
- #
- while True:
- line = fp.readline()
- if not line:
- break
- m = define_rx.match(line)
- if m:
- n, v = m.group(1, 2)
- try: v = int(v)
- except ValueError: pass
- g[n] = v
- else:
- m = undef_rx.match(line)
- if m:
- g[m.group(1)] = 0
- return g
+ return sysconfig.parse_config_h(fp, vars=g)
# Regexes needed for parsing Makefile (and similar syntaxes,
@@ -336,6 +305,7 @@ _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
+
def parse_makefile(fn, g=None):
"""Parse a Makefile-style file.
@@ -344,7 +314,9 @@ def parse_makefile(fn, g=None):
used instead of a new dictionary.
"""
from distutils.text_file import TextFile
- fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape")
+ fp = TextFile(
+ fn, strip_comments=1, skip_blanks=1, join_lines=1,
+ errors="surrogateescape")
if g is None:
g = {}
@@ -353,7 +325,7 @@ def parse_makefile(fn, g=None):
while True:
line = fp.readline()
- if line is None: # eof
+ if line is None: # eof
break
m = _variable_rx.match(line)
if m:
@@ -397,7 +369,8 @@ def parse_makefile(fn, g=None):
item = os.environ[n]
elif n in renamed_variables:
- if name.startswith('PY_') and name[3:] in renamed_variables:
+ if name.startswith('PY_') and \
+ name[3:] in renamed_variables:
item = ""
elif 'PY_' + n in notdone:
@@ -413,7 +386,8 @@ def parse_makefile(fn, g=None):
if "$" in after:
notdone[name] = value
else:
- try: value = int(value)
+ try:
+ value = int(value)
except ValueError:
done[name] = value.strip()
else:
@@ -421,7 +395,7 @@ def parse_makefile(fn, g=None):
del notdone[name]
if name.startswith('PY_') \
- and name[3:] in renamed_variables:
+ and name[3:] in renamed_variables:
name = name[3:]
if name not in done:
@@ -470,51 +444,6 @@ def expand_makefile_vars(s, vars):
_config_vars = None
-_sysconfig_name_tmpl = '_sysconfigdata_{abi}_{platform}_{multiarch}'
-
-
-def _init_posix():
- """Initialize the module as appropriate for POSIX systems."""
- # _sysconfigdata is generated at build time, see the sysconfig module
- name = os.environ.get(
- '_PYTHON_SYSCONFIGDATA_NAME',
- _sysconfig_name_tmpl.format(
- abi=sys.abiflags,
- platform=sys.platform,
- multiarch=getattr(sys.implementation, '_multiarch', ''),
- ),
- )
- try:
- _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
- except ImportError:
- # Python 3.5 and pypy 7.3.1
- _temp = __import__(
- '_sysconfigdata', globals(), locals(), ['build_time_vars'], 0)
- build_time_vars = _temp.build_time_vars
- global _config_vars
- _config_vars = {}
- _config_vars.update(build_time_vars)
-
-
-def _init_nt():
- """Initialize the module as appropriate for NT"""
- g = {}
- # set basic install directories
- g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
- g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
-
- # XXX hmmm.. a normal install puts include files here
- g['INCLUDEPY'] = get_python_inc(plat_specific=0)
-
- g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
- g['EXE'] = ".exe"
- g['VERSION'] = get_python_version().replace(".", "")
- g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
-
- global _config_vars
- _config_vars = g
-
-
def get_config_vars(*args):
"""With no arguments, return a dictionary of all configuration
variables relevant for the current platform. Generally this includes
@@ -527,60 +456,8 @@ def get_config_vars(*args):
"""
global _config_vars
if _config_vars is None:
- func = globals().get("_init_" + os.name)
- if func:
- func()
- else:
- _config_vars = {}
-
- # Normalized versions of prefix and exec_prefix are handy to have;
- # in fact, these are the standard versions used most places in the
- # Distutils.
- _config_vars['prefix'] = PREFIX
- _config_vars['exec_prefix'] = EXEC_PREFIX
-
- if not IS_PYPY:
- # For backward compatibility, see issue19555
- SO = _config_vars.get('EXT_SUFFIX')
- if SO is not None:
- _config_vars['SO'] = SO
-
- # Always convert srcdir to an absolute path
- srcdir = _config_vars.get('srcdir', project_base)
- if os.name == 'posix':
- if python_build:
- # If srcdir is a relative path (typically '.' or '..')
- # then it should be interpreted relative to the directory
- # containing Makefile.
- base = os.path.dirname(get_makefile_filename())
- srcdir = os.path.join(base, srcdir)
- else:
- # srcdir is not meaningful since the installation is
- # spread about the filesystem. We choose the
- # directory containing the Makefile since we know it
- # exists.
- srcdir = os.path.dirname(get_makefile_filename())
- _config_vars['srcdir'] = os.path.abspath(os.path.normpath(srcdir))
-
- # Convert srcdir into an absolute path if it appears necessary.
- # Normally it is relative to the build directory. However, during
- # testing, for example, we might be running a non-installed python
- # from a different directory.
- if python_build and os.name == "posix":
- base = project_base
- if (not os.path.isabs(_config_vars['srcdir']) and
- base != os.getcwd()):
- # srcdir is relative and we are not in the same directory
- # as the executable. Assume executable is in the build
- # directory and make srcdir absolute.
- srcdir = os.path.join(base, _config_vars['srcdir'])
- _config_vars['srcdir'] = os.path.normpath(srcdir)
-
- # OS X platforms require special customization to handle
- # multi-architecture, multi-os-version installers
- if sys.platform == 'darwin':
- import _osx_support
- _osx_support.customize_config_vars(_config_vars)
+ _config_vars = sysconfig.get_config_vars().copy()
+ py39compat.add_ext_suffix(_config_vars)
if args:
vals = []
@@ -590,6 +467,7 @@ def get_config_vars(*args):
else:
return _config_vars
+
def get_config_var(name):
"""Return the value of a single variable using the dictionary
returned by 'get_config_vars()'. Equivalent to
@@ -597,5 +475,6 @@ def get_config_var(name):
"""
if name == 'SO':
import warnings
- warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
+ warnings.warn(
+ 'SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
return get_config_vars().get(name)
diff --git a/setuptools/_distutils/tests/py38compat.py b/setuptools/_distutils/tests/py38compat.py
index 32269c7b..c949f58e 100644
--- a/setuptools/_distutils/tests/py38compat.py
+++ b/setuptools/_distutils/tests/py38compat.py
@@ -2,6 +2,11 @@
import contextlib
import builtins
+import sys
+
+from test.support import requires_zlib
+import test.support
+
ModuleNotFoundError = getattr(builtins, 'ModuleNotFoundError', ImportError)
@@ -51,3 +56,7 @@ try:
from test.support.warnings_helper import save_restore_warnings_filters
except (ModuleNotFoundError, ImportError):
save_restore_warnings_filters = _save_restore_warnings_filters
+
+
+if sys.version_info < (3, 9):
+ requires_zlib = lambda: test.support.requires_zlib
diff --git a/setuptools/_distutils/tests/test_archive_util.py b/setuptools/_distutils/tests/test_archive_util.py
index ce6456dc..800b9018 100644
--- a/setuptools/_distutils/tests/test_archive_util.py
+++ b/setuptools/_distutils/tests/test_archive_util.py
@@ -14,16 +14,11 @@ from distutils.archive_util import (check_archive_formats, make_tarball,
from distutils.spawn import find_executable, spawn
from distutils.tests import support
from test.support import run_unittest, patch
+from .unix_compat import require_unix_id, require_uid_0, grp, pwd, UID_0_SUPPORT
from .py38compat import change_cwd
from .py38compat import check_warnings
-try:
- import grp
- import pwd
- UID_GID_SUPPORT = True
-except ImportError:
- UID_GID_SUPPORT = False
try:
import zipfile
@@ -339,7 +334,7 @@ class ArchiveUtilTestCase(support.TempdirManager,
def test_make_archive_owner_group(self):
# testing make_archive with owner and group, with various combinations
# this works even if there's not gid/uid support
- if UID_GID_SUPPORT:
+ if UID_0_SUPPORT:
group = grp.getgrgid(0)[0]
owner = pwd.getpwuid(0)[0]
else:
@@ -364,7 +359,8 @@ class ArchiveUtilTestCase(support.TempdirManager,
self.assertTrue(os.path.exists(res))
@unittest.skipUnless(ZLIB_SUPPORT, "Requires zlib")
- @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
+ @require_unix_id
+ @require_uid_0
def test_tarfile_root_owner(self):
tmpdir = self._create_files()
base_name = os.path.join(self.mkdtemp(), 'archive')
@@ -391,7 +387,7 @@ class ArchiveUtilTestCase(support.TempdirManager,
archive.close()
def test_suite():
- return unittest.makeSuite(ArchiveUtilTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(ArchiveUtilTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_bdist.py b/setuptools/_distutils/tests/test_bdist.py
index 130d8bf1..8b7498e3 100644
--- a/setuptools/_distutils/tests/test_bdist.py
+++ b/setuptools/_distutils/tests/test_bdist.py
@@ -51,7 +51,7 @@ class BuildTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(BuildTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_bdist_dumb.py b/setuptools/_distutils/tests/test_bdist_dumb.py
index 01a233bc..bb860c8a 100644
--- a/setuptools/_distutils/tests/test_bdist_dumb.py
+++ b/setuptools/_distutils/tests/test_bdist_dumb.py
@@ -91,7 +91,7 @@ class BuildDumbTestCase(support.TempdirManager,
self.assertEqual(contents, sorted(wanted))
def test_suite():
- return unittest.makeSuite(BuildDumbTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildDumbTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_bdist_msi.py b/setuptools/_distutils/tests/test_bdist_msi.py
index 937266f8..b1831ef2 100644
--- a/setuptools/_distutils/tests/test_bdist_msi.py
+++ b/setuptools/_distutils/tests/test_bdist_msi.py
@@ -22,7 +22,7 @@ class BDistMSITestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(BDistMSITestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BDistMSITestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_bdist_rpm.py b/setuptools/_distutils/tests/test_bdist_rpm.py
index 6453a02b..08a7cb46 100644
--- a/setuptools/_distutils/tests/test_bdist_rpm.py
+++ b/setuptools/_distutils/tests/test_bdist_rpm.py
@@ -3,13 +3,16 @@
import unittest
import sys
import os
-from test.support import run_unittest, requires_zlib
+from test.support import run_unittest
from distutils.core import Distribution
from distutils.command.bdist_rpm import bdist_rpm
from distutils.tests import support
from distutils.spawn import find_executable
+from .py38compat import requires_zlib
+
+
SETUP_PY = """\
from distutils.core import setup
import foo
@@ -44,7 +47,7 @@ class BuildRpmTestCase(support.TempdirManager,
# spurious sdtout/stderr output under Mac OS X
@unittest.skipUnless(sys.platform.startswith('linux'),
'spurious sdtout/stderr output under Mac OS X')
- @requires_zlib
+ @requires_zlib()
@unittest.skipIf(find_executable('rpm') is None,
'the rpm command is not found')
@unittest.skipIf(find_executable('rpmbuild') is None,
@@ -87,7 +90,7 @@ class BuildRpmTestCase(support.TempdirManager,
# spurious sdtout/stderr output under Mac OS X
@unittest.skipUnless(sys.platform.startswith('linux'),
'spurious sdtout/stderr output under Mac OS X')
- @requires_zlib
+ @requires_zlib()
# http://bugs.python.org/issue1533164
@unittest.skipIf(find_executable('rpm') is None,
'the rpm command is not found')
@@ -129,7 +132,7 @@ class BuildRpmTestCase(support.TempdirManager,
os.remove(os.path.join(pkg_dir, 'dist', 'foo-0.1-1.noarch.rpm'))
def test_suite():
- return unittest.makeSuite(BuildRpmTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildRpmTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_bdist_wininst.py b/setuptools/_distutils/tests/test_bdist_wininst.py
index 31cf2628..59f25167 100644
--- a/setuptools/_distutils/tests/test_bdist_wininst.py
+++ b/setuptools/_distutils/tests/test_bdist_wininst.py
@@ -34,7 +34,7 @@ class BuildWinInstTestCase(support.TempdirManager,
self.assertGreater(len(exe_file), 10)
def test_suite():
- return unittest.makeSuite(BuildWinInstTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildWinInstTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_build.py b/setuptools/_distutils/tests/test_build.py
index b020a5ba..93724419 100644
--- a/setuptools/_distutils/tests/test_build.py
+++ b/setuptools/_distutils/tests/test_build.py
@@ -24,10 +24,10 @@ class BuildTestCase(support.TempdirManager,
wanted = os.path.join(cmd.build_base, 'lib')
self.assertEqual(cmd.build_purelib, wanted)
- # build_platlib is 'build/lib.platform-x.x[-pydebug]'
+ # build_platlib is 'build/lib.platform-cache_tag[-pydebug]'
# examples:
- # build/lib.macosx-10.3-i386-2.7
- plat_spec = '.%s-%d.%d' % (cmd.plat_name, *sys.version_info[:2])
+ # build/lib.macosx-10.3-i386-cpython39
+ plat_spec = '.%s-%s' % (cmd.plat_name, sys.implementation.cache_tag)
if hasattr(sys, 'gettotalrefcount'):
self.assertTrue(cmd.build_platlib.endswith('-pydebug'))
plat_spec += '-pydebug'
@@ -50,7 +50,7 @@ class BuildTestCase(support.TempdirManager,
self.assertEqual(cmd.executable, os.path.normpath(sys.executable))
def test_suite():
- return unittest.makeSuite(BuildTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_build_clib.py b/setuptools/_distutils/tests/test_build_clib.py
index 259c4352..d50ead7c 100644
--- a/setuptools/_distutils/tests/test_build_clib.py
+++ b/setuptools/_distutils/tests/test_build_clib.py
@@ -130,7 +130,7 @@ class BuildCLibTestCase(support.TempdirManager,
self.assertIn('libfoo.a', os.listdir(build_temp))
def test_suite():
- return unittest.makeSuite(BuildCLibTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildCLibTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_build_ext.py b/setuptools/_distutils/tests/test_build_ext.py
index 85ecf4b7..920e4dc8 100644
--- a/setuptools/_distutils/tests/test_build_ext.py
+++ b/setuptools/_distutils/tests/test_build_ext.py
@@ -493,12 +493,16 @@ class BuildExtTestCase(TempdirManager,
# format the target value as defined in the Apple
# Availability Macros. We can't use the macro names since
# at least one value we test with will not exist yet.
- if target[1] < 10:
+ if target[:2] < (10, 10):
# for 10.1 through 10.9.x -> "10n0"
target = '%02d%01d0' % target
else:
# for 10.10 and beyond -> "10nn00"
- target = '%02d%02d00' % target
+ if len(target) >= 2:
+ target = '%02d%02d00' % target
+ else:
+ # 11 and later can have no minor version (11 instead of 11.0)
+ target = '%02d0000' % target
deptarget_ext = Extension(
'deptarget',
[deptarget_c],
@@ -538,8 +542,8 @@ class ParallelBuildExtTestCase(BuildExtTestCase):
def test_suite():
suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(BuildExtTestCase))
- suite.addTest(unittest.makeSuite(ParallelBuildExtTestCase))
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(BuildExtTestCase))
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(ParallelBuildExtTestCase))
return suite
if __name__ == '__main__':
diff --git a/setuptools/_distutils/tests/test_build_py.py b/setuptools/_distutils/tests/test_build_py.py
index 0712e92c..a590a485 100644
--- a/setuptools/_distutils/tests/test_build_py.py
+++ b/setuptools/_distutils/tests/test_build_py.py
@@ -173,7 +173,7 @@ class BuildPyTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(BuildPyTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildPyTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_build_scripts.py b/setuptools/_distutils/tests/test_build_scripts.py
index 954fc763..f299e51e 100644
--- a/setuptools/_distutils/tests/test_build_scripts.py
+++ b/setuptools/_distutils/tests/test_build_scripts.py
@@ -106,7 +106,7 @@ class BuildScriptsTestCase(support.TempdirManager,
self.assertIn(name, built)
def test_suite():
- return unittest.makeSuite(BuildScriptsTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(BuildScriptsTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_check.py b/setuptools/_distutils/tests/test_check.py
index e534aca1..b41dba3d 100644
--- a/setuptools/_distutils/tests/test_check.py
+++ b/setuptools/_distutils/tests/test_check.py
@@ -71,6 +71,28 @@ class CheckTestCase(support.LoggingSilencer,
cmd = self._run(metadata)
self.assertEqual(cmd._warnings, 0)
+ def test_check_author_maintainer(self):
+ for kind in ("author", "maintainer"):
+ # ensure no warning when author_email or maintainer_email is given
+ # (the spec allows these fields to take the form "Name <email>")
+ metadata = {'url': 'xxx',
+ kind + '_email': 'Name <name@email.com>',
+ 'name': 'xxx', 'version': 'xxx'}
+ cmd = self._run(metadata)
+ self.assertEqual(cmd._warnings, 0)
+
+ # the check should warn if only email is given and it does not
+ # contain the name
+ metadata[kind + '_email'] = 'name@email.com'
+ cmd = self._run(metadata)
+ self.assertEqual(cmd._warnings, 1)
+
+ # the check should warn if only the name is given
+ metadata[kind] = "Name"
+ del metadata[kind + '_email']
+ cmd = self._run(metadata)
+ self.assertEqual(cmd._warnings, 1)
+
@unittest.skipUnless(HAS_DOCUTILS, "won't test without docutils")
def test_check_document(self):
pkg_info, dist = self.create_dist()
@@ -157,7 +179,7 @@ class CheckTestCase(support.LoggingSilencer,
'restructuredtext': 1})
def test_suite():
- return unittest.makeSuite(CheckTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(CheckTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_clean.py b/setuptools/_distutils/tests/test_clean.py
index c605afd8..92367499 100644
--- a/setuptools/_distutils/tests/test_clean.py
+++ b/setuptools/_distutils/tests/test_clean.py
@@ -43,7 +43,7 @@ class cleanTestCase(support.TempdirManager,
cmd.run()
def test_suite():
- return unittest.makeSuite(cleanTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(cleanTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_cmd.py b/setuptools/_distutils/tests/test_cmd.py
index cf5197c3..2319214a 100644
--- a/setuptools/_distutils/tests/test_cmd.py
+++ b/setuptools/_distutils/tests/test_cmd.py
@@ -120,7 +120,7 @@ class CommandTestCase(unittest.TestCase):
debug.DEBUG = False
def test_suite():
- return unittest.makeSuite(CommandTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(CommandTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_config.py b/setuptools/_distutils/tests/test_config.py
index 344084af..27bd9d44 100644
--- a/setuptools/_distutils/tests/test_config.py
+++ b/setuptools/_distutils/tests/test_config.py
@@ -66,7 +66,7 @@ class BasePyPIRCCommandTestCase(support.TempdirManager,
class command(PyPIRCCommand):
def __init__(self, dist):
- PyPIRCCommand.__init__(self, dist)
+ super().__init__(dist)
def initialize_options(self):
pass
finalize_options = initialize_options
@@ -135,7 +135,7 @@ class PyPIRCCommandTestCase(BasePyPIRCCommandTestCase):
def test_suite():
- return unittest.makeSuite(PyPIRCCommandTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(PyPIRCCommandTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_config_cmd.py b/setuptools/_distutils/tests/test_config_cmd.py
index 4cd9a6b9..2c84719a 100644
--- a/setuptools/_distutils/tests/test_config_cmd.py
+++ b/setuptools/_distutils/tests/test_config_cmd.py
@@ -92,7 +92,7 @@ class ConfigTestCase(support.LoggingSilencer,
self.assertFalse(os.path.exists(f))
def test_suite():
- return unittest.makeSuite(ConfigTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(ConfigTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_core.py b/setuptools/_distutils/tests/test_core.py
index d99cfd26..7270d699 100644
--- a/setuptools/_distutils/tests/test_core.py
+++ b/setuptools/_distutils/tests/test_core.py
@@ -159,7 +159,7 @@ class CoreTestCase(support.EnvironGuard, unittest.TestCase):
self.assertEqual(stdout.readlines()[0], wanted)
def test_suite():
- return unittest.makeSuite(CoreTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(CoreTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_cygwinccompiler.py b/setuptools/_distutils/tests/test_cygwinccompiler.py
index 2a02eed4..8715a535 100644
--- a/setuptools/_distutils/tests/test_cygwinccompiler.py
+++ b/setuptools/_distutils/tests/test_cygwinccompiler.py
@@ -2,28 +2,14 @@
import unittest
import sys
import os
-from io import BytesIO
from test.support import run_unittest
-from distutils import cygwinccompiler
from distutils.cygwinccompiler import (check_config_h,
CONFIG_H_OK, CONFIG_H_NOTOK,
- CONFIG_H_UNCERTAIN, get_versions,
+ CONFIG_H_UNCERTAIN,
get_msvcr)
from distutils.tests import support
-class FakePopen(object):
- test_class = None
-
- def __init__(self, cmd, shell, stdout):
- self.cmd = cmd.split()[0]
- exes = self.test_class._exes
- if self.cmd in exes:
- # issue #6438 in Python 3.x, Popen returns bytes
- self.stdout = BytesIO(exes[self.cmd])
- else:
- self.stdout = os.popen(cmd, 'r')
-
class CygwinCCompilerTestCase(support.TempdirManager,
unittest.TestCase):
@@ -35,29 +21,16 @@ class CygwinCCompilerTestCase(support.TempdirManager,
from distutils import sysconfig
self.old_get_config_h_filename = sysconfig.get_config_h_filename
sysconfig.get_config_h_filename = self._get_config_h_filename
- self.old_find_executable = cygwinccompiler.find_executable
- cygwinccompiler.find_executable = self._find_executable
- self._exes = {}
- self.old_popen = cygwinccompiler.Popen
- FakePopen.test_class = self
- cygwinccompiler.Popen = FakePopen
def tearDown(self):
sys.version = self.version
from distutils import sysconfig
sysconfig.get_config_h_filename = self.old_get_config_h_filename
- cygwinccompiler.find_executable = self.old_find_executable
- cygwinccompiler.Popen = self.old_popen
super(CygwinCCompilerTestCase, self).tearDown()
def _get_config_h_filename(self):
return self.python_h
- def _find_executable(self, name):
- if name in self._exes:
- return name
- return None
-
def test_check_config_h(self):
# check_config_h looks for "GCC" in sys.version first
@@ -81,40 +54,6 @@ class CygwinCCompilerTestCase(support.TempdirManager,
self.write_file(self.python_h, 'xxx __GNUC__ xxx')
self.assertEqual(check_config_h()[0], CONFIG_H_OK)
- def test_get_versions(self):
-
- # get_versions calls distutils.spawn.find_executable on
- # 'gcc', 'ld' and 'dllwrap'
- self.assertEqual(get_versions(), (None, None, None))
-
- # Let's fake we have 'gcc' and it returns '3.4.5'
- self._exes['gcc'] = b'gcc (GCC) 3.4.5 (mingw special)\nFSF'
- res = get_versions()
- self.assertEqual(str(res[0]), '3.4.5')
-
- # and let's see what happens when the version
- # doesn't match the regular expression
- # (\d+\.\d+(\.\d+)*)
- self._exes['gcc'] = b'very strange output'
- res = get_versions()
- self.assertEqual(res[0], None)
-
- # same thing for ld
- self._exes['ld'] = b'GNU ld version 2.17.50 20060824'
- res = get_versions()
- self.assertEqual(str(res[1]), '2.17.50')
- self._exes['ld'] = b'@(#)PROGRAM:ld PROJECT:ld64-77'
- res = get_versions()
- self.assertEqual(res[1], None)
-
- # and dllwrap
- self._exes['dllwrap'] = b'GNU dllwrap 2.17.50 20060824\nFSF'
- res = get_versions()
- self.assertEqual(str(res[2]), '2.17.50')
- self._exes['dllwrap'] = b'Cheese Wrap'
- res = get_versions()
- self.assertEqual(res[2], None)
-
def test_get_msvcr(self):
# none
@@ -151,7 +90,7 @@ class CygwinCCompilerTestCase(support.TempdirManager,
self.assertRaises(ValueError, get_msvcr)
def test_suite():
- return unittest.makeSuite(CygwinCCompilerTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(CygwinCCompilerTestCase)
if __name__ == '__main__':
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_dep_util.py b/setuptools/_distutils/tests/test_dep_util.py
index c6fae39c..0d52740a 100644
--- a/setuptools/_distutils/tests/test_dep_util.py
+++ b/setuptools/_distutils/tests/test_dep_util.py
@@ -74,7 +74,7 @@ class DepUtilTestCase(support.TempdirManager, unittest.TestCase):
def test_suite():
- return unittest.makeSuite(DepUtilTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(DepUtilTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_dir_util.py b/setuptools/_distutils/tests/test_dir_util.py
index d436cf83..1b1f3bbb 100644
--- a/setuptools/_distutils/tests/test_dir_util.py
+++ b/setuptools/_distutils/tests/test_dir_util.py
@@ -133,7 +133,7 @@ class DirUtilTestCase(support.TempdirManager, unittest.TestCase):
def test_suite():
- return unittest.makeSuite(DirUtilTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(DirUtilTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_dist.py b/setuptools/_distutils/tests/test_dist.py
index 45eadee8..36155be1 100644
--- a/setuptools/_distutils/tests/test_dist.py
+++ b/setuptools/_distutils/tests/test_dist.py
@@ -525,8 +525,8 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
def test_suite():
suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(DistributionTestCase))
- suite.addTest(unittest.makeSuite(MetadataTestCase))
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DistributionTestCase))
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(MetadataTestCase))
return suite
if __name__ == "__main__":
diff --git a/setuptools/_distutils/tests/test_extension.py b/setuptools/_distutils/tests/test_extension.py
index 2eb5b422..78a55daa 100644
--- a/setuptools/_distutils/tests/test_extension.py
+++ b/setuptools/_distutils/tests/test_extension.py
@@ -65,7 +65,7 @@ class ExtensionTestCase(unittest.TestCase):
"Unknown Extension options: 'chic'")
def test_suite():
- return unittest.makeSuite(ExtensionTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(ExtensionTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_file_util.py b/setuptools/_distutils/tests/test_file_util.py
index d2536075..81b90d6c 100644
--- a/setuptools/_distutils/tests/test_file_util.py
+++ b/setuptools/_distutils/tests/test_file_util.py
@@ -118,7 +118,7 @@ class FileUtilTestCase(support.TempdirManager, unittest.TestCase):
def test_suite():
- return unittest.makeSuite(FileUtilTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(FileUtilTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_filelist.py b/setuptools/_distutils/tests/test_filelist.py
index 9ec507b5..a90edcf1 100644
--- a/setuptools/_distutils/tests/test_filelist.py
+++ b/setuptools/_distutils/tests/test_filelist.py
@@ -344,8 +344,8 @@ class FindAllTestCase(unittest.TestCase):
def test_suite():
return unittest.TestSuite([
- unittest.makeSuite(FileListTestCase),
- unittest.makeSuite(FindAllTestCase),
+ unittest.TestLoader().loadTestsFromTestCase(FileListTestCase),
+ unittest.TestLoader().loadTestsFromTestCase(FindAllTestCase),
])
diff --git a/setuptools/_distutils/tests/test_install.py b/setuptools/_distutils/tests/test_install.py
index cce973dc..3aef9e43 100644
--- a/setuptools/_distutils/tests/test_install.py
+++ b/setuptools/_distutils/tests/test_install.py
@@ -56,14 +56,15 @@ class InstallTestCase(support.TempdirManager,
expected = os.path.normpath(expected)
self.assertEqual(got, expected)
- libdir = os.path.join(destination, "lib", "python")
+ impl_name = sys.implementation.name.replace("cpython", "python")
+ libdir = os.path.join(destination, "lib", impl_name)
check_path(cmd.install_lib, libdir)
_platlibdir = getattr(sys, "platlibdir", "lib")
- platlibdir = os.path.join(destination, _platlibdir, "python")
+ platlibdir = os.path.join(destination, _platlibdir, impl_name)
check_path(cmd.install_platlib, platlibdir)
check_path(cmd.install_purelib, libdir)
check_path(cmd.install_headers,
- os.path.join(destination, "include", "python", "foopkg"))
+ os.path.join(destination, "include", impl_name, "foopkg"))
check_path(cmd.install_scripts, os.path.join(destination, "bin"))
check_path(cmd.install_data, destination)
@@ -81,7 +82,9 @@ class InstallTestCase(support.TempdirManager,
install_module.USER_SITE = self.user_site
def _expanduser(path):
- return self.tmpdir
+ if path.startswith('~'):
+ return os.path.normpath(self.tmpdir + path[1:])
+ return path
self.old_expand = os.path.expanduser
os.path.expanduser = _expanduser
@@ -122,6 +125,17 @@ class InstallTestCase(support.TempdirManager,
self.assertIn('userbase', cmd.config_vars)
self.assertIn('usersite', cmd.config_vars)
+ actual_headers = os.path.relpath(cmd.install_headers, self.user_base)
+ if os.name == 'nt':
+ site_path = os.path.relpath(
+ os.path.dirname(self.old_user_site), self.old_user_base)
+ include = os.path.join(site_path, 'Include')
+ else:
+ include = sysconfig.get_python_inc(0, '')
+ expect_headers = os.path.join(include, 'xx')
+
+ self.assertEqual(os.path.normcase(actual_headers), os.path.normcase(expect_headers))
+
def test_handle_extra_path(self):
dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'})
cmd = install(dist)
@@ -244,7 +258,7 @@ class InstallTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(InstallTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(InstallTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_install_data.py b/setuptools/_distutils/tests/test_install_data.py
index 32ab296a..6191d2fa 100644
--- a/setuptools/_distutils/tests/test_install_data.py
+++ b/setuptools/_distutils/tests/test_install_data.py
@@ -69,7 +69,7 @@ class InstallDataTestCase(support.TempdirManager,
self.assertTrue(os.path.exists(os.path.join(inst, rone)))
def test_suite():
- return unittest.makeSuite(InstallDataTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(InstallDataTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_install_headers.py b/setuptools/_distutils/tests/test_install_headers.py
index 2217b321..1aa4d09c 100644
--- a/setuptools/_distutils/tests/test_install_headers.py
+++ b/setuptools/_distutils/tests/test_install_headers.py
@@ -33,7 +33,7 @@ class InstallHeadersTestCase(support.TempdirManager,
self.assertEqual(len(cmd.get_outputs()), 2)
def test_suite():
- return unittest.makeSuite(InstallHeadersTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(InstallHeadersTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_install_lib.py b/setuptools/_distutils/tests/test_install_lib.py
index fda6315b..652653f2 100644
--- a/setuptools/_distutils/tests/test_install_lib.py
+++ b/setuptools/_distutils/tests/test_install_lib.py
@@ -109,7 +109,7 @@ class InstallLibTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(InstallLibTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(InstallLibTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_install_scripts.py b/setuptools/_distutils/tests/test_install_scripts.py
index 1f7b1038..648db3b1 100644
--- a/setuptools/_distutils/tests/test_install_scripts.py
+++ b/setuptools/_distutils/tests/test_install_scripts.py
@@ -76,7 +76,7 @@ class InstallScriptsTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(InstallScriptsTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(InstallScriptsTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_log.py b/setuptools/_distutils/tests/test_log.py
index 75cf9006..ec2ae028 100644
--- a/setuptools/_distutils/tests/test_log.py
+++ b/setuptools/_distutils/tests/test_log.py
@@ -40,7 +40,7 @@ class TestLog(unittest.TestCase):
'Fαtal\t\\xc8rr\\u014dr')
def test_suite():
- return unittest.makeSuite(TestLog)
+ return unittest.TestLoader().loadTestsFromTestCase(TestLog)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_msvc9compiler.py b/setuptools/_distutils/tests/test_msvc9compiler.py
index 77a07ef3..6235405e 100644
--- a/setuptools/_distutils/tests/test_msvc9compiler.py
+++ b/setuptools/_distutils/tests/test_msvc9compiler.py
@@ -178,7 +178,7 @@ class msvc9compilerTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(msvc9compilerTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(msvc9compilerTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_msvccompiler.py b/setuptools/_distutils/tests/test_msvccompiler.py
index 46a51cd0..846e5bb8 100644
--- a/setuptools/_distutils/tests/test_msvccompiler.py
+++ b/setuptools/_distutils/tests/test_msvccompiler.py
@@ -98,7 +98,7 @@ class TestSpawn(unittest.TestCase):
compiler = _msvccompiler.MSVCCompiler()
compiler._paths = "expected"
inner_cmd = 'import os; assert os.environ["PATH"] == "expected"'
- command = ['python', '-c', inner_cmd]
+ command = [sys.executable, '-c', inner_cmd]
threads = [
CheckThread(target=compiler.spawn, args=[command])
@@ -132,7 +132,7 @@ class TestSpawn(unittest.TestCase):
def test_suite():
- return unittest.makeSuite(msvccompilerTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(msvccompilerTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_register.py b/setuptools/_distutils/tests/test_register.py
index 84607f99..5770ed58 100644
--- a/setuptools/_distutils/tests/test_register.py
+++ b/setuptools/_distutils/tests/test_register.py
@@ -319,7 +319,7 @@ class RegisterTestCase(BasePyPIRCCommandTestCase):
def test_suite():
- return unittest.makeSuite(RegisterTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(RegisterTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_sdist.py b/setuptools/_distutils/tests/test_sdist.py
index b087a817..4c51717c 100644
--- a/setuptools/_distutils/tests/test_sdist.py
+++ b/setuptools/_distutils/tests/test_sdist.py
@@ -7,6 +7,7 @@ import zipfile
from os.path import join
from textwrap import dedent
from test.support import captured_stdout, run_unittest
+from .unix_compat import require_unix_id, require_uid_0, pwd, grp
from .py38compat import check_warnings
@@ -16,13 +17,6 @@ try:
except ImportError:
ZLIB_SUPPORT = False
-try:
- import grp
- import pwd
- UID_GID_SUPPORT = True
-except ImportError:
- UID_GID_SUPPORT = False
-
from distutils.command.sdist import sdist, show_formats
from distutils.core import Distribution
from distutils.tests.test_config import BasePyPIRCCommandTestCase
@@ -440,7 +434,8 @@ class SDistTestCase(BasePyPIRCCommandTestCase):
'fake-1.0/README.manual'])
@unittest.skipUnless(ZLIB_SUPPORT, "requires zlib")
- @unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
+ @require_unix_id
+ @require_uid_0
@unittest.skipIf(find_executable('tar') is None,
"The tar command is not found")
@unittest.skipIf(find_executable('gzip') is None,
@@ -488,7 +483,7 @@ class SDistTestCase(BasePyPIRCCommandTestCase):
archive.close()
def test_suite():
- return unittest.makeSuite(SDistTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(SDistTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_spawn.py b/setuptools/_distutils/tests/test_spawn.py
index f620da78..c5ed8e2b 100644
--- a/setuptools/_distutils/tests/test_spawn.py
+++ b/setuptools/_distutils/tests/test_spawn.py
@@ -133,7 +133,7 @@ class SpawnTestCase(support.TempdirManager,
def test_suite():
- return unittest.makeSuite(SpawnTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(SpawnTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_sysconfig.py b/setuptools/_distutils/tests/test_sysconfig.py
index 80cd1599..e671f9e0 100644
--- a/setuptools/_distutils/tests/test_sysconfig.py
+++ b/setuptools/_distutils/tests/test_sysconfig.py
@@ -38,6 +38,14 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase):
config_h = sysconfig.get_config_h_filename()
self.assertTrue(os.path.isfile(config_h), config_h)
+ @unittest.skipIf(sys.platform == 'win32',
+ 'Makefile only exists on Unix like systems')
+ @unittest.skipIf(sys.implementation.name != 'cpython',
+ 'Makefile only exists in CPython')
+ def test_get_makefile_filename(self):
+ makefile = sysconfig.get_makefile_filename()
+ self.assertTrue(os.path.isfile(makefile), makefile)
+
def test_get_python_lib(self):
# XXX doesn't work on Linux when Python was never installed before
#self.assertTrue(os.path.isdir(lib_dir), lib_dir)
@@ -283,10 +291,27 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase):
outs, errs = p.communicate()
self.assertEqual(0, p.returncode, "Subprocess failed: " + outs)
+ def test_parse_config_h(self):
+ config_h = sysconfig.get_config_h_filename()
+ input = {}
+ with open(config_h, encoding="utf-8") as f:
+ result = sysconfig.parse_config_h(f, g=input)
+ self.assertTrue(input is result)
+ with open(config_h, encoding="utf-8") as f:
+ result = sysconfig.parse_config_h(f)
+ self.assertTrue(isinstance(result, dict))
+
+ @unittest.skipUnless(sys.platform == 'win32',
+ 'Testing windows pyd suffix')
+ @unittest.skipUnless(sys.implementation.name == 'cpython',
+ 'Need cpython for this test')
+ def test_win_ext_suffix(self):
+ self.assertTrue(sysconfig.get_config_var("EXT_SUFFIX").endswith(".pyd"))
+ self.assertNotEqual(sysconfig.get_config_var("EXT_SUFFIX"), ".pyd")
def test_suite():
suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(SysconfigTestCase))
+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(SysconfigTestCase))
return suite
diff --git a/setuptools/_distutils/tests/test_text_file.py b/setuptools/_distutils/tests/test_text_file.py
index 7e76240a..ebac3d52 100644
--- a/setuptools/_distutils/tests/test_text_file.py
+++ b/setuptools/_distutils/tests/test_text_file.py
@@ -101,7 +101,7 @@ class TextFileTestCase(support.TempdirManager, unittest.TestCase):
in_file.close()
def test_suite():
- return unittest.makeSuite(TextFileTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(TextFileTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_unixccompiler.py b/setuptools/_distutils/tests/test_unixccompiler.py
index 63c7dd37..c8b4c149 100644
--- a/setuptools/_distutils/tests/test_unixccompiler.py
+++ b/setuptools/_distutils/tests/test_unixccompiler.py
@@ -3,6 +3,7 @@ import os
import sys
import unittest
from test.support import run_unittest
+from unittest.mock import patch
from .py38compat import EnvironmentVarGuard
@@ -11,9 +12,12 @@ from distutils.errors import DistutilsPlatformError
from distutils.unixccompiler import UnixCCompiler
from distutils.util import _clear_cached_macosx_ver
-class UnixCCompilerTestCase(unittest.TestCase):
+from . import support
+
+class UnixCCompilerTestCase(support.TempdirManager, unittest.TestCase):
def setUp(self):
+ super().setUp()
self._backup_platform = sys.platform
self._backup_get_config_var = sysconfig.get_config_var
self._backup_get_config_vars = sysconfig.get_config_vars
@@ -23,6 +27,7 @@ class UnixCCompilerTestCase(unittest.TestCase):
self.cc = CompilerWrapper()
def tearDown(self):
+ super().tearDown()
sys.platform = self._backup_platform
sysconfig.get_config_var = self._backup_get_config_var
sysconfig.get_config_vars = self._backup_get_config_vars
@@ -211,6 +216,42 @@ class UnixCCompilerTestCase(unittest.TestCase):
self.assertEqual(self.cc.linker_so[0], 'my_cc')
@unittest.skipIf(sys.platform == 'win32', "can't test on Windows")
+ def test_cc_overrides_ldshared_for_cxx_correctly(self):
+ """
+ Ensure that setting CC env variable also changes default linker
+ correctly when building C++ extensions.
+
+ pypa/distutils#126
+ """
+ def gcv(v):
+ if v == 'LDSHARED':
+ return 'gcc-4.2 -bundle -undefined dynamic_lookup '
+ elif v == 'CXX':
+ return 'g++-4.2'
+ return 'gcc-4.2'
+
+ def gcvs(*args, _orig=sysconfig.get_config_vars):
+ if args:
+ return list(map(sysconfig.get_config_var, args))
+ return _orig()
+
+ sysconfig.get_config_var = gcv
+ sysconfig.get_config_vars = gcvs
+ with patch.object(self.cc, 'spawn', return_value=None) as mock_spawn, \
+ patch.object(self.cc, '_need_link', return_value=True), \
+ patch.object(self.cc, 'mkpath', return_value=None), \
+ EnvironmentVarGuard() as env:
+ env['CC'] = 'ccache my_cc'
+ env['CXX'] = 'my_cxx'
+ del env['LDSHARED']
+ sysconfig.customize_compiler(self.cc)
+ self.assertEqual(self.cc.linker_so[0:2], ['ccache', 'my_cc'])
+ self.cc.link(None, [], 'a.out', target_lang='c++')
+ call_args = mock_spawn.call_args[0][0]
+ expected = ['my_cxx', '-bundle', '-undefined', 'dynamic_lookup']
+ assert call_args[:4] == expected
+
+ @unittest.skipIf(sys.platform == 'win32', "can't test on Windows")
def test_explicit_ldshared(self):
# Issue #18080:
# ensure that setting CC env variable does not change
@@ -237,11 +278,12 @@ class UnixCCompilerTestCase(unittest.TestCase):
# ensure that setting output_dir does not raise
# FileNotFoundError: [Errno 2] No such file or directory: 'a.out'
self.cc.output_dir = 'scratch'
+ os.chdir(self.mkdtemp())
self.cc.has_function('abort', includes=['stdlib.h'])
def test_suite():
- return unittest.makeSuite(UnixCCompilerTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(UnixCCompilerTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_upload.py b/setuptools/_distutils/tests/test_upload.py
index bca5516d..ce3e84a2 100644
--- a/setuptools/_distutils/tests/test_upload.py
+++ b/setuptools/_distutils/tests/test_upload.py
@@ -217,7 +217,7 @@ class uploadTestCase(BasePyPIRCCommandTestCase):
def test_suite():
- return unittest.makeSuite(uploadTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(uploadTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_util.py b/setuptools/_distutils/tests/test_util.py
index bf0d4333..2738388e 100644
--- a/setuptools/_distutils/tests/test_util.py
+++ b/setuptools/_distutils/tests/test_util.py
@@ -2,6 +2,7 @@
import os
import sys
import unittest
+import sysconfig as stdlib_sysconfig
from copy import copy
from test.support import run_unittest
from unittest import mock
@@ -10,12 +11,10 @@ from distutils.errors import DistutilsPlatformError, DistutilsByteCompileError
from distutils.util import (get_platform, convert_path, change_root,
check_environ, split_quoted, strtobool,
rfc822_escape, byte_compile,
- grok_environment_error)
+ grok_environment_error, get_host_platform)
from distutils import util # used to patch _environ_checked
-from distutils.sysconfig import get_config_vars
from distutils import sysconfig
from distutils.tests import support
-import _osx_support
class UtilTestCase(support.EnvironGuard, unittest.TestCase):
@@ -63,110 +62,26 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
def _get_uname(self):
return self._uname
- def test_get_platform(self):
-
- # windows XP, 32bits
- os.name = 'nt'
- sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
- '[MSC v.1310 32 bit (Intel)]')
- sys.platform = 'win32'
- self.assertEqual(get_platform(), 'win32')
-
- # windows XP, amd64
- os.name = 'nt'
- sys.version = ('2.4.4 (#71, Oct 18 2006, 08:34:43) '
- '[MSC v.1310 32 bit (Amd64)]')
- sys.platform = 'win32'
- self.assertEqual(get_platform(), 'win-amd64')
-
- # macbook
- os.name = 'posix'
- sys.version = ('2.5 (r25:51918, Sep 19 2006, 08:49:13) '
- '\n[GCC 4.0.1 (Apple Computer, Inc. build 5341)]')
- sys.platform = 'darwin'
- self._set_uname(('Darwin', 'macziade', '8.11.1',
- ('Darwin Kernel Version 8.11.1: '
- 'Wed Oct 10 18:23:28 PDT 2007; '
- 'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
-
- get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
- '-fwrapv -O3 -Wall -Wstrict-prototypes')
-
- cursize = sys.maxsize
- sys.maxsize = (2 ** 31)-1
- try:
- self.assertEqual(get_platform(), 'macosx-10.3-i386')
- finally:
- sys.maxsize = cursize
-
- # macbook with fat binaries (fat, universal or fat64)
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
- get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
-
- self.assertEqual(get_platform(), 'macosx-10.4-fat')
-
- _osx_support._remove_original_values(get_config_vars())
- os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
- self.assertEqual(get_platform(), 'macosx-10.4-fat')
-
+ def test_get_host_platform(self):
+ with unittest.mock.patch('os.name', 'nt'):
+ with unittest.mock.patch('sys.version', '... [... (ARM64)]'):
+ self.assertEqual(get_host_platform(), 'win-arm64')
+ with unittest.mock.patch('sys.version', '... [... (ARM)]'):
+ self.assertEqual(get_host_platform(), 'win-arm32')
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
+ with unittest.mock.patch('sys.version_info', (3, 9, 0, 'final', 0)):
+ self.assertEqual(get_host_platform(), stdlib_sysconfig.get_platform())
- self.assertEqual(get_platform(), 'macosx-10.4-intel')
-
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
- self.assertEqual(get_platform(), 'macosx-10.4-fat3')
-
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
- self.assertEqual(get_platform(), 'macosx-10.4-universal')
-
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3')
-
- self.assertEqual(get_platform(), 'macosx-10.4-fat64')
-
- for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
- _osx_support._remove_original_values(get_config_vars())
- get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
- '/Developer/SDKs/MacOSX10.4u.sdk '
- '-fno-strict-aliasing -fno-common '
- '-dynamic -DNDEBUG -g -O3'%(arch,))
-
- self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
-
-
- # linux debian sarge
- os.name = 'posix'
- sys.version = ('2.3.5 (#1, Jul 4 2007, 17:28:59) '
- '\n[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)]')
- sys.platform = 'linux2'
- self._set_uname(('Linux', 'aglae', '2.6.21.1dedibox-r7',
- '#1 Mon Apr 30 17:25:38 CEST 2007', 'i686'))
-
- self.assertEqual(get_platform(), 'linux-i686')
-
- # XXX more platforms to tests here
+ def test_get_platform(self):
+ with unittest.mock.patch('os.name', 'nt'):
+ with unittest.mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'x86'}):
+ self.assertEqual(get_platform(), 'win32')
+ with unittest.mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'x64'}):
+ self.assertEqual(get_platform(), 'win-amd64')
+ with unittest.mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'arm'}):
+ self.assertEqual(get_platform(), 'win-arm32')
+ with unittest.mock.patch.dict('os.environ', {'VSCMD_ARG_TGT_ARCH': 'arm64'}):
+ self.assertEqual(get_platform(), 'win-arm64')
def test_convert_path(self):
# linux/mac
@@ -303,7 +218,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
def test_suite():
- return unittest.makeSuite(UtilTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(UtilTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/test_version.py b/setuptools/_distutils/tests/test_version.py
index 8671cd2f..8405aa3a 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))
@@ -81,7 +89,7 @@ class VersionTestCase(unittest.TestCase):
(v1, v2, res))
def test_suite():
- return unittest.makeSuite(VersionTestCase)
+ return unittest.TestLoader().loadTestsFromTestCase(VersionTestCase)
if __name__ == "__main__":
run_unittest(test_suite())
diff --git a/setuptools/_distutils/tests/unix_compat.py b/setuptools/_distutils/tests/unix_compat.py
new file mode 100644
index 00000000..b7718c26
--- /dev/null
+++ b/setuptools/_distutils/tests/unix_compat.py
@@ -0,0 +1,16 @@
+import sys
+import unittest
+
+try:
+ import grp
+ import pwd
+except ImportError:
+ grp = pwd = None
+
+
+UNIX_ID_SUPPORT = grp and pwd
+UID_0_SUPPORT = UNIX_ID_SUPPORT and sys.platform != "cygwin"
+
+require_unix_id = unittest.skipUnless(
+ UNIX_ID_SUPPORT, "Requires grp and pwd support")
+require_uid_0 = unittest.skipUnless(UID_0_SUPPORT, "Requires UID 0 support")
diff --git a/setuptools/_distutils/unixccompiler.py b/setuptools/_distutils/unixccompiler.py
index a07e5988..715408f5 100644
--- a/setuptools/_distutils/unixccompiler.py
+++ b/setuptools/_distutils/unixccompiler.py
@@ -22,9 +22,7 @@ from distutils.ccompiler import \
from distutils.errors import \
DistutilsExecError, CompileError, LibError, LinkError
from distutils import log
-
-if sys.platform == 'darwin':
- import _osx_support
+from ._macos_compat import compiler_fixup
# XXX Things not currently handled:
# * optimization/debug/warning flags; we just use whatever's in Python's
@@ -42,6 +40,66 @@ if sys.platform == 'darwin':
# options and carry on.
+def _split_env(cmd):
+ """
+ For macOS, split command into 'env' portion (if any)
+ and the rest of the linker command.
+
+ >>> _split_env(['a', 'b', 'c'])
+ ([], ['a', 'b', 'c'])
+ >>> _split_env(['/usr/bin/env', 'A=3', 'gcc'])
+ (['/usr/bin/env', 'A=3'], ['gcc'])
+ """
+ pivot = 0
+ if os.path.basename(cmd[0]) == "env":
+ pivot = 1
+ while '=' in cmd[pivot]:
+ pivot += 1
+ return cmd[:pivot], cmd[pivot:]
+
+
+def _split_aix(cmd):
+ """
+ AIX platforms prefix the compiler with the ld_so_aix
+ script, so split that from the linker command.
+
+ >>> _split_aix(['a', 'b', 'c'])
+ ([], ['a', 'b', 'c'])
+ >>> _split_aix(['/bin/foo/ld_so_aix', 'gcc'])
+ (['/bin/foo/ld_so_aix'], ['gcc'])
+ """
+ pivot = os.path.basename(cmd[0]) == 'ld_so_aix'
+ return cmd[:pivot], cmd[pivot:]
+
+
+def _linker_params(linker_cmd, compiler_cmd):
+ """
+ The linker command usually begins with the compiler
+ command (possibly multiple elements), followed by zero or more
+ params for shared library building.
+
+ If the LDSHARED env variable overrides the linker command,
+ however, the commands may not match.
+
+ Return the best guess of the linker parameters by stripping
+ the linker command. If the compiler command does not
+ match the linker command, assume the linker command is
+ just the first element.
+
+ >>> _linker_params('gcc foo bar'.split(), ['gcc'])
+ ['foo', 'bar']
+ >>> _linker_params('gcc foo bar'.split(), ['other'])
+ ['foo', 'bar']
+ >>> _linker_params('ccache gcc foo bar'.split(), 'ccache gcc'.split())
+ ['foo', 'bar']
+ >>> _linker_params(['gcc'], ['gcc'])
+ []
+ """
+ c_len = len(compiler_cmd)
+ pivot = c_len if linker_cmd[:c_len] == compiler_cmd else 1
+ return linker_cmd[pivot:]
+
+
class UnixCCompiler(CCompiler):
compiler_type = 'unix'
@@ -109,10 +167,8 @@ class UnixCCompiler(CCompiler):
raise CompileError(msg)
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
- compiler_so = self.compiler_so
- if sys.platform == 'darwin':
- compiler_so = _osx_support.compiler_fixup(compiler_so,
- cc_args + extra_postargs)
+ compiler_so = compiler_fixup(
+ self.compiler_so, cc_args + extra_postargs)
try:
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
extra_postargs)
@@ -173,33 +229,22 @@ class UnixCCompiler(CCompiler):
ld_args.extend(extra_postargs)
self.mkpath(os.path.dirname(output_filename))
try:
- if target_desc == CCompiler.EXECUTABLE:
- linker = self.linker_exe[:]
- else:
- linker = self.linker_so[:]
+ # Select a linker based on context: linker_exe when
+ # building an executable or linker_so (with shared options)
+ # when building a shared library.
+ building_exe = target_desc == CCompiler.EXECUTABLE
+ linker = (self.linker_exe if building_exe else self.linker_so)[:]
+
if target_lang == "c++" and self.compiler_cxx:
- # skip over environment variable settings if /usr/bin/env
- # is used to set up the linker's environment.
- # This is needed on OSX. Note: this assumes that the
- # normal and C++ compiler have the same environment
- # settings.
- i = 0
- if os.path.basename(linker[0]) == "env":
- i = 1
- while '=' in linker[i]:
- i += 1
-
- if os.path.basename(linker[i]) == 'ld_so_aix':
- # AIX platforms prefix the compiler with the ld_so_aix
- # script, so we need to adjust our linker index
- offset = 1
- else:
- offset = 0
-
- linker[i+offset] = self.compiler_cxx[i]
-
- if sys.platform == 'darwin':
- linker = _osx_support.compiler_fixup(linker, ld_args)
+ env, linker_ne = _split_env(linker)
+ aix, linker_na = _split_aix(linker_ne)
+ _, compiler_cxx_ne = _split_env(self.compiler_cxx)
+ _, linker_exe_ne = _split_env(self.linker_exe)
+
+ params = _linker_params(linker_na, linker_exe_ne)
+ linker = env + aix + compiler_cxx_ne + params
+
+ linker = compiler_fixup(linker, ld_args)
self.spawn(linker + ld_args)
except DistutilsExecError as msg:
diff --git a/setuptools/_distutils/util.py b/setuptools/_distutils/util.py
index ac6d446d..6d506d7e 100644
--- a/setuptools/_distutils/util.py
+++ b/setuptools/_distutils/util.py
@@ -9,6 +9,7 @@ import re
import importlib.util
import string
import sys
+import sysconfig
from distutils.errors import DistutilsPlatformError
from distutils.dep_util import newer
from distutils.spawn import spawn
@@ -20,82 +21,29 @@ from .py35compat import _optim_args_from_interpreter_flags
def get_host_platform():
"""Return a string that identifies the current platform. This is used mainly to
distinguish platform-specific build directories and platform-specific built
- distributions. Typically includes the OS name and version and the
- architecture (as supplied by 'os.uname()'), although the exact information
- included depends on the OS; eg. on Linux, the kernel version isn't
- particularly important.
-
- Examples of returned values:
- linux-i586
- linux-alpha (?)
- solaris-2.6-sun4u
-
- Windows will return one of:
- win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
- win32 (all others - specifically, sys.platform is returned)
-
- For other non-POSIX platforms, currently just returns 'sys.platform'.
-
+ distributions.
"""
- if os.name == 'nt':
- if 'amd64' in sys.version.lower():
- return 'win-amd64'
- if '(arm)' in sys.version.lower():
- return 'win-arm32'
- if '(arm64)' in sys.version.lower():
- return 'win-arm64'
- return sys.platform
-
- # Set for cross builds explicitly
- if "_PYTHON_HOST_PLATFORM" in os.environ:
- return os.environ["_PYTHON_HOST_PLATFORM"]
-
- if os.name != "posix" or not hasattr(os, 'uname'):
- # XXX what about the architecture? NT is Intel or Alpha,
- # Mac OS is M68k or PPC, etc.
- return sys.platform
-
- # Try to distinguish various flavours of Unix
-
- (osname, host, release, version, machine) = os.uname()
-
- # Convert the OS name to lowercase, remove '/' characters, and translate
- # spaces (for "Power Macintosh")
- osname = osname.lower().replace('/', '')
- machine = machine.replace(' ', '_')
- machine = machine.replace('/', '-')
-
- if osname[:5] == "linux":
- # At least on Linux/Intel, 'machine' is the processor --
- # i386, etc.
- # XXX what about Alpha, SPARC, etc?
- return "%s-%s" % (osname, machine)
- elif osname[:5] == "sunos":
- if release[0] >= "5": # SunOS 5 == Solaris 2
- osname = "solaris"
- release = "%d.%s" % (int(release[0]) - 3, release[2:])
- # We can't use "platform.architecture()[0]" because a
- # bootstrap problem. We use a dict to get an error
- # if some suspicious happens.
- bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
- machine += ".%s" % bitness[sys.maxsize]
- # fall through to standard osname-release-machine representation
- elif osname[:3] == "aix":
- from .py38compat import aix_platform
- return aix_platform(osname, version, release)
- elif osname[:6] == "cygwin":
- osname = "cygwin"
- rel_re = re.compile (r'[\d.]+', re.ASCII)
- m = rel_re.match(release)
- if m:
- release = m.group()
- elif osname[:6] == "darwin":
- import _osx_support, distutils.sysconfig
- osname, release, machine = _osx_support.get_platform_osx(
- distutils.sysconfig.get_config_vars(),
- osname, release, machine)
-
- return "%s-%s-%s" % (osname, release, machine)
+
+ # We initially exposed platforms as defined in Python 3.9
+ # even with older Python versions when distutils was split out.
+ # Now that we delegate to stdlib sysconfig we need to restore this
+ # in case anyone has started to depend on it.
+
+ if sys.version_info < (3, 8):
+ if os.name == 'nt':
+ if '(arm)' in sys.version.lower():
+ return 'win-arm32'
+ if '(arm64)' in sys.version.lower():
+ return 'win-arm64'
+
+ if sys.version_info < (3, 9):
+ if os.name == "posix" and hasattr(os, 'uname'):
+ osname, host, release, version, machine = os.uname()
+ if osname[:3] == "aix":
+ from .py38compat import aix_platform
+ return aix_platform(osname, version, release)
+
+ return sysconfig.get_platform()
def get_platform():
if os.name == 'nt':
diff --git a/setuptools/_distutils/version.py b/setuptools/_distutils/version.py
index c33bebae..31f504e4 100644
--- a/setuptools/_distutils/version.py
+++ b/setuptools/_distutils/version.py
@@ -27,6 +27,20 @@ Every version number class implements the following interface:
"""
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
@@ -38,6 +52,12 @@ class Version:
def __init__ (self, vstring=None):
if vstring:
self.parse(vstring)
+ warnings.warn(
+ "distutils Version classes are deprecated. "
+ "Use packaging.version instead.",
+ DeprecationWarning,
+ stacklevel=2,
+ )
def __repr__ (self):
return "%s ('%s')" % (self.__class__.__name__, str(self))
@@ -165,7 +185,8 @@ class StrictVersion (Version):
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 062c98f2..55f25d91 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