Fix Backend
This commit is contained in:
parent
a7153e5e8d
commit
939173f161
|
@ -0,0 +1 @@
|
||||||
|
/Env
|
|
@ -1,222 +0,0 @@
|
||||||
# don't import any costly modules
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
is_pypy = '__pypy__' in sys.builtin_module_names
|
|
||||||
|
|
||||||
|
|
||||||
def warn_distutils_present():
|
|
||||||
if 'distutils' not in sys.modules:
|
|
||||||
return
|
|
||||||
if is_pypy and sys.version_info < (3, 7):
|
|
||||||
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
|
|
||||||
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
|
|
||||||
return
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
warnings.warn(
|
|
||||||
"Distutils was imported before Setuptools, but importing Setuptools "
|
|
||||||
"also replaces the `distutils` module in `sys.modules`. This may lead "
|
|
||||||
"to undesirable behaviors or errors. To avoid these issues, avoid "
|
|
||||||
"using distutils directly, ensure that setuptools is installed in the "
|
|
||||||
"traditional way (e.g. not an editable install), and/or make sure "
|
|
||||||
"that setuptools is always imported before distutils."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def clear_distutils():
|
|
||||||
if 'distutils' not in sys.modules:
|
|
||||||
return
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
warnings.warn("Setuptools is replacing distutils.")
|
|
||||||
mods = [
|
|
||||||
name
|
|
||||||
for name in sys.modules
|
|
||||||
if name == "distutils" or name.startswith("distutils.")
|
|
||||||
]
|
|
||||||
for name in mods:
|
|
||||||
del sys.modules[name]
|
|
||||||
|
|
||||||
|
|
||||||
def enabled():
|
|
||||||
"""
|
|
||||||
Allow selection of distutils by environment variable.
|
|
||||||
"""
|
|
||||||
which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local')
|
|
||||||
return which == 'local'
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_local_distutils():
|
|
||||||
import importlib
|
|
||||||
|
|
||||||
clear_distutils()
|
|
||||||
|
|
||||||
# With the DistutilsMetaFinder in place,
|
|
||||||
# perform an import to cause distutils to be
|
|
||||||
# loaded from setuptools._distutils. Ref #2906.
|
|
||||||
with shim():
|
|
||||||
importlib.import_module('distutils')
|
|
||||||
|
|
||||||
# check that submodules load as expected
|
|
||||||
core = importlib.import_module('distutils.core')
|
|
||||||
assert '_distutils' in core.__file__, core.__file__
|
|
||||||
assert 'setuptools._distutils.log' not in sys.modules
|
|
||||||
|
|
||||||
|
|
||||||
def do_override():
|
|
||||||
"""
|
|
||||||
Ensure that the local copy of distutils is preferred over stdlib.
|
|
||||||
|
|
||||||
See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
|
|
||||||
for more motivation.
|
|
||||||
"""
|
|
||||||
if enabled():
|
|
||||||
warn_distutils_present()
|
|
||||||
ensure_local_distutils()
|
|
||||||
|
|
||||||
|
|
||||||
class _TrivialRe:
|
|
||||||
def __init__(self, *patterns):
|
|
||||||
self._patterns = patterns
|
|
||||||
|
|
||||||
def match(self, string):
|
|
||||||
return all(pat in string for pat in self._patterns)
|
|
||||||
|
|
||||||
|
|
||||||
class DistutilsMetaFinder:
|
|
||||||
def find_spec(self, fullname, path, target=None):
|
|
||||||
# optimization: only consider top level modules and those
|
|
||||||
# found in the CPython test suite.
|
|
||||||
if path is not None and not fullname.startswith('test.'):
|
|
||||||
return
|
|
||||||
|
|
||||||
method_name = 'spec_for_{fullname}'.format(**locals())
|
|
||||||
method = getattr(self, method_name, lambda: None)
|
|
||||||
return method()
|
|
||||||
|
|
||||||
def spec_for_distutils(self):
|
|
||||||
if self.is_cpython():
|
|
||||||
return
|
|
||||||
|
|
||||||
import importlib
|
|
||||||
import importlib.abc
|
|
||||||
import importlib.util
|
|
||||||
|
|
||||||
try:
|
|
||||||
mod = importlib.import_module('setuptools._distutils')
|
|
||||||
except Exception:
|
|
||||||
# There are a couple of cases where setuptools._distutils
|
|
||||||
# may not be present:
|
|
||||||
# - An older Setuptools without a local distutils is
|
|
||||||
# taking precedence. Ref #2957.
|
|
||||||
# - Path manipulation during sitecustomize removes
|
|
||||||
# setuptools from the path but only after the hook
|
|
||||||
# has been loaded. Ref #2980.
|
|
||||||
# In either case, fall back to stdlib behavior.
|
|
||||||
return
|
|
||||||
|
|
||||||
class DistutilsLoader(importlib.abc.Loader):
|
|
||||||
def create_module(self, spec):
|
|
||||||
mod.__name__ = 'distutils'
|
|
||||||
return mod
|
|
||||||
|
|
||||||
def exec_module(self, module):
|
|
||||||
pass
|
|
||||||
|
|
||||||
return importlib.util.spec_from_loader(
|
|
||||||
'distutils', DistutilsLoader(), origin=mod.__file__
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_cpython():
|
|
||||||
"""
|
|
||||||
Suppress supplying distutils for CPython (build and tests).
|
|
||||||
Ref #2965 and #3007.
|
|
||||||
"""
|
|
||||||
return os.path.isfile('pybuilddir.txt')
|
|
||||||
|
|
||||||
def spec_for_pip(self):
|
|
||||||
"""
|
|
||||||
Ensure stdlib distutils when running under pip.
|
|
||||||
See pypa/pip#8761 for rationale.
|
|
||||||
"""
|
|
||||||
if self.pip_imported_during_build():
|
|
||||||
return
|
|
||||||
clear_distutils()
|
|
||||||
self.spec_for_distutils = lambda: None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def pip_imported_during_build(cls):
|
|
||||||
"""
|
|
||||||
Detect if pip is being imported in a build script. Ref #2355.
|
|
||||||
"""
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
return any(
|
|
||||||
cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def frame_file_is_setup(frame):
|
|
||||||
"""
|
|
||||||
Return True if the indicated frame suggests a setup.py file.
|
|
||||||
"""
|
|
||||||
# some frames may not have __file__ (#2940)
|
|
||||||
return frame.f_globals.get('__file__', '').endswith('setup.py')
|
|
||||||
|
|
||||||
def spec_for_sensitive_tests(self):
|
|
||||||
"""
|
|
||||||
Ensure stdlib distutils when running select tests under CPython.
|
|
||||||
|
|
||||||
python/cpython#91169
|
|
||||||
"""
|
|
||||||
clear_distutils()
|
|
||||||
self.spec_for_distutils = lambda: None
|
|
||||||
|
|
||||||
sensitive_tests = (
|
|
||||||
[
|
|
||||||
'test.test_distutils',
|
|
||||||
'test.test_peg_generator',
|
|
||||||
'test.test_importlib',
|
|
||||||
]
|
|
||||||
if sys.version_info < (3, 10)
|
|
||||||
else [
|
|
||||||
'test.test_distutils',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
for name in DistutilsMetaFinder.sensitive_tests:
|
|
||||||
setattr(
|
|
||||||
DistutilsMetaFinder,
|
|
||||||
f'spec_for_{name}',
|
|
||||||
DistutilsMetaFinder.spec_for_sensitive_tests,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
DISTUTILS_FINDER = DistutilsMetaFinder()
|
|
||||||
|
|
||||||
|
|
||||||
def add_shim():
|
|
||||||
DISTUTILS_FINDER in sys.meta_path or insert_shim()
|
|
||||||
|
|
||||||
|
|
||||||
class shim:
|
|
||||||
def __enter__(self):
|
|
||||||
insert_shim()
|
|
||||||
|
|
||||||
def __exit__(self, exc, value, tb):
|
|
||||||
remove_shim()
|
|
||||||
|
|
||||||
|
|
||||||
def insert_shim():
|
|
||||||
sys.meta_path.insert(0, DISTUTILS_FINDER)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_shim():
|
|
||||||
try:
|
|
||||||
sys.meta_path.remove(DISTUTILS_FINDER)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
__import__('_distutils_hack').do_override()
|
|
|
@ -1 +0,0 @@
|
||||||
import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim();
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@ Albert-Guan
|
||||||
albertg
|
albertg
|
||||||
Alberto Sottile
|
Alberto Sottile
|
||||||
Aleks Bunin
|
Aleks Bunin
|
||||||
|
Ales Erjavec
|
||||||
Alethea Flowers
|
Alethea Flowers
|
||||||
Alex Gaynor
|
Alex Gaynor
|
||||||
Alex Grönholm
|
Alex Grönholm
|
||||||
|
@ -30,6 +31,7 @@ Alex Stachowiak
|
||||||
Alexander Shtyrov
|
Alexander Shtyrov
|
||||||
Alexandre Conrad
|
Alexandre Conrad
|
||||||
Alexey Popravka
|
Alexey Popravka
|
||||||
|
Aleš Erjavec
|
||||||
Alli
|
Alli
|
||||||
Ami Fischman
|
Ami Fischman
|
||||||
Ananya Maiti
|
Ananya Maiti
|
||||||
|
@ -71,6 +73,7 @@ atse
|
||||||
Atsushi Odagiri
|
Atsushi Odagiri
|
||||||
Avinash Karhana
|
Avinash Karhana
|
||||||
Avner Cohen
|
Avner Cohen
|
||||||
|
Awit (Ah-Wit) Ghirmai
|
||||||
Baptiste Mispelon
|
Baptiste Mispelon
|
||||||
Barney Gale
|
Barney Gale
|
||||||
barneygale
|
barneygale
|
||||||
|
@ -126,6 +129,7 @@ Chih-Hsuan Yen
|
||||||
Chris Brinker
|
Chris Brinker
|
||||||
Chris Hunt
|
Chris Hunt
|
||||||
Chris Jerdonek
|
Chris Jerdonek
|
||||||
|
Chris Kuehl
|
||||||
Chris McDonough
|
Chris McDonough
|
||||||
Chris Pawley
|
Chris Pawley
|
||||||
Chris Pryer
|
Chris Pryer
|
||||||
|
@ -156,6 +160,7 @@ Cristina Muñoz
|
||||||
Curtis Doty
|
Curtis Doty
|
||||||
cytolentino
|
cytolentino
|
||||||
Daan De Meyer
|
Daan De Meyer
|
||||||
|
Dale
|
||||||
Damian
|
Damian
|
||||||
Damian Quiroga
|
Damian Quiroga
|
||||||
Damian Shaw
|
Damian Shaw
|
||||||
|
@ -194,9 +199,11 @@ David Runge
|
||||||
David Tucker
|
David Tucker
|
||||||
David Wales
|
David Wales
|
||||||
Davidovich
|
Davidovich
|
||||||
|
ddelange
|
||||||
Deepak Sharma
|
Deepak Sharma
|
||||||
Deepyaman Datta
|
Deepyaman Datta
|
||||||
Denise Yu
|
Denise Yu
|
||||||
|
dependabot[bot]
|
||||||
derwolfe
|
derwolfe
|
||||||
Desetude
|
Desetude
|
||||||
Devesh Kumar Singh
|
Devesh Kumar Singh
|
||||||
|
@ -220,7 +227,10 @@ Dustin Ingram
|
||||||
Dwayne Bailey
|
Dwayne Bailey
|
||||||
Ed Morley
|
Ed Morley
|
||||||
Edgar Ramírez
|
Edgar Ramírez
|
||||||
|
Edgar Ramírez Mondragón
|
||||||
Ee Durbin
|
Ee Durbin
|
||||||
|
Efflam Lemaillet
|
||||||
|
efflamlemaillet
|
||||||
Eitan Adler
|
Eitan Adler
|
||||||
ekristina
|
ekristina
|
||||||
elainechan
|
elainechan
|
||||||
|
@ -250,6 +260,7 @@ Filip Kokosiński
|
||||||
Filipe Laíns
|
Filipe Laíns
|
||||||
Finn Womack
|
Finn Womack
|
||||||
finnagin
|
finnagin
|
||||||
|
Flavio Amurrio
|
||||||
Florian Briand
|
Florian Briand
|
||||||
Florian Rathgeber
|
Florian Rathgeber
|
||||||
Francesco
|
Francesco
|
||||||
|
@ -310,7 +321,9 @@ Ilya Baryshev
|
||||||
Inada Naoki
|
Inada Naoki
|
||||||
Ionel Cristian Mărieș
|
Ionel Cristian Mărieș
|
||||||
Ionel Maries Cristian
|
Ionel Maries Cristian
|
||||||
|
Itamar Turner-Trauring
|
||||||
Ivan Pozdeev
|
Ivan Pozdeev
|
||||||
|
J. Nick Koston
|
||||||
Jacob Kim
|
Jacob Kim
|
||||||
Jacob Walls
|
Jacob Walls
|
||||||
Jaime Sanz
|
Jaime Sanz
|
||||||
|
@ -330,10 +343,14 @@ Jarek Potiuk
|
||||||
jarondl
|
jarondl
|
||||||
Jason Curtis
|
Jason Curtis
|
||||||
Jason R. Coombs
|
Jason R. Coombs
|
||||||
|
JasonMo
|
||||||
|
JasonMo1
|
||||||
Jay Graves
|
Jay Graves
|
||||||
|
Jean Abou Samra
|
||||||
Jean-Christophe Fillion-Robin
|
Jean-Christophe Fillion-Robin
|
||||||
Jeff Barber
|
Jeff Barber
|
||||||
Jeff Dairiki
|
Jeff Dairiki
|
||||||
|
Jeff Widman
|
||||||
Jelmer Vernooij
|
Jelmer Vernooij
|
||||||
jenix21
|
jenix21
|
||||||
Jeremy Stanley
|
Jeremy Stanley
|
||||||
|
@ -344,6 +361,7 @@ Jim Fisher
|
||||||
Jim Garrison
|
Jim Garrison
|
||||||
Jiun Bae
|
Jiun Bae
|
||||||
Jivan Amara
|
Jivan Amara
|
||||||
|
Joe Bylund
|
||||||
Joe Michelini
|
Joe Michelini
|
||||||
John Paton
|
John Paton
|
||||||
John T. Wodder II
|
John T. Wodder II
|
||||||
|
@ -362,6 +380,7 @@ Joseph Long
|
||||||
Josh Bronson
|
Josh Bronson
|
||||||
Josh Hansen
|
Josh Hansen
|
||||||
Josh Schneier
|
Josh Schneier
|
||||||
|
Joshua
|
||||||
Juan Luis Cano Rodríguez
|
Juan Luis Cano Rodríguez
|
||||||
Juanjo Bazán
|
Juanjo Bazán
|
||||||
Judah Rand
|
Judah Rand
|
||||||
|
@ -392,6 +411,7 @@ KOLANICH
|
||||||
kpinc
|
kpinc
|
||||||
Krishna Oza
|
Krishna Oza
|
||||||
Kumar McMillan
|
Kumar McMillan
|
||||||
|
Kurt McKee
|
||||||
Kyle Persohn
|
Kyle Persohn
|
||||||
lakshmanaram
|
lakshmanaram
|
||||||
Laszlo Kiss-Kollar
|
Laszlo Kiss-Kollar
|
||||||
|
@ -408,6 +428,7 @@ lorddavidiii
|
||||||
Loren Carvalho
|
Loren Carvalho
|
||||||
Lucas Cimon
|
Lucas Cimon
|
||||||
Ludovic Gasc
|
Ludovic Gasc
|
||||||
|
Lukas Geiger
|
||||||
Lukas Juhrich
|
Lukas Juhrich
|
||||||
Luke Macken
|
Luke Macken
|
||||||
Luo Jiebin
|
Luo Jiebin
|
||||||
|
@ -441,6 +462,7 @@ Matthew Einhorn
|
||||||
Matthew Feickert
|
Matthew Feickert
|
||||||
Matthew Gilliard
|
Matthew Gilliard
|
||||||
Matthew Iversen
|
Matthew Iversen
|
||||||
|
Matthew Treinish
|
||||||
Matthew Trumbell
|
Matthew Trumbell
|
||||||
Matthew Willson
|
Matthew Willson
|
||||||
Matthias Bussonnier
|
Matthias Bussonnier
|
||||||
|
@ -523,6 +545,7 @@ Patrick Jenkins
|
||||||
Patrick Lawson
|
Patrick Lawson
|
||||||
patricktokeeffe
|
patricktokeeffe
|
||||||
Patrik Kopkan
|
Patrik Kopkan
|
||||||
|
Paul Ganssle
|
||||||
Paul Kehrer
|
Paul Kehrer
|
||||||
Paul Moore
|
Paul Moore
|
||||||
Paul Nasrat
|
Paul Nasrat
|
||||||
|
@ -563,6 +586,7 @@ Przemek Wrzos
|
||||||
Pulkit Goyal
|
Pulkit Goyal
|
||||||
q0w
|
q0w
|
||||||
Qiangning Hong
|
Qiangning Hong
|
||||||
|
Qiming Xu
|
||||||
Quentin Lee
|
Quentin Lee
|
||||||
Quentin Pradet
|
Quentin Pradet
|
||||||
R. David Murray
|
R. David Murray
|
||||||
|
@ -582,6 +606,7 @@ Rishi
|
||||||
RobberPhex
|
RobberPhex
|
||||||
Robert Collins
|
Robert Collins
|
||||||
Robert McGibbon
|
Robert McGibbon
|
||||||
|
Robert Pollak
|
||||||
Robert T. McGibbon
|
Robert T. McGibbon
|
||||||
robin elisha robinson
|
robin elisha robinson
|
||||||
Roey Berman
|
Roey Berman
|
||||||
|
@ -602,6 +627,7 @@ ryneeverett
|
||||||
Sachi King
|
Sachi King
|
||||||
Salvatore Rinchiera
|
Salvatore Rinchiera
|
||||||
sandeepkiran-js
|
sandeepkiran-js
|
||||||
|
Sander Van Balen
|
||||||
Savio Jomton
|
Savio Jomton
|
||||||
schlamar
|
schlamar
|
||||||
Scott Kitterman
|
Scott Kitterman
|
||||||
|
@ -614,6 +640,8 @@ SeongSoo Cho
|
||||||
Sergey Vasilyev
|
Sergey Vasilyev
|
||||||
Seth Michael Larson
|
Seth Michael Larson
|
||||||
Seth Woodworth
|
Seth Woodworth
|
||||||
|
Shahar Epstein
|
||||||
|
Shantanu
|
||||||
shireenrao
|
shireenrao
|
||||||
Shivansh-007
|
Shivansh-007
|
||||||
Shlomi Fish
|
Shlomi Fish
|
||||||
|
@ -638,7 +666,9 @@ Steve Barnes
|
||||||
Steve Dower
|
Steve Dower
|
||||||
Steve Kowalik
|
Steve Kowalik
|
||||||
Steven Myint
|
Steven Myint
|
||||||
|
Steven Silvester
|
||||||
stonebig
|
stonebig
|
||||||
|
studioj
|
||||||
Stéphane Bidoul
|
Stéphane Bidoul
|
||||||
Stéphane Bidoul (ACSONE)
|
Stéphane Bidoul (ACSONE)
|
||||||
Stéphane Klein
|
Stéphane Klein
|
||||||
|
@ -695,6 +725,7 @@ Vincent Philippon
|
||||||
Vinicyus Macedo
|
Vinicyus Macedo
|
||||||
Vipul Kumar
|
Vipul Kumar
|
||||||
Vitaly Babiy
|
Vitaly Babiy
|
||||||
|
Vladimir Fokow
|
||||||
Vladimir Rutsky
|
Vladimir Rutsky
|
||||||
W. Trevor King
|
W. Trevor King
|
||||||
Wil Tan
|
Wil Tan
|
||||||
|
@ -707,6 +738,7 @@ Wilson Mo
|
||||||
wim glenn
|
wim glenn
|
||||||
Winson Luk
|
Winson Luk
|
||||||
Wolfgang Maier
|
Wolfgang Maier
|
||||||
|
Wu Zhenyu
|
||||||
XAMES3
|
XAMES3
|
||||||
Xavier Fernandez
|
Xavier Fernandez
|
||||||
xoviat
|
xoviat
|
|
@ -1,11 +1,10 @@
|
||||||
Metadata-Version: 2.1
|
Metadata-Version: 2.1
|
||||||
Name: pip
|
Name: pip
|
||||||
Version: 23.1.2
|
Version: 24.0
|
||||||
Summary: The PyPA recommended tool for installing Python packages.
|
Summary: The PyPA recommended tool for installing Python packages.
|
||||||
Home-page: https://pip.pypa.io/
|
Author-email: The pip developers <distutils-sig@python.org>
|
||||||
Author: The pip developers
|
|
||||||
Author-email: distutils-sig@python.org
|
|
||||||
License: MIT
|
License: MIT
|
||||||
|
Project-URL: Homepage, https://pip.pypa.io/
|
||||||
Project-URL: Documentation, https://pip.pypa.io
|
Project-URL: Documentation, https://pip.pypa.io
|
||||||
Project-URL: Source, https://github.com/pypa/pip
|
Project-URL: Source, https://github.com/pypa/pip
|
||||||
Project-URL: Changelog, https://pip.pypa.io/en/stable/news/
|
Project-URL: Changelog, https://pip.pypa.io/en/stable/news/
|
||||||
|
@ -21,9 +20,11 @@ Classifier: Programming Language :: Python :: 3.8
|
||||||
Classifier: Programming Language :: Python :: 3.9
|
Classifier: Programming Language :: Python :: 3.9
|
||||||
Classifier: Programming Language :: Python :: 3.10
|
Classifier: Programming Language :: Python :: 3.10
|
||||||
Classifier: Programming Language :: Python :: 3.11
|
Classifier: Programming Language :: Python :: 3.11
|
||||||
|
Classifier: Programming Language :: Python :: 3.12
|
||||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
Requires-Python: >=3.7
|
Requires-Python: >=3.7
|
||||||
|
Description-Content-Type: text/x-rst
|
||||||
License-File: LICENSE.txt
|
License-File: LICENSE.txt
|
||||||
License-File: AUTHORS.txt
|
License-File: AUTHORS.txt
|
||||||
|
|
||||||
|
@ -32,9 +33,15 @@ pip - The Python Package Installer
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/pip.svg
|
.. image:: https://img.shields.io/pypi/v/pip.svg
|
||||||
:target: https://pypi.org/project/pip/
|
:target: https://pypi.org/project/pip/
|
||||||
|
:alt: PyPI
|
||||||
|
|
||||||
|
.. image:: https://img.shields.io/pypi/pyversions/pip
|
||||||
|
:target: https://pypi.org/project/pip
|
||||||
|
:alt: PyPI - Python Version
|
||||||
|
|
||||||
.. image:: https://readthedocs.org/projects/pip/badge/?version=latest
|
.. image:: https://readthedocs.org/projects/pip/badge/?version=latest
|
||||||
:target: https://pip.pypa.io/en/latest
|
:target: https://pip.pypa.io/en/latest
|
||||||
|
:alt: Documentation
|
||||||
|
|
||||||
pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
|
pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
|
||||||
|
|
||||||
|
@ -48,10 +55,6 @@ We release updates regularly, with a new version every 3 months. Find more detai
|
||||||
* `Release notes`_
|
* `Release notes`_
|
||||||
* `Release process`_
|
* `Release process`_
|
||||||
|
|
||||||
In pip 20.3, we've `made a big improvement to the heart of pip`_; `learn more`_. We want your input, so `sign up for our user experience research studies`_ to help us do it right.
|
|
||||||
|
|
||||||
**Note**: pip 21.0, in January 2021, removed Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3.
|
|
||||||
|
|
||||||
If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:
|
If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:
|
||||||
|
|
||||||
* `Issue tracking`_
|
* `Issue tracking`_
|
||||||
|
@ -78,10 +81,6 @@ rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.
|
||||||
.. _Release process: https://pip.pypa.io/en/latest/development/release-process/
|
.. _Release process: https://pip.pypa.io/en/latest/development/release-process/
|
||||||
.. _GitHub page: https://github.com/pypa/pip
|
.. _GitHub page: https://github.com/pypa/pip
|
||||||
.. _Development documentation: https://pip.pypa.io/en/latest/development
|
.. _Development documentation: https://pip.pypa.io/en/latest/development
|
||||||
.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html
|
|
||||||
.. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020
|
|
||||||
.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html
|
|
||||||
.. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support
|
|
||||||
.. _Issue tracking: https://github.com/pypa/pip/issues
|
.. _Issue tracking: https://github.com/pypa/pip/issues
|
||||||
.. _Discourse channel: https://discuss.python.org/c/packaging
|
.. _Discourse channel: https://discuss.python.org/c/packaging
|
||||||
.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
|
.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
Wheel-Version: 1.0
|
Wheel-Version: 1.0
|
||||||
Generator: bdist_wheel (0.37.1)
|
Generator: bdist_wheel (0.42.0)
|
||||||
Root-Is-Purelib: true
|
Root-Is-Purelib: true
|
||||||
Tag: py3-none-any
|
Tag: py3-none-any
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
__version__ = "23.1.2"
|
__version__ = "24.0"
|
||||||
|
|
||||||
|
|
||||||
def main(args: Optional[List[str]] = None) -> int:
|
def main(args: Optional[List[str]] = None) -> int:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
|
|
||||||
# Remove '' and current working directory from the first entry
|
# Remove '' and current working directory from the first entry
|
||||||
# of sys.path, if present to avoid using current directory
|
# of sys.path, if present to avoid using current directory
|
||||||
|
@ -20,12 +19,6 @@ if __package__ == "":
|
||||||
sys.path.insert(0, path)
|
sys.path.insert(0, path)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Work around the error reported in #9540, pending a proper fix.
|
|
||||||
# Note: It is essential the warning filter is set *before* importing
|
|
||||||
# pip, as the deprecation happens at import time, not runtime.
|
|
||||||
warnings.filterwarnings(
|
|
||||||
"ignore", category=DeprecationWarning, module=".*packaging\\.version"
|
|
||||||
)
|
|
||||||
from pip._internal.cli.main import main as _main
|
from pip._internal.cli.main import main as _main
|
||||||
|
|
||||||
sys.exit(_main())
|
sys.exit(_main())
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
import pip._internal.utils.inject_securetransport # noqa
|
|
||||||
from pip._internal.utils import _log
|
from pip._internal.utils import _log
|
||||||
|
|
||||||
# init_logging() must be called before any call to logging.getLogger()
|
# init_logging() must be called before any call to logging.getLogger()
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -78,12 +78,10 @@ class Cache:
|
||||||
if can_not_cache:
|
if can_not_cache:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
candidates = []
|
|
||||||
path = self.get_path_for_link(link)
|
path = self.get_path_for_link(link)
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
for candidate in os.listdir(path):
|
return [(candidate, path) for candidate in os.listdir(path)]
|
||||||
candidates.append((candidate, path))
|
return []
|
||||||
return candidates
|
|
||||||
|
|
||||||
def get_path_for_link(self, link: Link) -> str:
|
def get_path_for_link(self, link: Link) -> str:
|
||||||
"""Return a directory to store cached items in for link."""
|
"""Return a directory to store cached items in for link."""
|
||||||
|
@ -194,7 +192,17 @@ class CacheEntry:
|
||||||
self.origin: Optional[DirectUrl] = None
|
self.origin: Optional[DirectUrl] = None
|
||||||
origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME
|
origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME
|
||||||
if origin_direct_url_path.exists():
|
if origin_direct_url_path.exists():
|
||||||
self.origin = DirectUrl.from_json(origin_direct_url_path.read_text())
|
try:
|
||||||
|
self.origin = DirectUrl.from_json(
|
||||||
|
origin_direct_url_path.read_text(encoding="utf-8")
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(
|
||||||
|
"Ignoring invalid cache entry origin file %s for %s (%s)",
|
||||||
|
origin_direct_url_path,
|
||||||
|
link.filename,
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WheelCache(Cache):
|
class WheelCache(Cache):
|
||||||
|
@ -257,16 +265,26 @@ class WheelCache(Cache):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None:
|
def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None:
|
||||||
origin_path = Path(cache_dir) / ORIGIN_JSON_NAME
|
origin_path = Path(cache_dir) / ORIGIN_JSON_NAME
|
||||||
if origin_path.is_file():
|
if origin_path.exists():
|
||||||
origin = DirectUrl.from_json(origin_path.read_text())
|
try:
|
||||||
# TODO: use DirectUrl.equivalent when https://github.com/pypa/pip/pull/10564
|
origin = DirectUrl.from_json(origin_path.read_text(encoding="utf-8"))
|
||||||
# is merged.
|
except Exception as e:
|
||||||
if origin.url != download_info.url:
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Origin URL %s in cache entry %s does not match download URL %s. "
|
"Could not read origin file %s in cache entry (%s). "
|
||||||
"This is likely a pip bug or a cache corruption issue.",
|
"Will attempt to overwrite it.",
|
||||||
origin.url,
|
origin_path,
|
||||||
cache_dir,
|
e,
|
||||||
download_info.url,
|
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
# TODO: use DirectUrl.equivalent when
|
||||||
|
# https://github.com/pypa/pip/pull/10564 is merged.
|
||||||
|
if origin.url != download_info.url:
|
||||||
|
logger.warning(
|
||||||
|
"Origin URL %s in cache entry %s does not match download URL "
|
||||||
|
"%s. This is likely a pip bug or a cache corruption issue. "
|
||||||
|
"Will overwrite it with the new value.",
|
||||||
|
origin.url,
|
||||||
|
cache_dir,
|
||||||
|
download_info.url,
|
||||||
|
)
|
||||||
origin_path.write_text(download_info.to_json(), encoding="utf-8")
|
origin_path.write_text(download_info.to_json(), encoding="utf-8")
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -71,8 +71,9 @@ def autocomplete() -> None:
|
||||||
|
|
||||||
for opt in subcommand.parser.option_list_all:
|
for opt in subcommand.parser.option_list_all:
|
||||||
if opt.help != optparse.SUPPRESS_HELP:
|
if opt.help != optparse.SUPPRESS_HELP:
|
||||||
for opt_str in opt._long_opts + opt._short_opts:
|
options += [
|
||||||
options.append((opt_str, opt.nargs))
|
(opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts
|
||||||
|
]
|
||||||
|
|
||||||
# filter out previously specified options from available options
|
# filter out previously specified options from available options
|
||||||
prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]]
|
prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]]
|
||||||
|
|
|
@ -131,6 +131,17 @@ class Command(CommandContextMixIn):
|
||||||
", ".join(sorted(always_enabled_features)),
|
", ".join(sorted(always_enabled_features)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Make sure that the --python argument isn't specified after the
|
||||||
|
# subcommand. We can tell, because if --python was specified,
|
||||||
|
# we should only reach this point if we're running in the created
|
||||||
|
# subprocess, which has the _PIP_RUNNING_IN_SUBPROCESS environment
|
||||||
|
# variable set.
|
||||||
|
if options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ:
|
||||||
|
logger.critical(
|
||||||
|
"The --python option must be placed before the pip subcommand name"
|
||||||
|
)
|
||||||
|
sys.exit(ERROR)
|
||||||
|
|
||||||
# TODO: Try to get these passing down from the command?
|
# TODO: Try to get these passing down from the command?
|
||||||
# without resorting to os.environ to hold these.
|
# without resorting to os.environ to hold these.
|
||||||
# This also affects isolated builds and it should.
|
# This also affects isolated builds and it should.
|
||||||
|
@ -170,7 +181,7 @@ class Command(CommandContextMixIn):
|
||||||
assert isinstance(status, int)
|
assert isinstance(status, int)
|
||||||
return status
|
return status
|
||||||
except DiagnosticPipError as exc:
|
except DiagnosticPipError as exc:
|
||||||
logger.error("[present-rich] %s", exc)
|
logger.error("%s", exc, extra={"rich": True})
|
||||||
logger.debug("Exception information:", exc_info=True)
|
logger.debug("Exception information:", exc_info=True)
|
||||||
|
|
||||||
return ERROR
|
return ERROR
|
||||||
|
|
|
@ -92,10 +92,10 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
if check_target:
|
if check_target:
|
||||||
if dist_restriction_set and not options.target_dir:
|
if not options.dry_run and dist_restriction_set and not options.target_dir:
|
||||||
raise CommandError(
|
raise CommandError(
|
||||||
"Can not use any platform or abi specific options unless "
|
"Can not use any platform or abi specific options unless "
|
||||||
"installing via '--target'"
|
"installing via '--target' or using '--dry-run'"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -582,10 +582,7 @@ def _handle_python_version(
|
||||||
"""
|
"""
|
||||||
version_info, error_msg = _convert_python_version(value)
|
version_info, error_msg = _convert_python_version(value)
|
||||||
if error_msg is not None:
|
if error_msg is not None:
|
||||||
msg = "invalid --python-version value: {!r}: {}".format(
|
msg = f"invalid --python-version value: {value!r}: {error_msg}"
|
||||||
value,
|
|
||||||
error_msg,
|
|
||||||
)
|
|
||||||
raise_option_error(parser, option=option, msg=msg)
|
raise_option_error(parser, option=option, msg=msg)
|
||||||
|
|
||||||
parser.values.python_version = version_info
|
parser.values.python_version = version_info
|
||||||
|
@ -670,7 +667,10 @@ def prefer_binary() -> Option:
|
||||||
dest="prefer_binary",
|
dest="prefer_binary",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
default=False,
|
default=False,
|
||||||
help="Prefer older binary packages over newer source packages.",
|
help=(
|
||||||
|
"Prefer binary packages over source packages, even if the "
|
||||||
|
"source packages are newer."
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -823,7 +823,7 @@ def _handle_config_settings(
|
||||||
) -> None:
|
) -> None:
|
||||||
key, sep, val = value.partition("=")
|
key, sep, val = value.partition("=")
|
||||||
if sep != "=":
|
if sep != "=":
|
||||||
parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa
|
parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL")
|
||||||
dest = getattr(parser.values, option.dest)
|
dest = getattr(parser.values, option.dest)
|
||||||
if dest is None:
|
if dest is None:
|
||||||
dest = {}
|
dest = {}
|
||||||
|
@ -918,13 +918,13 @@ def _handle_merge_hash(
|
||||||
algo, digest = value.split(":", 1)
|
algo, digest = value.split(":", 1)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
parser.error(
|
parser.error(
|
||||||
"Arguments to {} must be a hash name " # noqa
|
f"Arguments to {opt_str} must be a hash name "
|
||||||
"followed by a value, like --hash=sha256:"
|
"followed by a value, like --hash=sha256:"
|
||||||
"abcde...".format(opt_str)
|
"abcde..."
|
||||||
)
|
)
|
||||||
if algo not in STRONG_HASHES:
|
if algo not in STRONG_HASHES:
|
||||||
parser.error(
|
parser.error(
|
||||||
"Allowed hash algorithms for {} are {}.".format( # noqa
|
"Allowed hash algorithms for {} are {}.".format(
|
||||||
opt_str, ", ".join(STRONG_HASHES)
|
opt_str, ", ".join(STRONG_HASHES)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -229,9 +229,9 @@ class ConfigOptionParser(CustomOptionParser):
|
||||||
val = strtobool(val)
|
val = strtobool(val)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.error(
|
self.error(
|
||||||
"{} is not a valid value for {} option, " # noqa
|
f"{val} is not a valid value for {key} option, "
|
||||||
"please specify a boolean value like yes/no, "
|
"please specify a boolean value like yes/no, "
|
||||||
"true/false or 1/0 instead.".format(val, key)
|
"true/false or 1/0 instead."
|
||||||
)
|
)
|
||||||
elif option.action == "count":
|
elif option.action == "count":
|
||||||
with suppress(ValueError):
|
with suppress(ValueError):
|
||||||
|
@ -240,10 +240,10 @@ class ConfigOptionParser(CustomOptionParser):
|
||||||
val = int(val)
|
val = int(val)
|
||||||
if not isinstance(val, int) or val < 0:
|
if not isinstance(val, int) or val < 0:
|
||||||
self.error(
|
self.error(
|
||||||
"{} is not a valid value for {} option, " # noqa
|
f"{val} is not a valid value for {key} option, "
|
||||||
"please instead specify either a non-negative integer "
|
"please instead specify either a non-negative integer "
|
||||||
"or a boolean value like yes/no or false/true "
|
"or a boolean value like yes/no or false/true "
|
||||||
"which is equivalent to 1/0.".format(val, key)
|
"which is equivalent to 1/0."
|
||||||
)
|
)
|
||||||
elif option.action == "append":
|
elif option.action == "append":
|
||||||
val = val.split()
|
val = val.split()
|
||||||
|
|
|
@ -58,12 +58,9 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import truststore
|
from pip._vendor import truststore
|
||||||
except ImportError:
|
except ImportError as e:
|
||||||
raise CommandError(
|
raise CommandError(f"The truststore feature is unavailable: {e}")
|
||||||
"To use the truststore feature, 'truststore' must be installed into "
|
|
||||||
"pip's current environment."
|
|
||||||
)
|
|
||||||
|
|
||||||
return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||||
|
|
||||||
|
@ -123,7 +120,7 @@ class SessionCommandMixin(CommandContextMixIn):
|
||||||
ssl_context = None
|
ssl_context = None
|
||||||
|
|
||||||
session = PipSession(
|
session = PipSession(
|
||||||
cache=os.path.join(cache_dir, "http") if cache_dir else None,
|
cache=os.path.join(cache_dir, "http-v2") if cache_dir else None,
|
||||||
retries=retries if retries is not None else options.retries,
|
retries=retries if retries is not None else options.retries,
|
||||||
trusted_hosts=options.trusted_hosts,
|
trusted_hosts=options.trusted_hosts,
|
||||||
index_urls=self._get_index_urls(options),
|
index_urls=self._get_index_urls(options),
|
||||||
|
@ -268,7 +265,7 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
if "legacy-resolver" in options.deprecated_features_enabled:
|
if "legacy-resolver" in options.deprecated_features_enabled:
|
||||||
return "legacy"
|
return "legacy"
|
||||||
|
|
||||||
return "2020-resolver"
|
return "resolvelib"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make_requirement_preparer(
|
def make_requirement_preparer(
|
||||||
|
@ -287,9 +284,10 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
"""
|
"""
|
||||||
temp_build_dir_path = temp_build_dir.path
|
temp_build_dir_path = temp_build_dir.path
|
||||||
assert temp_build_dir_path is not None
|
assert temp_build_dir_path is not None
|
||||||
|
legacy_resolver = False
|
||||||
|
|
||||||
resolver_variant = cls.determine_resolver_variant(options)
|
resolver_variant = cls.determine_resolver_variant(options)
|
||||||
if resolver_variant == "2020-resolver":
|
if resolver_variant == "resolvelib":
|
||||||
lazy_wheel = "fast-deps" in options.features_enabled
|
lazy_wheel = "fast-deps" in options.features_enabled
|
||||||
if lazy_wheel:
|
if lazy_wheel:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -300,6 +298,7 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
"production."
|
"production."
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
legacy_resolver = True
|
||||||
lazy_wheel = False
|
lazy_wheel = False
|
||||||
if "fast-deps" in options.features_enabled:
|
if "fast-deps" in options.features_enabled:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -320,6 +319,7 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
use_user_site=use_user_site,
|
use_user_site=use_user_site,
|
||||||
lazy_wheel=lazy_wheel,
|
lazy_wheel=lazy_wheel,
|
||||||
verbosity=verbosity,
|
verbosity=verbosity,
|
||||||
|
legacy_resolver=legacy_resolver,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -349,7 +349,7 @@ class RequirementCommand(IndexGroupCommand):
|
||||||
# The long import name and duplicated invocation is needed to convince
|
# The long import name and duplicated invocation is needed to convince
|
||||||
# Mypy into correctly typechecking. Otherwise it would complain the
|
# Mypy into correctly typechecking. Otherwise it would complain the
|
||||||
# "Resolver" class being redefined.
|
# "Resolver" class being redefined.
|
||||||
if resolver_variant == "2020-resolver":
|
if resolver_variant == "resolvelib":
|
||||||
import pip._internal.resolution.resolvelib.resolver
|
import pip._internal.resolution.resolvelib.resolver
|
||||||
|
|
||||||
return pip._internal.resolution.resolvelib.resolver.Resolver(
|
return pip._internal.resolution.resolvelib.resolver.Resolver(
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue