Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange sysconfig behaviour for source-compiled Python #10270

Closed
1 task done
danielm-c2a opened this issue Aug 5, 2021 · 17 comments · Fixed by #10503
Closed
1 task done

Strange sysconfig behaviour for source-compiled Python #10270

danielm-c2a opened this issue Aug 5, 2021 · 17 comments · Fixed by #10503
Assignees
Labels
type: bug A confirmed bug or unintended behavior
Milestone

Comments

@danielm-c2a
Copy link

danielm-c2a commented Aug 5, 2021

Description

A special case of #10151

The Python-3.8.2 seems to have a Windows structure despite my working on Linux. I was requested to open a new issue for this.

See: #10151 (comment)

>>> python -m pip install --upgrade opcua-client
WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
distutils: /usr/local/include/python3.8/UNKNOWN
sysconfig: /opt/Python-3.8.2/Include/UNKNOWN
WARNING: Additional context:
user = False
home = None
root = None
prefix = None

Expected behavior

No response

pip version

21.2.2

Python version

3.8.2

OS

Pop!_OS

How to Reproduce

python -m pip install --upgrade opcua-client

Output

/opt/Python-3.8.2
├── Doc
│   ├── c-api
│   ├── data
│   ├── distributing
│   ├── distutils
│   ├── extending
│   ├── faq
│   ├── howto
│   ├── includes
│   │   └── sqlite3
│   ├── install
│   ├── installing
│   ├── library
│   ├── reference
│   ├── tools
│   │   ├── extensions
│   │   ├── static
│   │   └── templates
│   ├── tutorial
│   ├── using
│   └── whatsnew
├── Grammar
├── Include
│   ├── cpython
│   └── internal
├── Lib
│   ├── __pycache__
│   ├── asyncio
│   │   └── __pycache__
│   ├── collections
│   │   └── __pycache__
│   ├── concurrent
│   │   ├── __pycache__
│   │   └── futures
│   │       └── __pycache__
│   ├── ctypes
│   │   ├── __pycache__
│   │   ├── macholib
│   │   └── test
│   ├── curses
│   │   └── __pycache__
│   ├── dbm
│   ├── distutils
│   │   ├── __pycache__
│   │   ├── command
│   │   │   └── __pycache__
│   │   └── tests
│   ├── email
│   │   ├── __pycache__
│   │   └── mime
│   ├── encodings
│   │   └── __pycache__
│   ├── ensurepip
│   │   ├── __pycache__
│   │   └── _bundled
│   ├── html
│   │   └── __pycache__
│   ├── http
│   │   └── __pycache__
│   ├── idlelib
│   │   ├── Icons
│   │   └── idle_test
│   ├── importlib
│   │   └── __pycache__
│   ├── json
│   │   └── __pycache__
│   ├── lib2to3
│   │   ├── __pycache__
│   │   ├── fixes
│   │   ├── pgen2
│   │   │   └── __pycache__
│   │   └── tests
│   │       └── data
│   │           └── fixers
│   │               └── myfixes
│   ├── logging
│   │   └── __pycache__
│   ├── msilib
│   ├── multiprocessing
│   │   ├── __pycache__
│   │   └── dummy
│   ├── pydoc_data
│   │   └── __pycache__
│   ├── site-packages
│   ├── sqlite3
│   │   ├── __pycache__
│   │   └── test
│   ├── test
│   │   ├── audiodata
│   │   ├── capath
│   │   ├── cjkencodings
│   │   ├── crashers
│   │   ├── data
│   │   ├── decimaltestdata
│   │   ├── dtracedata
│   │   ├── eintrdata
│   │   ├── encoded_modules
│   │   ├── imghdrdata
│   │   ├── leakers
│   │   ├── libregrtest
│   │   ├── sndhdrdata
│   │   ├── subprocessdata
│   │   ├── support
│   │   ├── test_asyncio
│   │   ├── test_email
│   │   │   └── data
│   │   ├── test_import
│   │   │   └── data
│   │   │       ├── circular_imports
│   │   │       │   └── subpkg
│   │   │       ├── package
│   │   │       └── package2
│   │   ├── test_importlib
│   │   │   ├── builtin
│   │   │   ├── data
│   │   │   ├── data01
│   │   │   │   └── subdirectory
│   │   │   ├── data02
│   │   │   │   ├── one
│   │   │   │   └── two
│   │   │   ├── data03
│   │   │   │   └── namespace
│   │   │   │       ├── portion1
│   │   │   │       └── portion2
│   │   │   ├── extension
│   │   │   ├── frozen
│   │   │   ├── import_
│   │   │   ├── namespace_pkgs
│   │   │   │   ├── both_portions
│   │   │   │   │   └── foo
│   │   │   │   ├── module_and_namespace_package
│   │   │   │   │   └── a_test
│   │   │   │   ├── not_a_namespace_pkg
│   │   │   │   │   └── foo
│   │   │   │   ├── portion1
│   │   │   │   │   └── foo
│   │   │   │   ├── portion2
│   │   │   │   │   └── foo
│   │   │   │   ├── project1
│   │   │   │   │   └── parent
│   │   │   │   │       └── child
│   │   │   │   ├── project2
│   │   │   │   │   └── parent
│   │   │   │   │       └── child
│   │   │   │   └── project3
│   │   │   │       └── parent
│   │   │   │           └── child
│   │   │   ├── source
│   │   │   ├── zipdata01
│   │   │   └── zipdata02
│   │   ├── test_json
│   │   ├── test_tools
│   │   ├── test_warnings
│   │   │   └── data
│   │   ├── tracedmodules
│   │   ├── xmltestdata
│   │   │   └── c14n-20
│   │   └── ziptestdata
│   ├── tkinter
│   │   ├── __pycache__
│   │   └── test
│   │       ├── test_tkinter
│   │       └── test_ttk
│   ├── turtledemo
│   ├── unittest
│   │   ├── __pycache__
│   │   └── test
│   │       └── testmock
│   ├── urllib
│   │   └── __pycache__
│   ├── venv
│   │   └── scripts
│   │       ├── common
│   │       ├── nt
│   │       └── posix
│   ├── wsgiref
│   ├── xml
│   │   ├── __pycache__
│   │   ├── dom
│   │   │   └── __pycache__
│   │   ├── etree
│   │   │   └── __pycache__
│   │   ├── parsers
│   │   │   └── __pycache__
│   │   └── sax
│   │       └── __pycache__
│   └── xmlrpc
│       └── __pycache__
├── Mac
│   ├── BuildScript
│   │   ├── resources
│   │   └── scripts
│   ├── IDLE
│   │   └── IDLE.app
│   │       └── Contents
│   │           ├── MacOS
│   │           └── Resources
│   ├── Icons
│   ├── PythonLauncher
│   │   └── English.lproj
│   │       ├── MainMenu.nib
│   │       ├── MyDocument.nib
│   │       └── PreferenceWindow.nib
│   ├── Resources
│   │   ├── app
│   │   │   └── Resources
│   │   ├── framework
│   │   └── iconsrc
│   └── Tools
├── Misc
├── Modules
│   ├── _blake2
│   │   ├── clinic
│   │   └── impl
│   ├── _ctypes
│   │   ├── darwin
│   │   └── libffi_osx
│   │       ├── include
│   │       ├── powerpc
│   │       └── x86
│   ├── _decimal
│   │   ├── libmpdec
│   │   │   └── literature
│   │   └── tests
│   ├── _io
│   │   └── clinic
│   ├── _multiprocessing
│   │   └── clinic
│   ├── _sha3
│   │   ├── clinic
│   │   └── kcp
│   ├── _sqlite
│   ├── _ssl
│   ├── _xxtestfuzz
│   │   ├── dictionaries
│   │   ├── fuzz_csv_reader_corpus
│   │   ├── fuzz_json_loads_corpus
│   │   └── fuzz_sre_compile_corpus
│   ├── cjkcodecs
│   │   └── clinic
│   ├── clinic
│   └── expat
├── Objects
│   ├── clinic
│   └── stringlib
│       └── clinic
├── PC
│   ├── bdist_wininst
│   ├── clinic
│   ├── icons
│   └── layout
│       └── support
├── PCbuild
├── Parser
│   └── pgen
├── Programs
├── Python
│   └── clinic
├── Tools
│   ├── buildbot
│   ├── c-globals
│   ├── ccbench
│   ├── clinic
│   ├── demo
│   ├── freeze
│   │   └── test
│   ├── gdb
│   ├── i18n
│   ├── importbench
│   ├── iobench
│   ├── msi
│   │   ├── bundle
│   │   │   ├── bootstrap
│   │   │   └── packagegroups
│   │   ├── core
│   │   ├── dev
│   │   ├── doc
│   │   ├── exe
│   │   ├── launcher
│   │   ├── lib
│   │   ├── path
│   │   ├── pip
│   │   ├── tcltk
│   │   ├── test
│   │   ├── tools
│   │   └── ucrt
│   ├── nuget
│   ├── parser
│   ├── pynche
│   │   └── X
│   ├── scripts
│   ├── ssl
│   ├── stringbench
│   ├── test2to3
│   │   ├── test
│   │   └── test2to3
│   ├── tz
│   ├── unicode
│   │   └── python-mappings
│   └── unittestgui
├── build
│   ├── lib.linux-x86_64-3.8
│   │   └── __pycache__
│   ├── scripts-3.8
│   └── temp.linux-x86_64-3.8
│       └── opt
│           └── Python-3.8.2
│               └── Modules
│                   ├── _blake2
│                   ├── _ctypes
│                   ├── _decimal
│                   │   └── libmpdec
│                   ├── _multiprocessing
│                   ├── _sha3
│                   ├── _sqlite
│                   ├── _xxtestfuzz
│                   ├── cjkcodecs
│                   └── expat
└── m4

