diff options
-rw-r--r-- | distutils/command/install.py | 20 | ||||
-rw-r--r-- | distutils/sysconfig.py | 85 | ||||
-rw-r--r-- | distutils/tests/py35compat.py | 77 | ||||
-rw-r--r-- | distutils/tests/test_build_clib.py | 4 | ||||
-rw-r--r-- | distutils/tests/test_build_ext.py | 4 | ||||
-rw-r--r-- | distutils/tests/test_config_cmd.py | 4 | ||||
-rw-r--r-- | distutils/tests/test_dist.py | 4 | ||||
-rw-r--r-- | distutils/tests/test_filelist.py | 5 | ||||
-rw-r--r-- | distutils/tests/test_install.py | 3 | ||||
-rw-r--r-- | distutils/tests/test_spawn.py | 4 | ||||
-rw-r--r-- | distutils/tests/test_sysconfig.py | 1 | ||||
-rw-r--r-- | distutils/tests/test_unixccompiler.py | 14 |
12 files changed, 182 insertions, 43 deletions
diff --git a/distutils/command/install.py b/distutils/command/install.py index 21f8c27c..13feeb89 100644 --- a/distutils/command/install.py +++ b/distutils/command/install.py @@ -43,6 +43,20 @@ INSTALL_SCHEMES = { 'data' : '$base', }, '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 @@ -455,6 +469,12 @@ class install(Command): 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 + not name.endswith(('_user', '_home'))): + if os.name == 'nt': + name = 'pypy_nt' + else: + name = 'pypy' scheme = INSTALL_SCHEMES[name] for key in SCHEME_KEYS: attrname = 'install_' + key diff --git a/distutils/sysconfig.py b/distutils/sysconfig.py index 79391e86..879b6981 100644 --- a/distutils/sysconfig.py +++ b/distutils/sysconfig.py @@ -16,6 +16,8 @@ import sys 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. PREFIX = os.path.normpath(sys.prefix) EXEC_PREFIX = os.path.normpath(sys.exec_prefix) @@ -97,7 +99,9 @@ def get_python_inc(plat_specific=0, prefix=None): """ if prefix is None: 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: # Assume the executable is in the build directory. The # 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): If 'prefix' is supplied, use it instead of sys.base_prefix or 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 standard_lib: prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX @@ -499,41 +511,42 @@ def get_config_vars(*args): _config_vars['prefix'] = PREFIX _config_vars['exec_prefix'] = EXEC_PREFIX - # 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) + 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 diff --git a/distutils/tests/py35compat.py b/distutils/tests/py35compat.py new file mode 100644 index 00000000..0c755261 --- /dev/null +++ b/distutils/tests/py35compat.py @@ -0,0 +1,77 @@ +""" +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)') diff --git a/distutils/tests/test_build_clib.py b/distutils/tests/test_build_clib.py index abd83137..259c4352 100644 --- a/distutils/tests/test_build_clib.py +++ b/distutils/tests/test_build_clib.py @@ -3,7 +3,9 @@ import unittest import os 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.errors import DistutilsSetupError diff --git a/distutils/tests/test_build_ext.py b/distutils/tests/test_build_ext.py index 5e47e077..1aec1537 100644 --- a/distutils/tests/test_build_ext.py +++ b/distutils/tests/test_build_ext.py @@ -82,7 +82,7 @@ class BuildExtTestCase(TempdirManager, else: ALREADY_TESTED = type(self).__name__ - code = textwrap.dedent(f""" + code = textwrap.dedent(""" tmp_dir = {self.tmp_dir!r} import sys @@ -108,7 +108,7 @@ class BuildExtTestCase(TempdirManager, unittest.main() - """) + """.format(**locals())) assert_python_ok('-c', code) def test_solaris_enable_shared(self): diff --git a/distutils/tests/test_config_cmd.py b/distutils/tests/test_config_cmd.py index 9aeab07b..4cd9a6b9 100644 --- a/distutils/tests/test_config_cmd.py +++ b/distutils/tests/test_config_cmd.py @@ -2,7 +2,9 @@ import unittest import os 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.tests import support diff --git a/distutils/tests/test_dist.py b/distutils/tests/test_dist.py index 60956dad..d431085b 100644 --- a/distutils/tests/test_dist.py +++ b/distutils/tests/test_dist.py @@ -83,6 +83,10 @@ class DistributionTestCase(support.LoggingSilencer, self.assertIsInstance(cmd, test_dist) 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): sys.argv.append("install") self.addCleanup(os.unlink, TESTFN) diff --git a/distutils/tests/test_filelist.py b/distutils/tests/test_filelist.py index c71342d0..71fde2b7 100644 --- a/distutils/tests/test_filelist.py +++ b/distutils/tests/test_filelist.py @@ -12,6 +12,9 @@ import test.support from test.support import captured_stdout, run_unittest from distutils.tests import support +from .py35compat import adapt_glob + + MANIFEST_IN = """\ include ok include xo @@ -60,7 +63,7 @@ class FileListTestCase(support.LoggingSilencer, ('foo????', r'(?s:foo[^%(sep)s][^%(sep)s][^%(sep)s][^%(sep)s])\Z'), (r'foo\\??', r'(?s:foo\\\\[^%(sep)s][^%(sep)s])\Z')): 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): # testing all MANIFEST.in template patterns diff --git a/distutils/tests/test_install.py b/distutils/tests/test_install.py index 51c80e04..eb684a09 100644 --- a/distutils/tests/test_install.py +++ b/distutils/tests/test_install.py @@ -58,7 +58,8 @@ class InstallTestCase(support.TempdirManager, libdir = os.path.join(destination, "lib", "python") 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_purelib, libdir) check_path(cmd.install_headers, diff --git a/distutils/tests/test_spawn.py b/distutils/tests/test_spawn.py index cf1faad5..919d0ad9 100644 --- a/distutils/tests/test_spawn.py +++ b/distutils/tests/test_spawn.py @@ -3,9 +3,11 @@ import os import stat import sys 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 .py35compat import unix_shell + from distutils.spawn import find_executable from distutils.spawn import spawn from distutils.errors import DistutilsExecError diff --git a/distutils/tests/test_sysconfig.py b/distutils/tests/test_sysconfig.py index 236755d0..d5076391 100644 --- a/distutils/tests/test_sysconfig.py +++ b/distutils/tests/test_sysconfig.py @@ -45,6 +45,7 @@ class SysconfigTestCase(support.EnvironGuard, unittest.TestCase): self.assertIsInstance(cvars, dict) self.assertTrue(cvars) + @unittest.skip('sysconfig.IS_PYPY') def test_srcdir(self): # See Issues #15322, #15364. srcdir = sysconfig.get_config_var('srcdir') diff --git a/distutils/tests/test_unixccompiler.py b/distutils/tests/test_unixccompiler.py index eef702cf..f2159662 100644 --- a/distutils/tests/test_unixccompiler.py +++ b/distutils/tests/test_unixccompiler.py @@ -11,6 +11,7 @@ class UnixCCompilerTestCase(unittest.TestCase): def setUp(self): self._backup_platform = sys.platform self._backup_get_config_var = sysconfig.get_config_var + self._backup_get_config_vars = sysconfig.get_config_vars class CompilerWrapper(UnixCCompiler): def rpath_foo(self): return self.runtime_library_dir_option('/foo') @@ -19,6 +20,7 @@ class UnixCCompilerTestCase(unittest.TestCase): def tearDown(self): sys.platform = self._backup_platform 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") def test_runtime_libdir_option(self): @@ -110,7 +112,13 @@ class UnixCCompilerTestCase(unittest.TestCase): if v == 'LDSHARED': return 'gcc-4.2 -bundle -undefined dynamic_lookup ' 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 EnvironmentVarGuard() as env: env['CC'] = 'my_cc' del env['LDSHARED'] @@ -126,7 +134,13 @@ class UnixCCompilerTestCase(unittest.TestCase): if v == 'LDSHARED': return 'gcc-4.2 -bundle -undefined dynamic_lookup ' 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 EnvironmentVarGuard() as env: env['CC'] = 'my_cc' env['LDSHARED'] = 'my_ld -bundle -dynamic' |