/
githubmirror
/
os-python3.9
Обзор
Документация
Войти
/
githubmirror
/
os-python3.9
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
bullseye
debian/patches/distutils-install-layout.diff
485 строк
19 KB
Huw Jones
Update distutils-install-layout to match python3.11
17 мар 2023, 14:39
Не верифицирован
17 мар 2023, 14:39
b60c598
Код
Авторство
О чём код?
Description: Debian: Add a distutils option --install-layout=deb This option: - installs into $prefix/dist-packages instead of $prefix/site-packages. - doesn't encode the python version into the egg name. . We install modules into dist-packages so that a local admin can build their own cpython from source, and they won't see each others' installed modules. This keeps Debian packaged applications working correctly, isolated from the local cpython. . Customize site.py to import from Debian's dist-packages layout. Forwarded: not-needed --- a/Lib/distutils/command/install_egg_info.py +++ b/Lib/distutils/command/install_egg_info.py @@ -14,18 +14,38 @@ description = "Install package's PKG-INFO metadata as an .egg-info file" user_options = [ ('install-dir=', 'd', "directory to install to"), + ('install-layout', None, "custom installation layout"), ] def initialize_options(self): self.install_dir = None + self.install_layout = None + self.prefix_option = None def finalize_options(self): self.set_undefined_options('install_lib',('install_dir','install_dir')) - basename = "%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.set_undefined_options('install',('install_layout','install_layout')) + self.set_undefined_options('install',('prefix_option','prefix_option')) + if self.install_layout: + if not self.install_layout.lower() in ['deb', 'unix']: + raise DistutilsOptionError( + "unknown value for --install-layout") + no_pyver = (self.install_layout.lower() == 'deb') + elif self.prefix_option: + no_pyver = False + else: + no_pyver = True + if no_pyver: + basename = "%s-%s.egg-info" % ( + to_filename(safe_name(self.distribution.get_name())), + to_filename(safe_version(self.distribution.get_version())) + ) + else: + basename = "%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) self.outputs = [self.target] --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py @@ -8,7 +8,7 @@ from distutils import log from distutils.core import Command from distutils.debug import DEBUG -from distutils.sysconfig import get_config_vars +from distutils.sysconfig import get_config_vars, is_virtual_environment from distutils.errors import DistutilsPlatformError from distutils.file_util import write_file from distutils.util import convert_path, subst_vars, change_root @@ -35,6 +35,20 @@ 'scripts': '$base/bin', 'data' : '$base', }, + 'unix_local': { + 'purelib': '$base/local/lib/python$py_version_short/dist-packages', + 'platlib': '$platbase/local/lib/python$py_version_short/dist-packages', + 'headers': '$base/local/include/python$py_version_short/$dist_name', + 'scripts': '$base/local/bin', + 'data' : '$base/local', + }, + 'deb_system': { + 'purelib': '$base/lib/python3/dist-packages', + 'platlib': '$platbase/lib/python3/dist-packages', + 'headers': '$base/include/python$py_version_short/$dist_name', + 'scripts': '$base/bin', + 'data' : '$base', + }, 'unix_home': { 'purelib': '$base/lib/python', 'platlib': '$base/$platlibdir/python', @@ -131,6 +145,9 @@ ('record=', None, "filename in which to record list of installed files"), + + ('install-layout=', None, + "installation layout to choose (known values: deb, unix)"), ] boolean_options = ['compile', 'force', 'skip-build'] @@ -151,6 +168,7 @@ self.exec_prefix = None self.home = None self.user = 0 + self.prefix_option = None # These select only the installation base; it's up to the user to # specify the installation scheme (currently, that means supplying @@ -172,6 +190,9 @@ self.install_userbase = USER_BASE self.install_usersite = USER_SITE + # enable custom installation, known values: deb + self.install_layout = None + self.compile = None self.optimize = None @@ -414,6 +435,7 @@ self.install_base = self.install_platbase = self.home self.select_scheme("unix_home") else: + self.prefix_option = self.prefix if self.prefix is None: if self.exec_prefix is not None: raise DistutilsOptionError( @@ -428,7 +450,23 @@ self.install_base = self.prefix self.install_platbase = self.exec_prefix - self.select_scheme("unix_prefix") + if self.install_layout: + if self.install_layout.lower() in ['deb']: + self.select_scheme("deb_system") + elif self.install_layout.lower() in ['unix']: + self.select_scheme("unix_prefix") + else: + raise DistutilsOptionError( + "unknown value for --install-layout") + elif ((self.prefix_option and + os.path.normpath(self.prefix) != '/usr/local') + or is_virtual_environment()): + self.select_scheme("unix_prefix") + else: + if os.path.normpath(self.prefix) == '/usr/local': + self.prefix = self.exec_prefix = '/usr' + self.install_base = self.install_platbase = '/usr' + self.select_scheme("unix_local") def finalize_other(self): """Finalizes options for non-posix platforms""" --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -138,6 +138,7 @@ If 'prefix' is supplied, use it instead of sys.base_prefix or sys.base_exec_prefix -- i.e., ignore 'plat_specific'. """ + is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local') if prefix is None: if standard_lib: prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX @@ -156,6 +157,8 @@ "python" + get_python_version()) if standard_lib: return libpython + elif is_default_prefix and not is_virtual_environment(): + return os.path.join(prefix, "lib", "python3", "dist-packages") else: return os.path.join(libpython, "site-packages") elif os.name == "nt": @@ -243,6 +246,10 @@ compiler.shared_lib_extension = shlib_suffix +def is_virtual_environment(): + return sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") + + def get_config_h_filename(): """Return full pathname of installed pyconfig.h file.""" if python_build: --- a/Lib/site.py +++ b/Lib/site.py @@ -7,12 +7,18 @@ This will append site-specific paths to the module search path. On Unix (including Mac OSX), it starts with sys.prefix and sys.exec_prefix (if different) and appends -lib/python<version>/site-packages. +lib/python3/dist-packages. On other platforms (such as Windows), it tries each of the prefixes directly, as well as with lib/site-packages appended. The resulting directories, if they exist, are appended to sys.path, and also inspected for path configuration files. +For Debian and derivatives, this sys.path is augmented with directories +for packages distributed within the distribution. Local addons go +into /usr/local/lib/python<version>/dist-packages, Debian addons +install into /usr/lib/python3/dist-packages. +/usr/lib/python<version>/site-packages is not used. + If a file named "pyvenv.cfg" exists one directory above sys.executable, sys.prefix and sys.exec_prefix are set to that directory and it is also checked for site-packages (sys.base_prefix and @@ -329,6 +335,8 @@ if prefixes is None: prefixes = PREFIXES + is_virtual_environment = sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") + for prefix in prefixes: if not prefix or prefix in seen: continue @@ -339,10 +347,21 @@ libdirs.append("lib") if os.sep == '/': + if is_virtual_environment: + sitepackages.append(os.path.join(prefix, "lib", + "python%d.%d" % sys.version_info[:2], + "site-packages")) + sitepackages.append(os.path.join(prefix, "local/lib", + "python%d.%d" % sys.version_info[:2], + "dist-packages")) + sitepackages.append(os.path.join(prefix, "lib", + "python3", + "dist-packages")) + # this one is deprecated for Debian for libdir in libdirs: path = os.path.join(prefix, libdir, "python%d.%d" % sys.version_info[:2], - "site-packages") + "dist-packages") sitepackages.append(path) else: sitepackages.append(prefix) --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -269,16 +269,16 @@ if os.sep == '/': # OS X, Linux, FreeBSD, etc if sys.platlibdir != "lib": - self.assertEqual(len(dirs), 2) - wanted = os.path.join('xoxo', sys.platlibdir, + self.assertEqual(len(dirs), 3) + wanted = os.path.join('xoxo', 'local', 'lib', 'python%d.%d' % sys.version_info[:2], - 'site-packages') + 'dist-packages') self.assertEqual(dirs[0], wanted) else: - self.assertEqual(len(dirs), 1) + self.assertEqual(len(dirs), 3) wanted = os.path.join('xoxo', 'lib', 'python%d.%d' % sys.version_info[:2], - 'site-packages') + 'dist-packages') self.assertEqual(dirs[-1], wanted) else: # other platforms --- a/Lib/distutils/tests/test_bdist_dumb.py +++ b/Lib/distutils/tests/test_bdist_dumb.py @@ -85,7 +85,7 @@ fp.close() contents = sorted(filter(None, map(os.path.basename, contents))) - wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2], 'foo.py'] + wanted = ['foo-0.1.egg-info', 'foo.py'] if not sys.dont_write_bytecode: wanted.append('foo.%s.pyc' % sys.implementation.cache_tag) self.assertEqual(contents, sorted(wanted)) --- a/Lib/distutils/tests/test_install.py +++ b/Lib/distutils/tests/test_install.py @@ -194,7 +194,7 @@ found = [os.path.basename(line) for line in content.splitlines()] expected = ['hello.py', 'hello.%s.pyc' % sys.implementation.cache_tag, 'sayhi', - 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]] + 'UNKNOWN-0.0.0.egg-info'] self.assertEqual(found, expected) def test_record_extensions(self): @@ -227,7 +227,7 @@ found = [os.path.basename(line) for line in content.splitlines()] expected = [_make_ext_name('xx'), - 'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]] + 'UNKNOWN-0.0.0.egg-info'] self.assertEqual(found, expected) def test_debug_mode(self): --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -505,6 +505,7 @@ 'marshal', 'posix', 'signal', 'sys', '_thread', 'zipimport') or (file.startswith(basedir) and + not file.startswith(os.path.join(basedir, 'dist-packages')) and not file.startswith(os.path.join(basedir, 'site-packages')))) and object.__name__ not in ('xml.etree', 'test.pydoc_mod')): if docloc.startswith(("http://", "https://")): --- /dev/null +++ b/Lib/_distutils_system_mod.py @@ -0,0 +1,180 @@ +""" +Apply Debian-specific patches to distutils commands. + +Extracts the customized behavior from patches as reported +in pypa/distutils#2 and applies those customizations (except +for scheme definitions) to those commands. + +Place this module somewhere in sys.path to take effect. +""" + +import os +import sys +import sysconfig + +import distutils.sysconfig +import distutils.command.install as orig_install +import distutils.command.install_egg_info as orig_install_egg_info +from distutils.command.install_egg_info import ( + to_filename, + safe_name, + safe_version, + ) +from distutils.errors import DistutilsOptionError + + +class install(orig_install.install): + user_options = list(orig_install.install.user_options) + [ + ('install-layout=', None, + "installation layout to choose (known values: deb, unix)"), + ] + + def initialize_options(self): + super().initialize_options() + self.prefix_option = None + self.install_layout = None + + def select_scheme(self, name): + if name == "posix_prefix": + if self.install_layout: + if self.install_layout.lower() in ['deb']: + name = "deb_system" + elif self.install_layout.lower() in ['unix']: + name = "posix_prefix" + else: + raise DistutilsOptionError( + "unknown value for --install-layout") + elif ((self.prefix_option and + os.path.normpath(self.prefix) != '/usr/local') + or is_virtual_environment()): + name = "posix_prefix" + else: + if os.path.normpath(self.prefix) == '/usr/local': + self.prefix = self.exec_prefix = '/usr' + self.install_base = self.install_platbase = '/usr' + name = "posix_local" + super().select_scheme(name) + + def finalize_unix(self): + self.prefix_option = self.prefix + super().finalize_unix() + + +class install_egg_info(orig_install_egg_info.install_egg_info): + user_options = list(orig_install_egg_info.install_egg_info.user_options) + [ + ('install-layout', None, "custom installation layout"), + ] + + def initialize_options(self): + super().initialize_options() + self.prefix_option = None + self.install_layout = None + + def finalize_options(self): + self.set_undefined_options('install',('install_layout','install_layout')) + self.set_undefined_options('install',('prefix_option','prefix_option')) + super().finalize_options() + + @property + def basename(self): + if self.install_layout: + if not self.install_layout.lower() in ['deb', 'unix']: + raise DistutilsOptionError( + "unknown value for --install-layout") + no_pyver = (self.install_layout.lower() == 'deb') + elif self.prefix_option: + no_pyver = False + else: + no_pyver = True + if no_pyver: + basename = "%s-%s.egg-info" % ( + to_filename(safe_name(self.distribution.get_name())), + to_filename(safe_version(self.distribution.get_version())) + ) + else: + basename = "%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] + ) + return basename + + +def is_virtual_environment(): + return sys.base_prefix != sys.prefix or hasattr(sys, "real_prefix") + + +def _posix_lib(standard_lib, libpython, early_prefix, prefix): + is_default_prefix = not early_prefix or os.path.normpath(early_prefix) in ('/usr', '/usr/local') + if standard_lib: + return libpython + elif is_default_prefix and not is_virtual_environment(): + return os.path.join(prefix, "lib", "python3", "dist-packages") + else: + return os.path.join(libpython, "site-packages") + + +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 + + headers: module headers install location (posix_local is /local/ prefixed) + include: cpython headers (Python.h) + See also: bpo-44445 + """ + if 'headers' not in scheme: + if name == 'posix_prefix': + headers = scheme['include'] + else: + headers = orig_install.INSTALL_SCHEMES['posix_prefix']['headers'] + if name == 'posix_local' and '/local/' not in headers: + headers = headers.replace('/include/', '/local/include/') + scheme['headers'] = headers + return scheme + + +def load_schemes_wrapper(_load_schemes): + """ + Implement the _inject_headers modification, above, but before + _inject_headers() was introduced, upstream. So, slower and messier. + """ + def wrapped_load_schemes(): + schemes = _load_schemes() + for name, scheme in schemes.items(): + _inject_headers(name, scheme) + return schemes + return wrapped_load_schemes + + +def add_debian_schemes(schemes): + """ + Ensure that the custom schemes we refer to above are present in schemes. + """ + for name in ('posix_prefix', 'posix_local', 'deb_system'): + if name not in schemes: + scheme = sysconfig.get_paths(name, expand=False) + schemes[name] = _inject_headers(name, scheme) + + +def apply_customizations(): + orig_install.install = install + orig_install_egg_info.install_egg_info = install_egg_info + distutils.sysconfig._posix_lib = _posix_lib + + if hasattr(orig_install, '_inject_headers'): + # setuptools-bundled distutils >= 60.0.5 + orig_install._inject_headers = _inject_headers + elif hasattr(orig_install, '_load_schemes'): + # setuptools-bundled distutils >= 59.2.0 + orig_install._load_schemes = load_schemes_wrapper(orig_install._load_schemes) + else: + # older version with only statically defined schemes + # this includes the version bundled with Python 3.10 that has our + # schemes already included + add_debian_schemes(orig_install.INSTALL_SCHEMES) + + +apply_customizations()