319 directories

Code of Conduct

@danielm-c2a danielm-c2a added S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior labels Aug 5, 2021
@uranusjr
Copy link
Member

uranusjr commented Aug 5, 2021

Huh, this is actually a CPython source tree! So you are not installing the compiled Python interepter into a prefix (like it’s normally done), but running it directly after compilation? That’s definitely not something we’ve considered (or even expliclty supported). Is you pip also installed in that prefix? (try which pip, pip --version, and pip debug)

@danielm-c2a
Copy link
Author

danielm-c2a commented Aug 5, 2021

which pip
/home/daniel/.local/bin/pip

pip --version
pip 21.3.dev0 from /home/daniel/.local/lib/python3.8/site-packages/pip (python 3.8)

pip debug

WARNING: This command is only meant for debugging. Do not use this with automation for parsing and getting these details, since the output and options of this command may change without notice.
pip version: pip 21.3.dev0 from /home/daniel/.local/lib/python3.8/site-packages/pip (python 3.8)
sys.version: 3.8.2 (default, May  6 2020, 16:36:37) 
[GCC 7.5.0]
sys.executable: /usr/local/bin/python3.8
sys.getdefaultencoding: utf-8
sys.getfilesystemencoding: utf-8
locale.getpreferredencoding: UTF-8
sys.platform: linux
sys.implementation:
  name: cpython
'cert' config value: Not specified
REQUESTS_CA_BUNDLE: None
CURL_CA_BUNDLE: None
pip._vendor.certifi.where(): /home/daniel/.local/lib/python3.8/site-packages/pip/_vendor/certifi/cacert.pem
pip._vendor.DEBUNDLED: False
vendored library versions:
  appdirs==1.4.4
  CacheControl==0.12.6
  colorama==0.4.4
  distlib==0.3.2
  distro==1.5.0 (Unable to locate actual module version, using vendor.txt specified version)
  html5lib==1.1
  msgpack==1.0.2 (Unable to locate actual module version, using vendor.txt specified version)
  packaging==21.0
  pep517==0.11.0
  progress==1.5
  pyparsing==2.4.7
  requests==2.26.0
  certifi==2021.05.30
  chardet==4.0.0
  idna==3.2
  urllib3==1.26.6
  resolvelib==0.7.1
  setuptools==44.0.0 (Unable to locate actual module version, using vendor.txt specified version)
  six==1.16.0
  tenacity==8.0.1 (Unable to locate actual module version, using vendor.txt specified version)
  tomli==1.0.3
  webencodings==0.5.1 (Unable to locate actual module version, using vendor.txt specified version)
Compatible tags: 524
  cp38-cp38-manylinux_2_27_x86_64
  cp38-cp38-manylinux_2_26_x86_64
  cp38-cp38-manylinux_2_25_x86_64
  cp38-cp38-manylinux_2_24_x86_64
  cp38-cp38-manylinux_2_23_x86_64
  cp38-cp38-manylinux_2_22_x86_64
  cp38-cp38-manylinux_2_21_x86_64
  cp38-cp38-manylinux_2_20_x86_64
  cp38-cp38-manylinux_2_19_x86_64
  cp38-cp38-manylinux_2_18_x86_64
  ...
  [First 10 tags shown. Pass --verbose to show all.]

@uranusjr uranusjr changed the title “Value for [key] does not match” warnings in pip 21.2.2, Strange Python-3.8.2 behaviour Strange Python-3.8.2 behaviour for sysconfig Aug 6, 2021
@uranusjr
Copy link
Member

uranusjr commented Aug 6, 2021

(I modified the title since the original one looks too much like #10151 in a browser tab bar.)

@uranusjr
Copy link
Member

uranusjr commented Aug 7, 2021

I think I have a clue. Could you run the followings for me?


$ /usr/local/bin/python3.8 -c 'import sysconfig; print(sysconfig._PYTHON_BUILD)'

If this is not True, could you share your sysconfig? (It might be patched)


$ /usr/local/bin/python3.8 -c 'import sys; print(sys._home)'

If sys._home is not None, if there a pyvenv.cfg file in either /usr/local/bin or /usr/local? What’s the content?


$ /usr/local/bin/python3.8 -c 'import os; print(os.environ["_PYTHON_PROJECT_BASE"])'

If this has a value (i.e. not raising KeyError or an empty value), try unsetting it and see if the problem goes away.


Technical note: This is probably due to _PYTHON_BUILD being set:

https://github.com/python/cpython/blob/v3.8.2/Lib/sysconfig.py#L143-L148

This flag indicates the current environment is a Python source tree being built, and adjusts the paths accordingly. distutils does not do this (because CPython does not use the module to build itself).

@uranusjr uranusjr removed the S: needs triage Issues/PRs that need to be triaged label Aug 7, 2021
@uranusjr uranusjr added this to the 21.2.4 milestone Aug 7, 2021
@danielm-c2a
Copy link
Author

danielm-c2a commented Aug 8, 2021

daniel@pop-os:~$ /usr/local/bin/python3.8 -c 'import sys; print(sys._home)'
None
daniel@pop-os:~$ /usr/local/bin/python3.8 -c 'import os; print(os.environ["_PYTHON_PROJECT_BASE"])'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/os.py", line 675, in __getitem__
    raise KeyError(key) from None
KeyError: '_PYTHON_PROJECT_BASE'
daniel@pop-os:~$ /usr/local/bin/python3.8 -c 'import sysconfig; print(sysconfig._PYTHON_BUILD)'
False

My sysconfig file:

> atom '/usr/local/lib/python3.8/sysconfig.py'

"""Access to Python's configuration information."""

import os
import sys
from os.path import pardir, realpath

__all__ = [
    'get_config_h_filename',
    'get_config_var',
    'get_config_vars',
    'get_makefile_filename',
    'get_path',
    'get_path_names',
    'get_paths',
    'get_platform',
    'get_python_version',
    'get_scheme_names',
    'parse_config_h',
]

_INSTALL_SCHEMES = {
    'posix_prefix': {
        'stdlib': '{installed_base}/lib/python{py_version_short}',
        'platstdlib': '{platbase}/lib/python{py_version_short}',
        'purelib': '{base}/lib/python{py_version_short}/site-packages',
        'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
        'include':
            '{installed_base}/include/python{py_version_short}{abiflags}',
        'platinclude':
            '{installed_platbase}/include/python{py_version_short}{abiflags}',
        'scripts': '{base}/bin',
        'data': '{base}',
        },
    'posix_home': {
        'stdlib': '{installed_base}/lib/python',
        'platstdlib': '{base}/lib/python',
        'purelib': '{base}/lib/python',
        'platlib': '{base}/lib/python',
        'include': '{installed_base}/include/python',
        'platinclude': '{installed_base}/include/python',
        'scripts': '{base}/bin',
        'data': '{base}',
        },
    'nt': {
        'stdlib': '{installed_base}/Lib',
        'platstdlib': '{base}/Lib',
        'purelib': '{base}/Lib/site-packages',
        'platlib': '{base}/Lib/site-packages',
        'include': '{installed_base}/Include',
        'platinclude': '{installed_base}/Include',
        'scripts': '{base}/Scripts',
        'data': '{base}',
        },
    # NOTE: When modifying "purelib" scheme, update site._get_path() too.
    'nt_user': {
        'stdlib': '{userbase}/Python{py_version_nodot}',
        'platstdlib': '{userbase}/Python{py_version_nodot}',
        'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
        'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
        'include': '{userbase}/Python{py_version_nodot}/Include',
        'scripts': '{userbase}/Python{py_version_nodot}/Scripts',
        'data': '{userbase}',
        },
    'posix_user': {
        'stdlib': '{userbase}/lib/python{py_version_short}',
        'platstdlib': '{userbase}/lib/python{py_version_short}',
        'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
        'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
        'include': '{userbase}/include/python{py_version_short}',
        'scripts': '{userbase}/bin',
        'data': '{userbase}',
        },
    'osx_framework_user': {
        'stdlib': '{userbase}/lib/python',
        'platstdlib': '{userbase}/lib/python',
        'purelib': '{userbase}/lib/python/site-packages',
        'platlib': '{userbase}/lib/python/site-packages',
        'include': '{userbase}/include',
        'scripts': '{userbase}/bin',
        'data': '{userbase}',
        },
    }

_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
                'scripts', 'data')

 # FIXME don't rely on sys.version here, its format is an implementation detail
 # of CPython, use sys.version_info or sys.hexversion
_PY_VERSION = sys.version.split()[0]
_PY_VERSION_SHORT = '%d.%d' % sys.version_info[:2]
_PY_VERSION_SHORT_NO_DOT = '%d%d' % sys.version_info[:2]
_PREFIX = os.path.normpath(sys.prefix)
_BASE_PREFIX = os.path.normpath(sys.base_prefix)
_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
_CONFIG_VARS = None
_USER_BASE = None


def _safe_realpath(path):
    try:
        return realpath(path)
    except OSError:
        return path

if sys.executable:
    _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
else:
    # sys.executable can be empty if argv[0] has been changed and Python is
    # unable to retrieve the real program name
    _PROJECT_BASE = _safe_realpath(os.getcwd())

if (os.name == 'nt' and
    _PROJECT_BASE.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
    _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))

# set for cross builds
if "_PYTHON_PROJECT_BASE" in os.environ:
    _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])

def _is_python_source_dir(d):
    for fn in ("Setup", "Setup.local"):
        if os.path.isfile(os.path.join(d, "Modules", fn)):
            return True
    return False

_sys_home = getattr(sys, '_home', None)

if os.name == 'nt':
    def _fix_pcbuild(d):
        if d and os.path.normcase(d).startswith(
                os.path.normcase(os.path.join(_PREFIX, "PCbuild"))):
            return _PREFIX
        return d
    _PROJECT_BASE = _fix_pcbuild(_PROJECT_BASE)
    _sys_home = _fix_pcbuild(_sys_home)

def is_python_build(check_home=False):
    if check_home and _sys_home:
        return _is_python_source_dir(_sys_home)
    return _is_python_source_dir(_PROJECT_BASE)

_PYTHON_BUILD = is_python_build(True)

if _PYTHON_BUILD:
    for scheme in ('posix_prefix', 'posix_home'):
        _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
        _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'


def _subst_vars(s, local_vars):
    try:
        return s.format(**local_vars)
    except KeyError:
        try:
            return s.format(**os.environ)
        except KeyError as var:
            raise AttributeError('{%s}' % var) from None

def _extend_dict(target_dict, other_dict):
    target_keys = target_dict.keys()
    for key, value in other_dict.items():
        if key in target_keys:
            continue
        target_dict[key] = value


def _expand_vars(scheme, vars):
    res = {}
    if vars is None:
        vars = {}
    _extend_dict(vars, get_config_vars())

    for key, value in _INSTALL_SCHEMES[scheme].items():
        if os.name in ('posix', 'nt'):
            value = os.path.expanduser(value)
        res[key] = os.path.normpath(_subst_vars(value, vars))
    return res


def _get_default_scheme():
    if os.name == 'posix':
        # the default scheme for posix is posix_prefix
        return 'posix_prefix'
    return os.name


# NOTE: site.py has copy of this function.
# Sync it when modify this function.
def _getuserbase():
    env_base = os.environ.get("PYTHONUSERBASE", None)
    if env_base:
        return env_base

    def joinuser(*args):
        return os.path.expanduser(os.path.join(*args))

    if os.name == "nt":
        base = os.environ.get("APPDATA") or "~"
        return joinuser(base, "Python")

    if sys.platform == "darwin" and sys._framework:
        return joinuser("~", "Library", sys._framework,
                        "%d.%d" % sys.version_info[:2])

    return joinuser("~", ".local")


def _parse_makefile(filename, vars=None):
    """Parse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    """
    # Regexes needed for parsing Makefile (and similar syntaxes,
    # like old-style Setup files).
    import re
    _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
    _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
    _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")

    if vars is None:
        vars = {}
    done = {}
    notdone = {}

    with open(filename, errors="surrogateescape") as f:
        lines = f.readlines()

    for line in lines:
        if line.startswith('#') or line.strip() == '':
            continue
        m = _variable_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            v = v.strip()
            # `$$' is a literal `$' in make
            tmpv = v.replace('$$', '')

            if "$" in tmpv:
                notdone[n] = v
            else:
                try:
                    v = int(v)
                except ValueError:
                    # insert literal `$'
                    done[n] = v.replace('$$', '$')
                else:
                    done[n] = v

    # do variable interpolation here
    variables = list(notdone.keys())

    # Variables with a 'PY_' prefix in the makefile. These need to
    # be made available without that prefix through sysconfig.
    # Special care is needed to ensure that variable expansion works, even
    # if the expansion uses the name without a prefix.
    renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')

    while len(variables) > 0:
        for name in tuple(variables):
            value = notdone[name]
            m1 = _findvar1_rx.search(value)
            m2 = _findvar2_rx.search(value)
            if m1 and m2:
                m = m1 if m1.start() < m2.start() else m2
            else:
                m = m1 if m1 else m2
            if m is not None:
                n = m.group(1)
                found = True
                if n in done:
                    item = str(done[n])
                elif n in notdone:
                    # get it on a subsequent round
                    found = False
                elif n in os.environ:
                    # do it like make: fall back to environment
                    item = os.environ[n]

                elif n in renamed_variables:
                    if (name.startswith('PY_') and
                        name[3:] in renamed_variables):
                        item = ""

                    elif 'PY_' + n in notdone:
                        found = False

                    else:
                        item = str(done['PY_' + n])

                else:
                    done[n] = item = ""

                if found:
                    after = value[m.end():]
                    value = value[:m.start()] + item + after
                    if "$" in after:
                        notdone[name] = value
                    else:
                        try:
                            value = int(value)
                        except ValueError:
                            done[name] = value.strip()
                        else:
                            done[name] = value
                        variables.remove(name)

                        if name.startswith('PY_') \
                        and name[3:] in renamed_variables:

                            name = name[3:]
                            if name not in done:
                                done[name] = value

            else:
                # bogus variable reference (e.g. "prefix=$/opt/python");
                # just drop it since we can't deal
                done[name] = value
                variables.remove(name)

    # strip spurious spaces
    for k, v in done.items():
        if isinstance(v, str):
            done[k] = v.strip()

    # save the results in the global dictionary
    vars.update(done)
    return vars


def get_makefile_filename():
    """Return the path of the Makefile."""
    if _PYTHON_BUILD:
        return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
    if hasattr(sys, 'abiflags'):
        config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
    else:
        config_dir_name = 'config'
    if hasattr(sys.implementation, '_multiarch'):
        config_dir_name += '-%s' % sys.implementation._multiarch
    return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')


def _get_sysconfigdata_name():
    return os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
        '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
        abi=sys.abiflags,
        platform=sys.platform,
        multiarch=getattr(sys.implementation, '_multiarch', ''),
    ))


def _generate_posix_vars():
    """Generate the Python module containing build-time variables."""
    import pprint
    vars = {}
    # load the installed Makefile:
    makefile = get_makefile_filename()
    try:
        _parse_makefile(makefile, vars)
    except OSError as e:
        msg = "invalid Python installation: unable to open %s" % makefile
        if hasattr(e, "strerror"):
            msg = msg + " (%s)" % e.strerror
        raise OSError(msg)
    # load the installed pyconfig.h:
    config_h = get_config_h_filename()
    try:
        with open(config_h) as f:
            parse_config_h(f, vars)
    except OSError as e:
        msg = "invalid Python installation: unable to open %s" % config_h
        if hasattr(e, "strerror"):
            msg = msg + " (%s)" % e.strerror
        raise OSError(msg)
    # On AIX, there are wrong paths to the linker scripts in the Makefile
    # -- these paths are relative to the Python source, but when installed
    # the scripts are in another directory.
    if _PYTHON_BUILD:
        vars['BLDSHARED'] = vars['LDSHARED']

    # There's a chicken-and-egg situation on OS X with regards to the
    # _sysconfigdata module after the changes introduced by #15298:
    # get_config_vars() is called by get_platform() as part of the
    # `make pybuilddir.txt` target -- which is a precursor to the
    # _sysconfigdata.py module being constructed.  Unfortunately,
    # get_config_vars() eventually calls _init_posix(), which attempts
    # to import _sysconfigdata, which we won't have built yet.  In order
    # for _init_posix() to work, if we're on Darwin, just mock up the
    # _sysconfigdata module manually and populate it with the build vars.
    # This is more than sufficient for ensuring the subsequent call to
    # get_platform() succeeds.
    name = _get_sysconfigdata_name()
    if 'darwin' in sys.platform:
        import types
        module = types.ModuleType(name)
        module.build_time_vars = vars
        sys.modules[name] = module

    pybuilddir = 'build/lib.%s-%s' % (get_platform(), _PY_VERSION_SHORT)
    if hasattr(sys, "gettotalrefcount"):
        pybuilddir += '-pydebug'
    os.makedirs(pybuilddir, exist_ok=True)
    destfile = os.path.join(pybuilddir, name + '.py')

    with open(destfile, 'w', encoding='utf8') as f:
        f.write('# system configuration generated and used by'
                ' the sysconfig module\n')
        f.write('build_time_vars = ')
        pprint.pprint(vars, stream=f)

    # Create file used for sys.path fixup -- see Modules/getpath.c
    with open('pybuilddir.txt', 'w', encoding='utf8') as f:
        f.write(pybuilddir)

def _init_posix(vars):
    """Initialize the module as appropriate for POSIX systems."""
    # _sysconfigdata is generated at build time, see _generate_posix_vars()
    name = _get_sysconfigdata_name()
    _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
    build_time_vars = _temp.build_time_vars
    vars.update(build_time_vars)

def _init_non_posix(vars):
    """Initialize the module as appropriate for NT"""
    # set basic install directories
    vars['LIBDEST'] = get_path('stdlib')
    vars['BINLIBDEST'] = get_path('platstdlib')
    vars['INCLUDEPY'] = get_path('include')
    vars['EXT_SUFFIX'] = '.pyd'
    vars['EXE'] = '.exe'
    vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
    vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))

#
# public APIs
#


def parse_config_h(fp, vars=None):
    """Parse a config.h-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    """
    if vars is None:
        vars = {}
    import re
    define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
    undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")

    while True:
        line = fp.readline()
        if not line:
            break
        m = define_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            try:
                v = int(v)
            except ValueError:
                pass
            vars[n] = v
        else:
            m = undef_rx.match(line)
            if m:
                vars[m.group(1)] = 0
    return vars


def get_config_h_filename():
    """Return the path of pyconfig.h."""
    if _PYTHON_BUILD:
        if os.name == "nt":
            inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
        else:
            inc_dir = _sys_home or _PROJECT_BASE
    else:
        inc_dir = get_path('platinclude')
    return os.path.join(inc_dir, 'pyconfig.h')


def get_scheme_names():
    """Return a tuple containing the schemes names."""
    return tuple(sorted(_INSTALL_SCHEMES))


def get_path_names():
    """Return a tuple containing the paths names."""
    return _SCHEME_KEYS


def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
    """Return a mapping containing an install scheme.

    ``scheme`` is the install scheme name. If not provided, it will
    return the default scheme for the current platform.
    """
    if expand:
        return _expand_vars(scheme, vars)
    else:
        return _INSTALL_SCHEMES[scheme]


def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
    """Return a path corresponding to the scheme.

    ``scheme`` is the install scheme name.
    """
    return get_paths(scheme, vars, expand)[name]


def get_config_vars(*args):
    """With no arguments, return a dictionary of all configuration
    variables relevant for the current platform.

    On Unix, this means every variable defined in Python's installed Makefile;
    On Windows it's a much smaller set.

    With arguments, return a list of values that result from looking up
    each argument in the configuration variable dictionary.
    """
    global _CONFIG_VARS
    if _CONFIG_VARS is None:
        _CONFIG_VARS = {}
        # Normalized versions of prefix and exec_prefix are handy to have;
        # in fact, these are the standard versions used most places in the
        # Distutils.
        _CONFIG_VARS['prefix'] = _PREFIX
        _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
        _CONFIG_VARS['py_version'] = _PY_VERSION
        _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
        _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
        _CONFIG_VARS['installed_base'] = _BASE_PREFIX
        _CONFIG_VARS['base'] = _PREFIX
        _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
        _CONFIG_VARS['platbase'] = _EXEC_PREFIX
        _CONFIG_VARS['projectbase'] = _PROJECT_BASE
        try:
            _CONFIG_VARS['abiflags'] = sys.abiflags
        except AttributeError:
            # sys.abiflags may not be defined on all platforms.
            _CONFIG_VARS['abiflags'] = ''

        if os.name == 'nt':
            _init_non_posix(_CONFIG_VARS)
        if os.name == 'posix':
            _init_posix(_CONFIG_VARS)
        # For backward compatibility, see issue19555
        SO = _CONFIG_VARS.get('EXT_SUFFIX')
        if SO is not None:
            _CONFIG_VARS['SO'] = SO
        # Setting 'userbase' is done below the call to the
        # init function to enable using 'get_config_var' in
        # the init-function.
        _CONFIG_VARS['userbase'] = _getuserbase()

        # Always convert srcdir to an absolute path
        srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
        if os.name == 'posix':
            if _PYTHON_BUILD:
                # If srcdir is a relative path (typically '.' or '..')
                # then it should be interpreted relative to the directory
                # containing Makefile.
                base = os.path.dirname(get_makefile_filename())
                srcdir = os.path.join(base, srcdir)
            else:
                # srcdir is not meaningful since the installation is
                # spread about the filesystem.  We choose the
                # directory containing the Makefile since we know it
                # exists.
                srcdir = os.path.dirname(get_makefile_filename())
        _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)

        # OS X platforms require special customization to handle
        # multi-architecture, multi-os-version installers
        if sys.platform == 'darwin':
            import _osx_support
            _osx_support.customize_config_vars(_CONFIG_VARS)

    if args:
        vals = []
        for name in args:
            vals.append(_CONFIG_VARS.get(name))
        return vals
    else:
        return _CONFIG_VARS


def get_config_var(name):
    """Return the value of a single variable using the dictionary returned by
    'get_config_vars()'.

    Equivalent to get_config_vars().get(name)
    """
    if name == 'SO':
        import warnings
        warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
    return get_config_vars().get(name)


def get_platform():
    """Return a string that identifies the current platform.

    This is used mainly to distinguish platform-specific build directories and
    platform-specific built distributions.  Typically includes the OS name and
    version and the architecture (as supplied by 'os.uname()'), although the
    exact information included depends on the OS; on Linux, the kernel version
    isn't particularly important.

    Examples of returned values:
       linux-i586
       linux-alpha (?)
       solaris-2.6-sun4u

    Windows will return one of:
       win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
       win32 (all others - specifically, sys.platform is returned)

    For other non-POSIX platforms, currently just returns 'sys.platform'.

    """
    if os.name == 'nt':
        if 'amd64' in sys.version.lower():
            return 'win-amd64'
        if '(arm)' in sys.version.lower():
            return 'win-arm32'
        if '(arm64)' in sys.version.lower():
            return 'win-arm64'
        return sys.platform

    if os.name != "posix" or not hasattr(os, 'uname'):
        # XXX what about the architecture? NT is Intel or Alpha
        return sys.platform

    # Set for cross builds explicitly
    if "_PYTHON_HOST_PLATFORM" in os.environ:
        return os.environ["_PYTHON_HOST_PLATFORM"]

    # Try to distinguish various flavours of Unix
    osname, host, release, version, machine = os.uname()

    # Convert the OS name to lowercase, remove '/' characters, and translate
    # spaces (for "Power Macintosh")
    osname = osname.lower().replace('/', '')
    machine = machine.replace(' ', '_')
    machine = machine.replace('/', '-')

    if osname[:5] == "linux":
        # At least on Linux/Intel, 'machine' is the processor --
        # i386, etc.
        # XXX what about Alpha, SPARC, etc?
        return  "%s-%s" % (osname, machine)
    elif osname[:5] == "sunos":
        if release[0] >= "5":           # SunOS 5 == Solaris 2
            osname = "solaris"
            release = "%d.%s" % (int(release[0]) - 3, release[2:])
            # We can't use "platform.architecture()[0]" because a
            # bootstrap problem. We use a dict to get an error
            # if some suspicious happens.
            bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
            machine += ".%s" % bitness[sys.maxsize]
        # fall through to standard osname-release-machine representation
    elif osname[:3] == "aix":
        return "%s-%s.%s" % (osname, version, release)
    elif osname[:6] == "cygwin":
        osname = "cygwin"
        import re
        rel_re = re.compile(r'[\d.]+')
        m = rel_re.match(release)
        if m:
            release = m.group()
    elif osname[:6] == "darwin":
        import _osx_support
        osname, release, machine = _osx_support.get_platform_osx(
                                            get_config_vars(),
                                            osname, release, machine)

    return "%s-%s-%s" % (osname, release, machine)


def get_python_version():
    return _PY_VERSION_SHORT


def _print_dict(title, data):
    for index, (key, value) in enumerate(sorted(data.items())):
        if index == 0:
            print('%s: ' % (title))
        print('\t%s = "%s"' % (key, value))


def _main():
    """Display all information sysconfig detains."""
    if '--generate-posix-vars' in sys.argv:
        _generate_posix_vars()
        return
    print('Platform: "%s"' % get_platform())
    print('Python version: "%s"' % get_python_version())
    print('Current installation scheme: "%s"' % _get_default_scheme())
    print()
    _print_dict('Paths', get_paths())
    print()
    _print_dict('Variables', get_config_vars())


if __name__ == '__main__':
    _main()

@uranusjr uranusjr modified the milestones: 21.2.4, 21.3 Aug 12, 2021
@uranusjr
Copy link
Member

Still not clear why this is happening :( Pushing this back to not block other bug fixes.

@wfsteele
Copy link

wfsteele commented Sep 7, 2021

Description:
I downloaded the source distribution of python 3.9.7, then built and installed it. At the end of the installation process the makefile runs pip, yielding the output:

WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
distutils: /Library/Frameworks/Python.framework/Versions/3.9/include/python3.9/UNKNOWN
sysconfig: /Programming/Python-3.9.7/Include/UNKNOWN
WARNING: Additional context:
user = False
home = None
root = '/'
prefix = None

pip debug yields:

pip version: pip 21.2.4 from /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pip (python 3.9)
sys.version: 3.9.7 (default, Sep  6 2021, 16:27:11) 
[Clang 10.0.0 (clang-1000.11.45.5)]
sys.executable: /Library/Frameworks/Python.framework/Versions/3.9/bin/python3.9

I have been using this same procedure for many years, whenever a new python version is released (most recently, before this release, a few months ago for python 3.9.6) and have never seen this warning 'til now.

OS: MacOS 10.13.6

Steps to reproduce:
-- download source distribution of python 3.9.7
-- expand archive
-- cd to top level directory of expanded archive
-- run:

./configure --enable-framework
make
sudo -H make frameworkinstall

@uranusjr
Copy link
Member

uranusjr commented Sep 7, 2021

Thanks for the information! Do you happen to know off the top of your head if there’s a way I can install a framework Python to a different location? I know for non-framework I can do make altinstall but am not sure what the equivalent is for frameworkinstall.

@vince-weka
Copy link

vince-weka commented Sep 7, 2021

WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
distutils: /usr/local/include/python3.9/UNKNOWN
sysconfig: /sns/Python-3.9.7/Include/UNKNOWN
WARNING: Additional context:
user = False
home = None
root = '/'
prefix = None
Looking in links: /tmp/tmpt2d_rkwl
Processing /tmp/tmpt2d_rkwl/setuptools-57.4.0-py3-none-any.whl
Processing /tmp/tmpt2d_rkwl/pip-21.2.3-py3-none-any.whl
Installing collected packages: setuptools, pip
  WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
  distutils: /usr/local/include/python3.9/setuptools
  sysconfig: /sns/Python-3.9.7/Include/setuptools
  WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
  distutils: /usr/local/include/python3.9/pip
  sysconfig: /sns/Python-3.9.7/Include/pip
Successfully installed pip-21.2.3 setuptools-57.4.0

# pip debug --verbose
WARNING: This command is only meant for debugging. Do not use this with automation for parsing and getting these details, since the output and options of this command may change without notice.
pip version: pip 21.1.2 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)
sys.version: 3.6.8 (default, Aug  7 2019, 17:28:10)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
sys.executable: /usr/bin/python3
sys.getdefaultencoding: utf-8
sys.getfilesystemencoding: utf-8
locale.getpreferredencoding: UTF-8
sys.platform: linux
sys.implementation:
  name: cpython
'cert' config value: Not specified
REQUESTS_CA_BUNDLE: None
CURL_CA_BUNDLE: None
pip._vendor.certifi.where(): /usr/local/lib/python3.6/site-packages/pip/_vendor/certifi/cacert.pem
pip._vendor.DEBUNDLED: False
vendored library versions:
  appdirs==1.4.4
  CacheControl==0.12.6
  colorama==0.4.4
  distlib==0.3.1
  distro==1.5.0 (Unable to locate actual module version, using vendor.txt specified version)
  html5lib==1.1
  msgpack==1.0.2 (Unable to locate actual module version, using vendor.txt specified version)
  packaging==20.9
  pep517==0.10.0
  progress==1.5
  pyparsing==2.4.7
  requests==2.25.1
  certifi==2020.12.05
  chardet==4.0.0
  idna==3.1
  urllib3==1.26.4
  resolvelib==0.7.0
  setuptools==44.0.0 (Unable to locate actual module version, using vendor.txt specified version)
  six==1.15.0
  tenacity==7.0.0 (Unable to locate actual module version, using vendor.txt specified version)
  toml==0.10.2
  webencodings==0.5.1 (Unable to locate actual module version, using vendor.txt specified version)
Compatible tags: 264
  cp36-cp36m-manylinux_2_17_x86_64
  cp36-cp36m-manylinux2014_x86_64
  cp36-cp36m-manylinux_2_16_x86_64
  cp36-cp36m-manylinux_2_15_x86_64
  cp36-cp36m-manylinux_2_14_x86_64
  cp36-cp36m-manylinux_2_13_x86_64
  cp36-cp36m-manylinux_2_12_x86_64
  cp36-cp36m-manylinux2010_x86_64
  cp36-cp36m-manylinux_2_11_x86_64
  cp36-cp36m-manylinux_2_10_x86_64
  cp36-cp36m-manylinux_2_9_x86_64
  cp36-cp36m-manylinux_2_8_x86_64
  cp36-cp36m-manylinux_2_7_x86_64
  cp36-cp36m-manylinux_2_6_x86_64
  cp36-cp36m-manylinux_2_5_x86_64
  cp36-cp36m-manylinux1_x86_64
  cp36-cp36m-linux_x86_64
  cp36-abi3-manylinux_2_17_x86_64
  cp36-abi3-manylinux2014_x86_64
  cp36-abi3-manylinux_2_16_x86_64
  cp36-abi3-manylinux_2_15_x86_64
  cp36-abi3-manylinux_2_14_x86_64
  cp36-abi3-manylinux_2_13_x86_64
  cp36-abi3-manylinux_2_12_x86_64
  cp36-abi3-manylinux2010_x86_64
  cp36-abi3-manylinux_2_11_x86_64
  cp36-abi3-manylinux_2_10_x86_64
  cp36-abi3-manylinux_2_9_x86_64
  cp36-abi3-manylinux_2_8_x86_64
  cp36-abi3-manylinux_2_7_x86_64
  cp36-abi3-manylinux_2_6_x86_64
  cp36-abi3-manylinux_2_5_x86_64
  cp36-abi3-manylinux1_x86_64
  cp36-abi3-linux_x86_64
  cp36-none-manylinux_2_17_x86_64
  cp36-none-manylinux2014_x86_64
  cp36-none-manylinux_2_16_x86_64
  cp36-none-manylinux_2_15_x86_64
  cp36-none-manylinux_2_14_x86_64
  cp36-none-manylinux_2_13_x86_64
  cp36-none-manylinux_2_12_x86_64
  cp36-none-manylinux2010_x86_64
  cp36-none-manylinux_2_11_x86_64
  cp36-none-manylinux_2_10_x86_64
  cp36-none-manylinux_2_9_x86_64
  cp36-none-manylinux_2_8_x86_64
  cp36-none-manylinux_2_7_x86_64
  cp36-none-manylinux_2_6_x86_64
  cp36-none-manylinux_2_5_x86_64
  cp36-none-manylinux1_x86_64
  cp36-none-linux_x86_64
  cp35-abi3-manylinux_2_17_x86_64
  cp35-abi3-manylinux2014_x86_64
  cp35-abi3-manylinux_2_16_x86_64
  cp35-abi3-manylinux_2_15_x86_64
  cp35-abi3-manylinux_2_14_x86_64
  cp35-abi3-manylinux_2_13_x86_64
  cp35-abi3-manylinux_2_12_x86_64
  cp35-abi3-manylinux2010_x86_64
  cp35-abi3-manylinux_2_11_x86_64
  cp35-abi3-manylinux_2_10_x86_64
  cp35-abi3-manylinux_2_9_x86_64
  cp35-abi3-manylinux_2_8_x86_64
  cp35-abi3-manylinux_2_7_x86_64
  cp35-abi3-manylinux_2_6_x86_64
  cp35-abi3-manylinux_2_5_x86_64
  cp35-abi3-manylinux1_x86_64
  cp35-abi3-linux_x86_64
  cp34-abi3-manylinux_2_17_x86_64
  cp34-abi3-manylinux2014_x86_64
  cp34-abi3-manylinux_2_16_x86_64
  cp34-abi3-manylinux_2_15_x86_64
  cp34-abi3-manylinux_2_14_x86_64
  cp34-abi3-manylinux_2_13_x86_64
  cp34-abi3-manylinux_2_12_x86_64
  cp34-abi3-manylinux2010_x86_64
  cp34-abi3-manylinux_2_11_x86_64
  cp34-abi3-manylinux_2_10_x86_64
  cp34-abi3-manylinux_2_9_x86_64
  cp34-abi3-manylinux_2_8_x86_64
  cp34-abi3-manylinux_2_7_x86_64
  cp34-abi3-manylinux_2_6_x86_64
  cp34-abi3-manylinux_2_5_x86_64
  cp34-abi3-manylinux1_x86_64
  cp34-abi3-linux_x86_64
  cp33-abi3-manylinux_2_17_x86_64
  cp33-abi3-manylinux2014_x86_64
  cp33-abi3-manylinux_2_16_x86_64
  cp33-abi3-manylinux_2_15_x86_64
  cp33-abi3-manylinux_2_14_x86_64
  cp33-abi3-manylinux_2_13_x86_64
  cp33-abi3-manylinux_2_12_x86_64
  cp33-abi3-manylinux2010_x86_64
  cp33-abi3-manylinux_2_11_x86_64
  cp33-abi3-manylinux_2_10_x86_64
  cp33-abi3-manylinux_2_9_x86_64
  cp33-abi3-manylinux_2_8_x86_64
  cp33-abi3-manylinux_2_7_x86_64
  cp33-abi3-manylinux_2_6_x86_64
  cp33-abi3-manylinux_2_5_x86_64
  cp33-abi3-manylinux1_x86_64
  cp33-abi3-linux_x86_64
  cp32-abi3-manylinux_2_17_x86_64
  cp32-abi3-manylinux2014_x86_64
  cp32-abi3-manylinux_2_16_x86_64
  cp32-abi3-manylinux_2_15_x86_64
  cp32-abi3-manylinux_2_14_x86_64
  cp32-abi3-manylinux_2_13_x86_64
  cp32-abi3-manylinux_2_12_x86_64
  cp32-abi3-manylinux2010_x86_64
  cp32-abi3-manylinux_2_11_x86_64
  cp32-abi3-manylinux_2_10_x86_64
  cp32-abi3-manylinux_2_9_x86_64
  cp32-abi3-manylinux_2_8_x86_64
  cp32-abi3-manylinux_2_7_x86_64
  cp32-abi3-manylinux_2_6_x86_64
  cp32-abi3-manylinux_2_5_x86_64
  cp32-abi3-manylinux1_x86_64
  cp32-abi3-linux_x86_64
  py36-none-manylinux_2_17_x86_64
  py36-none-manylinux2014_x86_64
  py36-none-manylinux_2_16_x86_64
  py36-none-manylinux_2_15_x86_64
  py36-none-manylinux_2_14_x86_64
  py36-none-manylinux_2_13_x86_64
  py36-none-manylinux_2_12_x86_64
  py36-none-manylinux2010_x86_64
  py36-none-manylinux_2_11_x86_64
  py36-none-manylinux_2_10_x86_64
  py36-none-manylinux_2_9_x86_64
  py36-none-manylinux_2_8_x86_64
  py36-none-manylinux_2_7_x86_64
  py36-none-manylinux_2_6_x86_64
  py36-none-manylinux_2_5_x86_64
  py36-none-manylinux1_x86_64
  py36-none-linux_x86_64
  py3-none-manylinux_2_17_x86_64
  py3-none-manylinux2014_x86_64
  py3-none-manylinux_2_16_x86_64
  py3-none-manylinux_2_15_x86_64
  py3-none-manylinux_2_14_x86_64
  py3-none-manylinux_2_13_x86_64
  py3-none-manylinux_2_12_x86_64
  py3-none-manylinux2010_x86_64
  py3-none-manylinux_2_11_x86_64
  py3-none-manylinux_2_10_x86_64
  py3-none-manylinux_2_9_x86_64
  py3-none-manylinux_2_8_x86_64
  py3-none-manylinux_2_7_x86_64
  py3-none-manylinux_2_6_x86_64
  py3-none-manylinux_2_5_x86_64
  py3-none-manylinux1_x86_64
  py3-none-linux_x86_64
  py35-none-manylinux_2_17_x86_64
  py35-none-manylinux2014_x86_64
  py35-none-manylinux_2_16_x86_64
  py35-none-manylinux_2_15_x86_64
  py35-none-manylinux_2_14_x86_64
  py35-none-manylinux_2_13_x86_64
  py35-none-manylinux_2_12_x86_64
  py35-none-manylinux2010_x86_64
  py35-none-manylinux_2_11_x86_64
  py35-none-manylinux_2_10_x86_64
  py35-none-manylinux_2_9_x86_64
  py35-none-manylinux_2_8_x86_64
  py35-none-manylinux_2_7_x86_64
  py35-none-manylinux_2_6_x86_64
  py35-none-manylinux_2_5_x86_64
  py35-none-manylinux1_x86_64
  py35-none-linux_x86_64
  py34-none-manylinux_2_17_x86_64
  py34-none-manylinux2014_x86_64
  py34-none-manylinux_2_16_x86_64
  py34-none-manylinux_2_15_x86_64
  py34-none-manylinux_2_14_x86_64
  py34-none-manylinux_2_13_x86_64
  py34-none-manylinux_2_12_x86_64
  py34-none-manylinux2010_x86_64
  py34-none-manylinux_2_11_x86_64
  py34-none-manylinux_2_10_x86_64
  py34-none-manylinux_2_9_x86_64
  py34-none-manylinux_2_8_x86_64
  py34-none-manylinux_2_7_x86_64
  py34-none-manylinux_2_6_x86_64
  py34-none-manylinux_2_5_x86_64
  py34-none-manylinux1_x86_64
  py34-none-linux_x86_64
  py33-none-manylinux_2_17_x86_64
  py33-none-manylinux2014_x86_64
  py33-none-manylinux_2_16_x86_64
  py33-none-manylinux_2_15_x86_64
  py33-none-manylinux_2_14_x86_64
  py33-none-manylinux_2_13_x86_64
  py33-none-manylinux_2_12_x86_64
  py33-none-manylinux2010_x86_64
  py33-none-manylinux_2_11_x86_64
  py33-none-manylinux_2_10_x86_64
  py33-none-manylinux_2_9_x86_64
  py33-none-manylinux_2_8_x86_64
  py33-none-manylinux_2_7_x86_64
  py33-none-manylinux_2_6_x86_64
  py33-none-manylinux_2_5_x86_64
  py33-none-manylinux1_x86_64
  py33-none-linux_x86_64
  py32-none-manylinux_2_17_x86_64
  py32-none-manylinux2014_x86_64
  py32-none-manylinux_2_16_x86_64
  py32-none-manylinux_2_15_x86_64
  py32-none-manylinux_2_14_x86_64
  py32-none-manylinux_2_13_x86_64
  py32-none-manylinux_2_12_x86_64
  py32-none-manylinux2010_x86_64
  py32-none-manylinux_2_11_x86_64
  py32-none-manylinux_2_10_x86_64
  py32-none-manylinux_2_9_x86_64
  py32-none-manylinux_2_8_x86_64
  py32-none-manylinux_2_7_x86_64
  py32-none-manylinux_2_6_x86_64
  py32-none-manylinux_2_5_x86_64
  py32-none-manylinux1_x86_64
  py32-none-linux_x86_64
  py31-none-manylinux_2_17_x86_64
  py31-none-manylinux2014_x86_64
  py31-none-manylinux_2_16_x86_64
  py31-none-manylinux_2_15_x86_64
  py31-none-manylinux_2_14_x86_64
  py31-none-manylinux_2_13_x86_64
  py31-none-manylinux_2_12_x86_64
  py31-none-manylinux2010_x86_64
  py31-none-manylinux_2_11_x86_64
  py31-none-manylinux_2_10_x86_64
  py31-none-manylinux_2_9_x86_64
  py31-none-manylinux_2_8_x86_64
  py31-none-manylinux_2_7_x86_64
  py31-none-manylinux_2_6_x86_64
  py31-none-manylinux_2_5_x86_64
  py31-none-manylinux1_x86_64
  py31-none-linux_x86_64
  py30-none-manylinux_2_17_x86_64
  py30-none-manylinux2014_x86_64
  py30-none-manylinux_2_16_x86_64
  py30-none-manylinux_2_15_x86_64
  py30-none-manylinux_2_14_x86_64
  py30-none-manylinux_2_13_x86_64
  py30-none-manylinux_2_12_x86_64
  py30-none-manylinux2010_x86_64
  py30-none-manylinux_2_11_x86_64
  py30-none-manylinux_2_10_x86_64
  py30-none-manylinux_2_9_x86_64
  py30-none-manylinux_2_8_x86_64
  py30-none-manylinux_2_7_x86_64
  py30-none-manylinux_2_6_x86_64
  py30-none-manylinux_2_5_x86_64
  py30-none-manylinux1_x86_64
  py30-none-linux_x86_64
  cp36-none-any
  py36-none-any
  py3-none-any
  py35-none-any
  py34-none-any
  py33-none-any
  py32-none-any
  py31-none-any
  py30-none-any
#

@wfsteele
Copy link

wfsteele commented Sep 8, 2021

Thanks for the information! Do you happen to know off the top of your head if there’s a way I can install a framework Python to a different location? I know for non-framework I can do make altinstall but am not sure what the equivalent is for frameworkinstall.

If you want to make a completely independent framework installation, create a new user, say piptest01. Then:
-- Switch to that user account
-- obtain the python source distribution and expand the archive
-- cd to the top level directory of the expanded archive
-- run the following commands:

./configure --enable-framework=/Users/piptest01/Library/Frameworks
make
make frameworkinstall

Note: Some parts of the Standard Library won't get built unless libraries they need are preinstalled. But that probably doesn't matter for the testing of pip that you are concerned with.

More details (such as locations where things are stored, and more about frameworks) can be found by referring to:
https://github.com/python/cpython/blob/3.9/Mac/README.rst
which can also be found in the Mac subdirectory of the source distribution.

@uranusjr uranusjr changed the title Strange Python-3.8.2 behaviour for sysconfig Strange sysconfig behaviour for source-compiled Python Sep 10, 2021
@uranusjr
Copy link
Member

Title modified to account for additional information we’ve received.

@truongsondq
Copy link

At the suggestion of Mr. uranusjr at #10151 , I would like to report the problem I have encountered:
I installed python 3.9.7 on amazon linux 2. The steps:

cd /opt
sudo wget https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tgz
sudo tar xzf Python-3.9.7.tgz
cd Python-3.9.7
sudo ./configure --enable-optimizations 
sudo make altinstall 

and encountered the warning:

WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
distutils: /usr/local/include/python3.9/UNKNOWN
sysconfig: /opt/Python-3.9.7/Include/UNKNOWN
WARNING: Additional context:
user = False
home = None
root = '/'
prefix = None
Looking in links: /tmp/tmph1x66agw
Processing /tmp/tmph1x66agw/setuptools-57.4.0-py3-none-any.whl
Processing /tmp/tmph1x66agw/pip-21.2.3-py3-none-any.whl
Installing collected packages: setuptools, pip
  WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
  distutils: /usr/local/include/python3.9/setuptools
  sysconfig: /opt/Python-3.9.7/Include/setuptools
  WARNING: Value for scheme.headers does not match. Please report this to <https://github.com/pypa/pip/issues/10151>
  distutils: /usr/local/include/python3.9/pip
  sysconfig: /opt/Python-3.9.7/Include/pip
  WARNING: The script pip3.9 is installed in '/usr/local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed pip-21.2.3 setuptools-57.4.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

@uranusjr
Copy link
Member

So to summarise, this warning only occurs when you install Python (when Python automatically populates pip), right? After installation, pip whould work fine without emitting any warnings, at least that’s what I see from my expriements.

@truongsondq
Copy link

So to summarise, this warning only occurs when you install Python (when Python automatically populates pip), right? After installation, pip whould work fine without emitting any warnings, at least that’s what I see from my expriements.

Yes, I update pip to 21.2.4 and work fine without emitting any warnings.

@wfsteele
Copy link

wfsteele commented Sep 12, 2021 via email

@pradyunsg
Copy link
Member

Is there anything actionable left on this issue?

@pradyunsg pradyunsg added the S: awaiting response Waiting for a response/more information label Sep 21, 2021
@uranusjr
Copy link
Member

I want to add a special rule to silence the message for this specific situation. The root cause is that during CPython compilation, ensurepip is invoked against the python command in the build directory, not the install target. This triggers special logic (sysconfig.is_python_build()) that relocates the include directory. This is fundamentally fine (all wheels populated in ensurepip must only depend on built-in include files, even if we generalise it beyond pip and setuptools), so the warning message is superfulous on pip’s side.

@uranusjr uranusjr self-assigned this Sep 22, 2021
@pradyunsg pradyunsg removed the S: awaiting response Waiting for a response/more information label Sep 22, 2021
inmantaci pushed a commit to inmanta/inmanta-core that referenced this issue Oct 12, 2021
Bumps [pip](https://github.com/pypa/pip) from 21.2.4 to 21.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/pypa/pip/blob/main/NEWS.rst">pip's changelog</a>.</em></p>
<blockquote>
<h1>21.3 (2021-10-11)</h1>
<h2>Deprecations and Removals</h2>
<ul>
<li>Improve deprecation warning regarding the copying of source trees when installing from a local directory. (<code>[#10128](pypa/pip#10128) &lt;https://github.com/pypa/pip/issues/10128&gt;</code>_)</li>
<li>Suppress location mismatch warnings when pip is invoked from a Python source
tree, so <code>ensurepip</code> does not emit warnings on CPython <code>make install</code>. (<code>[#10270](pypa/pip#10270) &lt;https://github.com/pypa/pip/issues/10270&gt;</code>_)</li>
<li>On Python 3.10 or later, the installation scheme backend has been changed to use
<code>sysconfig</code>. This is to anticipate the deprecation of <code>distutils</code> in Python
3.10, and its scheduled removal in 3.12. For compatibility considerations, pip
installations running on Python 3.9 or lower will continue to use <code>distutils</code>. (<code>[#10358](pypa/pip#10358) &lt;https://github.com/pypa/pip/issues/10358&gt;</code>_)</li>
<li>Remove the <code>--build-dir</code> option and aliases, one last time. (<code>[#10485](pypa/pip#10485) &lt;https://github.com/pypa/pip/issues/10485&gt;</code>_)</li>
<li>In-tree builds are now the default. <code>--use-feature=in-tree-build</code> is now
ignored. <code>--use-deprecated=out-of-tree-build</code> may be used temporarily to ease
the transition. (<code>[#10495](pypa/pip#10495) &lt;https://github.com/pypa/pip/issues/10495&gt;</code>_)</li>
<li>Un-deprecate source distribution re-installation behaviour. (<code>[#8711](pypa/pip#8711) &lt;https://github.com/pypa/pip/issues/8711&gt;</code>_)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Replace vendored appdirs with platformdirs. (<code>[#10202](pypa/pip#10202) &lt;https://github.com/pypa/pip/issues/10202&gt;</code>_)</li>
<li>Support <code>PEP 610 &lt;https://www.python.org/dev/peps/pep-0610/&gt;</code>_ to detect
editable installs in <code>pip freeze</code> and  <code>pip list</code>. The <code>pip list</code> column output
has a new <code>Editable project location</code> column, and the JSON output has a new
<code>editable_project_location</code> field. (<code>[#10249](pypa/pip#10249) &lt;https://github.com/pypa/pip/issues/10249&gt;</code>_)</li>
<li><code>pip freeze</code> will now always fallback to reporting the editable project
location when it encounters a VCS error while analyzing an editable
requirement. Before, it sometimes reported the requirement as non-editable. (<code>[#10410](pypa/pip#10410) &lt;https://github.com/pypa/pip/issues/10410&gt;</code>_)</li>
<li><code>pip show</code> now sorts <code>Requires</code> and <code>Required-By</code> alphabetically. (<code>[#10422](pypa/pip#10422) &lt;https://github.com/pypa/pip/issues/10422&gt;</code>_)</li>
<li>Do not raise error when there are no files to remove with <code>pip cache purge/remove</code>.
Instead log a warning and continue (to log that we removed 0 files). (<code>[#10459](pypa/pip#10459) &lt;https://github.com/pypa/pip/issues/10459&gt;</code>_)</li>
<li>When backtracking during dependency resolution, prefer the dependencies which are involved in the most recent conflict. This can significantly reduce the amount of backtracking required. (<code>[#10479](pypa/pip#10479) &lt;https://github.com/pypa/pip/issues/10479&gt;</code>_)</li>
<li>Cache requirement objects, to improve performance reducing reparses of requirement strings. (<code>[#10550](pypa/pip#10550) &lt;https://github.com/pypa/pip/issues/10550&gt;</code>_)</li>
<li>Support editable installs for projects that have a <code>pyproject.toml</code> and use a
build backend that supports :pep:<code>660</code>. (<code>[#8212](pypa/pip#8212) &lt;https://github.com/pypa/pip/issues/8212&gt;</code>_)</li>
<li>When a revision is specified in a Git URL, use git's partial clone feature to speed up source retrieval. (<code>[#9086](pypa/pip#9086) &lt;https://github.com/pypa/pip/issues/9086&gt;</code>_)</li>
<li>Add a <code>--debug</code> flag, to enable a mode that doesn't log errors and propagates them to the top level instead. This is primarily to aid with debugging pip's crashes. (<code>[#9349](pypa/pip#9349) &lt;https://github.com/pypa/pip/issues/9349&gt;</code>_)</li>
<li>If a host is explicitly specified as trusted by the user (via the --trusted-host option), cache HTTP responses from it in addition to HTTPS ones. (<code>[#9498](pypa/pip#9498) &lt;https://github.com/pypa/pip/issues/9498&gt;</code>_)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li>Present a better error message, when a <code>file:</code> URL is not found. (<code>[#10263](pypa/pip#10263) &lt;https://github.com/pypa/pip/issues/10263&gt;</code>_)</li>
<li>Fix the auth credential cache to allow for the case in which
the index url contains the username, but the password comes
from an external source, such as keyring. (<code>[#10269](pypa/pip#10269) &lt;https://github.com/pypa/pip/issues/10269&gt;</code>_)</li>
<li>Fix double unescape of HTML <code>data-requires-python</code> and <code>data-yanked</code> attributes. (<code>[#10378](pypa/pip#10378) &lt;https://github.com/pypa/pip/issues/10378&gt;</code>_)</li>
<li>New resolver: Fixes depth ordering of packages during resolution, e.g. a dependency 2 levels deep will be ordered before a dependecy 3 levels deep. (<code>[#10482](pypa/pip#10482) &lt;https://github.com/pypa/pip/issues/10482&gt;</code>_)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/pypa/pip/commit/abec8a701bfa66aa15fedf4c898011aa2d95f29e"><code>abec8a7</code></a> Bump for release</li>
<li><a href="https://github.com/pypa/pip/commit/68a70486c9224f9d25be3cbf56c73d8a33c6a713"><code>68a7048</code></a> Update AUTHORS.txt</li>
<li><a href="https://github.com/pypa/pip/commit/9f18a403ca41f4e42fbb89d286b6571a099cb54b"><code>9f18a40</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10481">#10481</a> from notatallshaw/prefer_failures</li>
<li><a href="https://github.com/pypa/pip/commit/db496cbce518fa159476695db0cd4f1c1a8ab6f5"><code>db496cb</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10563">#10563</a> from pradyunsg/shorter-timeout</li>
<li><a href="https://github.com/pypa/pip/commit/4fac2b90a5d200b46e7b576013bb25f4ebb3f937"><code>4fac2b9</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10550">#10550</a> from jbylund/joe/cache_requirement_creation</li>
<li><a href="https://github.com/pypa/pip/commit/786957cf85a641d49b4cfcceef717ef229ac8238"><code>786957c</code></a> Use a shorter timeout, to ensure that this fails more often</li>
<li><a href="https://github.com/pypa/pip/commit/1e3c127d4a938643aca1bbc25e6581493e316476"><code>1e3c127</code></a> Avoid passing <code>.</code> to vendoring</li>
<li><a href="https://github.com/pypa/pip/commit/610424f9f8ad1f99d0a48bf9a53e7a9df4242304"><code>610424f</code></a> Quote &quot;PreferenceInformation&quot; to avoid runtime NameError</li>
<li><a href="https://github.com/pypa/pip/commit/c01b5c6d8a4858cf733408b4b020933f902dda9e"><code>c01b5c6</code></a> Update a test for resolvelib 0.8.0</li>
<li><a href="https://github.com/pypa/pip/commit/394a24eb1a5f9af5da7d4d2452ed5fe952de5db2"><code>394a24e</code></a> Upgrade resolvelib to 0.8.0</li>
<li>Additional commits viewable in <a href="https://github.com/pypa/pip/compare/21.2.4...21.3">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pip&package-manager=pip&previous-version=21.2.4&new-version=21.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

</details>
mergify bot pushed a commit to andrewbolster/bolster that referenced this issue Oct 12, 2021
Bumps [pip](https://github.com/pypa/pip) from 21.2.4 to 21.3.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/pypa/pip/blob/main/NEWS.rst">pip's changelog</a>.</em></p>
<blockquote>
<h1>21.3 (2021-10-11)</h1>
<h2>Deprecations and Removals</h2>
<ul>
<li>Improve deprecation warning regarding the copying of source trees when installing from a local directory. (<code>[#10128](pypa/pip#10128) &lt;https://github.com/pypa/pip/issues/10128&gt;</code>_)</li>
<li>Suppress location mismatch warnings when pip is invoked from a Python source
tree, so <code>ensurepip</code> does not emit warnings on CPython <code>make install</code>. (<code>[#10270](pypa/pip#10270) &lt;https://github.com/pypa/pip/issues/10270&gt;</code>_)</li>
<li>On Python 3.10 or later, the installation scheme backend has been changed to use
<code>sysconfig</code>. This is to anticipate the deprecation of <code>distutils</code> in Python
3.10, and its scheduled removal in 3.12. For compatibility considerations, pip
installations running on Python 3.9 or lower will continue to use <code>distutils</code>. (<code>[#10358](pypa/pip#10358) &lt;https://github.com/pypa/pip/issues/10358&gt;</code>_)</li>
<li>Remove the <code>--build-dir</code> option and aliases, one last time. (<code>[#10485](pypa/pip#10485) &lt;https://github.com/pypa/pip/issues/10485&gt;</code>_)</li>
<li>In-tree builds are now the default. <code>--use-feature=in-tree-build</code> is now
ignored. <code>--use-deprecated=out-of-tree-build</code> may be used temporarily to ease
the transition. (<code>[#10495](pypa/pip#10495) &lt;https://github.com/pypa/pip/issues/10495&gt;</code>_)</li>
<li>Un-deprecate source distribution re-installation behaviour. (<code>[#8711](pypa/pip#8711) &lt;https://github.com/pypa/pip/issues/8711&gt;</code>_)</li>
</ul>
<h2>Features</h2>
<ul>
<li>Replace vendored appdirs with platformdirs. (<code>[#10202](pypa/pip#10202) &lt;https://github.com/pypa/pip/issues/10202&gt;</code>_)</li>
<li>Support <code>PEP 610 &lt;https://www.python.org/dev/peps/pep-0610/&gt;</code>_ to detect
editable installs in <code>pip freeze</code> and  <code>pip list</code>. The <code>pip list</code> column output
has a new <code>Editable project location</code> column, and the JSON output has a new
<code>editable_project_location</code> field. (<code>[#10249](pypa/pip#10249) &lt;https://github.com/pypa/pip/issues/10249&gt;</code>_)</li>
<li><code>pip freeze</code> will now always fallback to reporting the editable project
location when it encounters a VCS error while analyzing an editable
requirement. Before, it sometimes reported the requirement as non-editable. (<code>[#10410](pypa/pip#10410) &lt;https://github.com/pypa/pip/issues/10410&gt;</code>_)</li>
<li><code>pip show</code> now sorts <code>Requires</code> and <code>Required-By</code> alphabetically. (<code>[#10422](pypa/pip#10422) &lt;https://github.com/pypa/pip/issues/10422&gt;</code>_)</li>
<li>Do not raise error when there are no files to remove with <code>pip cache purge/remove</code>.
Instead log a warning and continue (to log that we removed 0 files). (<code>[#10459](pypa/pip#10459) &lt;https://github.com/pypa/pip/issues/10459&gt;</code>_)</li>
<li>When backtracking during dependency resolution, prefer the dependencies which are involved in the most recent conflict. This can significantly reduce the amount of backtracking required. (<code>[#10479](pypa/pip#10479) &lt;https://github.com/pypa/pip/issues/10479&gt;</code>_)</li>
<li>Cache requirement objects, to improve performance reducing reparses of requirement strings. (<code>[#10550](pypa/pip#10550) &lt;https://github.com/pypa/pip/issues/10550&gt;</code>_)</li>
<li>Support editable installs for projects that have a <code>pyproject.toml</code> and use a
build backend that supports :pep:<code>660</code>. (<code>[#8212](pypa/pip#8212) &lt;https://github.com/pypa/pip/issues/8212&gt;</code>_)</li>
<li>When a revision is specified in a Git URL, use git's partial clone feature to speed up source retrieval. (<code>[#9086](pypa/pip#9086) &lt;https://github.com/pypa/pip/issues/9086&gt;</code>_)</li>
<li>Add a <code>--debug</code> flag, to enable a mode that doesn't log errors and propagates them to the top level instead. This is primarily to aid with debugging pip's crashes. (<code>[#9349](pypa/pip#9349) &lt;https://github.com/pypa/pip/issues/9349&gt;</code>_)</li>
<li>If a host is explicitly specified as trusted by the user (via the --trusted-host option), cache HTTP responses from it in addition to HTTPS ones. (<code>[#9498](pypa/pip#9498) &lt;https://github.com/pypa/pip/issues/9498&gt;</code>_)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li>Present a better error message, when a <code>file:</code> URL is not found. (<code>[#10263](pypa/pip#10263) &lt;https://github.com/pypa/pip/issues/10263&gt;</code>_)</li>
<li>Fix the auth credential cache to allow for the case in which
the index url contains the username, but the password comes
from an external source, such as keyring. (<code>[#10269](pypa/pip#10269) &lt;https://github.com/pypa/pip/issues/10269&gt;</code>_)</li>
<li>Fix double unescape of HTML <code>data-requires-python</code> and <code>data-yanked</code> attributes. (<code>[#10378](pypa/pip#10378) &lt;https://github.com/pypa/pip/issues/10378&gt;</code>_)</li>
<li>New resolver: Fixes depth ordering of packages during resolution, e.g. a dependency 2 levels deep will be ordered before a dependecy 3 levels deep. (<code>[#10482](pypa/pip#10482) &lt;https://github.com/pypa/pip/issues/10482&gt;</code>_)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/pypa/pip/commit/abec8a701bfa66aa15fedf4c898011aa2d95f29e"><code>abec8a7</code></a> Bump for release</li>
<li><a href="https://github.com/pypa/pip/commit/68a70486c9224f9d25be3cbf56c73d8a33c6a713"><code>68a7048</code></a> Update AUTHORS.txt</li>
<li><a href="https://github.com/pypa/pip/commit/9f18a403ca41f4e42fbb89d286b6571a099cb54b"><code>9f18a40</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10481">#10481</a> from notatallshaw/prefer_failures</li>
<li><a href="https://github.com/pypa/pip/commit/db496cbce518fa159476695db0cd4f1c1a8ab6f5"><code>db496cb</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10563">#10563</a> from pradyunsg/shorter-timeout</li>
<li><a href="https://github.com/pypa/pip/commit/4fac2b90a5d200b46e7b576013bb25f4ebb3f937"><code>4fac2b9</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/10550">#10550</a> from jbylund/joe/cache_requirement_creation</li>
<li><a href="https://github.com/pypa/pip/commit/786957cf85a641d49b4cfcceef717ef229ac8238"><code>786957c</code></a> Use a shorter timeout, to ensure that this fails more often</li>
<li><a href="https://github.com/pypa/pip/commit/1e3c127d4a938643aca1bbc25e6581493e316476"><code>1e3c127</code></a> Avoid passing <code>.</code> to vendoring</li>
<li><a href="https://github.com/pypa/pip/commit/610424f9f8ad1f99d0a48bf9a53e7a9df4242304"><code>610424f</code></a> Quote &quot;PreferenceInformation&quot; to avoid runtime NameError</li>
<li><a href="https://github.com/pypa/pip/commit/c01b5c6d8a4858cf733408b4b020933f902dda9e"><code>c01b5c6</code></a> Update a test for resolvelib 0.8.0</li>
<li><a href="https://github.com/pypa/pip/commit/394a24eb1a5f9af5da7d4d2452ed5fe952de5db2"><code>394a24e</code></a> Upgrade resolvelib to 0.8.0</li>
<li>Additional commits viewable in <a href="https://github.com/pypa/pip/compare/21.2.4...21.3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pip&package-manager=pip&previous-version=21.2.4&new-version=21.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug A confirmed bug or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants