#85 Fedora < 36 only: Instruct pypa/distutils to add /local/ addition to prefix
Merged 2 years ago by churchyard. Opened 2 years ago by churchyard.
rpms/ churchyard/python3.10 f35-pip-force-distutils-local-setuptools  into  f35

@@ -2,41 +2,53 @@ 

  From: Michal Cyprian <m.cyprian@gmail.com>

  Date: Mon, 26 Jun 2017 16:32:56 +0200

  Subject: [PATCH] 00251: Change user install location

+ MIME-Version: 1.0

+ Content-Type: text/plain; charset=UTF-8

+ Content-Transfer-Encoding: 8bit

  

  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 pip and distutils install into separate location.

  

  Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe

- Downstream only: Awaiting resources to work on upstream PEP

+ Downstream only: Reworked in Fedora 36+ to follow https://bugs.python.org/issue43976

+ 

+ pypa/distutils integration: https://github.com/pypa/distutils/pull/70

+ 

+ Also set sysconfig._PIP_USE_SYSCONFIG = False, to force pip-upgraded-pip

+ to respect this patched distutils install command.

+ See https://bugzilla.redhat.com/show_bug.cgi?id=2014513

+ 

+ Co-authored-by: Miro Hrončok <miro@hroncok.cz>

  ---

-  Lib/distutils/command/install.py | 15 +++++++++++++--

+  Lib/distutils/command/install.py |  8 ++++++--

   Lib/site.py                      |  9 ++++++++-

-  2 files changed, 21 insertions(+), 3 deletions(-)

+  Lib/sysconfig.py                 | 16 ++++++++++++++++

+  3 files changed, 30 insertions(+), 3 deletions(-)

  

  diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py

- index 26696cfb9d..1826cbcb38 100644

+ index 01d5331a63..79f70f0de4 100644

  --- a/Lib/distutils/command/install.py

  +++ b/Lib/distutils/command/install.py

- @@ -441,8 +441,19 @@ def finalize_unix(self):

+ @@ -159,6 +159,8 @@ class install(Command):

+  

+      negative_opt = {'no-compile' : 'compile'}

+  

+ +    # Allow Fedora to add components to the prefix

+ +    _prefix_addition = getattr(sysconfig, '_prefix_addition', '')

_prefix_addition = getattr(sysconfig, '_prefix_addition', '')

Our patch is different from the upstream implementation:

_prefix_addition = getattr(sysconfig, '_prefix_addition', "")

Maybe we should contribute our improvement? Upstream first? :smile:

+  

+      def initialize_options(self):

+          """Initializes options."""

+ @@ -441,8 +443,10 @@ def finalize_unix(self):

                       raise DistutilsOptionError(

                             "must not supply exec-prefix without prefix")

   

  -                self.prefix = os.path.normpath(sys.prefix)

  -                self.exec_prefix = os.path.normpath(sys.exec_prefix)

- +                # self.prefix is set to sys.prefix + /local/

- +                # if neither RPM build nor virtual environment is

- +                # detected to make pip and distutils install packages

- +                # into the separate location.

- +                if (not (hasattr(sys, 'real_prefix') or

- +                    sys.prefix != sys.base_prefix) and

- +                    'RPM_BUILD_ROOT' not in os.environ):

- +                    addition = "/local"

- +                else:

- +                    addition = ""

- +

- +                self.prefix = os.path.normpath(sys.prefix) + addition

- +                self.exec_prefix = os.path.normpath(sys.exec_prefix) + addition

+ +                self.prefix = (

+ +                    os.path.normpath(sys.prefix) + self._prefix_addition)

+ +                self.exec_prefix = (

+ +                    os.path.normpath(sys.exec_prefix) + self._prefix_addition)

   

               else:

                   if self.exec_prefix is None:
@@ -61,3 +73,30 @@ 

       for sitedir in getsitepackages(prefixes):

           if os.path.isdir(sitedir):

               addsitedir(sitedir, known_paths)

+ diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py

+ index daf9f00006..b88f9a9de0 100644

+ --- a/Lib/sysconfig.py

+ +++ b/Lib/sysconfig.py

+ @@ -58,6 +58,22 @@

+          },

+      }

+  

+ +# Force pip to use distutils paths instead of sysconfig

+ +# https://github.com/pypa/pip/issues/10647

+ +_PIP_USE_SYSCONFIG = False

+ +

+ +# This is used by distutils.command.install in the stdlib

+ +# as well as pypa/distutils (e.g. bundled in setuptools).

+ +# The self.prefix value is set to sys.prefix + /local/

+ +# if neither RPM build nor virtual environment is

+ +# detected to make distutils install packages

+ +# into the separate location.

+ +# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe

+ +if (not (hasattr(sys, 'real_prefix') or

+ +    sys.prefix != sys.base_prefix) and

+ +    'RPM_BUILD_ROOT' not in os.environ):

+ +    _prefix_addition = "/local"

_prefix_addition = "/local"

Thinking out loud: Is it worth defining the variable as empty in an else branch? Defensive programming, in case someone grabs it somewhere without a default parameter? Probably too paranoid.

+ +

+  

+  # NOTE: site.py has copy of this function.

+  # Sync it when modify this function.

file modified
+14 -3
@@ -17,7 +17,7 @@ 

  #global prerel ...

  %global upstream_version %{general_version}%{?prerel}

  Version: %{general_version}%{?prerel:~%{prerel}}

- Release: 1%{?dist}

+ Release: 2%{?dist}

  License: Python

  

  
@@ -267,7 +267,7 @@ 

  # Was Patch0 in ivazquez' python3000 specfile

  Patch1: 00001-rpath.patch

  

- # 00251 # 5c445123f04d96be42a35eef5119378ba1713a96

+ # 00251 # 08a62456431df182dfad18ad75838f769aca2d08

  # Change user install location

  #

  # Set values of prefix and exec_prefix in distutils install command
@@ -275,7 +275,13 @@ 

  # is not detected to make pip and distutils install into separate location.

  #

  # Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe

- # Downstream only: Awaiting resources to work on upstream PEP

+ # Downstream only: Reworked in Fedora 36+ to follow https://bugs.python.org/issue43976

+ #

+ # pypa/distutils integration: https://github.com/pypa/distutils/pull/70

+ #

+ # Also set sysconfig._PIP_USE_SYSCONFIG = False, to force pip-upgraded-pip

+ # to respect this patched distutils install command.

+ # See https://bugzilla.redhat.com/show_bug.cgi?id=2014513

  Patch251: 00251-change-user-install-location.patch

  

  # 00328 # 318e500c98f5e59eb1f23e0fcd32db69b9bd17e1
@@ -1592,6 +1598,11 @@ 

  # ======================================================

  

  %changelog

+ * Thu Dec 09 2021 Miro Hrončok <mhroncok@redhat.com> - 3.10.1-2

+ - Instruct pip to use distutils

+ - Instruct pypa/distutils to add /local/ addition to prefix

+ - Fixes rhbz#2014513

+ 

  * Tue Dec 07 2021 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.10.1-1

  - Update to 3.10.1

  

Build succeeded.

rebased onto b7b2fa4

2 years ago

Build succeeded.

WRT pip, the change has not yet reached a release, so using git main-HEAD tarball.

Before (as root):

# rpm -q python3-libs
python3-libs-3.10.0-1.fc35.x86_64

# pip install -U https://github.com/pypa/pip/archive/refs/heads/main.zip
...
Successfully installed pip-22.0.dev0

# pip install pello
...
Successfully installed pello-1.0.2

# pip uninstall pello
...
Found existing installation: Pello 1.0.2
Uninstalling Pello-1.0.2:
  Would remove:
    /usr/bin/pello_greeting
    /usr/lib/python3.10/site-packages/Pello-1.0.2.dist-info/*
    /usr/lib/python3.10/site-packages/pello/*
Proceed (Y/n)? 

After (also as root):

# rpm -q python3-libs
python3-libs-3.10.1-2.fc35.x86_64

# pip install -U https://github.com/pypa/pip/archive/refs/heads/main.zip
...
Successfully installed pip-22.0.dev0

# pip install pello
...
Successfully installed pello-1.0.2

# pip uninstall pello
...
Found existing installation: Pello 1.0.2
Uninstalling Pello-1.0.2:
  Would remove:
    /usr/local/bin/pello_greeting
    /usr/local/lib/python3.10/site-packages/Pello-1.0.2.dist-info/*
    /usr/local/lib/python3.10/site-packages/pello/*
Proceed (Y/n)? 

So, it works.

setuptools already released the change, so using latest setuptools from pypi.

Before (as root):

# rpm -q python3-libs
python3-libs-3.10.0-1.fc35.x86_64

# pip install -U setuptools
...
Successfully installed setuptools-59.6.0

# git clone https://github.com/fedora-python/Pello
...
# cd Pello/
# export SETUPTOOLS_USE_DISTUTILS=local
# python3 setup.py install
...
creating /usr/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg
Extracting Pello-1.0.2-py3.10.egg to /usr/lib/python3.10/site-packages
byte-compiling /usr/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/__init__.py to __init__.cpython-310.pyc
byte-compiling /usr/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/__main__.py to __main__.cpython-310.pyc
byte-compiling /usr/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/pello_greeting.py to pello_greeting.cpython-310.pyc
...

# pip uninstall Pello
Found existing installation: Pello 1.0.2
Uninstalling Pello-1.0.2:
  Would remove:
    /usr/bin/pello_greeting
    /usr/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg
Proceed (Y/n)? 

After (also as root):

# rpm -q python3-libs
python3-libs-3.10.1-2.fc35.x86_64

# pip install -U setuptools
...
Successfully installed setuptools-59.6.0

# git clone https://github.com/fedora-python/Pello
...
# cd Pello/
# export SETUPTOOLS_USE_DISTUTILS=local
# python3 setup.py install
...
creating /usr/local/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg
Extracting Pello-1.0.2-py3.10.egg to /usr/local/lib/python3.10/site-packages
byte-compiling /usr/local/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/__init__.py to __init__.cpython-310.pyc
byte-compiling /usr/local/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/__main__.py to __main__.cpython-310.pyc
byte-compiling /usr/local/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg/pello/pello_greeting.py to pello_greeting.cpython-310.pyc
...

# pip uninstall Pello
...
Found existing installation: Pello 1.0.2
Uninstalling Pello-1.0.2:
  Would remove:
    /usr/local/lib/python3.10/site-packages/Pello-1.0.2-py3.10.egg
Proceed (Y/n)? 

So from my perspective, this works.

_prefix_addition = getattr(sysconfig, '_prefix_addition', '')

Our patch is different from the upstream implementation:

_prefix_addition = getattr(sysconfig, '_prefix_addition', "")

Maybe we should contribute our improvement? Upstream first? :smile:

_prefix_addition = "/local"

Thinking out loud: Is it worth defining the variable as empty in an else branch? Defensive programming, in case someone grabs it somewhere without a default parameter? Probably too paranoid.

The code is spotless, the logic is sound, testing checks out, I can't find any problem with this. Good work.

I've only read the patch, but I haven't found an issue.

Setuptools released the change, I'm shipping this.

https://setuptools.pypa.io/en/latest/history.html#v60-0-0

Setuptools once again makes its local copy of distutils the default. To override, set SETUPTOOLS_USE_DISTUTILS=stdlib.

Pull-Request has been merged by churchyard

2 years ago