1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -143,6 +143,8 @@ class easy_install(Command):
('allow-hosts=', 'H', "pattern(s) that hostnames must match"),
('local-snapshots-ok', 'l', "allow building eggs from local checkouts"),
('version', None, "print version information and exit"),
+ ('install-layout=', None, "installation layout to choose (known values: deb)"),
+ ('force-installation-into-system-dir', '0', "force installation into /usr"),
(
'no-find-links',
None,
@@ -157,7 +159,7 @@ class easy_install(Command):
'upgrade',
'always-copy',
'editable',
- 'no-deps',
+ 'no-deps', 'local-snapshots-ok', 'force-installation-into-system-dir'
'local-snapshots-ok',
'version',
'user',
@@ -200,6 +202,10 @@ class easy_install(Command):
self.pth_file = self.always_copy_from = None
self.site_dirs = None
self.installed_projects = {}
+ # enable custom installation, known values: deb
+ self.install_layout = None
+ self.force_installation_into_system_dir = None
+
# Always read easy_install options, even if we are subclassed, or have
# an independent instance created. This ensures that defaults will
# always come from the standard configuration file(s)' "easy_install"
@@ -282,6 +288,11 @@ class easy_install(Command):
self.expand_basedirs()
self.expand_dirs()
+ if self.install_layout:
+ if not self.install_layout.lower() in ['deb']:
+ raise DistutilsOptionError("unknown value for --install-layout")
+ self.install_layout = self.install_layout.lower()
+
self._expand(
'install_dir',
'script_dir',
@@ -306,6 +317,15 @@ class easy_install(Command):
if self.user and self.install_purelib:
self.install_dir = self.install_purelib
self.script_dir = self.install_scripts
+
+ if self.prefix == '/usr' and not self.force_installation_into_system_dir:
+ raise DistutilsOptionError("""installation into /usr
+
+Trying to install into the system managed parts of the file system. Please
+consider to install to another location, or use the option
+--force-installation-into-system-dir to overwrite this warning.
+""")
+
# default --record from the install command
self.set_undefined_options('install', ('record', 'record'))
self.all_site_dirs = get_site_dirs()
@@ -1377,11 +1397,28 @@ class easy_install(Command):
self.debug_print(f"os.makedirs('{path}', 0o700)")
os.makedirs(path, 0o700)
+ if sys.version[:3] in ('2.3', '2.4', '2.5') or 'real_prefix' in sys.__dict__:
+ sitedir_name = 'site-packages'
+ else:
+ sitedir_name = 'dist-packages'
+
INSTALL_SCHEMES = dict(
posix=dict(
install_dir='$base/lib/python$py_version_short/site-packages',
script_dir='$base/bin',
),
+ unix_local = dict(
+ install_dir = '$base/local/lib/python$py_version_short/%s' % sitedir_name,
+ script_dir = '$base/local/bin',
+ ),
+ posix_local = dict(
+ install_dir = '$base/local/lib/python$py_version_short/%s' % sitedir_name,
+ script_dir = '$base/local/bin',
+ ),
+ deb_system = dict(
+ install_dir = '$base/lib/python3/%s' % sitedir_name,
+ script_dir = '$base/bin',
+ ),
)
DEFAULT_SCHEME = dict(
@@ -1392,11 +1429,18 @@ class easy_install(Command):
def _expand(self, *attrs):
config_vars = self.get_finalized_command('install').config_vars
- if self.prefix:
+ if self.prefix or self.install_layout:
+ if self.install_layout and self.install_layout in ['deb']:
+ scheme_name = "deb_system"
+ self.prefix = '/usr'
+ elif self.prefix or 'real_prefix' in sys.__dict__:
+ scheme_name = os.name
+ else:
+ scheme_name = "posix_local"
# Set default install_dir/scripts from --prefix
config_vars = dict(config_vars)
config_vars['base'] = self.prefix
- scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME)
+ scheme = self.INSTALL_SCHEMES.get(scheme_name,self.DEFAULT_SCHEME)
for attr, val in scheme.items():
if getattr(self, attr, None) is None:
setattr(self, attr, val)
@@ -1440,9 +1484,15 @@ def get_site_dirs():
sitedirs.extend([
os.path.join(
prefix,
+ "local/lib",
+ f"python{sys.version_info.major}.{sys.version_info.minor}",
+ "dist-packages",
+ ),
+ os.path.join(
+ prefix,
"lib",
f"python{sys.version_info.major}.{sys.version_info.minor}",
- "site-packages",
+ "dist-packages",
),
os.path.join(prefix, "lib", "site-python"),
])
--- a/setuptools/command/install_egg_info.py
+++ b/setuptools/command/install_egg_info.py
@@ -1,4 +1,4 @@
-import os
+import os, sys
from setuptools import Command, namespaces
from setuptools.archive_util import unpack_archive
@@ -19,11 +19,28 @@ class install_egg_info(namespaces.Instal
def initialize_options(self):
self.install_dir = None
+ self.install_layout = None
+ self.prefix_option = None
def finalize_options(self) -> None:
self.set_undefined_options('install_lib', ('install_dir', 'install_dir'))
+ self.set_undefined_options('install',('install_layout','install_layout'))
+ if sys.hexversion > 0x2060000:
+ self.set_undefined_options('install',('prefix_option','prefix_option'))
ei_cmd = self.get_finalized_command("egg_info")
basename = f"{ei_cmd._get_egg_basename()}.egg-info"
+
+ if self.install_layout:
+ if not self.install_layout.lower() in ['deb']:
+ raise DistutilsOptionError("unknown value for --install-layout")
+ self.install_layout = self.install_layout.lower()
+ basename = basename.replace('-py%s' % sys.version[:4], '')
+ elif self.prefix_option or 'real_prefix' in sys.__dict__:
+ # don't modify for virtualenv
+ pass
+ else:
+ basename = basename.replace('-py%s' % sys.version[:4], '')
+
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
self.outputs: list[str] = []
|