Commit 7a8c226c authored by Jason R. Coombs's avatar Jason R. Coombs

Merge https://github.com/pypa/distutils into distutils

parents b596e4b0 76d53a85
...@@ -43,6 +43,20 @@ INSTALL_SCHEMES = { ...@@ -43,6 +43,20 @@ INSTALL_SCHEMES = {
'data' : '$base', 'data' : '$base',
}, },
'nt': WINDOWS_SCHEME, 'nt': WINDOWS_SCHEME,
'pypy': {
'purelib': '$base/site-packages',
'platlib': '$base/site-packages',
'headers': '$base/include/$dist_name',
'scripts': '$base/bin',
'data' : '$base',
},
'pypy_nt': {
'purelib': '$base/site-packages',
'platlib': '$base/site-packages',
'headers': '$base/include/$dist_name',
'scripts': '$base/Scripts',
'data' : '$base',
},
} }
# user site schemes # user site schemes
...@@ -455,6 +469,12 @@ class install(Command): ...@@ -455,6 +469,12 @@ class install(Command):
def select_scheme(self, name): def select_scheme(self, name):
"""Sets the install directories by applying the install schemes.""" """Sets the install directories by applying the install schemes."""
# it's the caller's problem if they supply a bad name! # it's the caller's problem if they supply a bad name!
if (hasattr(sys, 'pypy_version_info') and
not name.endswith(('_user', '_home'))):
if os.name == 'nt':
name = 'pypy_nt'
else:
name = 'pypy'
scheme = INSTALL_SCHEMES[name] scheme = INSTALL_SCHEMES[name]
for key in SCHEME_KEYS: for key in SCHEME_KEYS:
attrname = 'install_' + key attrname = 'install_' + key
......
...@@ -16,6 +16,8 @@ import sys ...@@ -16,6 +16,8 @@ import sys
from .errors import DistutilsPlatformError from .errors import DistutilsPlatformError
IS_PYPY = '__pypy__' in sys.builtin_module_names
# These are needed in a couple of spots, so just compute them once. # These are needed in a couple of spots, so just compute them once.
PREFIX = os.path.normpath(sys.prefix) PREFIX = os.path.normpath(sys.prefix)
EXEC_PREFIX = os.path.normpath(sys.exec_prefix) EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
...@@ -97,7 +99,9 @@ def get_python_inc(plat_specific=0, prefix=None): ...@@ -97,7 +99,9 @@ def get_python_inc(plat_specific=0, prefix=None):
""" """
if prefix is None: if prefix is None:
prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
if os.name == "posix": if IS_PYPY:
return os.path.join(prefix, 'include')
elif os.name == "posix":
if python_build: if python_build:
# Assume the executable is in the build directory. The # Assume the executable is in the build directory. The
# pyconfig.h file should be in the same directory. Since # pyconfig.h file should be in the same directory. Since
...@@ -138,6 +142,14 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): ...@@ -138,6 +142,14 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
If 'prefix' is supplied, use it instead of sys.base_prefix or If 'prefix' is supplied, use it instead of sys.base_prefix or
sys.base_exec_prefix -- i.e., ignore 'plat_specific'. sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
""" """
if IS_PYPY:
# PyPy-specific schema
if prefix is None:
prefix = PREFIX
if standard_lib:
return os.path.join(prefix, "lib-python", sys.version[0])
return os.path.join(prefix, 'site-packages')
if prefix is None: if prefix is None:
if standard_lib: if standard_lib:
prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
...@@ -499,41 +511,42 @@ def get_config_vars(*args): ...@@ -499,41 +511,42 @@ def get_config_vars(*args):
_config_vars['prefix'] = PREFIX _config_vars['prefix'] = PREFIX
_config_vars['exec_prefix'] = EXEC_PREFIX _config_vars['exec_prefix'] = EXEC_PREFIX
# For backward compatibility, see issue19555 if not IS_PYPY:
SO = _config_vars.get('EXT_SUFFIX') # For backward compatibility, see issue19555
if SO is not None: SO = _config_vars.get('EXT_SUFFIX')
_config_vars['SO'] = SO if SO is not None:
_config_vars['SO'] = SO
# Always convert srcdir to an absolute path
srcdir = _config_vars.get('srcdir', project_base) # Always convert srcdir to an absolute path
if os.name == 'posix': srcdir = _config_vars.get('srcdir', project_base)
if python_build: if os.name == 'posix':
# If srcdir is a relative path (typically '.' or '..') if python_build:
# then it should be interpreted relative to the directory # If srcdir is a relative path (typically '.' or '..')
# containing Makefile. # then it should be interpreted relative to the directory
base = os.path.dirname(get_makefile_filename()) # containing Makefile.
srcdir = os.path.join(base, srcdir) base = os.path.dirname(get_makefile_filename())
else: srcdir = os.path.join(base, srcdir)
# srcdir is not meaningful since the installation is else:
# spread about the filesystem. We choose the # srcdir is not meaningful since the installation is
# directory containing the Makefile since we know it # spread about the filesystem. We choose the
# exists. # directory containing the Makefile since we know it
srcdir = os.path.dirname(get_makefile_filename()) # exists.
_config_vars['srcdir'] = os.path.abspath(os.path.normpath(srcdir)) 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 # Convert srcdir into an absolute path if it appears necessary.
# testing, for example, we might be running a non-installed python # Normally it is relative to the build directory. However, during
# from a different directory. # testing, for example, we might be running a non-installed python
if python_build and os.name == "posix": # from a different directory.
base = project_base if python_build and os.name == "posix":
if (not os.path.isabs(_config_vars['srcdir']) and base = project_base
base != os.getcwd()): if (not os.path.isabs(_config_vars['srcdir']) and
# srcdir is relative and we are not in the same directory base != os.getcwd()):
# as the executable. Assume executable is in the build # srcdir is relative and we are not in the same directory
# directory and make srcdir absolute. # as the executable. Assume executable is in the build
srcdir = os.path.join(base, _config_vars['srcdir']) # directory and make srcdir absolute.
_config_vars['srcdir'] = os.path.normpath(srcdir) srcdir = os.path.join(base, _config_vars['srcdir'])
_config_vars['srcdir'] = os.path.normpath(srcdir)
# OS X platforms require special customization to handle # OS X platforms require special customization to handle
# multi-architecture, multi-os-version installers # multi-architecture, multi-os-version installers
......
"""
Backward compatibility support for Python 3.5
"""
import sys
import test.support
import subprocess
# copied from Python 3.9 test.support module
def _missing_compiler_executable(cmd_names=[]):
"""Check if the compiler components used to build the interpreter exist.
Check for the existence of the compiler executables whose names are listed
in 'cmd_names' or all the compiler executables when 'cmd_names' is empty
and return the first missing executable or None when none is found
missing.
"""
from distutils import ccompiler, sysconfig, spawn
compiler = ccompiler.new_compiler()
sysconfig.customize_compiler(compiler)
for name in compiler.executables:
if cmd_names and name not in cmd_names:
continue
cmd = getattr(compiler, name)
if cmd_names:
assert cmd is not None, \
"the '%s' executable is not configured" % name
elif not cmd:
continue
if spawn.find_executable(cmd[0]) is None:
return cmd[0]
missing_compiler_executable = vars(test.support).setdefault(
'missing_compiler_executable',
_missing_compiler_executable,
)
try:
from test.support import unix_shell
except ImportError:
# Adapted from Python 3.9 test.support module
is_android = hasattr(sys, 'getandroidapilevel')
unix_shell = (
None if sys.platform == 'win32' else
'/system/bin/sh' if is_android else
'/bin/sh'
)
# copied from Python 3.9 subprocess module
def _optim_args_from_interpreter_flags():
"""Return a list of command-line arguments reproducing the current
optimization settings in sys.flags."""
args = []
value = sys.flags.optimize
if value > 0:
args.append('-' + 'O' * value)
return args
vars(subprocess).setdefault(
'_optim_args_from_interpreter_flags',
_optim_args_from_interpreter_flags,
)
def adapt_glob(regex):
"""
Supply legacy expectation on Python 3.5
"""
if sys.version_info > (3, 6):
return regex
return regex.replace('(?s:', '').replace(r')\Z', r'\Z(?ms)')
...@@ -3,7 +3,9 @@ import unittest ...@@ -3,7 +3,9 @@ import unittest
import os import os
import sys import sys
from test.support import run_unittest, missing_compiler_executable from test.support import run_unittest
from .py35compat import missing_compiler_executable
from distutils.command.build_clib import build_clib from distutils.command.build_clib import build_clib
from distutils.errors import DistutilsSetupError from distutils.errors import DistutilsSetupError
......
...@@ -82,7 +82,7 @@ class BuildExtTestCase(TempdirManager, ...@@ -82,7 +82,7 @@ class BuildExtTestCase(TempdirManager,
else: else:
ALREADY_TESTED = type(self).__name__ ALREADY_TESTED = type(self).__name__
code = textwrap.dedent(f""" code = textwrap.dedent("""
tmp_dir = {self.tmp_dir!r} tmp_dir = {self.tmp_dir!r}
import sys import sys
...@@ -108,7 +108,7 @@ class BuildExtTestCase(TempdirManager, ...@@ -108,7 +108,7 @@ class BuildExtTestCase(TempdirManager,
unittest.main() unittest.main()
""") """.format(**locals()))
assert_python_ok('-c', code) assert_python_ok('-c', code)
def test_solaris_enable_shared(self): def test_solaris_enable_shared(self):
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
import unittest import unittest
import os import os
import sys import sys
from test.support import run_unittest, missing_compiler_executable from test.support import run_unittest
from .py35compat import missing_compiler_executable
from distutils.command.config import dump_file, config from distutils.command.config import dump_file, config
from distutils.tests import support from distutils.tests import support
......
...@@ -83,6 +83,10 @@ class DistributionTestCase(support.LoggingSilencer, ...@@ -83,6 +83,10 @@ class DistributionTestCase(support.LoggingSilencer,
self.assertIsInstance(cmd, test_dist) self.assertIsInstance(cmd, test_dist)
self.assertEqual(cmd.sample_option, "sometext") self.assertEqual(cmd.sample_option, "sometext")
@unittest.skipIf(
'distutils' not in Distribution.parse_config_files.__module__,
'Cannot test when virtualenv has monkey-patched Distribution.',
)
def test_venv_install_options(self): def test_venv_install_options(self):
sys.argv.append("install") sys.argv.append("install")
self.addCleanup(os.unlink, TESTFN) self.addCleanup(os.unlink, TESTFN)
......
...@@ -12,6 +12,9 @@ import test.support ...@@ -12,6 +12,9 @@ import test.support
from test.support import captured_stdout, run_unittest from test.support import captured_stdout, run_unittest
from distutils.tests import support from distutils.tests import support
from .py35compat import adapt_glob
MANIFEST_IN = """\ MANIFEST_IN = """\
include ok include ok
include xo include xo
...@@ -60,7 +63,7 @@ class FileListTestCase(support.LoggingSilencer, ...@@ -60,7 +63,7 @@ class FileListTestCase(support.LoggingSilencer,
('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'), ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'),
(r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z')): (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z')):
regex = regex % {'sep': sep} regex = regex % {'sep': sep}
self.assertEqual(glob_to_re(glob), regex) self.assertEqual(glob_to_re(glob), adapt_glob(regex))
def test_process_template_line(self): def test_process_template_line(self):
# testing all MANIFEST.in template patterns # testing all MANIFEST.in template patterns
......
...@@ -58,7 +58,8 @@ class InstallTestCase(support.TempdirManager, ...@@ -58,7 +58,8 @@ class InstallTestCase(support.TempdirManager,
libdir = os.path.join(destination, "lib", "python") libdir = os.path.join(destination, "lib", "python")
check_path(cmd.install_lib, libdir) check_path(cmd.install_lib, libdir)
platlibdir = os.path.join(destination, sys.platlibdir, "python") _platlibdir = getattr(sys, "platlibdir", "lib")
platlibdir = os.path.join(destination, _platlibdir, "python")
check_path(cmd.install_platlib, platlibdir) check_path(cmd.install_platlib, platlibdir)
check_path(cmd.install_purelib, libdir) check_path(cmd.install_purelib, libdir)
check_path(cmd.install_headers, check_path(cmd.install_headers,
......
...@@ -3,9 +3,11 @@ import os ...@@ -3,9 +3,11 @@ import os
import stat import stat
import sys import sys
import unittest.mock import unittest.mock
from test.support import run_unittest, unix_shell from test.support import run_unittest
from test import support as test_support from test import support as test_support
from .py35compat import unix_shell
from distutils.spawn import find_executable from distutils.spawn import find_executable
from distutils.spawn import spawn from distutils.spawn import spawn
from distutils.errors import DistutilsExecError from distutils.errors import DistutilsExecError
......
...@@ -45,6 +45,7 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase): ...@@ -45,6 +45,7 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase):
self.assertIsInstance(cvars, dict) self.assertIsInstance(cvars, dict)
self.assertTrue(cvars) self.assertTrue(cvars)
@unittest.skip('sysconfig.IS_PYPY')
def test_srcdir(self): def test_srcdir(self):
# See Issues #15322, #15364. # See Issues #15322, #15364.
srcdir = sysconfig.get_config_var('srcdir') srcdir = sysconfig.get_config_var('srcdir')
......
...@@ -11,6 +11,7 @@ class UnixCCompilerTestCase(unittest.TestCase): ...@@ -11,6 +11,7 @@ class UnixCCompilerTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self._backup_platform = sys.platform self._backup_platform = sys.platform
self._backup_get_config_var = sysconfig.get_config_var self._backup_get_config_var = sysconfig.get_config_var
self._backup_get_config_vars = sysconfig.get_config_vars
class CompilerWrapper(UnixCCompiler): class CompilerWrapper(UnixCCompiler):
def rpath_foo(self): def rpath_foo(self):
return self.runtime_library_dir_option('/foo') return self.runtime_library_dir_option('/foo')
...@@ -19,6 +20,7 @@ class UnixCCompilerTestCase(unittest.TestCase): ...@@ -19,6 +20,7 @@ class UnixCCompilerTestCase(unittest.TestCase):
def tearDown(self): def tearDown(self):
sys.platform = self._backup_platform sys.platform = self._backup_platform
sysconfig.get_config_var = self._backup_get_config_var sysconfig.get_config_var = self._backup_get_config_var
sysconfig.get_config_vars = self._backup_get_config_vars
@unittest.skipIf(sys.platform == 'win32', "can't test on Windows") @unittest.skipIf(sys.platform == 'win32', "can't test on Windows")
def test_runtime_libdir_option(self): def test_runtime_libdir_option(self):
...@@ -110,7 +112,13 @@ class UnixCCompilerTestCase(unittest.TestCase): ...@@ -110,7 +112,13 @@ class UnixCCompilerTestCase(unittest.TestCase):
if v == 'LDSHARED': if v == 'LDSHARED':
return 'gcc-4.2 -bundle -undefined dynamic_lookup ' return 'gcc-4.2 -bundle -undefined dynamic_lookup '
return 'gcc-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_var = gcv
sysconfig.get_config_vars = gcvs
with EnvironmentVarGuard() as env: with EnvironmentVarGuard() as env:
env['CC'] = 'my_cc' env['CC'] = 'my_cc'
del env['LDSHARED'] del env['LDSHARED']
...@@ -126,7 +134,13 @@ class UnixCCompilerTestCase(unittest.TestCase): ...@@ -126,7 +134,13 @@ class UnixCCompilerTestCase(unittest.TestCase):
if v == 'LDSHARED': if v == 'LDSHARED':
return 'gcc-4.2 -bundle -undefined dynamic_lookup ' return 'gcc-4.2 -bundle -undefined dynamic_lookup '
return 'gcc-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_var = gcv
sysconfig.get_config_vars = gcvs
with EnvironmentVarGuard() as env: with EnvironmentVarGuard() as env:
env['CC'] = 'my_cc' env['CC'] = 'my_cc'
env['LDSHARED'] = 'my_ld -bundle -dynamic' env['LDSHARED'] = 'my_ld -bundle -dynamic'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment