Skip to content

Commit

Permalink
Merge pull request #2875 from pypa/feature/local-schemes
Browse files Browse the repository at this point in the history
Update distutils @514e9d0
  • Loading branch information
jaraco committed Nov 18, 2021
2 parents 24c766c + 4a8a79d commit d508e38
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 77 deletions.
1 change: 1 addition & 0 deletions changelog.d/2875.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Introduce changes from pypa/distutils@514e9d0, including support for overrides from Debian and pkgsrc, unlocking the possibility of making SETUPTOOLS_USE_DISTUTILS=local the default again.
11 changes: 10 additions & 1 deletion setuptools/_distutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@
"""

import sys
import importlib

__version__ = sys.version[:sys.version.index(' ')]

local = True

try:
# Allow Debian and pkgsrc (only) to customize system
# behavior. Ref pypa/distutils#2 and pypa/distutils#16.
# This hook is deprecated and no other environments
# should use it.
importlib.import_module('_distutils_system_mod')
except ImportError:
pass
118 changes: 74 additions & 44 deletions setuptools/_distutils/command/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import sys
import os
import contextlib
import sysconfig
import itertools

from distutils import log
from distutils.core import Command
Expand All @@ -20,69 +23,94 @@
HAS_USER_SITE = True

WINDOWS_SCHEME = {
'purelib': '$base/Lib/site-packages',
'platlib': '$base/Lib/site-packages',
'headers': '$base/Include/$dist_name',
'scripts': '$base/Scripts',
'data' : '$base',
'purelib': '{base}/Lib/site-packages',
'platlib': '{base}/Lib/site-packages',
'headers': '{base}/Include/{dist_name}',
'scripts': '{base}/Scripts',
'data' : '{base}',
}

INSTALL_SCHEMES = {
'unix_prefix': {
'purelib': '$base/lib/$implementation_lower$py_version_short/site-packages',
'platlib': '$platbase/$platlibdir/$implementation_lower$py_version_short/site-packages',
'headers': '$base/include/$implementation_lower$py_version_short$abiflags/$dist_name',
'scripts': '$base/bin',
'data' : '$base',
'posix_prefix': {
'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages',
'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages',
'headers': '{base}/include/{implementation_lower}{py_version_short}{abiflags}/{dist_name}',
'scripts': '{base}/bin',
'data' : '{base}',
},
'unix_home': {
'purelib': '$base/lib/$implementation_lower',
'platlib': '$base/$platlibdir/$implementation_lower',
'headers': '$base/include/$implementation_lower/$dist_name',
'scripts': '$base/bin',
'data' : '$base',
'posix_home': {
'purelib': '{base}/lib/{implementation_lower}',
'platlib': '{base}/{platlibdir}/{implementation_lower}',
'headers': '{base}/include/{implementation_lower}/{dist_name}',
'scripts': '{base}/bin',
'data' : '{base}',
},
'nt': WINDOWS_SCHEME,
'pypy': {
'purelib': '$base/site-packages',
'platlib': '$base/site-packages',
'headers': '$base/include/$dist_name',
'scripts': '$base/bin',
'data' : '$base',
'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',
'purelib': '{base}/site-packages',
'platlib': '{base}/site-packages',
'headers': '{base}/include/{dist_name}',
'scripts': '{base}/Scripts',
'data' : '{base}',
},
}

# user site schemes
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',
'data' : '$userbase',
'purelib': '{usersite}',
'platlib': '{usersite}',
'headers': '{userbase}/{implementation}{py_version_nodot}/Include/{dist_name}',
'scripts': '{userbase}/{implementation}{py_version_nodot}/Scripts',
'data' : '{userbase}',
}

INSTALL_SCHEMES['unix_user'] = {
'purelib': '$usersite',
'platlib': '$usersite',
INSTALL_SCHEMES['posix_user'] = {
'purelib': '{usersite}',
'platlib': '{usersite}',
'headers':
'$userbase/include/$implementation_lower$py_version_short$abiflags/$dist_name',
'scripts': '$userbase/bin',
'data' : '$userbase',
'{userbase}/include/{implementation_lower}{py_version_short}{abiflags}/{dist_name}',
'scripts': '{userbase}/bin',
'data' : '{userbase}',
}

# The keys to an installation scheme; if any new types of files are to be
# installed, be sure to add an entry to every installation scheme above,
# and to SCHEME_KEYS here.
SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')


def _load_sysconfig_schemes():
with contextlib.suppress(AttributeError):
return {
scheme: sysconfig.get_paths(scheme, expand=False)
for scheme in sysconfig.get_scheme_names()
}


def _load_schemes():
"""
Extend default schemes with schemes from sysconfig.
"""

sysconfig_schemes = _load_sysconfig_schemes() or {}

return {
scheme: {
**INSTALL_SCHEMES.get(scheme, {}),
**sysconfig_schemes.get(scheme, {}),
}
for scheme in set(itertools.chain(INSTALL_SCHEMES, sysconfig_schemes))
}


def _get_implementation():
if hasattr(sys, 'pypy_version_info'):
return 'PyPy'
Expand Down Expand Up @@ -284,7 +312,7 @@ def finalize_options(self):
# input a heady brew of prefix, exec_prefix, home, install_base,
# install_platbase, user-supplied versions of
# install_{purelib,platlib,lib,scripts,data,...}, and the
# INSTALL_SCHEME dictionary above. Phew!
# install schemes. Phew!

self.dump_dirs("pre-finalize_{unix,other}")

Expand Down Expand Up @@ -335,6 +363,8 @@ def finalize_options(self):
# 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'])

if DEBUG:
from pprint import pprint
Expand Down Expand Up @@ -431,10 +461,10 @@ def finalize_unix(self):
raise DistutilsPlatformError(
"User base directory is not specified")
self.install_base = self.install_platbase = self.install_userbase
self.select_scheme("unix_user")
self.select_scheme("posix_user")
elif self.home is not None:
self.install_base = self.install_platbase = self.home
self.select_scheme("unix_home")
self.select_scheme("posix_home")
else:
if self.prefix is None:
if self.exec_prefix is not None:
Expand All @@ -450,7 +480,7 @@ def finalize_unix(self):

self.install_base = self.prefix
self.install_platbase = self.exec_prefix
self.select_scheme("unix_prefix")
self.select_scheme("posix_prefix")

def finalize_other(self):
"""Finalizes options for non-posix platforms"""
Expand All @@ -462,7 +492,7 @@ def finalize_other(self):
self.select_scheme(os.name + "_user")
elif self.home is not None:
self.install_base = self.install_platbase = self.home
self.select_scheme("unix_home")
self.select_scheme("posix_home")
else:
if self.prefix is None:
self.prefix = os.path.normpath(sys.prefix)
Expand All @@ -484,7 +514,7 @@ def select_scheme(self, name):
name = 'pypy_nt'
else:
name = 'pypy'
scheme = INSTALL_SCHEMES[name]
scheme = _load_schemes()[name]
for key in SCHEME_KEYS:
attrname = 'install_' + key
if getattr(self, attrname) is None:
Expand Down
15 changes: 11 additions & 4 deletions setuptools/_distutils/command/install_egg_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ class install_egg_info(Command):
def initialize_options(self):
self.install_dir = None

def finalize_options(self):
self.set_undefined_options('install_lib',('install_dir','install_dir'))
basename = "%s-%s-py%d.%d.egg-info" % (
@property
def basename(self):
"""
Allow basename to be overridden by child class.
Ref pypa/distutils#2.
"""
return "%s-%s-py%d.%d.egg-info" % (
to_filename(safe_name(self.distribution.get_name())),
to_filename(safe_version(self.distribution.get_version())),
*sys.version_info[:2]
)
self.target = os.path.join(self.install_dir, basename)

def finalize_options(self):
self.set_undefined_options('install_lib',('install_dir','install_dir'))
self.target = os.path.join(self.install_dir, self.basename)
self.outputs = [self.target]

def run(self):
Expand Down
9 changes: 9 additions & 0 deletions setuptools/_distutils/cygwinccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ def get_msvcr():
elif msc_ver == '1600':
# VS2010 / MSVC 10.0
return ['msvcr100']
elif msc_ver == '1700':
# VS2012 / MSVC 11.0
return ['msvcr110']
elif msc_ver == '1800':
# VS2013 / MSVC 12.0
return ['msvcr120']
elif 1900 <= int(msc_ver) < 2000:
# VS2015 / MSVC 14.0
return ['ucrt', 'vcruntime140']
else:
raise ValueError("Unknown MS Compiler version %s " % msc_ver)

Expand Down
49 changes: 36 additions & 13 deletions setuptools/_distutils/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ def get_python_inc(plat_specific=0, prefix=None):
"on platform '%s'" % os.name)


# allow this behavior to be monkey-patched. Ref pypa/distutils#2.
def _posix_lib(standard_lib, libpython, early_prefix, prefix):
if standard_lib:
return libpython
else:
return os.path.join(libpython, "site-packages")


def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
"""Return the directory containing the Python library (standard or
site additions).
Expand All @@ -152,6 +160,8 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
return os.path.join(prefix, "lib-python", sys.version[0])
return os.path.join(prefix, 'site-packages')

early_prefix = prefix

if prefix is None:
if standard_lib:
prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
Expand All @@ -169,10 +179,7 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
implementation = 'pypy' if IS_PYPY else 'python'
libpython = os.path.join(prefix, libdir,
implementation + get_python_version())
if standard_lib:
return libpython
else:
return os.path.join(libpython, "site-packages")
return _posix_lib(standard_lib, libpython, early_prefix, prefix)
elif os.name == "nt":
if standard_lib:
return os.path.join(prefix, "Lib")
Expand Down Expand Up @@ -273,14 +280,24 @@ def get_config_h_filename():
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}'


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)
config_file = 'config-{}{}'.format(get_python_version(), build_flags)
if hasattr(sys.implementation, '_multiarch'):
config_file += '-%s' % sys.implementation._multiarch
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')


Expand Down Expand Up @@ -452,15 +469,21 @@ 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',
'_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
abi=sys.abiflags,
platform=sys.platform,
multiarch=getattr(sys.implementation, '_multiarch', ''),
))
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:
Expand Down
5 changes: 4 additions & 1 deletion setuptools/_distutils/tests/test_cygwinccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,13 @@ def test_get_msvcr(self):
sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
'[MSC v.1500 32 bits (Intel)]')
self.assertEqual(get_msvcr(), ['msvcr90'])

sys.version = '3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 18:46:30) [MSC v.1929 32 bit (Intel)]'
self.assertEqual(get_msvcr(), ['ucrt', 'vcruntime140'])

# unknown
sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) '
'[MSC v.1999 32 bits (Intel)]')
'[MSC v.2000 32 bits (Intel)]')
self.assertRaises(ValueError, get_msvcr)

def test_suite():
Expand Down
2 changes: 1 addition & 1 deletion setuptools/_distutils/tests/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def cleanup():

self.addCleanup(cleanup)

for key in ('nt_user', 'unix_user'):
for key in ('nt_user', 'posix_user'):
self.assertIn(key, INSTALL_SCHEMES)

dist = Distribution({'name': 'xx'})
Expand Down
Loading

0 comments on commit d508e38

Please sign in to comment.