Skip to content

Commit b5dc3a4

Browse files
hroncokencukoumcyprianfrenzymadness
authored andcommitted
00251: Change user install location
Set values of base and platbase in sysconfig from /usr to /usr/local when RPM build is not detected to make pip and similar tools install into separate location. Set values of prefix and exec_prefix in distutils install command to /usr/local if executable is /usr/bin/python* and RPM build is not detected to make distutils and pypa/distutils install into separate location. Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe Downstream only. We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976 but we have identified serious problems with that approach, see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183 pypa/distutils integration: pypa/distutils#70 Co-authored-by: Petr Viktorin <[email protected]> Co-authored-by: Miro Hrončok <[email protected]> Co-authored-by: Michal Cyprian <[email protected]> Co-authored-by: Lumír Balhar <[email protected]>
1 parent de1a9d6 commit b5dc3a4

File tree

4 files changed

+81
-6
lines changed

4 files changed

+81
-6
lines changed

Lib/distutils/command/install.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class install(Command):
159159

160160
negative_opt = {'no-compile' : 'compile'}
161161

162+
# Allow Fedora to add components to the prefix
163+
_prefix_addition = getattr(sysconfig, '_prefix_addition', '')
162164

163165
def initialize_options(self):
164166
"""Initializes options."""
@@ -441,8 +443,10 @@ def finalize_unix(self):
441443
raise DistutilsOptionError(
442444
"must not supply exec-prefix without prefix")
443445

444-
self.prefix = os.path.normpath(sys.prefix)
445-
self.exec_prefix = os.path.normpath(sys.exec_prefix)
446+
self.prefix = (
447+
os.path.normpath(sys.prefix) + self._prefix_addition)
448+
self.exec_prefix = (
449+
os.path.normpath(sys.exec_prefix) + self._prefix_addition)
446450

447451
else:
448452
if self.exec_prefix is None:

Lib/site.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,15 @@ def getsitepackages(prefixes=None):
390390
return sitepackages
391391

392392
def addsitepackages(known_paths, prefixes=None):
393-
"""Add site-packages to sys.path"""
393+
"""Add site-packages to sys.path
394+
395+
'/usr/local' is included in PREFIXES if RPM build is not detected
396+
to make packages installed into this location visible.
397+
398+
"""
394399
_trace("Processing global site-packages")
400+
if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ:
401+
PREFIXES.insert(0, "/usr/local")
395402
for sitedir in getsitepackages(prefixes):
396403
if os.path.isdir(sitedir):
397404
addsitedir(sitedir, known_paths)

Lib/sysconfig.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@
5858
},
5959
}
6060

61+
# For a brief period of time in the Fedora 36 life cycle,
62+
# this installation scheme existed and was documented in the release notes.
63+
# For backwards compatibility, we keep it here (at least on 3.10 and 3.11).
64+
_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix']
65+
# Virtualenv >= 20.10.0 favors the "venv" scheme over the defaults when creating virtual environments.
66+
# See: https://github.com/pypa/virtualenv/commit/8da79db86d8a5c74d03667a40e64ff832076445e
67+
# See: https://bugs.python.org/issue45413
68+
# "venv" should be the same as the posix_prefix for us,
69+
# so new virtual environments aren't created with paths like venv/local/bin/python.
70+
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_prefix']
6171

6272
# NOTE: site.py has copy of this function.
6373
# Sync it when modify this function.
@@ -117,6 +127,19 @@ def joinuser(*args):
117127
},
118128
}
119129

130+
# This is used by distutils.command.install in the stdlib
131+
# as well as pypa/distutils (e.g. bundled in setuptools).
132+
# The self.prefix value is set to sys.prefix + /local/
133+
# if neither RPM build nor virtual environment is
134+
# detected to make distutils install packages
135+
# into the separate location.
136+
# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
137+
if (not (hasattr(sys, 'real_prefix') or
138+
sys.prefix != sys.base_prefix) and
139+
'RPM_BUILD_ROOT' not in os.environ):
140+
_prefix_addition = '/local'
141+
142+
120143
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
121144
'scripts', 'data')
122145

@@ -211,11 +234,39 @@ def _extend_dict(target_dict, other_dict):
211234
target_dict[key] = value
212235

213236

237+
_CONFIG_VARS_LOCAL = None
238+
239+
240+
def _config_vars_local():
241+
# This function returns the config vars with prefixes amended to /usr/local
242+
# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
243+
global _CONFIG_VARS_LOCAL
244+
if _CONFIG_VARS_LOCAL is None:
245+
_CONFIG_VARS_LOCAL = dict(get_config_vars())
246+
_CONFIG_VARS_LOCAL['base'] = '/usr/local'
247+
_CONFIG_VARS_LOCAL['platbase'] = '/usr/local'
248+
return _CONFIG_VARS_LOCAL
249+
250+
214251
def _expand_vars(scheme, vars):
215252
res = {}
216253
if vars is None:
217254
vars = {}
218-
_extend_dict(vars, get_config_vars())
255+
256+
# when we are not in a virtual environment or an RPM build
257+
# we change '/usr' to '/usr/local'
258+
# to avoid surprises, we explicitly check for the /usr/ prefix
259+
# Python virtual environments have different prefixes
260+
# we only do this for posix_prefix, not to mangle the venv scheme
261+
# posix_prefix is used by sudo pip install
262+
# we only change the defaults here, so explicit --prefix will take precedence
263+
# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
264+
if (scheme == 'posix_prefix' and
265+
_PREFIX == '/usr' and
266+
'RPM_BUILD_ROOT' not in os.environ):
267+
_extend_dict(vars, _config_vars_local())
268+
else:
269+
_extend_dict(vars, get_config_vars())
219270

220271
for key, value in _INSTALL_SCHEMES[scheme].items():
221272
if os.name in ('posix', 'nt'):

Lib/test/test_sysconfig.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,19 @@ def test_get_path(self):
105105
for scheme in _INSTALL_SCHEMES:
106106
for name in _INSTALL_SCHEMES[scheme]:
107107
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
108+
tested = get_path(name, scheme)
109+
# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
110+
if tested.startswith('/usr/local'):
111+
# /usr/local should only be used in posix_prefix
112+
self.assertEqual(scheme, 'posix_prefix')
113+
# Fedora CI runs tests for venv and virtualenv that check for other prefixes
114+
self.assertEqual(sys.prefix, '/usr')
115+
# When building the RPM of Python, %check runs this with RPM_BUILD_ROOT set
116+
# Fedora CI runs this with RPM_BUILD_ROOT unset
117+
self.assertNotIn('RPM_BUILD_ROOT', os.environ)
118+
tested = tested.replace('/usr/local', '/usr')
108119
self.assertEqual(
109-
os.path.normpath(get_path(name, scheme)),
120+
os.path.normpath(tested),
110121
os.path.normpath(expected),
111122
)
112123

@@ -263,7 +274,7 @@ def test_get_config_h_filename(self):
263274
self.assertTrue(os.path.isfile(config_h), config_h)
264275

265276
def test_get_scheme_names(self):
266-
wanted = ['nt', 'posix_home', 'posix_prefix']
277+
wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix', 'venv']
267278
if HAS_USER_BASE:
268279
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
269280
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -274,6 +285,8 @@ def test_symlink(self): # Issue 7880
274285
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
275286
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
276287

288+
@unittest.skipIf('RPM_BUILD_ROOT' not in os.environ,
289+
"Test doesn't expect Fedora's paths")
277290
def test_user_similar(self):
278291
# Issue #8759: make sure the posix scheme for the users
279292
# is similar to the global posix_prefix one

0 commit comments

Comments
 (0)