# Technical Documentation: pypa/pip

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/pypa/pip)

### Overview (`build-project/README.md`)

# pip build

This is a project to build `pip` in a reproducible manner.

Running `python build-project.py` will produce pip build artifacts in `../dist`.

A weekly scheduled GitHub action will create a PR to update `pylock.toml` in
this directory.

---

### Html Getting Started (`docs/html/getting-started.md`)

# Getting Started

To get started with using pip, you should [install Python] on your system.

[install Python]: https://realpython.com/installing-python/

## Ensure you have a working pip

As a first step, you should check that you have a working Python with pip
installed. This can be done by running the following commands and making
sure that the output looks similar.

```{pip-cli}
$ python --version
Python 3.N.N
$ pip --version
pip X.Y.Z from ... (python 3.N.N)
```

If that worked, congratulations! You have a working pip in your environment.

If you got output that does not look like the sample above, please read
the {doc}`installation` page. It provides guidance on how to install pip
within a Python environment that doesn't have it.

## Common tasks

### Install a package

```{pip-cli}
$ pip install sampleproject
[...]
Successfully installed sampleproject
```

By default, pip will fetch packages from [Python Package Index][PyPI], a
repository of software for the Python programming language where anyone can
upload packages.

[PyPI]: https://pypi.org/

### Install a package from GitHub

```{pip-cli}
$ pip install git+https://github.com/pypa/sampleproject.git@main
[...]
Successfully installed sampleproject
```

See {doc}`topics/vcs-support` for more information about this syntax.

### Install a package from a distribution file

Pip can install directly from distribution files as well. They come in 2 forms:

- {term}`source distribution <Source Distribution (or "sdist")>` (usually shortened to "sdist")
- {term}`wheel distribution <Wheel>` (usually shortened to "wheel")

```{pip-cli}
$ pip install sampleproject-1.0.tar.gz
[...]
Successfully installed sampleproject
$ pip install sampleproject-1.0-py3-none-any.whl
[...]
Successfully installed sampleproject
```

### Install multiple packages using a requirements file

Many Python projects use {file}`requirements.txt` files, to specify the
list of packages that need to be installed for the project to run. To install
the packages listed in that file, you can run:

```{pip-cli}
$ pip install -r requirements.txt
[...]
Successfully installed sampleproject
```

### Upgrade a package

```{pip-cli}
$ pip install --upgrade sampleproject
   [...]
Successfully installed sampleproject
```

### Uninstall a package

```{pip-cli}
$ pip uninstall sampleproject
Uninstalling sampleproject:
   [...]
Proceed (Y/n)? y
Successfully uninstalled sampleproject
```

## Next Steps

It is recommended to learn about what virtual environments are and how to use
them. This is covered in the {doc}`Installing Packages <pypug:tutorials/installing-packages>`
tutorial on packaging.python.org.

---

### Html Index (`docs/html/index.md`)

---
hide-toc: true
---

# Pip

Pip is the [package installer for Python][recommended]. You can use it to
install packages from the [Python Package Index][pypi] and other indexes.

```{toctree}
:hidden:

getting-started
installation
user_guide
topics/index
reference/index
cli/index
```

```{toctree}
:caption: Project
:hidden:

development/index
ux-research-design/index
news
Code of Conduct <https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md>
GitHub <https://github.com/pypa/pip>
```

If you want to learn about how to use pip, check out the following resources:

- [Getting Started](getting-started)
- [Python Packaging User Guide](https://packaging.python.org)

If you find bugs, need help, or want to talk to the developers, use our mailing
lists or chat rooms:

- [GitHub Issues][issue-tracker]
- [Discourse channel][packaging-discourse]
- [User IRC][irc-pypa]
- [Development IRC][irc-pypa-dev]

[recommended]: https://packaging.python.org/guides/tool-recommendations/
[pypi]: https://pypi.org/
[issue-tracker]: https://github.com/pypa/pip/issues/
[packaging-discourse]: https://discuss.python.org/c/packaging/14
[irc-pypa]: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
[irc-pypa-dev]: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev

If you find any security issues, please report to [security@python.org](mailto:security@python.org)

## Privacy Notice

Pip does not collect any telemetry, however, it will send
non-identifying environment information (Python version, OS, etc.) to any remote indices
used, who may choose to retain such information. Please consult PyPI's privacy
policy for their data collection and retention practices.

---

### Html Cli Index (`docs/html/cli/index.md`)

# Commands

The general options that apply to all the commands listed below can be
found [under the `pip` page in this section](pip).

```{toctree}
:maxdepth: 1
:hidden:

pip
```

```{toctree}
:maxdepth: 1
:caption: Environment Management and Introspection

pip_install
pip_uninstall
pip_inspect
pip_list
pip_show
pip_freeze
pip_check
```

```{toctree}
:maxdepth: 1
:caption: Resolving dependencies

pip_lock
```

```{toctree}
:maxdepth: 1
:caption: Handling Distribution Files

pip_download
pip_wheel
pip_hash
```

```{toctree}
:maxdepth: 1
:caption: Package Index information

pip_search
pip_index
```

```{toctree}
:maxdepth: 1
:caption: Managing pip itself

pip_cache
pip_config
pip_debug
```

---

### Html Reference Index (`docs/html/reference/index.md`)

# Reference

Reference provides information about various file formats, interfaces and
interoperability standards that pip utilises/implements.

```{toctree}
:titlesonly:

build-system
requirement-specifiers
requirements-file-format
installation-report
inspect-report
```

---

### Html Topics Index (`docs/html/topics/index.md`)

# Topic Guides

These pages provide detailed information on individual topics.

```{note}
This section of the documentation is currently being fleshed out. See
{issue}`9475` for more details.
```

```{toctree}
:maxdepth: 1

authentication
caching
configuration
dependency-resolution
more-dependency-resolution
https-certificates
local-project-installs
repeatable-installs
secure-installs
vcs-support
python-option
workflow
```

---

### Html Ux Research Design Index (`docs/html/ux-research-design/index.md`)

# UX Research & Design

```{toctree}
:hidden:

contribute
guidance
research-results/index
```

Welcome to pip’s UX research and design documentation. The purpose of this section of the documentation is to:

- [Identify where new contributors can participate in or lead UX research and design activities](contribute)
- [Share pip UX guidelines](guidance), including an introduction to User Centered Design practices, and how they can be applied to the pip project
- Share [results of user research](research-results/index) that the pip team has already conducted

---

### Html Ux Research Design Research Results Index (`docs/html/ux-research-design/research-results/index.md`)

# UX Research Results

Over the course of 2020, the pip team worked on improving pip's user experience, developing a better understanding of pip's UX challenges and opportunities, with a particular focus on pip's new dependency resolver. The [Simply Secure](https://simplysecure.org/) team focused on 4 key areas:

- [Understanding who uses pip](https://github.com/pypa/pip/issues/8518)
- [Understanding how pip compares to other package managers, and supports other Python packaging tools](https://github.com/pypa/pip/issues/8515)
- [Understanding how pip's functionality is used could be improved](https://github.com/pypa/pip/issues/8516), and
- [Understanding how pip's documentation is used, and how it could be improved](https://github.com/pypa/pip/issues/8517)

Some key outcomes from the 2020 work are:

- This documentation & resource section!
- A pip UX research panel ([Sign up here!](https://mail.python.org/mailman3/lists/pip-ux-studies.python.org/))
- New and expanded GitHub issues
- UX improvements in 2020
  - UX work supporting the dependency resolver
  - Improved error messaging
  - Supporting Documentation
- UX Training for the Pypa + pip maintainers

This work was made possible through the [pip donor funded roadmap](https://wiki.python.org/psf/Pip2020DonorFundedRoadmap).

## Outreach

We [recruited participants](https://www.ei8fdb.org/thoughts/2020/03/pip-ux-study-recruitment/) for a user research panel that we could contact when we wanted to run surveys and interviews about pip. In total 472 people signed up to the panel, although some unsubscribed during the research period.

At the end of the 2020 research, we asked users to opt-in to a [long-term panel](https://mail.python.org/mailman3/lists/pip-ux-studies.python.org/), where they can be contacted for future UX studies. Should the pip team wish to continue to build this panel, we recommend translating the sign-up form into multiple languages and better leveraging local communities and outreach groups (e.g. PyLadies) to increase the diversity of the participants.

## User Interviews

In total, we **interviewed 48 pip users**, recruited from the user panel, and through social media channels.

During the interviews, we asked users about:

- How they use Python
- How long they have been using pip
- Whether or not they use a virtual environment
- If and how they address security issues associated with pip
- Which pip commands they regularly use
- How they install packages with pip
- Their experience using pip list, pip show and pip freeze
- Their experience using pip wheel
- Whether or not they use other package managers, and how pip compares to their experience with these other tools
- What the pip team could do to improve pip
- Problems they have experienced while using pip, and how they solved these problems
- Their perception and use of the pip documentation
- What other technical documentation they value, and how the pip docs could take inspiration from these
- What other resources the pip team could provide to help pip users solve their problems

## Surveys

We **published 10 surveys** to gather feedback about pip's users and their preferences:

<div class="wy-table-responsive">
  <table class="colwidths-auto docutils">
    <thead>
      <tr>
      <th>Title</th>
      <th>Purpose</th>
      <th>Results</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>
          Pip research panel survey
        </td>
        <td>
          Recruit pip users to participate in user research, user tests and participate in future surveys. See <a href="https://bit.ly/pip-ux-studies">associated blog post</a> for more information.
        </td>
        <td>
          472 full sign-ups
        </td>
      </tr>
      <tr>
        <td>
          Feedback for testing the new pip resolver
        </td>
        <td>
          Understand use cases where the new resolver fails due to dependency conflicts. See <a href="https://bit.ly/pip-ux-test-the-new-resolver">associated blog post</a> for more information.
        </td>
        <td>
          459 responses via the feedback form, approx. 8 issues transferred to issue tracker
        </td>
      </tr>
      <tr>
        <td>
          How should pip handle conflicts with already installed packages when updating other packages?
        </td>
        <td>
          Determine if the way that pip handles package upgrades is in-line with user's expectations/needs. See <a href="https://www.ei8fdb.org/thoughts/2020/07/how-should-pip-handle-conflicts-when-updating-already-installed-packages/">related blog post</a> and <a href="https://github.com/pypa/pip/issues/7744">GitHub issue</a> for more information.
        </td>
        <td>
          See <a href="pip-upgrade-conflict">write up, including recommendations</a>
        </td>
      </tr>
      <tr>
        <td>
          Learning about our users
        </td>
        <td>
          Learn about pip's users, including:
          <ul>
            <li>their usage of Python and pip</li>
            <li>why and how they started using Python</li>
            <li>if they are living with any disabilities, and if so what effect (if any) this has on their usage of Python and pip</li>
            <li>if they use assistive technologies when using Python and pip and how this work for them</li>
            <li>where they get support when you have issues with pip</li>
          </ul>
        </td>
        <td>
          See <a href="about-our-users">write up</a>
        </td>
      </tr>
      <tr>
        <td>
          Buy a pip feature
        </td>
        <td>
          Establish which features are most important to pip's users
        </td>
        <td>
          See <a href="prioritizing-features">write up</a>
        </td>
      </tr>
      <tr>
        <td>
          Should pip install conflicting dependencies?
        </td>
        <td>
          Establish whether pip should provide an override that allows users to install packages with conflicting dependencies
        </td>
        <td>
          See <a href="override-conflicting-dependencies">write up</a>
        </td>
      </tr>
      <tr>
        <td>
          How should pip force reinstall work?
        </td>
        <td>
          Establish whether or not pip force reinstall should continue to behave the way it currently does, if the functionality should be changed, or if the option should be removed
        </td>
        <td>
          See <a href="pip-force-reinstall">write up</a>
        </td>
      </tr>
      <tr>
        <td>
          Feedback on pip search
        </td>
        <td>
          To establish whether or not to remove or redesign pip search. See <a href="https://github.com/pypa/pip/issues/5216">this GitHub issue</a> for more information.
        </td>
        <td>
          See <a href="pip-search">write up</a>
        </td>
      </tr>
      <tr>
        <td>
          Feedback on pip's docs
        </td>
        <td>
          To gather feedback on pip's docs, supplementing feedback gathered in user interviews
        </td>
        <td>
          See <a href="improving-pips-documentation">write up</a>
        </td>
      </tr>
    </tbody>
  </table>
</div>

## All Results

```{toctree}
:maxdepth: 1

about-our-users
mental-models
users-and-security
ci-cd
personas
prioritizing-features
override-conflicting-dependencies
pip-force-reinstall
pip-search
pip-upgrade-conflict
improving-pips-documentation
```

## Read More

- [Pip team midyear report (blog, July 2020)](https://pyfound.blogspot.com/2020/07/pip-team-midyear-report.html)
- [Creating rapid CLI prototypes with cli-output (blog, Oct 2020)](https://www.ei8fdb.org/prototyping-command-line-interfaces-with-cli-output/)
- [Changes are coming to pip (video)](https://www.youtube.com/watch?v=B4GQCBBsuNU)
- [How should pip handle dependency conflicts when updating already installed packages? (blog, July 2020)](https://www.ei8fdb.org/how-should-pip-handle-conflicts-when-updating-already-installed-packages/)
- [Test pip's alpha resolver and help us document dependency conflicts (blog, May 2020)](https://www.ei8fdb.org/test-pips-alpha-resolver-and-help-us-document-dependency-conflicts/)
- [How do you deal with conflicting dependencies caused by pip installs? (blog, April 2020)](https://www.ei8fdb.org/how-do-you-deal-with-conflicting-dependencies-caused-by-pip-installs/)
- [pip UX studies: response data (blog, March 2020)](https://www.ei8fdb.org/pip-ux-studies-response-data/)

Other PyPA UX work:

- [PyPI User Research (blog, July 2018)](https://whoisnicoleharris.com/2018/07/22/pypi-user-research.html)
- [Warehouse - The Future of PyPI](https://whoisnicoleharris.com/warehouse/)
- [Accessibility on Warehouse (PyPI) (blog, May 2018)](https://whoisnicoleharris.com/2018/05/17/warehouse-accessibility.html)
- [User Testing Warehouse (blog, Mar 2018)](https://whoisnicoleharris.com/2018/03/13/user-testing-warehouse.html)
- [Designing Warehouse - An Overview (blog, Dec 2015)](https://whoisnicoleharris.com/2015/12/31/designing-warehouse-an-overview.html)

---

### Html Copyright (`docs/html/copyright.rst`)

:orphan:

=========
Copyright
=========

pip and this documentation is:

Copyright © 2008-2020 The pip developers (see `AUTHORS.txt <https://github.com/pypa/pip/blob/main/AUTHORS.txt>`_ file). All rights reserved.

---

### Html Installation (`docs/html/installation.md`)

# Installation

Usually, pip is automatically installed if you are:

- working in a
  {ref}`virtual environment <pypug:Creating and using Virtual Environments>`
- using Python downloaded from [python.org](https://www.python.org)
- using Python that has not been modified by a redistributor to remove
  {mod}`ensurepip`

## Supported Methods

If your Python environment does not have pip installed, there are 2 mechanisms
to install pip supported directly by pip's maintainers:

- [`ensurepip`](#ensurepip)
- [`get-pip.py`](#get-pippy)

### `ensurepip`

Python comes with an {mod}`ensurepip` module[^python], which can install pip in
a Python environment.

```{pip-cli}
$ python -m ensurepip --upgrade
```

More details about how {mod}`ensurepip` works and how it can be used, is
available in the standard library documentation.

### `get-pip.py`

This is a Python script that uses some bootstrapping logic to install
pip.

- Download the script, from <https://bootstrap.pypa.io/get-pip.py>.
- Open a terminal/command prompt, `cd` to the folder containing the
  `get-pip.py` file and run:

  ```{pip-cli}
  $ python get-pip.py
  ```

More details about this script can be found in [pypa/get-pip]'s README.

[pypa/get-pip]: https://github.com/pypa/get-pip

### Standalone zip application

```{note}
The zip application is currently experimental. We test that pip runs correctly
in this form, but it is possible that there could be issues in some situations.
We will accept bug reports in such cases, but for now the zip application should
not be used in production environments.
```

In addition to installing pip in your environment, pip is available as a
standalone [zip application](https://docs.python.org/3.11/library/zipapp.html).
This can be downloaded from <https://bootstrap.pypa.io/pip/pip.pyz>. There are
also zip applications for specific pip versions, named `pip-X.Y.Z.pyz`.

The zip application can be run using any supported version of Python:

```{pip-cli}
$ python pip.pyz --help
```

If run directly:

````{tab} Linux
```console
$ chmod +x ./pip.pyz
$ ./pip.pyz
```

then the currently active Python interpreter will be used.
````

````{tab} MacOS
```console
$ chmod +x ./pip.pyz
$ ./pip.pyz
```

then the currently active Python interpreter will be used.
````

````{tab} Windows
```doscon
C:> .\pip.pyz
```

then the currently active Python interpreter will be used.

You may need to configure your system to recognise the ``.pyz`` extension
before this will work.
````

## Alternative Methods

Depending on how you installed Python, there might be other mechanisms
available to you for installing pip such as
{ref}`using Linux package managers <pypug:installing pip/setuptools/wheel with linux package managers>`.

These mechanisms are provided by redistributors of pip, who may have modified
pip to change its behaviour. This has been a frequent source of user confusion,
since it causes a mismatch between documented behaviour in this documentation
and how pip works after those modifications.

If you face issues when using Python and pip installed using these mechanisms,
it is recommended to request for support from the relevant provider (eg: Linux
distro community, cloud provider support channels, etc).

## Upgrading `pip`

Upgrade your `pip` by running:

```{pip-cli}
$ pip install --upgrade pip
```

(compatibility-requirements)=

## Compatibility

The current version of pip works on:

- Windows, Linux and macOS.
- CPython 3.10, 3.11, 3.12, 3.13, 3.14, 3.15 and latest PyPy3.

Pip is tested to work on the latest patch version of the Python interpreter,
for each of the minor versions listed above. Previous patch versions are
supported on a best effort approach.

Other operating systems and Python versions are not supported by pip's
maintainers.

Users who are on unsupported platforms should be aware that if they hit issues, they may have to resolve them for themselves. If they received pip from a source which provides support for their platform, they should request pip support from that source.

[^python]: The `ensurepip` module was added to the Python standard library in Python 3.4.

---

### Html Installing (`docs/html/installing.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../installation/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`installation`

---

### Html News (`docs/html/news.rst`)

=========
Changelog
=========

.. attention::

    Major and minor releases of pip also include changes listed within
    prior beta releases.

.. towncrier-draft-entries:: Not yet released

.. pip-news-include:: ../../NEWS.rst

---

### Html Quickstart (`docs/html/quickstart.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../getting-started/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`getting-started`

---

### Html User Guide (`docs/html/user_guide.rst`)

==========
User Guide
==========

.. Hello there!

   If you're thinking of adding content to this page... please take a moment
   to consider if this content can live on its own, within a topic guide or a
   reference page.

   There is active effort being put toward *reducing* the amount of content on
   this specific page (https://github.com/pypa/pip/issues/9475) and moving it
   into more focused single-page documents that cover that specific topic.

Running pip
===========

Pip is a command line program. When you install pip, a ``pip`` command is added
to your system, which can be run from the command prompt as follows:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip <pip arguments>

   ``python -m pip`` executes pip using the Python interpreter you
   specified as python. So ``/usr/bin/python3.7 -m pip`` means
   you are executing pip for your interpreter located at ``/usr/bin/python3.7``.

.. tab:: Windows

   .. code-block:: shell

      py -m pip <pip arguments>

   ``py -m pip`` executes pip using the latest Python interpreter you
   have installed. For more details, read the `Python Windows launcher`_ docs.


Installing Packages
===================

Pip supports installing from `PyPI`_, version control, local projects, and
directly from distribution files.


The most common scenario is to install from `PyPI`_ using :ref:`Requirement
Specifiers`

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install SomePackage            # latest version
      python -m pip install SomePackage==1.0.4     # specific version
      python -m pip install 'SomePackage>=1.0.4'     # minimum version

.. tab:: Windows

   .. code-block:: shell

      py -m pip install SomePackage            # latest version
      py -m pip install SomePackage==1.0.4     # specific version
      py -m pip install 'SomePackage>=1.0.4'   # minimum version

For more information and examples, see the :ref:`pip install` reference.

.. _PyPI: https://pypi.org/

.. _`0-basic-authentication-credentials`:
.. rubric:: Basic Authentication Credentials

This is now covered in :doc:`topics/authentication`.

.. _`0-netrc-support`:
.. rubric:: netrc Support

This is now covered in :doc:`topics/authentication`.

.. _`0-keyring-support`:
.. rubric:: Keyring Support

This is now covered in :doc:`topics/authentication`.

Using a Proxy Server
====================

When installing packages from `PyPI`_, pip requires internet access, which
in many corporate environments requires an outbound HTTP proxy server.

Pip can be configured to connect through a proxy server in various ways:

* using the ``--proxy`` command-line option to specify a proxy in the form
  ``scheme://[user:passwd@]proxy.server:port``
* using ``proxy`` in a :ref:`config-file`
* by setting the standard environment-variables ``http_proxy``, ``https_proxy``
  and ``no_proxy``.
* using the ``--no-proxy-env`` command-line option to ignore proxies set through
  those environment variables (an explicit ``--proxy`` is still used).
* using the environment variable ``PIP_USER_AGENT_USER_DATA`` to include
  a JSON-encoded string in the user-agent variable used in pip's requests.


.. _`Requirements Files`:


Requirements Files
==================

"Requirements files" are files containing a list of items to be
installed using :ref:`pip install` like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install -r requirements.txt

Details on the format of the files are here: :ref:`requirements-file-format`.

Logically, a Requirements file is just a list of :ref:`pip install` arguments
placed in a file. Note that you should not rely on the items in the file being
installed by pip in any particular order.

Requirements files can also be served via a URL, e.g.
http://example.com/requirements.txt besides as local files, so that they can
be stored and served in a centralized place.

In practice, there are 4 common uses of Requirements files:

1. Requirements files are used to hold the result from :ref:`pip freeze` for the
   purpose of achieving :doc:`topics/repeatable-installs`.  In
   this case, your requirement file contains a pinned version of everything that
   was installed when ``pip freeze`` was run.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip freeze > requirements.txt
         python -m pip install -r requirements.txt

   .. tab:: Windows

      .. code-block:: shell

         py -m pip freeze > requirements.txt
         py -m pip install -r requirements.txt

2. Requirements files are used to force pip to properly resolve dependencies.
   pip 20.2 and earlier `doesn't have true dependency resolution
   <https://github.com/pypa/pip/issues/988>`_, but instead simply uses the first
   specification it finds for a project. E.g. if ``pkg1`` requires
   ``pkg3>=1.0`` and ``pkg2`` requires ``pkg3>=1.0,<=2.0``, and if ``pkg1`` is
   resolved first, pip will only use ``pkg3>=1.0``, and could easily end up
   installing a version of ``pkg3`` that conflicts with the needs of ``pkg2``.
   To solve this problem, you can place ``pkg3>=1.0,<=2.0`` (i.e. the correct
   specification) into your requirements file directly along with the other top
   level requirements. Like so::

     pkg1
     pkg2
     pkg3>=1.0,<=2.0

3. Requirements files are used to force pip to install an alternate version of a
   sub-dependency.  For example, suppose ``ProjectA`` in your requirements file
   requires ``ProjectB``, but the latest version (v1.3) has a bug, you can force
   pip to accept earlier versions like so::

     ProjectA
     ProjectB<1.3

4. Requirements files are used to override a dependency with a local patch that
   lives in version control.  For example, suppose a dependency
   ``SomeDependency`` from PyPI has a bug, and you can't wait for an upstream
   fix.
   You could clone/copy the src, make the fix, and place it in VCS with the tag
   ``sometag``.  You'd reference it in your requirements file with a line like
   so::

     SomeDependency @ git+https://myvcs.com/some_dependency@sometag

   If ``SomeDependency`` was previously a top-level requirement in your
   requirements file, then **replace** that line with the new line. If
   ``SomeDependency`` is a sub-dependency, then **add** the new line.


It's important to be clear that pip determines package dependencies using
the project metadata (typically in ``pyproject.toml`` or ``setup.py``),
not by discovering ``requirements.txt`` files embedded in projects.

See also:

* :ref:`requirements-file-format`
* :ref:`pip freeze`
* `"setup.py vs requirements.txt" (an article by Donald Stufft)
  <https://caremad.io/2013/07/setup-vs-requirement/>`_


.. _`Constraints Files`:


Constraints Files
=================

Constraints files are requirements files that only control which version of a
requirement is installed, not whether it is installed or not. Their syntax and
contents is a subset of :ref:`Requirements Files`, with several kinds of syntax
not allowed: constraints must have a name, they cannot be editable, and they
cannot specify extras. In terms of semantics, there is one key difference:
Including a package in a constraints file does not trigger installation of the
package.

Use a constraints file like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install -c constraints.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install -c constraints.txt

Constraints files are used for exactly the same reason as requirements files
when you don't know exactly what things you want to install. For instance, say
that the "helloworld" package doesn't work in your environment, so you have a
local patched version. Some things you install depend on "helloworld", and some
don't.

One way to ensure that the patched version is used consistently is to
manually audit the dependencies of everything you install, and if "helloworld"
is present, write a requirements file to use when installing that thing.

Constraints files offer a better way: write a single constraints file for your
organisation and use that everywhere. If the thing being installed requires
"helloworld" to be installed, your fixed version specified in your constraints
file will be used.

Constraints file support was added in pip 7.1. In :ref:`Resolver
changes 2020` we did a fairly comprehensive overhaul, removing several
undocumented and unsupported quirks from the previous implementation,
and stripped constraints files down to being purely a way to specify
global (version) limits for packages.

Same as requirements files, constraints files can also be served via a URL,
e.g. http://example.com/constraints.txt, so that your organization can store and
serve them in a centralized place.


.. _`Build Constraints`:

Build Constraints
-----------------

.. versionadded:: 25.3

.. versionchanged:: 26.2
   Constraints files, including those set with the ``PIP_CONSTRAINT`` environment
   variable, no longer affect isolated build environments. Use build constraints
   to constrain build dependencies.

Build constraints are a type of constraints file that applies only to isolated
build environments used for building packages from source. Unlike regular
constraints, which affect the packages installed in your environment, build
constraints only influence the versions of packages available during the
build process.

This is useful when you need to constrain build dependencies
(such as ``setuptools``, ``cython``, etc.) without affecting the
final installed environment.

Use build constraints like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --build-constraint build-constraints.txt SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --build-constraint build-constraints.txt SomePackage

Example build constraints file (``build-constraints.txt``):

.. code-block:: text

   # Constrain setuptools version during build
   setuptools>=45,<80
   # Pin Cython for packages that use it to build
   cython==0.29.24

The ``--build-constraint`` option can be set with the ``PIP_BUILD_CONSTRAINT``
environment variable.

Controlling Pre-release Installation
=====================================

.. versionadded:: 26.0

By default, pip installs stable versions of packages, unless their specifier includes
a pre-release version (e.g., ``SomePackage>=1.0a1``) or if there are no stable versions
available that satisfy the requirement. The ``--all-releases`` and ``--only-final``
options provide per-package control over pre-release selection.

Use ``--all-releases`` to allow pre-releases for specific packages:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --all-releases=DependencyPackage SomePackage
      python -m pip install --all-releases=:all: SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --all-releases=DependencyPackage SomePackage
      py -m pip install --all-releases=:all: SomePackage

Use ``--only-final`` to explicitly disable pre-releases for specific packages:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --only-final=DependencyPackage SomePackage
      python -m pip install --only-final=:all: SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --only-final=DependencyPackage SomePackage
      py -m pip install --only-final=:all: SomePackage

Both options accept ``:all:`` to apply to all packages, ``:none:`` to clear
the setting, or comma-separated package names. Package-specific settings
override ``:all:``. These options can also be used in requirements files.

.. note::

   The ``--pre`` flag is equivalent to ``--all-releases :all:`` but cannot
   be combined with ``--all-releases`` or ``--only-final``.


.. _`Filtering by Upload Time`:

Filtering by Upload Time
=========================

.. versionadded:: 26.0

The ``--uploaded-prior-to`` option allows you to filter packages by their upload time
to an index, only considering packages that were uploaded before a specified value.
This can be useful for creating reproducible builds by ensuring you only install
packages that were available at a known point in time.

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --uploaded-prior-to=2025-03-16T00:00:00Z SomePackage
      python -m pip install --uploaded-prior-to=P3D SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --uploaded-prior-to=2025-03-16T00:00:00Z SomePackage
      py -m pip install --uploaded-prior-to=P3D SomePackage

The option accepts ISO 8601 datetime strings in several formats:

* ``2025-03-16`` - Date in local timezone
* ``2025-03-16T12:30:00`` - Datetime in local timezone
* ``2025-03-16T12:30:00Z`` - Datetime in UTC
* ``2025-03-16T12:30:00+05:00`` - Datetime in UTC offset

For consistency across machines, use either UTC format (with 'Z' suffix) or UTC offset
format (with timezone offset like '+05:00'). Local timezone formats may produce different
results on different machines.

.. versionchanged:: 26.1

``--uploaded-prior-to`` also accepts a duration in the ``PnD`` format, where ``n`` is
the number of days. This only considers packages uploaded at least ``n`` days ago.
A day is always 24 hours; daylight savings and other time zone transitions are ignored.

* ``P3D`` - uploaded at least 3 days ago
* ``P7D`` - uploaded at least 7 days ago
* ``P30D`` - uploaded at least 30 days ago

To override a duration set in configuration, pass ``P0D`` on the command line.

.. warning::

    While a duration can help protect against supply chain attacks by avoiding
    newly published packages, it will also delay security fixes reaching your
    environment. If you use this option, pair it with a vulnerability scanning
    tool such as Dependabot or pip-audit so that you are notified of security
    issues independently of your update schedule.

.. note::

    This option only applies to packages from remote indexes, not local files or VCS
    requirements. Local package files are allowed regardless of the
    ``--uploaded-prior-to`` setting, e.g. ``pip install /path/to/package.whl``,
    packages from ``--find-links`` directories, or VCS requirements like
    ``git+https://...``.

    This option requires package indexes that provide upload-time metadata
    (such as PyPI). If the index does not provide upload-time metadata for a
    package file, pip will fail immediately with an error message indicating
    that upload-time metadata is required when using ``--uploaded-prior-to``.

You can combine this option with other filtering mechanisms like constraints files:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install -c constraints.txt --uploaded-prior-to=2025-03-16 SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install -c constraints.txt --uploaded-prior-to=2025-03-16 SomePackage

.. _`Refresh Package`:

Refreshing Package Metadata
===========================

.. versionadded:: 26.2

By default, pip may use cached package index information when looking for packages.
If you have just published a new version of a package and want to
install it immediately without waiting for the cache to expire, use
``--refresh-package``:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --refresh-package=requests requests

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --refresh-package=requests requests

The option accepts ``:all:`` to force refresh for all packages, ``:none:`` to
disable refresh entirely, or a comma-separated list of package names to refresh
only specific packages:

.. tab:: Unix/macOS

   .. code-block:: shell

      # Refresh metadata for a single package
      python -m pip install --refresh-package=requests requests

      # Refresh metadata for multiple packages
      python -m pip install --refresh-package=requests,urllib3 requests urllib3

      # Refresh metadata for all packages
      python -m pip install --refresh-package=:all: -r requirements.txt

      # Disable refresh explicitly
      python -m pip install --refresh-package=:none: -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --refresh-package=requests requests
      py -m pip install --refresh-package=requests,urllib3 requests urllib3
      py -m pip install --refresh-package=:all: -r requirements.txt
      py -m pip install --refresh-package=:none: -r requirements.txt

.. _`Dependency Groups`:


Dependency Groups
=================

.. versionadded:: 25.1

"Dependency Groups" are lists of items to be installed stored in a
``pyproject.toml`` file.

A dependency group is logically just a list of requirements, similar to the
contents of :ref:`Requirements Files`. Unlike requirements files, dependency
groups cannot contain non-package arguments for :ref:`pip install`.

Groups can be declared like so:

.. code-block:: toml

    # pyproject.toml
    [dependency-groups]
    groupA = [
        "pkg1",
        "pkg2",
    ]

and installed with :ref:`pip install` like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --group groupA

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --group groupA

Full details on the contents of ``[dependency-groups]`` and more examples are
available in :ref:`the specification documentation <pypug:dependency-groups>`.

.. note::

    Dependency Groups are defined by a standard, and therefore do not support
    ``pip``-specific syntax for requirements, only :ref:`standard dependency
    specifiers <pypug:dependency-specifiers>`.

Pip does not search projects or directories to discover ``pyproject.toml``
files. The ``--group`` option is used to pass the path to the file,
and if the path is omitted, as in the example above, it defaults to
``pyproject.toml`` in the current directory. Using explicit paths,
:ref:`pip install` can use a file from another directory. For example:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --group './project/subproject/pyproject.toml:groupA'

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --group './project/subproject/pyproject.toml:groupA'


This also makes it possible to install groups from multiple different projects
at once. For example, with a directory structure like so::

    + project/
      + sub1/
        - pyproject.toml
      + sub2/
        - pyproject.toml

it is possible to install, from the ``project/`` directory, groups from the
subprojects thusly:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --group './sub1/pyproject.toml:groupA' --group './sub2/pyproject.toml:groupB'

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --group './sub1/pyproject.toml:groupA' --group './sub2/pyproject.toml:groupB'


.. _`Installing from Wheels`:


Installing only dependencies
============================

.. versionadded:: 26.2

In some cases it is desirable to install only the dependencies of a package, not
the package itself. This is possible with the ``--only-deps`` flag, which
instructs pip to handle only the dependencies of the supplied packages.
Consider the package ``SomePackage`` with the dependency ``SomeDependency``. To
install ``SomeDependency`` but not ``SomePackage``:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install SomePackage --only-deps

.. tab:: Windows

   .. code-block:: shell

      py -m pip install SomePackage --only-deps

Note that ``--only-deps`` is incompatible with the legacy resolver
(``--use-deprecated=legacy-resolver``), dependency groups (``--group``), ``-r``/
``--requirement``, ``--requirements-from-script``, and ``--no-deps``.

In some situations, ``--only-deps`` can exhibit seemingly confusing behavior.
Consider the example above: ``SomePackage`` which depends on ``SomeDependency``.
If you specify both with ``--only-deps``, pip will not install
``SomeDependency``, as both dependencies are user-supplied:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install SomePackage SomeDependency --only-deps

.. tab:: Windows

   .. code-block:: shell

      py -m pip install SomePackage SomeDependency --only-deps

The reason is that it is impossible to know what the intent of the user is, as
pip cannot guess if the user wants to install ``SomeDependency`` as a dependency
of ``SomePackage`` or if they do not want to install it. To keep the
implementation easy and err on the side of caution, pip will thus not install
SomeDependency.


A note on ``--only-deps`` and ``--requirement`` / ``--requirements-from-script`` and ``--group``
-------------------------------------------------------------------------------------------------

The ``--only-deps`` option is inherently incompatible with ``--requirement``
and ``--group``.

In the ``--requirements`` case, all specified packages are considered to be
user-supplied; thus when pip would allow both options together, no packages
listed in the requirements file would be installed, but all dependencies not
listed would be. The same applies for ``--requirements-from-script``.

Similarly, the ``--group`` option already allows to install only a set of
dependencies meant for a specific purpose, e.g., for building the documentation
or setting up a developer environment. Pip considers the members of the group to
be user-supplied. Pairing this with ``--only-deps`` would make it impossible to
know if the user wanted to install the dependencies of the packages listed in
the group, or if they were expecting the packages of the group to be installed.


Installing from Wheels
======================

"Wheel" is a built, archive format that can greatly speed installation compared
to building and installing from source archives. For more information, see the
:ref:`specification <pypug:binary-distribution-format>`.

Pip prefers wheels where they are available. To disable this, use the
:ref:`--no-binary <install_--no-binary>` flag for :ref:`pip install`.

If no satisfactory wheels are found, pip will default to finding source
archives.


To install directly from a wheel archive:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install SomePackage-1.0-py2.py3-none-any.whl

.. tab:: Windows

   .. code-block:: shell

      py -m pip install SomePackage-1.0-py2.py3-none-any.whl

To include optional dependencies provided in the ``provides_extras``
metadata in the wheel, you must add quotes around the install target
name:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install './somepackage-1.0-py2.py3-none-any.whl[my-extras]'

.. tab:: Windows

   .. code-block:: shell

      py -m pip install './somepackage-1.0-py2.py3-none-any.whl[my-extras]'

.. note::

    In the future, the ``path[extras]`` syntax may become deprecated. It is
    recommended to use :ref:`standard <pypug:dependency-specifiers>`
    syntax wherever possible.

For the cases where wheels are not available, pip offers :ref:`pip wheel` as a
convenience, to build wheels for all your requirements and dependencies.

To build wheels for your requirements and all their dependencies to a local
directory:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install wheel
      python -m pip wheel --wheel-dir=/local/wheels -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install wheel
      py -m pip wheel --wheel-dir=/local/wheels -r requirements.txt

And *then* to install those requirements just using your local directory of
wheels (and not from PyPI):

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --no-index --find-links=/local/wheels -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --no-index --find-links=/local/wheels -r requirements.txt


Uninstalling Packages
=====================

Pip is able to uninstall most packages like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip uninstall SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip uninstall SomePackage


Pip also performs an automatic uninstall of an old version of a package
before upgrading to a newer version.

For more information and examples, see the :ref:`pip uninstall` reference.


Listing Packages
================

To list installed packages:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip list
      docutils (0.9.1)
      Jinja2 (2.6)
      Pygments (1.5)
      Sphinx (1.1.2)

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip list
      docutils (0.9.1)
      Jinja2 (2.6)
      Pygments (1.5)
      Sphinx (1.1.2)


To list outdated packages, and show the latest version available:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip list --outdated
      docutils (Current: 0.9.1 Latest: 0.10)
      Sphinx (Current: 1.1.2 Latest: 1.1.3)

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip list --outdated
      docutils (Current: 0.9.1 Latest: 0.10)
      Sphinx (Current: 1.1.2 Latest: 1.1.3)

To show details about an installed package:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip show sphinx
      ---
      Name: Sphinx
      Version: 1.1.3
      Location: /my/env/lib/pythonx.x/site-packages
      Requires: Pygments, Jinja2, docutils

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip show sphinx
      ---
      Name: Sphinx
      Version: 1.1.3
      Location: /my/env/lib/pythonx.x/site-packages
      Requires: Pygments, Jinja2, docutils

For more information and examples, see the :ref:`pip list` and :ref:`pip show`
reference pages.


Searching for Packages
======================

Pip can search remote indexes that provide an XML-RPC search API for
packages using the ``pip search`` command:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip search "query"

.. tab:: Windows

   .. code-block:: shell

      py -m pip search "query"

The query will be used to search the names and summaries of all
packages.

.. note::

   `PyPI`_ has removed its XML-RPC search API, so ``pip search`` no longer
   works against PyPI. To search for packages on PyPI, use the
   `PyPI search page <https://pypi.org/search/>`_ in a browser instead.

For more information and examples, see the :ref:`pip search` reference.

.. _`0-configuration`:
.. rubric:: Configuration

This is now covered in :doc:`topics/configuration`.

.. _`0-config-file`:
.. rubric:: Config file

This is now covered in :doc:`topics/configuration`.

.. _`0-environment-variables`:
.. rubric:: Environment Variables

This is now covered in :doc:`topics/configuration`.

.. _`0-config-precedence`:
.. rubric:: Config Precedence

This is now covered in :doc:`topics/configuration`.

Command Completion
==================

Pip comes with support for command line completion in bash, zsh and fish.

To setup for bash::

    python -m pip completion --bash >> ~/.profile

To setup for zsh::

    python -m pip completion --zsh >> ~/.zshrc

If you see ``command not found: compdef``, ensure your ``~/.zshrc`` initializes
auto-completion (for example, by running ``autoload -Uz compinit && compinit``)
before the appended pip snippet.

To setup for fish::

    python -m pip completion --fish > ~/.config/fish/completions/pip.fish

To setup for powershell::

   python -m pip completion --powershell | Out-File -Encoding default -Append $PROFILE

Alternatively, you can use the result of the ``completion`` command directly
with the eval function of your shell, e.g. by adding the following to your
startup file::

    eval "`pip completion --bash`"



.. _`Installing from local packages`:


Installing from local packages
==============================

In some cases, you may want to install from local packages only, with no traffic
to PyPI.

First, download the archives that fulfill your requirements:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip download --destination-directory DIR -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip download --destination-directory DIR -r requirements.txt

Note that ``pip download`` will look in your wheel cache first, before
trying to download from PyPI.  If you've never installed your requirements
before, you won't have a wheel cache for those items.  In that case, if some of
your requirements don't come as wheels from PyPI, and you want wheels, then run
this instead:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip wheel --wheel-dir DIR -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip wheel --wheel-dir DIR -r requirements.txt

Then, to install from local only, you'll be using :ref:`--find-links
<install_--find-links>` and :ref:`--no-index <install_--no-index>` like so:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --no-index --find-links=DIR -r requirements.txt

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --no-index --find-links=DIR -r requirements.txt


"Only if needed" Recursive Upgrade
==================================

``pip install --upgrade`` now has a ``--upgrade-strategy`` option which
controls how pip handles upgrading of dependencies. There are 2 upgrade
strategies supported:

- ``eager``: upgrades all dependencies regardless of whether they still satisfy
  the new parent requirements
- ``only-if-needed``: upgrades a dependency only if it does not satisfy the new
  parent requirements

The default strategy is ``only-if-needed``. This was changed in pip 10.0 due to
the breaking nature of ``eager`` when upgrading conflicting dependencies.

It is important to note that ``--upgrade`` affects *direct requirements* (e.g.
those specified on the command-line or via a requirements file) while
``--upgrade-strategy`` affects *indirect requirements* (dependencies of direct
requirements).

As an example, say ``SomePackage`` has a dependency, ``SomeDependency``, and
both of them are already installed but are not the latest available versions:

- ``pip install SomePackage``: will not upgrade the existing ``SomePackage`` or
  ``SomeDependency``.
- ``pip install --upgrade SomePackage``: will upgrade ``SomePackage``, but not
  ``SomeDependency`` (unless a minimum requirement is not met).
- ``pip install --upgrade SomePackage --upgrade-strategy=eager``: upgrades both
  ``SomePackage`` and ``SomeDependency``.

As an historic note, an earlier "fix" for getting the ``only-if-needed``
behaviour was:

.. tab:: Unix/macOS

   .. code-block:: shell

      python -m pip install --upgrade --no-deps SomePackage
      python -m pip install SomePackage

.. tab:: Windows

   .. code-block:: shell

      py -m pip install --upgrade --no-deps SomePackage
      py -m pip install SomePackage


A proposal for an ``upgrade-all`` command is being considered as a safer
alternative to the behaviour of eager upgrading.


User Installs
=============

With Python 2.6 came the `"user scheme" for installation
<https://docs.python.org/3/library/sysconfig.html#sysconfig-user-scheme>`_,
which means that all Python distributions support an alternative install
location that is specific to a user.  The default location for each OS is
explained in the python documentation for the `site.USER_BASE
<https://docs.python.org/3/library/site.html#site.USER_BASE>`_ variable.
This mode of installation can be turned on by specifying the :ref:`--user
<install_--user>` option to ``pip install``.

Moreover, the "user scheme" can be customized by setting the
``PYTHONUSERBASE`` environment variable, which updates the value of
``site.USER_BASE``.

To install "SomePackage" into an environment with ``site.USER_BASE`` customized to
'/myappenv', do the following:

.. tab:: Unix/macOS

   .. code-block:: shell

      export PYTHONUSERBASE=/myappenv
      python -m pip install --user SomePackage

.. tab:: Windows

   .. code-block:: shell

      set PYTHONUSERBASE=c:/myappenv
      py -m pip install --user SomePackage

``pip install --user`` follows four rules:

#. When globally installed packages are on the python path, and they *conflict*
   with the installation requirements, they are ignored, and *not*
   uninstalled.
#. When globally installed packages are on the python path, and they *satisfy*
   the installation requirements, pip does nothing, and reports that
   requirement is satisfied (similar to how global packages can satisfy
   requirements when installing packages in a ``--system-site-packages``
   virtualenv).
#. Pip will not perform a ``--user`` install in a ``--no-site-packages``
   virtualenv (i.e. the default kind of virtualenv), due to the user site not
   being on the python path.  The installation would be pointless.
#. In a ``--system-site-packages`` virtualenv, pip will not install a package
   that conflicts with a package in the virtualenv site-packages.  The --user
   installation would lack sys.path precedence and be pointless.


To make the rules clearer, here are some examples:

From within a ``--no-site-packages`` virtualenv (i.e. the default kind):

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install --user SomePackage
      Can not perform a '--user' install. User site-packages are not visible in this virtualenv.

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install --user SomePackage
      Can not perform a '--user' install. User site-packages are not visible in this virtualenv.


From within a ``--system-site-packages`` virtualenv where ``SomePackage==0.3``
is already installed in the virtualenv:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install --user SomePackage==0.4
      Will not install to the user site because it will lack sys.path precedence

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install --user SomePackage==0.4
      Will not install to the user site because it will lack sys.path precedence

From within a real python, where ``SomePackage`` is *not* installed globally:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install --user SomePackage
      [...]
      Successfully installed SomePackage

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install --user SomePackage
      [...]
      Successfully installed SomePackage

From within a real python, where ``SomePackage`` *is* installed globally, but
is *not* the latest version:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install --user SomePackage
      [...]
      Requirement already satisfied (use --upgrade to upgrade)
      $ python -m pip install --user --upgrade SomePackage
      [...]
      Successfully installed SomePackage

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install --user SomePackage
      [...]
      Requirement already satisfied (use --upgrade to upgrade)
      C:\> py -m pip install --user --upgrade SomePackage
      [...]
      Successfully installed SomePackage

From within a real python, where ``SomePackage`` *is* installed globally, and
is the latest version:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install --user SomePackage
      [...]
      Requirement already satisfied (use --upgrade to upgrade)
      $ python -m pip install --user --upgrade SomePackage
      [...]
      Requirement already up-to-date: SomePackage
      # force the install
      $ python -m pip install --user --ignore-installed SomePackage
      [...]
      Successfully installed SomePackage

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install --user SomePackage
      [...]
      Requirement already satisfied (use --upgrade to upgrade)
      C:\> py -m pip install --user --upgrade SomePackage
      [...]
      Requirement already up-to-date: SomePackage
      # force the install
      C:\> py -m pip install --user --ignore-installed SomePackage
      [...]
      Successfully installed SomePackage

.. _`0-repeatability`:
.. _`0-ensuring-repeatability`:
.. rubric:: Ensuring Repeatability

This is now covered in :doc:`../topics/repeatable-installs`.

.. _`0-fixing-conflicting-dependencies`:
.. rubric:: Fixing conflicting dependencies

This is now covered in :doc:`../topics/dependency-resolution`.

.. _`Using pip from your program`:

Using pip from your program
===========================

As noted previously, pip is a command line program. While it is implemented in
Python, and so is available from your Python code via ``import pip``, you must
not use pip's internal APIs in this way. There are a number of reasons for this:

#. The pip code assumes that it is in sole control of the global state of the
   program.
   pip manages things like the logging system configuration, or the values of
   the standard IO streams, without considering the possibility that user code
   might be affected.

#. Pip's code is *not* thread safe. If you were to run pip in a thread, there
   is no guarantee that either your code or pip's would work as you expect.

#. Pip assumes that once it has finished its work, the process will terminate.
   It doesn't need to handle the possibility that other code will continue to
   run after that point, so (for example) calling pip twice in the same process
   is likely to have issues.

This does not mean that the pip developers are opposed in principle to the idea
that pip could be used as a library - it's just that this isn't how it was
written, and it would be a lot of work to redesign the internals for use as a
library, handling all of the above issues, and designing a usable, robust and
stable API that we could guarantee would remain available across multiple
releases of pip. And we simply don't currently have the resources to even
consider such a task.

What this means in practice is that everything inside of pip is considered an
implementation detail. Even the fact that the import name is ``pip`` is subject
to change without notice. While we do try not to break things as much as
possible, all the internal APIs can change at any time, for any reason. It also
means that we generally *won't* fix issues that are a result of using pip in an
unsupported way.

It should also be noted that installing packages into ``sys.path`` in a running
Python process is something that should only be done with care. The import
system caches certain data, and installing new packages while a program is
running may not always behave as expected. In practice, there is rarely an
issue, but it is something to be aware of.

Having said all of the above, it is worth covering the options available if you
decide that you do want to run pip from within your program. The most reliable
approach, and the one that is fully supported, is to run pip in a subprocess.
This is easily done using the standard ``subprocess`` module::

  subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'my_package'])

If you want to process the output further, use one of the other APIs in the module.
We are using `freeze`_ here which outputs installed packages in requirements format.::

  reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])

To programmatically monitor download progress use the ``--progress-bar=raw`` option.
This will print lines to stdout in the format ``Progress CURRENT of TOTAL``, where
``CURRENT`` and ``TOTAL`` are integers and the unit is bytes.
If the real total is unknown then ``TOTAL`` is set to ``0``. Be aware that the
specific formatting of pip's outputs are *not* guaranteed to be the same in future versions.

If you don't want to use pip's command line functionality, but are rather
trying to implement code that works with Python packages, their metadata, or
PyPI, then you should consider other, supported, packages that offer this type
of ability. Some examples that you could consider include:

* ``packaging`` - Utilities to work with standard package metadata (versions,
  requirements, etc.)

* ``importlib.metadata`` in the Python stdlib - Functions for querying what
  packages the user has installed on their system.

* ``distlib`` - Packaging and distribution utilities (including functions for
  interacting with PyPI).

.. _changes-to-the-pip-dependency-resolver-in-20-2-2020:

.. _`Resolver changes 2020`:

Changes to the pip dependency resolver in 20.3 (2020)
=====================================================

Pip 20.3 has a new dependency resolver, on by default for Python 3
users. (Pip 20.1 and 20.2 included pre-release versions of the new
dependency resolver, hidden behind optional user flags.) Read below
for a migration guide, how to invoke the legacy resolver, and the
deprecation timeline. We also made a `two-minute video explanation`_
you can watch.

We will continue to improve the pip dependency resolver in response to
testers' feedback. Please give us feedback through the `resolver
testing survey`_.

.. _`Migration guide for 2020 resolver changes`:

Watch out for
-------------

The big change in this release is to the pip dependency resolver
within pip.

Computers need to know the right order to install pieces of software
("to install ``x``, you need to install ``y`` first"). So, when Python
programmers share software as packages, they have to precisely describe
those installation prerequisites, and pip needs to navigate tricky
situations where it's getting conflicting instructions. This new
dependency resolver will make pip better at handling that tricky
logic, and make pip easier for you to use and troubleshoot.

The most significant changes to the resolver are:

* It will **reduce inconsistency**: it will *no longer install a
  combination of packages that is mutually inconsistent*. In older
  versions of pip, it is possible for pip to install a package which
  does not satisfy the declared requirements of another installed
  package. For example, in pip 20.0, ``pip install "six<1.12"
  "virtualenv==20.0.2"`` does the wrong thing, “successfully” installing
  ``six==1.11``, even though ``virtualenv==20.0.2`` requires
  ``six>=1.12.0,<2`` (`defined here
  <https://github.com/pypa/virtualenv/blob/20.0.2/setup.cfg#L42-L50>`__).
  The new resolver, instead, outright rejects installing anything if it
  gets that input.

* It will be **stricter** - if you ask pip to install two packages with
  incompatible requirements, it will refuse (rather than installing a
  broken combination, like it did in previous versions).

So, if you have been using workarounds to force pip to deal with
incompatible or inconsistent requirements combinations, now's a good
time to fix the underlying problem in the packages, because pip will
be stricter from here on out.

This also means that, when you run a ``pip install`` command, pip only
considers the packages you are installing in that command, and **may
break already-installed packages**. It will not guarantee that your
environment will be consistent all the time. If you ``pip install x``
and then ``pip install y``, it's possible that the version of ``y``
you get will be different than it would be if you had run ``pip
install x y`` in a single command. We are considering changing this
behavior (per :issue:`7744`) and would like your thoughts on what
pip's behavior should be; please answer `our survey on upgrades that
create conflicts`_.

We are also changing our support for :ref:`Constraints Files`,
editable installs, and related functionality. We did a fairly
comprehensive overhaul and stripped constraints files down to being
purely a way to specify global (version) limits for packages, and so
some combinations that used to be allowed will now cause
errors. Specifically:

* Constraints don't override the existing requirements; they simply
  constrain what versions are visible as input to the resolver (see
  :issue:`9020`)
* Providing an editable requirement (``-e .``) does not cause pip to
  ignore version specifiers or constraints (see :issue:`8076`), and if
  you have a conflict between a pinned requirement and a local
  directory then pip will indicate that it cannot find a version
  satisfying both (see :issue:`8307`)
* Hash-checking mode requires that all requirements are specified as a
  ``==`` match on a version and may not work well in combination with
  constraints (see :issue:`9020` and :issue:`8792`)
* If necessary to satisfy constraints, pip will happily reinstall
  packages, upgrading or downgrading, without needing any additional
  command-line options (see :issue:`8115` and :doc:`development/architecture/upgrade-options`)
* Unnamed requirements are not allowed as constraints (see :issue:`6628` and :issue:`8210`)
* Links are not allowed as constraints (see :issue:`8253`)
* Constraints cannot have extras (see :issue:`6628`)

Per our :ref:`Python 2 Support` policy, pip 20.3 users who are using
Python 2 will use the legacy resolver by default. Python 2 users
should upgrade to Python 3 as soon as possible, since in pip 21.0 in
January 2021, pip dropped support for Python 2 altogether.


How to upgrade and migrate
--------------------------

1. **Install pip 20.3** with ``python -m pip install --upgrade pip``.

2. **Validate your current environment** by running ``pip check``. This
   will report if you have any inconsistencies in your set of installed
   packages. Having a clean installation will make it much less likely
   that you will hit issues with the new resolver (and may
   address hidden problems in your current environment!). If you run
   ``pip check`` and run into stuff you can’t figure out, please `ask
   for help in our issue tracker or chat <https://pip.pypa.io/>`__.

3. **Test the new version of pip**.

   While we have tried to make sure that pip’s test suite covers as
   many cases as we can, we are very aware that there are people using
   pip with many different workflows and build processes, and we will
   not be able to cover all of those without your help.

   -  If you use pip to install your software, try out the new resolver
      and let us know if it works for you with ``pip install``. Try:

      - installing several packages simultaneously
      - re-creating an environment using a ``requirements.txt`` file
      - using ``pip install --force-reinstall`` to check whether
        it does what you think it should
      - using constraints files
      - the "Setups to test with special attention" and "Examples to try" below

   -  If you have a build pipeline that depends on pip installing your
      dependencies for you, check that the new resolver does what you
      need.

   -  Run your project’s CI (test suite, build process, etc.) using the
      new resolver, and let us know of any issues.
   -  If you have encountered resolver issues with pip in the past,
      check whether the new resolver fixes them, and read :ref:`Fixing
      conflicting dependencies`. Also, let us know if the new resolver
      has issues with any workarounds you put in to address the
      current resolver’s limitations. We’ll need to ensure that people
      can transition off such workarounds smoothly.
   -  If you develop or support a tool that wraps pip or uses it to
      deliver part of your functionality, please test your integration
      with pip 20.3.

4. **Troubleshoot and try these workarounds if necessary.**

   -  If pip is taking longer to install packages, read :doc:`Dependency
      resolution backtracking <topics/dependency-resolution>` for ways to
      reduce the time pip spends backtracking due to dependency conflicts.
   -  If you don't want pip to actually resolve dependencies, use the
      ``--no-deps`` option. This is useful when you have a set of package
      versions that work together in reality, even though their metadata says
      that they conflict. For guidance on a long-term fix, read
      :ref:`Fixing conflicting dependencies`.
   -  If you run into resolution errors and need a workaround while you're
      fixing their root causes, you can choose the old resolver behavior using
      the flag ``--use-deprecated=legacy-resolver``. This will work until we
      release pip 21.0 (see
      :ref:`Deprecation timeline for 2020 resolver changes`).

5. **Please report bugs** through the `resolver testing survey`_.


Setups to test with special attention
-------------------------------------

*    Requirements files with 100+ packages

*    Installation workflows that involve multiple requirements files

*    Requirements files that include hashes (:ref:`hash-checking mode`)
     or pinned dependencies (perhaps as output from ``pip-compile`` within
     ``pip-tools``)

*    Using :ref:`Constraints Files`

*    Continuous integration/continuous deployment setups

*    Installing from any kind of version control systems (i.e., Git, Subversion, Mercurial, or CVS), per :doc:`topics/vcs-support`

*    Installing from source code held in local directories

Examples to try
^^^^^^^^^^^^^^^

Install:

* `tensorflow`_
* ``hacking``
* ``pycodestyle``
* ``pandas``
* ``tablib``
* ``elasticsearch`` and ``requests`` together
* ``six`` and ``cherrypy`` together
* ``pip install flake8-import-order==0.17.1 flake8==3.5.0 --use-feature=2020-resolver``
* ``pip install tornado==5.0 sprockets.http==1.5.0 --use-feature=2020-resolver``

Try:

* ``pip install``
* ``pip uninstall``
* ``pip check``
* ``pip cache``


Tell us about
-------------

Specific things we'd love to get feedback on:

*    Cases where the new resolver produces the wrong result,
     obviously. We hope there won't be too many of these, but we'd like
     to trap such bugs before we remove the legacy resolver.

*    Cases where the resolver produced an error when you believe it
     should have been able to work out what to do.

*    Cases where the resolver gives an error because there's a problem
     with your requirements, but you need better information to work out
     what's wrong.

*    If you have workarounds to address issues with the current resolver,
     does the new resolver let you remove those workarounds? Tell us!

Please let us know through the `resolver testing survey`_.

.. _`Deprecation timeline for 2020 resolver changes`:

Deprecation timeline
--------------------

We plan for the resolver changeover to proceed as follows, using
:ref:`Feature Flags` and following our :ref:`Release Cadence`:

*    pip 20.1: an alpha version of the new resolver was available,
     opt-in, using the optional flag
     ``--unstable-feature=resolver``. pip defaulted to legacy
     behavior.

*    pip 20.2: a beta of the new resolver was available, opt-in, using
     the flag ``--use-feature=2020-resolver``. pip defaulted to legacy
     behavior. Users of pip 20.2 who want pip to default to using the
     new resolver can run ``pip config set global.use-feature
     2020-resolver`` (for more on that and the alternate
     ``PIP_USE_FEATURE`` environment variable option, see `issue
     8661`_).

*    pip 20.3: pip defaults to the new resolver in Python 3 environments,
     but a user can opt-out and choose the old resolver behavior,
     using the flag ``--use-deprecated=legacy-resolver``. In Python 2
     environments, pip defaults to the old resolver, and the new one is
     available using the flag ``--use-feature=2020-resolver``.

*    pip 21.0: pip uses new resolver by default, and the old resolver is
     no longer supported. It will be removed after a currently undecided
     amount of time, as the removal is dependent on pip's volunteer
     maintainers' availability. Python 2 support is removed per our
     :ref:`Python 2 Support` policy.

Since this work will not change user-visible behavior described in the
pip documentation, this change is not covered by the :ref:`Deprecation
Policy`.

.. attention::

    The legacy resolver is deprecated and unsupported. New features, such
    as :doc:`reference/installation-report`, will not work with the
    legacy resolver and this resolver will be removed in a future
    release.

Context and followup
--------------------

As discussed in `our announcement on the PSF blog`_, the pip team are
in the process of developing a new "dependency resolver" (the part of
pip that works out what to install based on your requirements).

We're tracking our rollout in :issue:`6536` and you can watch for
announcements on the `low-traffic packaging announcements list`_ and
`the official Python blog`_.

.. _freeze: https://pip.pypa.io/en/latest/reference/pip_freeze/
.. _resolver testing survey: https://tools.simplysecure.org/survey/index.php?r=survey/index&sid=989272&lang=en
.. _issue 8661: https://github.com/pypa/pip/issues/8661
.. _our announcement on the PSF blog: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html
.. _two-minute video explanation: https://www.youtube.com/watch?v=B4GQCBBsuNU
.. _tensorflow: https://pypi.org/project/tensorflow/
.. _low-traffic packaging announcements list: https://mail.python.org/mailman3/lists/pypi-announce.python.org/
.. _our survey on upgrades that create conflicts: https://docs.google.com/forms/d/e/1FAIpQLSeBkbhuIlSofXqCyhi3kGkLmtrpPOEBwr6iJA6SzHdxWKfqdA/viewform
.. _the official Python blog: https://blog.python.org/
.. _Python Windows launcher: https://docs.python.org/3/using/windows.html#launcher

.. _`0-using-system-trust-stores-for-verifying-https`:
.. rubric:: Using system trust stores for verifying HTTPS

This is now covered in :doc:`topics/https-certificates`.

---

### Man Index (`docs/man/index.rst`)

:orphan:

========
Man Page
========

SYNOPSIS
********

pip <command> [options]

DESCRIPTION
***********

pip is the PyPA recommended package manager for Python packages

OPTIONS
*******

.. pip-general-options::

COMMANDS
********

pip-install(1)
    Install packages.

pip-download(1)
    Download packages.

pip-uninstall(1)
    Uninstall packages.

pip-freeze(1)
    Output installed packages in requirements format.

pip-lock(1)
    Generate a lock file for requirements and their dependencies.

pip-list(1)
    List installed packages.

pip-show(1)
    Show information about installed packages.

pip-check(1)
    Verify installed packages have compatible dependencies.

pip-search(1)
    Search PyPI for packages.

pip-wheel(1)
    Build wheels from your requirements.

pip-hash(1)
    Compute hashes of package archives.

pip-help(1)
    Show help for pip commands.

---

### Html Cli Pip (`docs/html/cli/pip.rst`)

===
pip
===


Usage
*****

.. tab:: Unix/macOS

    .. code-block:: shell

        python -m pip <command> [options]

.. tab:: Windows

    .. code-block:: shell

        py -m pip <command> [options]

Description
***********


.. _`Logging`:


Logging
=======

Console logging
~~~~~~~~~~~~~~~

Pip offers :ref:`-v, --verbose <--verbose>` and :ref:`-q, --quiet <--quiet>`
to control the console log level. By default, some messages (error and warnings)
are colored in the terminal. If you want to suppress the colored output use
:ref:`--no-color <--no-color>`.


.. _`FileLogging`:

File logging
~~~~~~~~~~~~

Pip offers the :ref:`--log <--log>` option for specifying a file where a maximum
verbosity log will be kept.  This option is empty by default. This log appends
to previous logging.

Like all pip options, ``--log`` can also be set as an environment variable, or
placed into the pip config file. See the :doc:`../topics/configuration` section.

.. _`exists-action`:

--exists-action option
======================

This option specifies default behavior when path already exists.
Possible cases: downloading files or checking out repositories for installation,
creating archives. If ``--exists-action`` is not defined, pip will prompt
when decision is needed.

*(s)witch*
    Only relevant to VCS checkout. Attempt to switch the checkout
    to the appropriate URL and/or revision.
*(i)gnore*
    Abort current operation (e.g. don't copy file, don't create archive,
    don't modify a checkout).
*(w)ipe*
    Delete the file or VCS checkout before trying to create, download, or checkout a new one.
*(b)ackup*
    Rename the file or checkout to ``{name}{'.bak' * n}``, where n is some number
    of ``.bak`` extensions, such that the file didn't exist at some point.
    So the most recent backup will be the one with the largest number after ``.bak``.
*(a)bort*
    Abort pip and return non-zero exit status.

.. _`2-build-system-interface`:
.. rubric:: Build System Interface

This is now covered in :doc:`../reference/build-system`.

.. _`General Options`:

General Options
***************

.. pip-general-options::

---

### Html Cli Pip Cache (`docs/html/cli/pip_cache.rst`)

.. _`pip cache`:

pip cache
---------


Usage
*****

.. tab:: Unix/macOS

   .. pip-command-usage:: cache "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: cache "py -m pip"

Description
***********

.. pip-command-description:: cache

Options
*******

.. pip-command-options:: cache

---

### Html Cli Pip Check (`docs/html/cli/pip_check.rst`)

.. _`pip check`:

=========
pip check
=========


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: check "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: check "py -m pip"


Description
===========

.. pip-command-description:: check


Examples
========

#. If all dependencies are compatible:

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip check
         No broken requirements found.
         $ echo $?
         0

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip check
         No broken requirements found.
         C:\> echo %errorlevel%
         0

#. If a package is missing:

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip check
         pyramid 1.5.2 requires WebOb, which is not installed.
         $ echo $?
         1

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip check
         pyramid 1.5.2 requires WebOb, which is not installed.
         C:\> echo %errorlevel%
         1

#. If a package has the wrong version:

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip check
         pyramid 1.5.2 has requirement WebOb>=1.3.1, but you have WebOb 0.8.
         $ echo $?
         1

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip check
         pyramid 1.5.2 has requirement WebOb>=1.3.1, but you have WebOb 0.8.
         C:\> echo %errorlevel%
         1

---

### Html Cli Pip Config (`docs/html/cli/pip_config.rst`)

.. _`pip config`:

==========
pip config
==========


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: config "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: config "py -m pip"


Description
===========

.. pip-command-description:: config


Options
=======

.. pip-command-options:: config

---

### Html Cli Pip Debug (`docs/html/cli/pip_debug.rst`)

.. _`pip debug`:

=========
pip debug
=========


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: debug "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: debug "py -m pip"


.. warning::

    This command is only meant for debugging.
    Its options and outputs are provisional and may change without notice.


Description
===========

.. pip-command-description:: debug


Options
=======

.. pip-command-options:: debug

---

### Html Cli Pip Download (`docs/html/cli/pip_download.rst`)

.. _`pip download`:

============
pip download
============


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: download "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: download "py -m pip"


Description
===========

.. pip-command-description:: download

Overview
--------

``pip download`` does the same resolution and downloading as ``pip install``,
but instead of installing the dependencies, it collects the downloaded
distributions into the directory provided (defaulting to the current
directory). This directory can later be passed as the value to ``pip install
--find-links`` to facilitate offline or locked down package installation.

``pip download`` with the ``--platform``, ``--python-version``,
``--implementation``, and ``--abi`` options provides the ability to fetch
dependencies for an interpreter and system other than the ones that pip is
running on. ``--only-binary=:all:`` or ``--no-deps`` is required when using any
of these options. It is important to note that these options all default to the
current system/interpreter, and not to the most restrictive constraints (e.g.
platform any, abi none, etc). To avoid fetching dependencies that happen to
match the constraint of the current interpreter (but not your target one), it
is recommended to specify all of these options if you are specifying one of
them. Generic dependencies (e.g. universal wheels, or dependencies with no
platform, abi, or implementation constraints) will still match an over-
constrained download requirement. If some of your dependencies are not
available as binaries, you can build them manually for your target platform
and let pip download know where to find them using ``--find-links``.

.. note::

   To determine the appropriate values for ``--python-version`` and ``--platform``, you can query the target system using the following commands:

   - For the Python version, use :func:`sysconfig.get_python_version() <sysconfig.get_python_version>`.
   - For the platform, use :func:`packaging.tags.platform_tags() <packaging.tags.platform_tags>`.

Options
=======

.. pip-command-options:: download

.. pip-index-options:: download

.. pip-package-selection-options:: download


Examples
========

#. Download a package and all of its dependencies

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip download SomePackage
         python -m pip download -d . SomePackage  # equivalent to above
         python -m pip download --no-index --find-links=/tmp/wheelhouse -d /tmp/otherwheelhouse SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip download SomePackage
         py -m pip download -d . SomePackage  # equivalent to above
         py -m pip download --no-index --find-links=/tmp/wheelhouse -d /tmp/otherwheelhouse SomePackage


#. Download a package and all of its dependencies with OSX specific interpreter constraints.
   This forces OSX 10.10 or lower compatibility. Since OSX deps are forward compatible,
   this will also match ``macosx_10_9_x86_64``, ``macosx_10_8_x86_64``, ``macosx_10_8_intel``,
   etc.
   It will also match deps with platform ``any``. Also force the interpreter version to ``27``
   (or more generic, i.e. ``2``) and implementation to ``cp`` (or more generic, i.e. ``py``).

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip download \
            --only-binary=:all: \
            --platform macosx_10_10_x86_64 \
            --python-version 27 \
            --implementation cp \
            SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip download ^
            --only-binary=:all: ^
            --platform macosx_10_10_x86_64 ^
            --python-version 27 ^
            --implementation cp ^
            SomePackage

#. Download a package and its dependencies with linux specific constraints.
   Force the interpreter to be any minor version of py3k, and only accept
   ``cp34m`` or ``none`` as the abi.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip download \
            --only-binary=:all: \
            --platform linux_x86_64 \
            --python-version 3 \
            --implementation cp \
            --abi cp34m \
            SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip download ^
            --only-binary=:all: ^
            --platform linux_x86_64 ^
            --python-version 3 ^
            --implementation cp ^
            --abi cp34m ^
            SomePackage

#. Force platform, implementation, and abi agnostic deps.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip download \
            --only-binary=:all: \
            --platform any \
            --python-version 3 \
            --implementation py \
            --abi none \
            SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip download ^
            --only-binary=:all: ^
            --platform any ^
            --python-version 3 ^
            --implementation py ^
            --abi none ^
            SomePackage

#. Even when overconstrained, this will still correctly fetch the pip universal wheel.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip download \
            --only-binary=:all: \
            --platform linux_x86_64 \
            --python-version 33 \
            --implementation cp \
            --abi cp34m \
            pip>=8

      .. code-block:: console

         $ ls pip-8.1.1-py2.py3-none-any.whl
         pip-8.1.1-py2.py3-none-any.whl

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip download ^
            --only-binary=:all: ^
            --platform linux_x86_64 ^
            --python-version 33 ^
            --implementation cp ^
            --abi cp34m ^
            pip>=8

      .. code-block:: console

         C:\> dir pip-8.1.1-py2.py3-none-any.whl
         pip-8.1.1-py2.py3-none-any.whl

#. Download a package supporting one of several ABIs and platforms.
   This is useful when fetching wheels for a well-defined interpreter, whose
   supported ABIs and platforms are known and fixed, different than the one pip is
   running under.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip download \
            --only-binary=:all: \
            --platform manylinux1_x86_64 --platform linux_x86_64 --platform any \
            --python-version 36 \
            --implementation cp \
            --abi cp36m --abi cp36 --abi abi3 --abi none \
            SomePackage

   .. tab:: Windows

      .. code-block:: console

         C:> py -m pip download ^
            --only-binary=:all: ^
            --platform manylinux1_x86_64 --platform linux_x86_64 --platform any ^
            --python-version 36 ^
            --implementation cp ^
            --abi cp36m --abi cp36 --abi abi3 --abi none ^
            SomePackage

---

### Html Cli Pip Freeze (`docs/html/cli/pip_freeze.rst`)

.. _`pip freeze`:

==========
pip freeze
==========


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: freeze "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: freeze "py -m pip"


Description
===========

.. pip-command-description:: freeze

.. note::
   By default, ``pip freeze`` omits bootstrap packaging tools so the output
   focuses on your project’s dependencies. On Python **3.11 and earlier**
   this excludes ``pip``, ``setuptools``, ``wheel`` and ``distribute``; on
   Python **3.12 and later** only ``pip`` is excluded. Use ``--all`` to
   include those packages when you need a complete environment snapshot.
   ``pip freeze`` reports what is installed; it does **not** compute a
   lockfile or a solver result.


Options
=======

.. pip-command-options:: freeze


Examples
========

#. Generate output suitable for a requirements file.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip freeze
         docutils==0.11
         Jinja2==2.7.2
         MarkupSafe==0.19
         Pygments==1.6
         Sphinx==1.2.2

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip freeze
         docutils==0.11
         Jinja2==2.7.2
         MarkupSafe==0.19
         Pygments==1.6
         Sphinx==1.2.2

#. Generate a requirements file and then install from it in another environment.

   .. tab:: Unix/macOS

      .. code-block:: shell

         env1/bin/python -m pip freeze > requirements.txt
         env2/bin/python -m pip install -r requirements.txt

   .. tab:: Windows

      .. code-block:: shell

         env1\bin\python -m pip freeze > requirements.txt
         env2\bin\python -m pip install -r requirements.txt


Fixing "Permission denied:" errors
==================================

The purpose of this section of documentation is to provide practical
suggestions to users seeing a `"Permission denied" error <https://github.com/pypa/pip/issues/8418>`__ on ``pip freeze``.

This error occurs, for instance, when the command is installed only for another
user, and the current user doesn't have the permission to execute the other
user's command.

To solve that issue, you can try one of the following:

- Install the command for yourself (e.g. in your home directory).
- Ask the system admin to allow this command for all users.
- Check and correct the PATH variable of your own environment.
- Check the `ACL (Access-Control List) <https://en.wikipedia.org/wiki/Access-control_list>`_ for this command.

---

### Html Cli Pip Hash (`docs/html/cli/pip_hash.rst`)

.. _`pip hash`:

========
pip hash
========


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: hash "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: hash "py -m pip"


Description
===========

.. pip-command-description:: hash

Overview
--------

``pip hash`` is a convenient way to get a hash digest for use with
:ref:`hash-checking mode`, especially for packages with multiple archives. The
error message from ``pip install --require-hashes ...`` will give you one
hash, but, if there are multiple archives (like source and binary ones), you
will need to manually download and compute a hash for the others. Otherwise, a
spurious hash mismatch could occur when :ref:`pip install` is passed a
different set of options, like :ref:`--no-binary <install_--no-binary>`.


Options
=======

.. pip-command-options:: hash


Example
=======

Compute the hash of a downloaded archive:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip download SomePackage
      Collecting SomePackage
         Downloading SomePackage-2.2.tar.gz
         Saved ./pip_downloads/SomePackage-2.2.tar.gz
      Successfully downloaded SomePackage
      $ python -m pip hash ./pip_downloads/SomePackage-2.2.tar.gz
      ./pip_downloads/SomePackage-2.2.tar.gz:
      --hash=sha256:93e62e05c7ad3da1a233def6731e8285156701e3419a5fe279017c429ec67ce0

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip download SomePackage
      Collecting SomePackage
         Downloading SomePackage-2.2.tar.gz
         Saved ./pip_downloads/SomePackage-2.2.tar.gz
      Successfully downloaded SomePackage
      C:\> py -m pip hash ./pip_downloads/SomePackage-2.2.tar.gz
      ./pip_downloads/SomePackage-2.2.tar.gz:
      --hash=sha256:93e62e05c7ad3da1a233def6731e8285156701e3419a5fe279017c429ec67ce0

---

### Html Cli Pip Index (`docs/html/cli/pip_index.rst`)

.. _`pip index`:

===========
pip index
===========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: index "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: index "py -m pip"


Description
===========

.. pip-command-description:: index



Options
=======

.. pip-command-options:: index

.. pip-index-options:: index

.. pip-package-selection-options:: index


Examples
========

#. Search for "peppercorn" versions

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip index versions peppercorn
         peppercorn (0.6)
         Available versions: 0.6, 0.5, 0.4, 0.3, 0.2, 0.1


   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip index peppercorn
         peppercorn (0.6)
         Available versions: 0.6, 0.5, 0.4, 0.3, 0.2, 0.1

---

### Html Cli Pip Inspect (`docs/html/cli/pip_inspect.rst`)

.. _`pip inspect`:

===========
pip inspect
===========

.. versionadded:: 22.2


Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: inspect "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: inspect "py -m pip"


Description
===========

.. pip-command-description:: inspect

The format of the JSON output is described in :doc:`../reference/inspect-report`.


Options
=======

.. pip-command-options:: inspect

---

### Html Cli Pip Install (`docs/html/cli/pip_install.rst`)

.. _`pip install`:

===========
pip install
===========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: install 'python -m pip'

.. tab:: Windows

   .. pip-command-usage:: install "py -m pip"



Description
===========

.. pip-command-description:: install

Overview
--------

``pip install`` has several stages:

1. Identify the base requirements. The user supplied arguments are processed
   here.
2. Resolve dependencies. What will be installed is determined here.
3. Build wheels. All the dependencies that can be are built into wheels.
4. Install the packages (and uninstall anything being upgraded/replaced).

Note that ``pip install`` prefers to leave the installed version as-is
unless ``--upgrade`` is specified.

Argument Handling
-----------------

When looking at the items to be installed, pip checks what type of item
each is, in the following order:

1. Project or archive URL.
2. Local directory (which must contain a ``pyproject.toml`` or ``setup.py``,
   otherwise pip will report an error).
3. Local file (a sdist or wheel format archive, following the naming
   conventions for those formats).
4. A :ref:`version specifier <pypug:version-specifiers>`.

Each item identified is added to the set of requirements to be satisfied by
the install.

Working Out the Name and Version
--------------------------------

For each candidate item, pip needs to know the project name and version. For
wheels (identified by the ``.whl`` file extension) this can be obtained from
the filename, as per the Wheel spec. For local directories, or explicitly
specified source distributions (sdists), pip determines project metadata using
the project's build backend. For sdists located via an index, the filename is
parsed for the name and project version (this is in theory slightly less
reliable than obtaining metadata from the distribution, but avoids downloading
and processing unnecessary numbers of files).

The :ref:`Direct URL requirement syntax <pypug:dependency-specifiers>` can be used
to explicitly state the project name (see :doc:`../topics/vcs-support`).

Satisfying Requirements
-----------------------

Once pip has the set of requirements to satisfy, it chooses which version of
each requirement to install using the simple rule that the latest version that
satisfies the given constraints will be installed (but see :ref:`here <Pre Release Versions>`
for an exception regarding pre-release versions). Where more than one source of
the chosen version is available, it is assumed that any source is acceptable
(as otherwise the versions would differ).

Obtaining information about what was installed
----------------------------------------------

The install command has a ``--report`` option that will generate a JSON report of what
pip has installed. In combination with the ``--dry-run`` and ``--ignore-installed`` it
can be used to *resolve* a set of requirements without actually installing them.

The report can be written to a file, or to standard output (using ``--report -`` in
combination with ``--quiet``).

The format of the JSON report is described in :doc:`../reference/installation-report`.

Installation Order
------------------

.. note::

   This section is only about installation order of runtime dependencies, and
   does not apply to build dependencies (those are specified using the
   :ref:`[build-system] table <pypug:pyproject-build-system-table>`).

As of v6.1.0, pip installs dependencies before their dependents, i.e. in
"topological order."  This is the only commitment pip currently makes related
to order.  While it may be coincidentally true that pip will install things in
the order of the install arguments or in the order of the items in a
requirements file, this is not a promise.

In the event of a dependency cycle (aka "circular dependency"), the current
implementation (which might possibly change later) has it such that the first
encountered member of the cycle is installed last.

For instance, if quux depends on foo which depends on bar which depends on baz,
which depends on foo:

.. tab:: Unix/macOS

   .. code-block:: console

      $ python -m pip install quux
      ...
      Installing collected packages baz, bar, foo, quux

      $ python -m pip install bar
      ...
      Installing collected packages foo, baz, bar

.. tab:: Windows

   .. code-block:: console

      C:\> py -m pip install quux
      ...
      Installing collected packages baz, bar, foo, quux

      C:\> py -m pip install bar
      ...
      Installing collected packages foo, baz, bar


Prior to v6.1.0, pip made no commitments about install order.

The decision to install topologically is based on the principle that
installations should proceed in a way that leaves the environment usable at each
step. This has two main practical benefits:

1. Concurrent use of the environment during the install is more likely to work.
2. A failed install is less likely to leave a broken environment.  Although pip
   would like to support failure rollbacks eventually, in the mean time, this is
   an improvement.

Although the new install order is not intended to replace (and does not replace)
the use of ``setup_requires`` to declare build dependencies, it may help certain
projects install from sdist (that might previously fail) that fit the following
profile:

1. They have build dependencies that are also declared as install dependencies
   using ``install_requires``.
2. ``python setup.py egg_info`` works without their build dependencies being
   installed.
3. For whatever reason, they don't or won't declare their build dependencies using
   ``setup_requires``.

.. _`0-requirements-file-format`:
.. rubric:: Requirements File Format

This section has been moved to :doc:`../reference/requirements-file-format`.

.. _`0-requirement-specifiers`:
.. rubric:: Requirement Specifiers

This section has been moved to :doc:`../reference/requirement-specifiers`.

.. _`0-per-requirement-overrides`:
.. rubric:: Per-requirement Overrides

This is now covered in :doc:`../reference/requirements-file-format`.

.. _`Pre Release Versions`:

Pre-release Versions
--------------------

Starting with v1.4, pip will only install stable versions as specified by
`pre-releases`_ by default. If a version cannot be parsed as a
:ref:`compliant <pypug:version-specifiers>` version then it is assumed to be
a pre-release.

If a Requirement specifier includes a pre-release or development version
(e.g. ``>=0.0.dev0``) then pip will allow pre-release and development versions
for that requirement. This does not include the != flag.

The ``pip install`` command also supports a :ref:`--pre <install_--pre>` flag
that enables installation of pre-releases and development releases.


.. _pre-releases: https://www.python.org/dev/peps/pep-0440/#handling-of-pre-releases

.. _`0-vcs-support`:
.. rubric:: VCS Support

This is now covered in :doc:`../topics/vcs-support`.

Finding Packages
----------------

Pip searches for packages on `PyPI`_ using the
`HTTP simple interface <https://pypi.org/simple/>`_,
which is documented `here <https://packaging.python.org/specifications/simple-repository-api/>`_
and `there <https://www.python.org/dev/peps/pep-0503/>`_.

Pip offers a number of package index options for modifying how packages are
found.

Pip looks for packages in a number of places: on PyPI (or the index given as
``--index-url``, if not disabled via ``--no-index``), in the local filesystem,
and in any additional repositories specified via ``--find-links`` or
``--extra-index-url``. There is no priority in the locations that are searched.
Rather they are all checked, and the "best" match for the requirements (in
terms of version number - see the
:ref:`specification <pypug:version-specifiers>` for details) is selected.

See the :ref:`pip install Examples<pip install Examples>`.

.. _`0-ssl certificate verification`:
.. rubric:: SSL Certificate Verification

This is now covered in :doc:`../topics/https-certificates`.

.. _`0-caching`:
.. rubric:: Caching

This is now covered in :doc:`../topics/caching`.

.. _`0-wheel-cache`:
.. rubric:: Wheel Cache

This is now covered in :doc:`../topics/caching`.

.. _`0-hash-checking-mode`:
.. rubric:: Hash checking mode

This is now covered in :doc:`../topics/secure-installs`.

.. _`0-local-project-installs`:
.. rubric:: Local Project Installs

This is now covered in :doc:`../topics/local-project-installs`.

.. _`0-editable-installs`:
.. rubric:: Editable installs

This is now covered in :doc:`../topics/local-project-installs`.

.. _`0-build-system-interface`:
.. rubric:: Build System Interface

This is now covered in :doc:`../reference/build-system`.

.. _`pip install Options`:

Options
=======

.. pip-command-options:: install

.. pip-index-options:: install

.. pip-package-selection-options:: install

.. _`pip install Examples`:


Examples
========

#. Install ``SomePackage`` and its dependencies from `PyPI`_ using :ref:`Requirement Specifiers`

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install SomePackage            # latest version
         python -m pip install 'SomePackage==1.0.4'   # specific version
         python -m pip install 'SomePackage>=1.0.4'   # minimum version

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install SomePackage            # latest version
         py -m pip install "SomePackage==1.0.4"   # specific version
         py -m pip install "SomePackage>=1.0.4"   # minimum version


#. Install a list of requirements specified in a file.  See the :ref:`Requirements files <Requirements Files>`.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install -r requirements.txt

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install -r requirements.txt


#. Upgrade an already installed ``SomePackage`` to the latest from PyPI.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install --upgrade SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install --upgrade SomePackage

   .. note::

      This will guarantee an update to ``SomePackage`` as it is a direct
      requirement, and possibly upgrade dependencies if their installed
      versions do not meet the minimum requirements of ``SomePackage``.
      Any non-requisite updates of its dependencies (indirect requirements)
      will be affected by the ``--upgrade-strategy`` command.

#. Install a local project in "editable" mode. See the section on :ref:`Editable Installs <editable-installs>`.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install -e .                # project in current directory
         python -m pip install -e path/to/project  # project in another directory

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install -e .                 # project in current directory
         py -m pip install -e path/to/project   # project in another directory


#. Install a project from VCS

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install 'SomeProject@git+https://git.repo/some_pkg.git@1.3.1'

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install "SomeProject@git+https://git.repo/some_pkg.git@1.3.1"


#. Install a project from VCS in "editable" mode. See the sections on :doc:`../topics/vcs-support` and :ref:`Editable Installs <editable-installs>`.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install -e 'SomePackage @ git+https://git.repo/some_pkg.git'          # from git
         python -m pip install -e 'SomePackage @ hg+https://hg.repo/some_pkg.git'            # from mercurial
         python -m pip install -e 'SomePackage @ svn+svn://svn.repo/some_pkg/trunk/'         # from svn
         python -m pip install -e 'SomePackage @ git+https://git.repo/some_pkg.git@feature'  # from 'feature' branch
         python -m pip install -e 'SomePackage @ git+https://git.repo/some_repo.git#subdirectory=subdir_path' # install a python package from a repo subdirectory

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install -e "SomePackage @ git+https://git.repo/some_pkg.git"          # from git
         py -m pip install -e "SomePackage @ hg+https://hg.repo/some_pkg.git"            # from mercurial
         py -m pip install -e "SomePackage @ svn+svn://svn.repo/some_pkg/trunk/"         # from svn
         py -m pip install -e "SomePackage @ git+https://git.repo/some_pkg.git@feature"  # from 'feature' branch
         py -m pip install -e "SomePackage @ git+https://git.repo/some_repo.git#subdirectory=subdir_path" # install a python package from a repo subdirectory

#. Install a package with extras, i.e., optional dependencies
   (:ref:`specification <pypug:dependency-specifiers>`).

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install 'SomePackage[PDF]'
         python -m pip install 'SomePackage[PDF] @ git+https://git.repo/SomePackage@main#subdirectory=subdir_path'
         python -m pip install '.[PDF]'  # project in current directory
         python -m pip install 'SomePackage[PDF]==3.0'
         python -m pip install 'SomePackage[PDF,EPUB]'  # multiple extras

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install "SomePackage[PDF]"
         py -m pip install "SomePackage[PDF] @ git+https://git.repo/SomePackage@main#subdirectory=subdir_path"
         py -m pip install ".[PDF]"  # project in current directory
         py -m pip install "SomePackage[PDF]==3.0"
         py -m pip install "SomePackage[PDF,EPUB]"  # multiple extras

#. Install a particular source archive file.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install './downloads/SomePackage-1.0.4.tar.gz'
         python -m pip install 'http://my.package.repo/SomePackage-1.0.4.zip'

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install "./downloads/SomePackage-1.0.4.tar.gz"
         py -m pip install "http://my.package.repo/SomePackage-1.0.4.zip"

#. Install a particular source archive file following direct references
   (:ref:`specification <pypug:dependency-specifiers>`).

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install 'SomeProject@http://my.package.repo/SomeProject-1.2.3-py33-none-any.whl'
         python -m pip install 'SomeProject @ http://my.package.repo/SomeProject-1.2.3-py33-none-any.whl'
         python -m pip install 'SomeProject@http://my.package.repo/1.2.3.tar.gz'

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install "SomeProject@http://my.package.repo/SomeProject-1.2.3-py33-none-any.whl"
         py -m pip install "SomeProject @ http://my.package.repo/SomeProject-1.2.3-py33-none-any.whl"
         py -m pip install "SomeProject@http://my.package.repo/1.2.3.tar.gz"

#. Install from alternative package repositories.

   Install from a different index, and not `PyPI`_

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install --index-url http://my.package.repo/simple/ SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install --index-url http://my.package.repo/simple/ SomePackage

   Install from a local flat directory containing archives (and don't scan indexes):

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install --no-index --find-links=file:///local/dir/ SomePackage
         python -m pip install --no-index --find-links=/local/dir/ SomePackage
         python -m pip install --no-index --find-links=relative/dir/ SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install --no-index --find-links=file:///local/dir/ SomePackage
         py -m pip install --no-index --find-links=/local/dir/ SomePackage
         py -m pip install --no-index --find-links=relative/dir/ SomePackage

   Search an additional index during install, in addition to `PyPI`_

   .. warning::

       Using the ``--extra-index-url`` option to search for packages which are
       not in the main repository (for example, private packages) is unsafe.
       This is a class of security issue known as `dependency confusion <https://azure.microsoft.com/en-us/resources/3-ways-to-mitigate-risk-using-private-package-feeds/>`_: an
       attacker can publish a package with the same name to a public index,
       which may then be chosen instead of your private package.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install --extra-index-url http://my.package.repo/simple SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install --extra-index-url http://my.package.repo/simple SomePackage


#. Find pre-release and development versions, in addition to stable versions.  By default, pip only finds stable versions.

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install --pre SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install --pre SomePackage


#. Install packages from source.

   Do not use any binary packages

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install SomePackage1 SomePackage2 --no-binary :all:

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install SomePackage1 SomePackage2 --no-binary :all:

   Specify ``SomePackage1`` to be installed from source:

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip install SomePackage1 SomePackage2 --no-binary SomePackage1

   .. tab:: Windows

      .. code-block:: shell

         py -m pip install SomePackage1 SomePackage2 --no-binary SomePackage1

.. _PyPI: https://pypi.org/

---

### Html Cli Pip List (`docs/html/cli/pip_list.rst`)

.. _`pip list`:

========
pip list
========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: list "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: list "py -m pip"


Description
===========

.. pip-command-description:: list


Options
=======

.. pip-command-options:: list

.. pip-index-options:: list

.. pip-package-selection-options:: list


Examples
========

#. List installed packages (with the default column formatting).

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list
         Package Version
         ------- -------
         docopt  0.6.2
         idlex   1.13
         jedi    0.9.0

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list
         Package Version
         ------- -------
         docopt  0.6.2
         idlex   1.13
         jedi    0.9.0

#. List outdated packages with column formatting.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list --outdated --format columns
         Package    Version Latest Type
         ---------- ------- ------ -----
         retry      0.8.1   0.9.1  wheel
         setuptools 20.6.7  21.0.0 wheel

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list --outdated --format columns
         Package    Version Latest Type
         ---------- ------- ------ -----
         retry      0.8.1   0.9.1  wheel
         setuptools 20.6.7  21.0.0 wheel

#. List packages that are not dependencies of other packages. Can be combined with
   other options.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list --outdated --not-required
         Package  Version Latest Type
         -------- ------- ------ -----
         docutils 0.14    0.17.1 wheel

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list --outdated --not-required
         Package  Version Latest Type
         -------- ------- ------ -----
         docutils 0.14    0.17.1 wheel

#. Use json formatting

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list --format=json
         [{'name': 'colorama', 'version': '0.3.7'}, {'name': 'docopt', 'version': '0.6.2'}, ...

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list --format=json
         [{'name': 'colorama', 'version': '0.3.7'}, {'name': 'docopt', 'version': '0.6.2'}, ...

#. Use freeze formatting

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list --format=freeze
         colorama==0.3.7
         docopt==0.6.2
         idlex==1.13
         jedi==0.9.0

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list --format=freeze
         colorama==0.3.7
         docopt==0.6.2
         idlex==1.13
         jedi==0.9.0

#. List packages installed in editable mode

   When some packages are installed in editable mode, ``pip list`` outputs an
   additional column that shows the directory where the editable project is
   located (i.e. the directory that contains the ``pyproject.toml`` or
   ``setup.py`` file).

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list
         Package          Version  Editable project location
         ---------------- -------- -------------------------------------
         pip              21.2.4
         pip-test-package 0.1.1    /home/you/.venv/src/pip-test-package
         setuptools       57.4.0
         wheel            0.36.2


   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list
         Package          Version  Editable project location
         ---------------- -------- ----------------------------------------
         pip              21.2.4
         pip-test-package 0.1.1    C:\Users\You\.venv\src\pip-test-package
         setuptools       57.4.0
         wheel            0.36.2

   The json format outputs an additional ``editable_project_location`` field.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip list --format=json | python -m json.tool
         [
           {
             "name": "pip",
             "version": "21.2.4",
           },
           {
             "name": "pip-test-package",
             "version": "0.1.1",
             "editable_project_location": "/home/you/.venv/src/pip-test-package"
           },
           {
             "name": "setuptools",
             "version": "57.4.0"
           },
           {
             "name": "wheel",
             "version": "0.36.2"
           }
         ]

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip list --format=json | py -m json.tool
         [
           {
             "name": "pip",
             "version": "21.2.4",
           },
           {
             "name": "pip-test-package",
             "version": "0.1.1",
             "editable_project_location": "C:\Users\You\.venv\src\pip-test-package"
           },
           {
             "name": "setuptools",
             "version": "57.4.0"
           },
           {
             "name": "wheel",
             "version": "0.36.2"
           }
         ]

.. note::

   Contrary to the ``freeze``  command, ``pip list --format=freeze`` will not
   report editable install information, but the version of the package at the
   time it was installed.

---

### Html Cli Pip Lock (`docs/html/cli/pip_lock.rst`)

.. _`pip lock`:

========
pip lock
========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: lock "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: lock "py -m pip"


Description
===========

.. pip-command-description:: lock

Options
=======

.. pip-command-options:: lock

.. pip-index-options:: lock

.. pip-package-selection-options:: lock


Examples
========

#. Emit a ``pylock.toml`` for the project in the current directory

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip lock -e .

   .. tab:: Windows

      .. code-block:: shell

         py -m pip lock -e .

---

### Html Cli Pip Search (`docs/html/cli/pip_search.rst`)

.. _`pip search`:

==========
pip search
==========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: search "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: search "py -m pip"


Description
===========

.. attention::
    PyPI no longer supports ``pip search`` (or XML-RPC search). Please use https://pypi.org/search (via a browser)
    instead. See https://warehouse.pypa.io/api-reference/xml-rpc/#deprecated-methods for more information.

    However, XML-RPC search (and this command) may still be supported by indexes other than PyPI.

.. pip-command-description:: search


Options
=======

.. pip-command-options:: search


Examples
========

#. Search for "peppercorn"

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip search peppercorn
         pepperedform    - Helpers for using peppercorn with formprocess.
         peppercorn      - A library for converting a token stream into [...]

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip search peppercorn
         pepperedform    - Helpers for using peppercorn with formprocess.
         peppercorn      - A library for converting a token stream into [...]

---

### Html Cli Pip Show (`docs/html/cli/pip_show.rst`)

.. _`pip show`:

========
pip show
========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: show "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: show "py -m pip"


Description
===========

.. pip-command-description:: show


Options
=======

.. pip-command-options:: show


Examples
========

#. Show information about a package:

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip show sphinx
         Name: Sphinx
         Version: 1.4.5
         Summary: Python documentation generator
         Home-page: http://sphinx-doc.org/
         Author: Georg Brandl
         Author-email: georg@python.org
         License: BSD
         Location: /my/env/lib/python2.7/site-packages
         Requires: docutils, snowballstemmer, alabaster, Pygments, imagesize, Jinja2, babel, six

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip show sphinx
         Name: Sphinx
         Version: 1.4.5
         Summary: Python documentation generator
         Home-page: http://sphinx-doc.org/
         Author: Georg Brandl
         Author-email: georg@python.org
         License: BSD
         Location: /my/env/lib/python2.7/site-packages
         Requires: docutils, snowballstemmer, alabaster, Pygments, imagesize, Jinja2, babel, six

#. Show all information about a package

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip show --verbose sphinx
         Name: Sphinx
         Version: 1.4.5
         Summary: Python documentation generator
         Home-page: http://sphinx-doc.org/
         Author: Georg Brandl
         Author-email: georg@python.org
         License: BSD
         Location: /my/env/lib/python2.7/site-packages
         Requires: docutils, snowballstemmer, alabaster, Pygments, imagesize, Jinja2, babel, six
         Metadata-Version: 2.0
         Installer:
         Classifiers:
            Development Status :: 5 - Production/Stable
            Environment :: Console
            Environment :: Web Environment
            Intended Audience :: Developers
            Intended Audience :: Education
            License :: OSI Approved :: BSD License
            Operating System :: OS Independent
            Programming Language :: Python
            Programming Language :: Python :: 2
            Programming Language :: Python :: 3
            Framework :: Sphinx
            Framework :: Sphinx :: Extension
            Framework :: Sphinx :: Theme
            Topic :: Documentation
            Topic :: Documentation :: Sphinx
            Topic :: Text Processing
            Topic :: Utilities
         Entry-points:
            [console_scripts]
            sphinx-apidoc = sphinx.apidoc:main
            sphinx-autogen = sphinx.ext.autosummary.generate:main
            sphinx-build = sphinx:main
            sphinx-quickstart = sphinx.quickstart:main
            [distutils.commands]
            build_sphinx = sphinx.setup_command:BuildDoc

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip show --verbose sphinx
         Name: Sphinx
         Version: 1.4.5
         Summary: Python documentation generator
         Home-page: http://sphinx-doc.org/
         Author: Georg Brandl
         Author-email: georg@python.org
         License: BSD
         Location: /my/env/lib/python2.7/site-packages
         Requires: docutils, snowballstemmer, alabaster, Pygments, imagesize, Jinja2, babel, six
         Metadata-Version: 2.0
         Installer:
         Classifiers:
            Development Status :: 5 - Production/Stable
            Environment :: Console
            Environment :: Web Environment
            Intended Audience :: Developers
            Intended Audience :: Education
            License :: OSI Approved :: BSD License
            Operating System :: OS Independent
            Programming Language :: Python
            Programming Language :: Python :: 2
            Programming Language :: Python :: 3
            Framework :: Sphinx
            Framework :: Sphinx :: Extension
            Framework :: Sphinx :: Theme
            Topic :: Documentation
            Topic :: Documentation :: Sphinx
            Topic :: Text Processing
            Topic :: Utilities
         Entry-points:
            [console_scripts]
            sphinx-apidoc = sphinx.apidoc:main
            sphinx-autogen = sphinx.ext.autosummary.generate:main
            sphinx-build = sphinx:main
            sphinx-quickstart = sphinx.quickstart:main
            [distutils.commands]
            build_sphinx = sphinx.setup_command:BuildDoc

---

### Html Cli Pip Uninstall (`docs/html/cli/pip_uninstall.rst`)

.. _`pip uninstall`:

=============
pip uninstall
=============



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: uninstall "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: uninstall "py -m pip"


Description
===========

.. pip-command-description:: uninstall


Options
=======

.. pip-command-options:: uninstall


Examples
========

#. Uninstall a package.

   .. tab:: Unix/macOS

      .. code-block:: console

         $ python -m pip uninstall simplejson
         Uninstalling simplejson:
            /home/me/env/lib/python3.9/site-packages/simplejson
            /home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
         Proceed (Y/n)? y
            Successfully uninstalled simplejson

   .. tab:: Windows

      .. code-block:: console

         C:\> py -m pip uninstall simplejson
         Uninstalling simplejson:
            /home/me/env/lib/python3.9/site-packages/simplejson
            /home/me/env/lib/python3.9/site-packages/simplejson-2.2.1-py3.9.egg-info
         Proceed (Y/n)? y
            Successfully uninstalled simplejson

---

### Html Cli Pip Wheel (`docs/html/cli/pip_wheel.rst`)

.. _`pip wheel`:

=========
pip wheel
=========



Usage
=====

.. tab:: Unix/macOS

   .. pip-command-usage:: wheel "python -m pip"

.. tab:: Windows

   .. pip-command-usage:: wheel "py -m pip"


Description
===========

.. pip-command-description:: wheel


.. _`1-build-system-interface`:
.. rubric:: Build System Interface

This is now covered in :doc:`../reference/build-system`.

Differences to ``build``
------------------------

`build <https://pypi.org/project/build/>`_ is a simple tool which can among other things build
wheels for projects using the standard ``pyproject.toml``-based build interface. It
is comparable to the execution of ``pip wheel --no-deps .``.
It can also build source distributions which is not possible with ``pip``.
``pip wheel`` covers the wheel scope of ``build`` but offers many additional features.

Options
=======

.. pip-command-options:: wheel

.. pip-index-options:: wheel

.. pip-package-selection-options:: wheel


Examples
========

#. Build wheels for a requirement (and all its dependencies), and then install

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip wheel --wheel-dir=/tmp/wheelhouse SomePackage
         python -m pip install --no-index --find-links=/tmp/wheelhouse SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip wheel --wheel-dir=/tmp/wheelhouse SomePackage
         py -m pip install --no-index --find-links=/tmp/wheelhouse SomePackage

#. Build a wheel for a package from source

   .. tab:: Unix/macOS

      .. code-block:: shell

         python -m pip wheel --no-binary SomePackage SomePackage

   .. tab:: Windows

      .. code-block:: shell

         py -m pip wheel --no-binary SomePackage SomePackage

---

### Html Development Ci (`docs/html/development/ci.rst`)

.. note::

    This section of the documentation is currently out of date.

    pip developers welcome your help to update this documentation. If
    you're interested in helping out, please let us know in the
    `tracking issue`_, or just submit a pull request and mention it in
    that tracking issue.

.. _`tracking issue`: https://github.com/pypa/pip/issues/7279

======================
Continuous Integration
======================

Supported interpreters
======================

Pip supports a variety of Python interpreters:

- CPython 3.10
- CPython 3.11
- CPython 3.12
- CPython 3.13
- CPython 3.14
- CPython 3.15
- Latest PyPy3

on different operating systems:

- Linux
- Windows
- macOS

and on different architectures:

- x64
- x86
- arm64 (macOS only)

so 56 hypothetical interpreters.


Checks
======

``pip`` CI runs different kind of tests:

- lint (defined in ``.pre-commit-config.yaml``)
- docs
- vendoring (is the ``src/_internal/_vendor`` directory cleanly vendored)
- unit tests (present in ``tests/unit``)
- "integration" tests (mostly present in ``tests/functional``)
- package (test the packaging steps)

Since lint, docs, vendoring and package tests only need to run on a pip
developer/contributor machine, they only need to be tested on the x64 variant
of the 3 different operating systems, and when an interpreter needs to be
specified it's ok to require the latest CPython interpreter.

So only unit tests and integration tests would need to be run with the different
interpreters.


Services
========

The pip test suite and checks are distributed on `GitHub Actions`_ which provides
free executors for open source packages.

.. _`GitHub Actions`: https://github.com/features/actions


Current run tests
=================

Developer tasks
---------------

======== =============== ================ ================== =============
   OS          docs            lint           vendoring        packaging
======== =============== ================ ================== =============
Linux         GitHub           GitHub           GitHub           GitHub
Windows       GitHub           GitHub           GitHub           GitHub
macOS         GitHub           GitHub           GitHub           GitHub
======== =============== ================ ================== =============

Actual testing
--------------

+------------------------------+---------------+-----------------+
|       **interpreter**        |   **unit**    | **integration** |
+-----------+----------+-------+---------------+-----------------+
|           |   x86    | CP3.10|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
|  Windows  +----------+-------+---------------+-----------------+
|           |   x64    | CP3.10|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
+-----------+----------+-------+---------------+-----------------+
|           |   x86    | CP3.10|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|               |                 |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
|   Linux   +----------+-------+---------------+-----------------+
|           |   x64    | CP3.10|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
+-----------+----------+-------+---------------+-----------------+
|           |  arm64   | CP3.10|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
|   macOS   +----------+-------+---------------+-----------------+
|           |   x64    | CP3.10|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.11|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.12|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.13|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.14|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | CP3.15|   GitHub      |   GitHub        |
|           |          +-------+---------------+-----------------+
|           |          | PyPy3 |               |                 |
+-----------+----------+-------+---------------+-----------------+

---

### Html Development Contributing (`docs/html/development/contributing.rst`)

============
Contributing
============

Pip's internals
===============

We have an in-progress guide to the
:ref:`architecture-pip-internals`. It might be helpful as you dive in.

AI Policy
=========

While we do not dictate what tools contributors use to create pull requests,
LLM (Large Language Model) tools are often used to generate code that the
human contributor does not fully understand, and may not even be legally
considered the owner of. Therefore, contributors wishing to use LLM tools
should read and follow the project `AI policy`_.

Submitting Pull Requests
========================

Submit pull requests against the ``main`` branch, providing a good
description of what you're doing and why. You must have legal permission to
distribute any code you contribute to pip and it must be available under the
MIT License.

Provide tests that cover your changes and run the tests locally first. pip
:ref:`supports <compatibility-requirements>` multiple Python versions and
operating systems. Any pull request must consider and work on all these
platforms.

Pull requests should be small to facilitate easier review. Keep them
self-contained, and limited in scope. `Studies have shown`_ that review quality
falls off as patch size grows. Sometimes this will result in many small PRs to
land a single large feature. In particular, pull requests must not be treated
as "feature branches", with ongoing development work happening within the PR.
Instead, the feature should be broken up into smaller, independent parts which
can be reviewed and merged individually.

Additionally, avoid including "cosmetic" changes to code that
is unrelated to your change, as these make reviewing the PR more difficult.
Examples include re-flowing text in comments or documentation, or adding or
removing blank lines or whitespace within lines. Such changes can be made
separately, as a "formatting cleanup" PR, if needed.

.. attention::

   While contributors may use whatever tools they like when developing a pull
   request, it is the contributor's responsibility to ensure that submitted
   code meets the project requirements, and that they understand the submitted
   code well enough to respond to review comments.

Automated Testing
=================

All pull requests and merges to 'main' branch are tested using `GitHub
Actions`_ based on our `.github/workflows`_ files. More details about pip's
Continuous Integration can be found in the `CI Documentation`_


You can find the status and results to the CI runs for your PR on GitHub's web
UI for the pull request. You can also find links to the CI services' pages for
the specific builds in the form of "Details" links, in case the CI run fails
and you wish to view the output.

To trigger CI to run again for a pull request, you can close and open the pull
request or submit another change to the pull request. If needed, project
maintainers can manually trigger a restart of a job/build.

To understand the broader software architecture around dependency
resolution in pip, and how we automatically test this functionality,
see `Testing the next-gen pip dependency resolver`_.

NEWS Entries
============

The ``NEWS.rst`` file is managed using `towncrier`_ and all non trivial changes
must be accompanied by a news entry.

To add an entry to the news file, first you need to have created an issue
describing the change you want to make. A Pull Request itself *may* function as
such, but it is preferred to have a dedicated issue (for example, in case the
PR ends up rejected due to code quality reasons).

Once you have an issue or pull request, you take the number and you create a
file inside of the ``news/`` directory, named after that issue number with a
"type" of ``removal``, ``feature``, ``bugfix``, or ``doc`` associated with it.

If your issue or PR number is ``1234`` and this change is fixing a bug,
then you would create a file ``news/1234.bugfix.rst``. PRs can span multiple
categories by creating multiple files (for instance, if you added a feature and
deprecated/removed the old feature at the same time, you would create
``news/NNNN.feature.rst`` and ``news/NNNN.removal.rst``).

If a PR touches multiple issues/PRs, you may create a file for each of them
with the exact same contents and Towncrier will deduplicate them.

Contents of a NEWS entry
------------------------

The contents of this file are reStructuredText formatted text that
will be used as the content of the news file entry. You do not need to
reference the issue or PR numbers in the entry, since ``towncrier``
will automatically add a reference to all of the affected issues when
rendering the NEWS file. There must be a newline at the end of the file.

In order to maintain a consistent style in the ``NEWS.rst`` file, it is
preferred to keep the news entry to the point, in sentence case, shorter than
80 characters and in an imperative tone -- an entry should complete the sentence
"This change will ...". In rare cases, where one line is not enough, use a
summary line in an imperative tone followed by a blank line separating it
from a description of the feature/change in one or more paragraphs, each wrapped
at 80 characters. Remember that a news entry is meant for end users and should
only contain details relevant to an end user.

.. _`choosing-news-entry-type`:

Choosing the type of NEWS entry
-------------------------------

A trivial change is anything that does not warrant an entry in the news file.
Some examples are: Code refactors that don't change anything as far as the
public is concerned, typo fixes, white space modification, etc. To mark a PR
as trivial a contributor simply needs to add a randomly named, empty file to
the ``news/`` directory with the extension of ``.trivial.rst``. If you are on a
POSIX like operating system, one can be added by running
``touch news/$(uuidgen).trivial.rst``. On Windows, the same result can be
achieved in Powershell using ``New-Item "news/$([guid]::NewGuid()).trivial.rst"``.
Core committers may also add a "skip news" label to the PR which will accomplish
the same thing.

Upgrading, removing, or adding a new vendored library gets a special mention
using a ``news/<library>.vendor.rst`` file. This is in addition to any features,
bugfixes, or other kinds of news that pulling in this library may have. This
uses the library name as the key so that updating the same library twice doesn't
produce two news file entries.

Changes to the processes, policies, or other non code related changed that are
otherwise notable can be done using a ``news/<name>.process.rst`` file. This is
not typically used, but can be used for things like changing version schemes,
updating deprecation policy, etc.


Updating your branch
====================

As you work, you might need to update your local main branch up-to-date with
the ``main`` branch in the main pip repository, which moves forward as the
maintainers merge pull requests. Most people working on the project use the
following workflow.

This assumes that you have Git configured so that when you run the following
command:

.. code-block:: console

    git remote -v

Your output looks like this:

.. code-block:: console

    origin  https://github.com/USERNAME/pip.git (fetch)
    origin  https://github.com/USERNAME/pip.git (push)
    upstream  https://github.com/pypa/pip.git (fetch)
    upstream  https://github.com/pypa/pip.git (push)

In the example above, ``USERNAME`` is your username on GitHub.

First, fetch the latest changes from the main pip repository, ``upstream``:

.. code-block:: console

    git fetch upstream

Then, check out your local ``main`` branch, and rebase the changes on top of
it:

.. code-block:: console

    git checkout main
    git rebase upstream/main

At this point, you might have to `resolve merge conflicts`_. Once this is done,
push the updates you have just made to your local ``main`` branch to your
``origin`` repository on GitHub:

.. code-block:: console

    git checkout main
    git push origin main

Now your local ``main`` branch and the ``main`` branch in your ``origin``
repo have been updated with the most recent changes from the main pip
repository.

To keep your branches updated, the process is similar:

.. code-block:: console

    git checkout awesome-feature
    git fetch upstream
    git rebase upstream/main

Now your branch has been updated with the latest changes from the
``main`` branch on the upstream pip repository.

It's good practice to back up your branches by pushing them to your
``origin`` on GitHub as you are working on them. To push a branch,
run this command:

.. code-block:: console

    git push origin awesome-feature

In this example, ``<awesome-feature>`` is the name of your branch. This
will push the branch you are working on to GitHub, but will not
create a PR.

Once you have pushed your branch to your ``origin``, if you need to
update it again, you will have to force push your changes by running the
following command:

.. code-block:: console

    git push -f origin awesome-feature

The ``-f`` (or ``--force``) flag after ``push`` forces updates from your local
branch to update your ``origin`` branch. If you have a PR open on your
branch, force pushing will update your PR. (This is a useful command
when someone requests changes on a PR.)

If you get an error message like this:

.. code-block:: console

    ! [rejected]        awesome-feature -> awesome-feature (non-fast-forward)
    error: failed to push some refs to 'https://github.com/USERNAME/pip.git'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Try force-pushing your branch with ``push -f``.

The ``main`` branch in the main pip repository gets updated frequently, so
you might have to update your branch at least once while you are working on it.

Thank you for your contribution!


Becoming a maintainer
=====================

If you want to become an official maintainer, start by helping out.

As a first step, we welcome you to triage issues on pip's issue
tracker. pip maintainers provide triage abilities to contributors once
they have been around for some time (probably at least 2-3 months) and
contributed positively to the project. This is optional and highly
recommended for becoming a pip maintainer.

Later, when you think you're ready (probably at least 5 months after
starting to triage), get in touch with one of the maintainers and they
will initiate a vote among the existing maintainers.

.. note::

    Upon becoming a maintainer, a person should be given access to various
    pip-related tooling across multiple platforms. These are noted here for
    future reference by the maintainers:

    - GitHub Push Access
    - PyPI Publishing Access
    - CI Administration capabilities
    - ReadTheDocs Administration capabilities

.. _`AI policy`: https://github.com/pypa/pip/blob/main/AI_POLICY.md
.. _`Studies have shown`: https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/
.. _`resolve merge conflicts`: https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line
.. _`GitHub Actions`: https://github.com/features/actions
.. _`.github/workflows`: https://github.com/pypa/pip/blob/main/.github/workflows
.. _`CI Documentation`: https://pip.pypa.io/en/latest/development/ci/
.. _`towncrier`: https://pypi.org/project/towncrier/
.. _`Testing the next-gen pip dependency resolver`: https://pradyunsg.me/blog/2020/03/27/pip-resolver-testing/

---

### Html Development Conventions (`docs/html/development/conventions.rst`)

:orphan:

=========================
Documentation Conventions
=========================

This document describes the conventions used in pip's documentation. We
expect it to evolve over time as additional conventions are identified
and past conventions are rendered obsolete.

.. note::

   Currently, these conventions are not enforced automatically, and
   need to be verified manually during code review. We are interested
   in linters that can help us enforce these conventions automatically.


Files
=====

Naming
------

Folder names should be a single word, all lowercase.

File names must use the kebab-case style (all lowercase, hyphen for
separating words) and have the extension ``.rst``.

Encoding
--------

All files in our documentation must use UTF-8 encoding.

Line Length
-----------

Limit all lines to a maximum of 72 characters, where possible. This may
be exceeded when it does not make sense to abide by it (eg. long links,
code blocks).

Headings
========

Use the following symbols to create headings:

#. ``=`` with overline
#. ``=``
#. ``-``
#. ``^``
#. ``'``
#. ``*``

For visual separation from the rest of the content, all other headings
must have one empty line before and after. Heading 2 (``=``) should have
two empty lines before, for indicating the end of the section prior to
it.

::

   =========
   Heading 1
   =========

   Lorem ipsum dolor sit amet consectetur adipisicing elit.


   Heading 2
   =========

   Lorem ipsum dolor sit amet consectetur adipisicing elit.

   Heading 3
   ---------

   Lorem ipsum dolor sit amet consectetur adipisicing elit.

   Heading 4
   ^^^^^^^^^

   Lorem ipsum dolor sit amet consectetur adipisicing elit.

   Heading 5
   '''''''''

   Lorem ipsum dolor sit amet consectetur adipisicing elit.

   Heading 6
   *********

   Lorem ipsum dolor sit amet consectetur adipisicing elit.


Writing
=======

The name of the application (and the project) is "pip". This is a normal noun,
and as such should be capitalised the same as any other noun (uppercase at the
start of a sentence, lowercase within a sentence).

The command name, ``pip`` (generally rendered in a fixed-width font, as
here), is case sensitive and should be rendered in lowercase at all times.
If you find that you need to start a sentence with ``pip`` (the command name),
you should still use lowercase, but it can be better to reword your text to
avoid starting the sentence with the command name. A simple rewording is
to use the phrase "The ``pip`` command...".

.. note::

   Previously, it was a common practice to write "pip" in lowercase in all
   contexts. You may still see that usage in some cases. However, this was
   never the formal project policy, and the advice here supersedes that
   convention.

Avoid using phrases such as "easy", "just", "simply" etc, which imply
that the task is trivial. If it were trivial, the user wouldn't be
reading the documentation for it.

---

### Html Development Getting Started (`docs/html/development/getting-started.rst`)

===============
Getting Started
===============

We’re pleased that you are interested in working on pip.

This document is meant to get you setup to work on pip and to act as a guide and
reference to the development setup. If you face any issues during this
process, please `open an issue`_ about it on the issue tracker.


Get the source code
===================

To work on pip, you first need to get the source code of pip. The source code is
available on `GitHub`_.

.. code-block:: console

    $ git clone https://github.com/pypa/pip
    $ cd pip


Development Environment
=======================

Pip is a command line application written in Python. For developing pip,
you should `install Python`_ on your computer.

For developing pip, you need to install :pypi:`nox`. The full development setup would then be:

.. tab:: Unix/macOS

    .. code-block:: shell

        python -m venv .venv
        source .venv/bin/activate
        python -m pip install nox

.. tab:: Windows

    .. code-block:: shell

        py -m venv .venv
        .venv\Scripts\activate
        py -m pip install nox

Running pip From Source Tree
============================

To run the pip executable from your source tree during development, install pip
locally using editable installation (inside a virtualenv).
You can then invoke your local source tree pip normally (be sure virtualenv is active).

.. tab:: Unix/macOS

    .. code-block:: shell

        python -m pip install -e .
        python -m pip --version

.. tab:: Windows

    .. code-block:: shell

        py -m pip install -e .
        py -m pip --version

Running Tests
=============

Pip's tests are written using the :pypi:`pytest` test framework and
:mod:`unittest.mock`. :pypi:`nox` is used to automate the setup and execution
of pip's tests.

It is preferable to run the tests in parallel for a better experience during development,
since the tests can take a long time to finish when run sequentially.

To run tests:

.. code-block:: console

    $ nox -s test-3.10 -- -n auto

To run tests without parallelization, run:

.. code-block:: console

    $ nox -s test-3.10

The example above runs tests against Python 3.10. You can also use other
versions like ``3.15`` and ``pypy3``.

``nox`` has been configured to forward any additional arguments it is given to
``pytest``. This enables the use of pytest's `rich CLI`_. As an example, you
can select tests using the various ways that pytest provides:

.. code-block:: console

    $ # Using file name
    $ nox -s test-3.10 -- tests/functional/test_install.py
    $ # Using markers
    $ nox -s test-3.10 -- -m unit
    $ # Using keywords
    $ nox -s test-3.10 -- -k "install and not wheel"

.. note::

    When running pip's tests with OS distribution Python versions, be aware that some
    functional tests may fail due to potential patches introduced by the distribution.
    For all tests to pass consider:

    - Installing Python from `python.org`_ or compile from source
    - Or, using `pyenv`_ to assist with source compilation

Running pip's entire test suite requires supported version control tools
(subversion, bazaar, git, and mercurial) to be installed. If you are missing
any of these VCS, those tests should be skipped automatically. You can also
explicitly tell pytest to skip those tests:

.. code-block:: console

    $ nox -s test-3.10 -- -k "not svn"
    $ nox -s test-3.10 -- -k "not (svn or git)"

.. _python.org: https://www.python.org/downloads/
.. _pyenv: https://github.com/pyenv/pyenv


Running Linters
===============

Pip uses :pypi:`pre-commit` for managing linting of the codebase.
``pre-commit`` performs various checks on all files in pip and uses tools that
help follow a consistent code style within the codebase.

To use linters locally, run:

.. code-block:: console

    $ nox -s lint

.. note::

    Avoid using ``# noqa`` comments to suppress linter warnings - wherever
    possible, warnings should be fixed instead. ``# noqa`` comments are
    reserved for rare cases where the recommended style causes severe
    readability problems.


Running pip under a debugger
============================

In order to debug pip's behavior, you can run it under a debugger like so:

.. code-block:: console

    $ python -m pdb -m pip --debug ...


Replace the ``...`` with arguments you'd like to run pip with. Give PDB the
``c`` ("continue") command afterwards, to run the process.

The ``--debug`` flag disables pip's exception handler, which would normally
catch all unhandled exceptions. With this flag, pip will let these exceptions
propagate outside of its main subroutine, letting them get caught by the
debugger. This way you'll be able to debug an exception post-mortem via PDB.


Building Documentation
======================

Pip's documentation is built using :pypi:`Sphinx`. The documentation is written
in reStructuredText.

To build it locally, run:

.. code-block:: console

    $ nox -s docs

The built documentation can be found in the ``docs/build`` folder.

For each Pull Request made the documentation is deployed following this link:

.. code-block:: none

    https://pip--<PR-NUMBER>.org.readthedocs.build/en/<PR-NUMBER>


What Next?
==========

The following pages may be helpful for new contributors on where to look next
in order to start contributing.

* Some `good first issues`_ on GitHub for new contributors
* A deep dive into `pip's architecture`_
* A guide on `triaging issues`_ for issue tracker
* Getting started with Git

  - `Hello World for Git`_
  - `Understanding the GitHub flow`_
  - `Start using Git on the command line`_


.. _`open an issue`: https://github.com/pypa/pip/issues/new?title=Trouble+with+pip+development+environment
.. _`install Python`: https://realpython.com/installing-python/
.. _`rich CLI`: https://docs.pytest.org/en/latest/how-to/usage.html#specifying-which-tests-to-run
.. _`GitHub`: https://github.com/pypa/pip
.. _`good first issues`: https://github.com/pypa/pip/labels/good%20first%20issue
.. _`pip's architecture`: https://pip.pypa.io/en/latest/development/architecture/
.. _`triaging issues`: https://pip.pypa.io/en/latest/development/issue-triage/
.. _`Hello World for Git`: https://docs.github.com/en/get-started/start-your-journey/hello-world
.. _`Understanding the GitHub flow`: https://docs.github.com/en/get-started/using-github/github-flow
.. _`Start using Git on the command line`: https://docs.gitlab.com/topics/git/

---

### Html Development Index (`docs/html/development/index.rst`)

===========
Development
===========

Pip is a volunteer maintained open source project and we welcome contributions
of all forms. The sections below will help you get started with development,
testing, and documentation.

You can also join ``#pypa`` (general packaging discussion and user support) and
``#pypa-dev`` (discussion about development of packaging tools) `on Libera.chat`_,
or the ``#pip`` channel on the `PyPA Discord`_, to ask questions or get involved.

.. toctree::
    :maxdepth: 2

    getting-started
    contributing
    ci
    issue-triage
    architecture/index
    release-process
    vendoring-policy

.. note::

    pip's development documentation has been rearranged and some older
    references might be broken.

.. _`on Libera.chat`: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev
.. _`PyPA Discord`: https://discord.gg/pypa

---

### Html Development Issue Triage (`docs/html/development/issue-triage.md`)

```{note}
This section of the documentation is currently being written. The pip
developers welcome your help to complete this documentation. If
you're interested in helping out, please let us know in the
[tracking issue](https://github.com/pypa/pip/issues/6583), or
just submit a pull request and mention it in that tracking issue.
```

# Issue Triage

This serves as an introduction to issue tracking in pip as well as
how to help triage reported issues.

## Issue Tracker

The [pip issue tracker](https://github.com/pypa/pip/issues) is hosted on
GitHub alongside the project.

Currently, the issue tracker is used for bugs, feature requests, and general
user support.

In the pip issue tracker, we make use of labels and milestones to organize and
track work.

### Labels

Issue labels are used to:

1. Categorize issues
2. Provide status information for contributors and reporters
3. Help contributors find tasks to work on

The current set of labels are divided into several categories identified by
prefix:

**C - Category**
: which area of `pip` functionality a feature request or issue is related to

**kind**
: for notable traits like crashes or backwards-incompatible changes

**OS - Operating System**
: for issues that are OS-specific

**project**
: related to something external to `pip`

**resolution**
: no more discussion is really needed, an action has been identified and the
issue is waiting or closed

**state**
: for some automatic labels and other indicators that work is needed

**type**
: the role or flavor of an issue

The specific labels falling into each category have a description that can be
seen on the [Labels](https://github.com/pypa/pip/labels) page.

In addition, there are several standalone labels:

**good first issue**
: this label marks an issue as beginner-friendly and shows up in banners that
GitHub displays for first-time visitors to the repository

**S: needs triage**
: default label given to issues when they are created

**skip news**
: special label for pull requests that removes the
{ref}`news file requirement <choosing-news-entry-type>`

**needs rebase or merge**

: marks PRs that have merge conflicts

### Automation

There are several helpers to manage issues and pull requests.

Issues created on the issue tracker are automatically given the
`S: needs triage` label by the issue templates. Triagers remove the
label when an issue has been categorized.

When an issue needs feedback from the author we can label it with
`S: awaiting response`. The label is removed manually once the author
responds.

After an issue has been closed for 30 days, the
[lock-threads](https://github.com/dessant/lock-threads) GitHub Action
locks the issue (closed pull requests are locked after 15 days). This
allows us to avoid monitoring existing closed
issues, but unfortunately prevents and references to issues from showing up as
links on the closed issue.

## Triage Issues

Users can make issues for a number of reasons:

1. Suggestions about pip features that could be added or improved
2. Problems using pip
3. Concerns about pip usability
4. General packaging problems to be solved with pip
5. Problems installing or using Python packages
6. Problems managing virtual environments
7. Problems managing Python installations

To triage issues means to identify what kind of issue is happening and

- confirm bugs
- provide support
- discuss and design around the uses of the tool

Specifically, to address an issue:

1. Read issue title
2. Scan issue description
3. Ask questions
4. If time is available, try to reproduce
5. Search for or remember related issues and link to them
6. Identify an appropriate area of concern (if applicable)

Keep in mind that all communication is happening with other people and
should be done with respect per the
[Code of Conduct](https://www.pypa.io/en/latest/code-of-conduct/).

The lifecycle of an issue (bug or support) generally looks like:

1. waiting for triage (marked with label `triage`)

2. confirming issue - some discussion with the user, gathering
   details, trying to reproduce the issue (may be marked with a specific
   category, `S: awaiting response`, `state: needs discussion`, or
   `state: needs reproducer`)

3. confirmed - the issue is pretty consistently reproducible in a
   straightforward way, or a mechanism that could be causing the issue has been
   identified

4. awaiting fix - the fix is identified and no real discussion on the issue
   is needed, should be marked `state: awaiting PR`

5. closed - can be for several reasons

   - fixed
   - could not be reproduced, no more details could be obtained, and no
     progress can be made
   - actual issue was with another project or related to system
     configuration and pip cannot (or will not) be adapted for it

### Requesting information

Requesting more information to better understand the context and environment
that led to the issue. Examples of specific information that may be useful
depending on the situation:

- Pip debug: `pip debug`
- Pip version: `pip -V`
- Python version: `python -VV`
- Python path: `python -c 'import sys; print(sys.executable)'`
- `python` on `PATH`: Unix: `which python`; Windows: `where python`
- Python as resolved by the shell: `type python`
- Origin of pip (get-pip.py, OS-level package manager, ensurepip, manual
  installation)
- Using a virtual environment (with `--system-site-packages`?)
- Using a conda environment
- `PATH` environment variable
- Network situation (e.g. airgapped environment, firewalls)
- `--verbose` output of a failing command
- (Unix) `strace` output from a failing command (be careful not to output
  into the same directory as a package that's being installed, otherwise pip
  will loop forever copying the log file...)
- (Windows)
  [procmon](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon)
  output during a failing command
  ([example request](https://github.com/pypa/pip/issues/6814#issuecomment-516611389))
- Listing of files relevant to the issue (e.g. `ls -l venv/lib/pythonX.Y/problem-package.dist-info/`)
- whether the unexpected behavior ever worked as expected - if so then what
  were the details of the setup (same information as above)

Generally, information is good to request if it can help confirm or rule out
possible sources of error. We shouldn't request information that does not
improve our understanding of the situation.

### Reproducing issues

Whenever an issue happens and the cause isn't obvious, it is important
that we be able to reproduce it independently. This serves several purposes:

1. If it is a pip bug, then any fix will need tests - a good reproducer
   is most of the way towards that.
2. If it is not reproducible using the provided instructions, that helps
   rule out a lot of possible causes.
3. A clear set of instructions is an easy way to get on the same page as
   someone reporting an issue.

The best way to reproduce an issue is with a script.

A script can be copied into a file and executed, whereas shell output
has to be manually copied a line at a time.

Scripts to reproduce issues should be:

- portable (few/no assumptions about the system, other that it being Unix or Windows as applicable)
- non-destructive
- convenient
- require little/no setup on the part of the runner

Examples:

- creating and installing multiple wheels with different versions
  ([link](https://github.com/pypa/pip/issues/4331#issuecomment-520156471))
- using a small web server for authentication errors
  ([link](https://github.com/pypa/pip/issues/2920#issuecomment-508953118))
- using docker to test system or global configuration-related issues
  ([link](https://github.com/pypa/pip/issues/5533#issuecomment-520159896))
- using docker to test special filesystem permission/configurations
  ([link](https://github.com/pypa/pip/issues/6364#issuecomment-507074729))
- using docker for global installation with get-pip
  ([link](https://github.com/pypa/pip/issues/6498#issuecomment-513501112))
- get-pip on system with no `/usr/lib64`
  ([link](https://github.com/pypa/pip/issues/5379#issuecomment-515270576))
- reproducing with `pip` from current development branch
  ([link](https://github.com/pypa/pip/issues/6707#issue-467770959))

### Reaching resolution

Some user support questions are more related to system configuration than pip.
It's important to treat these issues with the same care and attention as
others, specifically:

1. Unless the issue is very old and the user doesn't seem active, wait for
   confirmation before closing the issue

2. Direct the user to the most appropriate forum for their questions:

   - For Ubuntu, [askubuntu](https://askubuntu.com/)
   - For Other linuxes/unixes, [serverfault](https://serverfault.com/)
   - For network connectivity issues,
     [serverfault](https://serverfault.com/)

3. Just because a user support question is best solved using some other forum
   doesn't mean that we can't make things easier. Try to extract and
   understand from the user query how things could have been made easier for
   them or you, for example with better warning or error messages. If an issue
   does not exist covering that case then create one. If an issue does exist then
   make sure to reference that issue before closing this one.

4. A user may be having trouble installing a package, where the package
   `setup.py` or build-backend configuration is non-trivial. In these cases we
   can help to troubleshoot but the best advice is going to be to direct them
   to the support channels for the related projects.

5. Do not be hasty to assume it is one cause or another. What looks like
   someone else's problem may still be an issue in pip or at least something
   that could be improved.

6. For general discussion on Python packaging:

   - [pypa/packaging](https://github.com/pypa/packaging-problems)
   - [discuss.python.org/packaging](https://discuss.python.org/c/packaging)

### Closing issues

An issue may be considered resolved and closed when:

- for each possible improvement or problem represented in the issue
  discussion:

  - Consensus has been reached on a specific action and the actions
    appear to be external to the project, with no follow up needed
    in the project afterwards.

    - PEP updates (with a corresponding issue in
      [python/peps](https://github.com/python/peps))
    - already tracked by another issue

  - A project-specific issue has been identified and the issue no
    longer occurs as of the latest commit on the main branch.

- An enhancement or feature request no longer has a proponent and the maintainers
  don't think it's worth keeping open.

- An issue has been identified as a duplicate, and it is clearly a duplicate (i.e. the
  original report was very good and points directly to the issue)

- The issue has been fixed, and can be independently validated as no longer being an
  issue. If this is with code then the specific change/PR that led to it should be
  identified and posted for tracking.

## Common issues

1. network-related issues - any issue involving retries, address lookup, or
   anything like that are typically network issues.

2. issues related to having multiple Python versions, or an OS package
   manager-managed pip/python installation (specifically with Debian/Ubuntu).
   These typically present themselves as:

   1. Not being able to find installed packages
   2. basic libraries not able to be found, fundamental OS components missing
   3. In these situations you will want to make sure that we know how they got
      their Python and pip. Knowing the relevant package manager commands can
      help, e.g. `dpkg -S`.

## For issues caused by changes by redistributors

Certain issues are caused by patches that redistributors of Python/pip
make to Python/pip.

Certain redistributors have shared preferred wording to redirect users
to their issue trackers.

Fedora, RHEL, CentOS (and probably other derivatives – Rocky, Scientific, CloudLinux):

```
This issue looks like it's caused by changes that Fedora or Red Hat
made in their pip packaging. Please file a Fedora bug at
https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=python-pip

cc @encukou @hroncok
```

Debian:

```
This issue looks like it's caused by changes that Debian made in
their pip packaging. Please file a bug with Debian, with
`reportbug python3-pip` [Docs](https://www.debian.org/Bugs/Reporting).
You can link to this issue in your bug report.

In the meantime, you may be able to work-around your issue by upgrading
pip inside your virtualenv: `python -m pip install -U pip`
```

Ubuntu:

```
This issue looks like it's caused by changes that Ubuntu made in
their pip packaging. Please file a bug with Ubuntu, with
`ubuntu-bug python3-pip` [Docs](https://help.ubuntu.com/community/ReportingBugs).
You can link to this issue in your bug report.

In the meantime, you may be able to work-around your issue by upgrading
pip inside your virtualenv: `python -m pip install -U pip`
```

---

### Html Development Release Process (`docs/html/development/release-process.rst`)

===============
Release process
===============

.. _`Release Cadence`:

Release Cadence
===============

The pip project has a release cadence of releasing whatever is on ``main``
every 3 months. This gives users a predictable pattern for when releases
are going to happen and prevents locking up improvements for fixes for long
periods of time, while still preventing massively fracturing the user base
with version numbers.

Our release months are January, April, July, October. The release date within
that month will be up to the release manager for that release. If there are
no changes, then that release month is skipped and the next release will be
3 months later.

The version number of pip is ``YY.N``, where ``YY`` is the year of the release
and ``N`` identifies the quarter of the year (0-3).

The release manager may, at their discretion, choose whether or not there
will be a pre-release period for a release, and if there is may extend that
period into the next month if needed.

Because releases are made direct from the ``main`` branch, it is essential
that ``main`` is always in a releasable state. It is acceptable to merge
PRs that partially implement a new feature, but only if the partially
implemented version is usable in that state (for example, with reduced
functionality or disabled by default). In the case where a merged PR is found
to need extra work before being released, the release manager always has the
option to back out the partial change prior to a release. The PR can then be
reworked and resubmitted for the next release.

Vendoring updates will be picked up from the ``main`` branch, as for any other
update. Ideally, vendoring updates should be merged between releases, just like
any other change. If there are outstanding updates to vendored packages, the
release manager *may* at their discretion choose to do a vendoring update
before the release. However this is *not* a requirement and in particular,
updates to vendored packages that fix issues in pip should be merged
proactively, to ensure that they will be present in the next release.


.. _`Deprecation Policy`:

Deprecation Policy
==================

Any change to pip that removes or significantly alters user-visible behavior
that is described in the pip documentation will be deprecated for a minimum of
6 months before the change occurs.

Certain changes may be fast tracked and have a deprecation period of 3 months.
This requires at least two members of the pip team to be in favor of doing so,
and no pip maintainers opposing.

Deprecation will take the form of a warning being issued by pip when the
feature is used. Longer deprecation periods, or deprecation warnings for
behavior changes that would not normally be covered by this policy, are also
possible depending on circumstances, but this is at the discretion of the pip
maintainers.

Note that the documentation is the sole reference for what counts as agreed
behavior. If something isn't explicitly mentioned in the documentation, it can
be changed without warning, or any deprecation period, in a pip release.
However, we are aware that the documentation isn't always complete - PRs that
document existing behavior with the intention of covering that behavior with
the above deprecation process are always acceptable, and will be considered on
their merits.

.. note::

  Pip has a helper function for making deprecation easier for pip maintainers.
  The supporting documentation can be found in the source code of
  ``pip._internal.utils.deprecation.deprecated``. The function is not a part of
  pip's public API.

Supported Versions
==================

The latest version of the pip is the only supported version, previous
versions should be considered unsupported. Users are encouraged to make
regular updates to their version of pip in order to remain supported.

.. _`Python 2 Support`:

Python 2 Support
----------------

Pip 20.3 was the last version of pip that supported Python 2. Bugs reported
with pip which only occur on Python 2.7 will likely be closed as "won't fix"
issues by pip's maintainers.

Python Support Policy
---------------------

Pip supports `CPython versions that are not end-of-life`_. Older versions of CPython may
be supported at the discretion of pip maintainers (based on criteria such as download
statistics on PyPI, Python versions supported by the vendored dependencies and
maintenance burden).

The pip maintainers accept pull requests to support other Python implementations, but the
pip CI does not test for compatibility with them.

.. _`Feature Flags`:

Feature Flags
=============

``--use-deprecated``
--------------------

Example: ``--use-deprecated=legacy-resolver``

Use for features that will be deprecated. Deprecated features should remain
available behind this flag for at least six months, as per the deprecation
policy.

Features moved behind this flag should always include a warning that indicates
when the feature is scheduled to be removed.

Once the feature is removed, users who use the flag should be shown an error.

``--use-feature``
-----------------

Example: ``--use-feature=2020-resolver``

Use for new features that users can test before they become pip's default
behaviour (e.g. alpha or beta releases).

Once the feature becomes the default behaviour, this flag can remain in place,
but should issue a warning telling the user that it is no longer necessary.

Release Process
===============

Creating a new release
----------------------

#. Ensure you have the latest ``nox`` installed.
#. Create a new ``release/YY.N`` branch off ``main`` and switch to it.
#. Prepare for release using ``nox -s prepare-release -- YY.N``.
   This will update the relevant files and tag the correct commit.
#. Submit the ``release/YY.N`` branch as a pull request and ensure CI passes.
   Merge the changes back into ``main`` and pull them back locally.
#. Push the tag created by ``prepare-release``. This will trigger the release
   workflow on GitHub.
#. Go to https://github.com/pypa/pip/actions, find the latest ``Publish Python
   🐍 distribution 📦 to PyPI`` workflow run, open it, wait for the build step
   to complete, then approve the PyPI environment to let the publishing step
   run. If you desire, you have the possibility to download and inspect the
   artifacts before approving.
#. Regenerate the ``get-pip.py`` script in the `get-pip repository`_ (as
   documented there) and commit the results.
#. Submit a Pull Request to `CPython`_ adding the new version of pip
   to ``Lib/ensurepip/_bundled``, removing the existing version, and
   adjusting the versions listed in ``Lib/ensurepip/__init__.py``.


.. note::

  If the release dropped the support of an obsolete Python version ``M.m``,
  a new ``M.m/get-pip.py`` needs to be published: update the ``all`` task from
  ``tasks/generate.py`` in `get-pip repository`_ and make a pull request to
  `psf-salt repository`_ to add the new ``get-pip.py`` (and its directory) to
  ``salt/pypa/bootstrap/init.sls``.


.. note::

  If the ``get-pip.py`` script needs to be updated due to changes in pip internals
  and if the last ``M.m/get-pip.py`` published still uses the default template, make
  sure to first duplicate ``templates/default.py`` as ``templates/pre-YY.N.py``
  before updating it and specify in ``tasks/generate.py`` that ``M.m/get-pip.py``
  now needs to use ``templates/pre-YY.N.py``.


Creating a bug-fix release
--------------------------

Sometimes we need to release a bugfix release of the form ``YY.N.Z+1``. In
order to create one of these the changes should already be merged into the
``main`` branch.

Note that this process is only needed when there are changes on the main branch
that you do *not* want to include in the bugfix release. For a bugfix release
that will include everything that is on the ``main`` branch, the above process
for creating a new release can be used, simply changing the version number.

#. Create a new ``release/YY.N.Z+1`` branch off of the ``YY.N`` tag using the
   command ``git checkout -b release/YY.N.Z+1 YY.N``.
#. Cherry pick the fixed commits off of the ``main`` branch, fixing any
   conflicts.
#. Run ``nox -s prepare-release -- YY.N.Z+1``.
#. Merge main into your release branch and drop the news files that have been
   included in your release (otherwise they would also appear in the ``YY.N+1``
   changelog)
#. Push the ``release/YY.N.Z+1`` branch to github and submit a PR for it against
   the ``main`` branch and wait for the tests to run.
#. Once tests run, merge the ``release/YY.N.Z+1`` branch into ``main``, and
   follow the above release process starting with step 5.

.. _`get-pip repository`: https://github.com/pypa/get-pip
.. _`psf-salt repository`: https://github.com/python/psf-salt
.. _`CPython`: https://github.com/python/cpython
.. _`CPython versions that are not end-of-life`: https://devguide.python.org/versions/

---

### Html Reference Build System (`docs/html/reference/build-system.md`)

(build-interface)=

# Build System Interface

When dealing with installable source distributions of a package, pip does not
directly handle the build process for the package. This responsibility is
delegated to "build backends" -- also known as "build systems". This means
that pip needs an interface, to interact with these build backends.

Modern Python packages can contain a `pyproject.toml` file, first introduced in
{pep}`518` and later expanded in {pep}`517`, {pep}`621` and {pep}`660`.
This file contains build system requirements and information, which are used by
pip to build the package.

## Build process

The overall process for building a package is:

- Create an isolated build environment.
- Populate the build environment with build dependencies.
- Generate the package's metadata, if necessary and possible.
- Generate a wheel for the package.

The wheel can then be used to perform an installation, if necessary.

### Build Isolation

For building packages using this interface, pip uses an _isolated environment_.
That is, pip will install build-time Python dependencies in a temporary
directory which will be added to `sys.path` for the build commands. This ensures
that build requirements are handled independently of the user's runtime
environment.

For example, a project that needs an older version of setuptools to build can
still be installed, even if the user has a newer version installed (and
without silently replacing that version).

### Build-time dependencies

Introduced in {pep}`518`, the `build-system.requires` key in the
`pyproject.toml` file is a list of requirement specifiers for build-time
dependencies of a package.

```toml
[build-system]
requires = ["setuptools ~= 58.0", "cython ~= 0.29.0"]
```

It is also possible for a build backend to provide dynamically calculated
build dependencies, using {pep}`517`'s `get_requires_for_build_wheel` hook. This
hook will be called by pip, and dependencies it describes will also be installed
in the build environment. For example, newer versions of setuptools expose the
contents of `setup_requires` to pip via this hook.

Build-time requirement specifiers follow {pep}`508`, so it's possible to
reference packages with URLs. For example:

```toml
[build-system]
requires = ["setuptools @ git+https://github.com/pypa/setuptools.git@main"]
```

### Metadata Generation

```{versionadded} 19.0

```

Once the build environment has been created and populated with build-time
dependencies, `pip` will usually need metadata about a package (name, version,
dependencies, and more).

If {pep}`517`'s `prepare_metadata_for_build_wheel` hook is provided by the
build backend, that will be used to generate the packages' metadata. Otherwise,
a wheel will be generated (as described below) and the metadata contained
within such a wheel will be used.

### Wheel Generation

```{versionadded} 19.0

```

For generating a wheel, pip uses the {pep}`517` `build_wheel` hook that has
to be provided by the build backend. The build backend will generate a wheel,
which may involve compiling extension code written in C/C++ (or other
languages).

Wheels generated using this mechanism can be [cached](wheel-caching) for reuse,
to speed up future installations.

### Editable Installation

```{versionadded} 21.3

```

For performing editable installs, pip will use {pep}`660`
`build_wheel_for_editable` hook that has to be provided by the build backend.
The wheels generated using this mechanism are not cached.

### Backend Configuration

Build backends have the ability to accept configuration settings, which can
change the way the build is handled. These settings take the form of a
series of `key=value` pairs. The user can supply configuration settings
using the `--config-settings` command line option (which can be supplied
multiple times, in order to specify multiple settings).

The supplied configuration settings are passed to every backend hook call.

Configuration settings provided via `--config-settings` command line options (or the
equivalent environment variables or configuration file entries) are passed to the build
of requirements explicitly provided as pip command line arguments. They are not passed
to the build of dependencies, or to the build of requirements provided in requirement
files.

## Build output

It is the responsibility of the build backend to ensure that the output is
in the correct encoding, as described in {pep}`517`.

## Fallback Behaviour

```{warning}
The following snippet merely describes the fallback behavior. For valid
examples of `pyproject.toml` to use with setuptools, please refer to
[the setuptools documentation](
https://setuptools.pypa.io/en/stable/userguide/quickstart.html#basic-use).
```

If a project does not have a `pyproject.toml` file containing a `build-system`
section, and contains a `setup.py` it will be assumed to have the following
backend settings:

```toml
[build-system]
requires = ["setuptools>=40.8.0"]
build-backend = "setuptools.build_meta:__legacy__"
```

If a project has a `build-system` section but no `build-backend`, then:

- It is expected to include `setuptools` as a build requirement. An
  error is reported if the available version of `setuptools` is not recent
  enough.

- The `setuptools.build_meta:__legacy__` build backend will be used.

## Disabling build isolation

This can be disabled using the `--no-build-isolation` flag -- users supplying
this flag are responsible for ensuring the build environment is managed
appropriately, including ensuring that all required build-time dependencies are
installed, since pip does not manage build-time dependencies when this flag is
passed.

## Historical notes

```{versionadded} 10.0

```

As this feature was incrementally rolled out, there have been various notable
changes and improvements in it.

Setuptools 40.8.0 is the first version of setuptools that offers a
{pep}`517` backend that closely mimics directly executing `setup.py`.

```{versionadded} 18.0
Prior to pip 18.0, pip only supports installing build requirements from
wheels, and does not support the use of environment markers and extras (only
version specifiers are respected).
```

```{versionadded} 18.1
Prior to pip 18.1, build dependencies using `.pth` files are not properly
supported; as a result namespace packages do not work under Python 3.2 and
earlier.
```

```{versionchanged} 23.1
The legacy interface where pip could invoke `setup.py install`
in some circumstances was removed,
in favor of the fallback behavior described above.
```

```{versionchanged} 25.3
The legacy interface where pip could invoke `setup.py build_wheel` or
`setup.py develop` in some circumstances was removed,
in favor of the fallback behavior described above.
```

---

### Html Reference Inspect Report (`docs/html/reference/inspect-report.md`)

# `pip inspect` JSON output specification

```{versionadded} 22.2
```

```{versionchanged} 23.0
``version`` has been bumped to ``1`` and the format declared stable.
```

The `pip inspect` command produces a detailed JSON report of the Python
environment, including installed distributions.

## Specification

The report is a JSON object with the following properties:

- `version`: the string `1`. It will change only if
  and when backward incompatible changes are introduced, such as removing mandatory
  fields or changing the semantics or data type of existing fields. The introduction of
  backward incompatible changes will follow the usual pip processes such as the
  deprecation cycle or feature flags. Tools must check this field to ensure they support
  the corresponding version.

- `pip_version`: a string with the version of pip used to produce the report.

- `installed`: an array of [`InspectReportItem`](InspectReportItem) representing the
  distribution packages that are installed.

- `environment`: an object describing the environment where the installation report was
  generated. See the section on environment markers in the {ref}`pypug:dependency-specifiers`
  specification for more information. Values have a string type.

(InspectReportItem)=

An `InspectReportItem` is an object describing an installed distribution package with
the following properties:

- `metadata`: the metadata of the distribution, converted to a JSON object according to
  the [PEP 566
  transformation](https://www.python.org/dev/peps/pep-0566/#json-compatible-metadata).

- `metadata_location`: the location of the metadata of the installed distribution. Most
  of the time this is the `.dist-info` directory. For legacy installs it is the
  `.egg-info` directory.

  ```{warning}
  This field may not necessarily point to a directory, for instance, in the case of older
  `.egg` installs.
  ```

- `direct_url`: Information about the direct URL that was used for installation, if any,
  using the [direct URL data
  structure](https://packaging.python.org/en/latest/specifications/direct-url-data-structure/).
  In most case, this field corresponds to the
  [`direct_url.json`](https://packaging.python.org/en/latest/specifications/direct-url)
  metadata, except for legacy editable installs, where it is emulated.

- `requested`: `true` if the `REQUESTED` metadata is present, `false` otherwise. This
  field is only present for modern `.dist-info` installations.

  ```{note}
  The `REQUESTED` metadata may not be generated by all installers.
  It is generated by pip since version 20.2.
  ```

- `installer`: the content of the `INSTALLER` metadata, if present and not empty.

## Example

Running the ``pip inspect`` command, in an environment where `pip` is installed in
editable mode and `packaging` is installed as well, will produce an output similar to
this (metadata abriged for brevity):

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Html Reference Installation Report (`docs/html/reference/installation-report.md`)

# Installation Report

```{versionadded} 22.2
```

```{versionchanged} 23.0
``version`` has been bumped to ``1`` and the format declared stable.
```

The `--report` option of the pip install command produces a detailed JSON report of what
it did install (or what it would have installed, if used with the `--dry-run` option).

```{note}
When considering use cases, please bear in mind that

- while the `--report` option may be used to implement requirement locking tools (among
  other use cases), this format is *not* meant to be a lock file format as such;
- there is no plan for pip to accept an installation report as input for the `install`,
  `download` or `wheel` commands;
- while the `--report` option and this format is a supported pip feature,
  it is *not* a PyPA interoperability standard and as such its evolution is governed by
  the pip processes and not the PyPA standardization processes.
```

## Specification

The report is a JSON object with the following properties:

- `version`: the string `1`. It will change only if
  and when backward incompatible changes are introduced, such as removing mandatory
  fields or changing the semantics or data type of existing fields. The introduction of
  backward incompatible changes will follow the usual pip processes such as the
  deprecation cycle or feature flags. Tools must check this field to ensure they support
  the corresponding version.

- `pip_version`: a string with the version of pip used to produce the report.

- `install`: an array of [`InstallationReportItem`](InstallationReportItem) representing
  the distribution packages (to be) installed.

- `environment`: an object describing the environment where the installation report was
  generated. See [PEP 508 environment
  markers](https://peps.python.org/pep-0508/#environment-markers) for more information.
  Values have a string type.

(InstallationReportItem)=

An `InstallationReportItem` is an object describing a (to be) installed distribution
package with the following properties:

- `metadata`: the metadata of the distribution, converted to a JSON object according to
  the [PEP 566
  transformation](https://www.python.org/dev/peps/pep-0566/#json-compatible-metadata).

- `is_direct`: `true` if the requirement was provided as, or constrained to, a direct
  URL reference. `false` if the requirements was provided as a name and version
  specifier.

- `is_yanked`: `true` if the requirement was yanked from the index, but was still
  selected by pip conform to [PEP 592](https://peps.python.org/pep-0592/#installers).

- `download_info`: Information about the artifact (to be) downloaded for installation,
  using the [direct URL data
  structure](https://packaging.python.org/en/latest/specifications/direct-url-data-structure/).
  When `is_direct` is `true`, this field is the same as the
  [`direct_url.json`](https://packaging.python.org/en/latest/specifications/direct-url)
  metadata, otherwise it represents the URL of the artifact obtained from the index or
  `--find-links`.

  ```{note}
  For source archives, `download_info.archive_info.hashes` may
  be absent when the requirement was installed from the wheel cache
  and the cache entry was populated by an older pip version that did not
  record the origin URL of the downloaded artifact.
  ```

- `requested`: `true` if the requirement was explicitly provided by the user, either
  directly via a command line argument or indirectly via a requirements file. `false`
  if the requirement was installed as a dependency of another requirement.

- `requested_extras`: extras requested by the user. This field is only present when the
  `requested` field is true.

## Example

The following command:

```console
pip install \
  --ignore-installed --dry-run --quiet \
  --report - \
  "pydantic>=1.9" git+https://github.com/pypa/packaging@main
```

will produce an output similar to this (metadata abriged for brevity):

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Html Reference Pip (`docs/html/reference/pip.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip`

---

### Html Reference Pip Cache (`docs/html/reference/pip_cache.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_cache/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_cache`

---

### Html Reference Pip Check (`docs/html/reference/pip_check.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_check/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_check`

---

### Html Reference Pip Config (`docs/html/reference/pip_config.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_config/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_config`

---

### Html Reference Pip Debug (`docs/html/reference/pip_debug.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_debug/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_debug`

---

### Html Reference Pip Download (`docs/html/reference/pip_download.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_download/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_download`

---

### Html Reference Pip Freeze (`docs/html/reference/pip_freeze.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_freeze/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_freeze`

---

### Html Reference Pip Hash (`docs/html/reference/pip_hash.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_hash/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_hash`

---

### Html Reference Pip Index (`docs/html/reference/pip_index.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_index/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_index`

---

### Html Reference Pip Install (`docs/html/reference/pip_install.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_install/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_install`

---

### Html Reference Pip List (`docs/html/reference/pip_list.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_list/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_list`

---

### Html Reference Pip Search (`docs/html/reference/pip_search.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_search/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_search`

---

### Html Reference Pip Show (`docs/html/reference/pip_show.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_show/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_show`

---

### Html Reference Pip Uninstall (`docs/html/reference/pip_uninstall.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_uninstall/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_uninstall`

---

### Html Reference Pip Wheel (`docs/html/reference/pip_wheel.rst`)

:orphan:

.. meta::

  :http-equiv=refresh: 3; url=../../cli/pip_wheel/

This page has moved
===================

You should be redirected automatically in 3 seconds. If that didn't
work, here's a link: :doc:`../cli/pip_wheel`

---

### Html Reference Requirement Specifiers (`docs/html/reference/requirement-specifiers.md`)

(Requirement Specifiers)=

# Requirement Specifiers

Pip supports installing from a package index using a {term}`requirement specifier <pypug:Requirement Specifier>`. Generally speaking, a requirement specifier is composed of a project name followed by optional {term}`version specifiers <pypug:Version Specifier>`.

{pep}`508` contains a full specification of the format of a requirement.

```{versionadded} 6.0
Support for environment markers.
```

```{versionadded} 19.1
Support for the direct URL reference form.
```

## Overview

A requirement specifier comes in two forms:

- name-based, which is composed of:

  - a package name (eg: `requests`)
  - optionally, a set of "extras" that serve to install optional dependencies (eg: `security`)
  - optionally, constraints to apply on the version of the package
  - optionally, environment markers

- URL-based, which is composed of:

  - a package name (eg: `requests`)
  - optionally, a set of "extras" that serve to install optional dependencies (eg: `security`)
  - a URL for the package
  - optionally, environment markers

## Examples

A few example name-based requirement specifiers:

```
SomeProject
SomeProject == 1.3
SomeProject >= 1.2, < 2.0
SomeProject[foo, bar]
SomeProject ~= 1.4.2
SomeProject == 5.4 ; python_version < '3.8'
SomeProject ; sys_platform == 'win32'
requests [security] >= 2.8.1, == 2.8.* ; python_version < "2.7"
```

```{note}
Use quotes around specifiers in the shell when using `>`, `<`, or when using environment markers.

Do _not_ use quotes in requirement files. There is only one exception: pip v7.0 and v7.0.1 (from May 2015) required quotes around specifiers containing environment markers in requirement files.
```

A few example URL-based requirement specifiers:

```none
pip @ https://github.com/pypa/pip/archive/22.0.2.zip
requests [security] @ https://github.com/psf/requests/archive/refs/heads/main.zip ; python_version >= "3.11"
```

## Self-referential extras

```{versionadded} 21.2
Support for self-referential extras.
```

A package can define optional dependencies that refer back to itself with other extras. This is useful for creating convenience extras that combine multiple existing ones.

For example, a `pyproject.toml` could define:

```toml
[project]
name = "SomeProject"

[project.optional-dependencies]
test = ["pytest", "pytest-cov"]
format = ["ruff"]
docs = ["sphinx"]
dev = ["SomeProject[test]", "SomeProject[format]"]  # separate form
all = ["SomeProject[test, format, docs]"]  # combined form
```

Installing `SomeProject[all]` would install `pytest`, `pytest-cov`, `ruff`, and `sphinx`.

---

### Html Reference Requirements File Format (`docs/html/reference/requirements-file-format.md`)

(requirements-file-format)=

# Requirements File Format

Requirements files serve as a list of items to be installed by pip, when
using {ref}`pip install`. Files that use this format are often called
"pip requirements.txt files", since `requirements.txt` is usually what
these files are named (although, that is not a requirement).

```{note}
The requirements file format is closely tied to a number of internal details of
pip (e.g., pip's command line options). The basic format is relatively stable
and portable but the full syntax, as described here, is only intended for
consumption by pip, and other tools should take that into account before using
it for their own purposes.
```

## Example

```
# This is a comment, to show how #-prefixed lines are ignored.
# It is possible to specify requirements as plain names.
pytest
pytest-cov
beautifulsoup4

# The syntax supported here is the same as that of requirement specifiers.
docopt == 0.6.1
requests [security] >= 2.8.1, == 2.8.* ; python_version < "2.7"
urllib3 @ https://github.com/urllib3/urllib3/archive/refs/tags/1.26.8.zip

# It is possible to refer to other requirement files or constraints files.
-r other-requirements.txt
-c constraints.txt

# It is possible to refer to specific local distribution paths.
./downloads/numpy-1.9.2-cp34-none-win32.whl

# It is possible to refer to URLs.
http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl
```

## Structure

Each line of the requirements file indicates something to be installed,
or arguments to {ref}`pip install`. The following forms are supported:

- `[[--option]...]`
- `<requirement specifier>`
- `<archive url/path>`
- `[-e] <local project path>`
- `[-e] <vcs project url>`

For details on requirement specifiers, see {ref}`Requirement Specifiers`. For
examples of all these forms, see {ref}`pip install Examples`.

### Encoding

The default encoding for requirement files is `UTF-8` unless a different
encoding is specified using a {pep}`263` style comment (e.g. `# -*- coding:
<encoding name> -*-`).

### Line continuations

A line ending in an unescaped `\` is treated as a line continuation
and the newline following it is effectively ignored.

### Comments

A line that begins with `#` is treated as a comment and ignored. Whitespace
followed by a `#` causes the `#` and the remainder of the line to be
treated as a comment.

Comments are stripped _after_ line continuations are processed.

## Supported options

Requirements files only supports certain pip install options, which are listed
below.

### Global options

The following options have an effect on the _entire_ `pip install` run, and
must be specified on their individual lines.

```{eval-rst}
.. pip-requirements-file-options-ref-list::
```

````{admonition} Example
To specify {ref}`--pre <install_--pre>`, {ref}`--no-index <install_--no-index>`
and two {ref}`--find-links <install_--find-links>` locations:

```
--pre
--no-index
--find-links /my/local/archives
--find-links http://some.archives.com/archives
```
````

(per-requirement-options)=

### Per-requirement options

```{versionadded} 7.0

```

The options which can be applied to individual requirements are:

- {ref}`--config-settings <install_--config-settings>`
- `--hash` (for {ref}`Hash-checking mode`)

## Referring to other requirements files

If you wish, you can refer to other requirements files, like this:

```
-r more_requirements.txt
```

You can also refer to {ref}`constraints files <Constraints Files>`, like this:

```
-c some_constraints.txt
```

## Using environment variables

```{versionadded} 10.0

```

Pip supports the use of environment variables inside the
requirements file.

You have to use the POSIX format for variable names including brackets around
the uppercase name as shown in this example: `${API_TOKEN}`. Pip will attempt
to find the corresponding environment variable defined on the host system at
runtime.

```{note}
There is no support for other variable expansion syntaxes such as `$VARIABLE`
and `%VARIABLE%`.
```

You can now store sensitive data (tokens, keys, etc.) in environment variables
and only specify the variable name for your requirements, letting pip lookup
the value at runtime. This approach aligns with the commonly used
[12-factor configuration pattern](https://12factor.net/config).

---

### Html Topics Authentication (`docs/html/topics/authentication.md`)

# Authentication

## Basic HTTP authentication

Pip supports basic HTTP-based authentication credentials. This is done by
providing the username (and optionally password) in the URL:

```
https://username:password@pypi.company.com/simple
```

For indexes that only require single-part authentication tokens, provide the
token as the "username" and do not provide a password:

```
https://0123456789abcdef@pypi.company.com/simple
```

### Percent-encoding special characters

```{versionadded} 10.0
```

Certain special characters are not valid in the credential part of a URL.
If the user or password part of your login credentials contain any of these
[special characters][reserved-chars], then they must be percent-encoded. As an
example, for a user with username `user` and password `he//o` accessing a
repository at `pypi.company.com/simple`, the URL with credentials would look
like:

```
https://user:he%2F%2Fo@pypi.company.com/simple
```

[reserved-chars]: https://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters

## netrc support

Pip supports loading credentials from a user's `.netrc` file. If no credentials
are part of the URL, pip will attempt to get authentication credentials for the
URL's hostname from the user's `.netrc` file. This behaviour comes from the
underlying use of {pypi}`requests`, which in turn delegates it to the
[Python standard library's `netrc` module][netrc-std-lib].

```{note}
As mentioned in the [standard library documentation for netrc][netrc-std-lib],
only ASCII characters are allowed in `.netrc` files. Whitespace and
non-printable characters are not allowed in passwords.
```

Below is an example `.netrc`, for the host `example.com`, with a user named
`daniel`, using the password `qwerty`:

```
machine example.com
login daniel
password qwerty
```

More information about the `.netrc` file format can be found in the GNU [`ftp`
man pages][netrc-docs].

[netrc-docs]: https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
[netrc-std-lib]: https://docs.python.org/3/library/netrc.html

## Keyring Support

Pip supports loading credentials stored in your keyring using the
{pypi}`keyring` library, which can be enabled by passing `--keyring-provider`
with a value of `auto`, `disabled`, `import`, or `subprocess`. The default
value `auto` respects `--no-input` and does not query keyring at all if the option
is used; otherwise it tries the `import`, `subprocess`, and `disabled`
providers (in this order) and uses the first one that works.

### Configuring pip's keyring usage

Since the keyring configuration is likely system-wide, a more common way to
configure its usage would be to use a configuration instead:

```{seealso}
{doc}`./configuration` describes how pip configuration works.
```

```bash
$ pip config set --global global.keyring-provider subprocess

# A different user on the same system which has PYTHONPATH configured and
# wanting to use keyring installed that way could then run
$ pip config set --user global.keyring-provider import

# For a specific virtual environment you might want to use disable it again
# because you will only be using PyPI and the private repo (and mirror)
# requires 2FA with a keycard and a pincode
$ pip config set --site global.index https://pypi.org/simple
$ pip config set --site global.keyring-provider disabled

# configuring it via environment variable is also possible
$ export PIP_KEYRING_PROVIDER=disabled
```

### Using keyring's Python module

Setting `keyring-provider` to `import` makes pip communicate with `keyring` via
its Python interface.

```bash
# install keyring from PyPI
$ pip install keyring --index-url https://pypi.org/simple
$ echo "your-password" | keyring set pypi.company.com your-username
$ pip install your-package --keyring-provider import --index-url https://pypi.company.com/
```

### Using keyring as a command line application

Setting `keyring-provider` to `subprocess` makes pip look for and use the
`keyring` command found on `PATH`.

For this use case, a username *must* be included in the URL, since it is
required by `keyring`'s command line interface. See the example below or the
basic HTTP authentication section at the top of this page.

```bash
# Install keyring from PyPI using pipx, which we assume is installed properly
# you can also create a venv somewhere and add it to the PATH yourself instead
$ pipx install keyring --index-url https://pypi.org/simple

# For Azure DevOps, also install its keyring backend.
$ pipx inject keyring artifacts-keyring --index-url https://pypi.org/simple

# For Google Artifact Registry, also install and initialize its keyring backend.
$ pipx inject keyring keyrings.google-artifactregistry-auth --index-url https://pypi.org/simple
$ gcloud auth login

# Note that a username is required in the index URL.
$ pip install your-package --keyring-provider subprocess --index-url https://username@pypi.example.com/
```

### Here be dragons

The `auto` provider is conservative and does not query keyring at all when
`--no-input` is used because the keyring might require user interaction such as
prompting the user on the console. Third party tools frequently call Pip for
you and do indeed pass `--no-input` as they are well-behaved and don't have
much information to work with. (Keyring does have an api to request a backend
that does not require user input.) You have more information about your system,
however!

You can force keyring usage by requesting a keyring provider other than `auto`
(or `disabled`). Leaving `import` and `subprocess`. You do this by passing
`--keyring-provider import` or one of the following methods:

```bash
# via config file, possibly with --user, --global or --site
$ pip config set global.keyring-provider subprocess
# or via environment variable
$ export PIP_KEYRING_PROVIDER=import
```

```{warning}
Be careful when doing this since it could cause tools such as pipx and Pipenv
to appear to hang. They show their own progress indicator while hiding output
from the subprocess in which they run pip. You won't know whether the keyring
backend is waiting the user input or not in such situations.
```

Note that `keyring` (the Python package) needs to be installed separately from
pip. This can create a bootstrapping issue if you need the credentials stored in
the keyring to download and install keyring.

It is, thus, expected that users that wish to use pip's keyring support have
some mechanism for downloading and installing {pypi}`keyring`.

---

### Html Topics Caching (`docs/html/topics/caching.md`)

# Caching

```{versionadded} 6.0

```

Pip provides an on-by-default caching, designed to reduce the amount of time
spent on duplicate downloads and builds.

## What is cached

### HTTP responses

This cache functions like a web browser cache.

When making any HTTP request, pip will first check its local cache to determine
if it has a suitable response stored for that request which has not expired. If
it does then it returns that response and doesn't re-download the content.

If it has a response stored but it has expired, then it will attempt to make a
conditional request to refresh the cache which will either return an empty
response telling pip to simply use the cached item (and refresh the expiration
timer) or it will return a whole new response which pip can then store in the
cache.

While this cache attempts to minimize network activity, it does not prevent
network access altogether. If you want a local install solution that
circumvents accessing PyPI, see {ref}`Installing from local packages`.

```{versionchanged} 23.3
A new cache format is now used, stored in a directory called `http-v2` (see
below for this directory's location). Previously this cache was stored in a
directory called `http` in the main cache directory. If you have completely
switched to newer versions of `pip`, you may wish to delete the old directory.
```

(wheel-caching)=

### Locally built wheels

Pip attempts to use wheels from its local wheel cache whenever possible.

This means that if there is a cached wheel for the same version of a specific
package name, pip will use that wheel instead of rebuilding the project.

When no wheels are found for a source distribution, pip will attempt to build a
wheel using the package's build system. If the build is successful, this wheel
is added to the cache and used in subsequent installs for the same package
version.

Wheels built from source distributions provided to pip as a direct path (such
as `pip install .`) are not cached across runs, though they may be reused within
the same `pip` execution.

```{versionchanged} 20.0
Pip now caches wheels when building from an immutable Git reference
(i.e. a commit hash).
```

## Where is the cache stored

```{caution}
The exact filesystem structure of pip's cache's contents is considered to be
an implementation detail and may change between any two versions of pip.
```

### `pip cache dir`

```{versionadded} 20.1

```

You can use `pip cache dir` to get the cache directory that pip is currently configured to use.

### Default paths

````{tab} Linux
```
~/.cache/pip
```

Pip will also respect `XDG_CACHE_HOME`.
````

````{tab} MacOS
```
~/Library/Caches/pip
```

Pip will also respect `XDG_CACHE_HOME`.
````

````{tab} Windows
```
%LocalAppData%\pip\Cache
```
````

```{versionchanged} 26.2
Pip will also respect `XDG_CACHE_HOME` on macOS.
```

## Avoiding caching

Pip tries to use its cache whenever possible, and it is designed do the right
thing by default.

In some cases, pip's caching behaviour can be undesirable. As an example, if you
have package with optional C extensions, that generates a pure Python wheel
when the C extension can’t be built, pip will use that cached wheel even when
you later invoke it from an environment that could have built those optional C
extensions. This is because pip is seeing a cached wheel that matches the
package being built, and pip assumes that the result of building a package from
a package index is deterministic.

The recommended approach for dealing with these situations is to directly
install from a source distribution instead of letting pip auto-discover the
package when it is trying to install. Installing directly from a source
distribution will make pip build a wheel, regardless of whether there is a
matching cached wheel. This usually means doing something like:

```{pip-cli}
$ pip download sampleproject==1.0.0 --no-binary :all:
$ pip install sampleproject-1.0.0.tar.gz
```

It is also a good idea to remove the offending cached wheel using the
{ref}`pip cache` command.

## Cache management

The {ref}`pip cache` command can be used to manage pip's cache.

### General overview

`pip cache info` provides an overview of the contents of pip's cache, such as the total size and location of various parts of it.

### Removing a single package

`pip cache remove setuptools` removes all wheel files related to setuptools from pip's cache. HTTP cache files are not removed at this time.

### Removing the cache

`pip cache purge` will clear all files from pip's wheel and HTTP caches.

### Listing cached files

`pip cache list` will list all wheel files from pip's cache.

`pip cache list setuptools` will list all setuptools-related wheel files from pip's cache.

## Disabling caching

Pip's caching behaviour is disabled by passing the `--no-cache-dir` option.

It is, however, recommended to **NOT** disable pip's caching unless you have caching at a higher level (eg: layered caches in container builds). Doing so can
significantly slow down pip (due to repeated operations and package builds)
and result in significantly more network usage.

---

### Html Topics Configuration (`docs/html/topics/configuration.md`)

(configuration)=

# Configuration

Pip allows a user to change its behaviour via 3 mechanisms:

- command line options
- environment variables
- configuration files

This page explains how the configuration files and environment variables work,
and how they are related to pip's various command line options.

```{seealso}
{doc}`../cli/pip_config` command, which helps manage pip's configuration.
```

(config-file)=

## Configuration Files

Configuration files can change the default values for command line options.
The files are written using standard INI format.

Pip has 3 "levels" of configuration files:

- `global`: system-wide configuration file, shared across users.
- `user`: per-user configuration file.
- `site`: per-environment configuration file; i.e. per-virtualenv or python installation.

Additionally, environment variables can be specified which will override any of the above.

### Location

Pip's configuration files are located in fairly standard locations. This
location is different on different operating systems, and has some additional
complexity for backwards compatibility reasons. Note that if user config files
exist in both the legacy and current locations, values in the current file
will override values in the legacy file.

```{tab} Unix

Global
: In a "pip" subdirectory of any of the paths set in the environment variable
  `XDG_CONFIG_DIRS` (if it exists), for example {file}`/etc/xdg/pip/pip.conf`.

  This will be followed by loading {file}`/etc/pip.conf`.

User
: {file}`$HOME/.config/pip/pip.conf`, which respects the `XDG_CONFIG_HOME` environment variable.

  The legacy "per-user" configuration file is also loaded, if it exists: {file}`$HOME/.pip/pip.conf`.

Site
: {file}`$VIRTUAL_ENV/pip.conf`. If no virtual environment is activated, `pip.conf` is loaded from the
  Python installation root (run `pip config debug` to identify the exact path).
```

```{tab} MacOS

Global
: In a "pip" subdirectory of each path listed in the environment
  variable `XDG_DATA_DIRS` (if it is non-empty).

  If `XDG_DATA_DIRS` is unset or empty,
  {file}`/Library/Application Support/pip/pip.conf` is loaded instead
  (run `pip config debug` to identify the exact paths).

User
: The user configuration file is loaded from one of the following
  locations:

  * {file}`$XDG_DATA_HOME/pip/pip.conf`, if `XDG_DATA_HOME` is
    non-empty and {file}`$XDG_DATA_HOME/pip` exists.
  * {file}`$HOME/Library/Application Support/pip/pip.conf`, if
    `XDG_DATA_HOME` is unset or empty and
    {file}`$HOME/Library/Application Support/pip` exists.
  * {file}`$HOME/.config/pip/pip.conf`, otherwise.

  The legacy "per-user" configuration file is also loaded, if it exists: {file}`$HOME/.pip/pip.conf`.

Site
: {file}`$VIRTUAL_ENV/pip.conf`. If no virtual environment is activated, `pip.conf` is loaded from the
  Python installation root (run `pip config debug` to identify the exact path).
```

```{tab} Windows

Global
: * On Windows 7 and later: {file}`C:\\ProgramData\\pip\\pip.ini`
    (hidden but writeable)
  * On Windows Vista: Global configuration is not supported.
  * On Windows XP:
    {file}`C:\\Documents and Settings\\All Users\\Application Data\\pip\\pip.ini`

User
: {file}`%APPDATA%\\pip\\pip.ini`

  The legacy "per-user" configuration file is also loaded, if it exists: {file}`%HOME%\\pip\\pip.ini`

Site
: {file}`%VIRTUAL_ENV%\\pip.ini`, If no virtual environment is activated, `pip.ini` is loaded from
  the Python installation root (run `pip config debug` to identify the exact path).
```

```{versionchanged} 26.2
Pip will also respect `XDG_DATA_DIRS` and `XDG_DATA_HOME` on macOS.
```

### `PIP_CONFIG_FILE`

Additionally, the environment variable `PIP_CONFIG_FILE` can be used to specify
a configuration file that's loaded last, and whose values override the values
set in the aforementioned files. Setting this to {any}`os.devnull`
disables the loading of _all_ configuration files. Note that if a file exists
at the location that this is set to, the user config file will not be loaded.

(config-precedence)=

### Loading order

When multiple configuration files are found, pip combines them in the following
order:

- Global
- User
- Site
- `PIP_CONFIG_FILE`, if given.

Each file read overrides any values read from previous files, so if the
global timeout is specified in both the global file and the per-user file
then the latter value will be used.

### Naming

The names of the settings are derived from the long command line option.

As an example, if you want to use a different package index (`--index-url`) and
set the HTTP timeout (`--timeout`) to 60 seconds, your config file would
look like this:

```ini
[global]
timeout = 60
index-url = https://download.zope.org/ppix
```

### Per-command section

Each subcommand can be configured optionally in its own section. This overrides
the global setting with the same name.

As an example, if you want to decrease the `timeout` to `10` seconds when
running the {ref}`pip freeze`, and use `60` seconds for all other commands:

```ini
[global]
timeout = 60

[freeze]
timeout = 10
```

### Boolean options

Boolean options like `--ignore-installed` or `--no-dependencies` can be set
like this:

```ini
[install]
ignore-installed = true
no-dependencies = yes
```

To enable the boolean options `--no-compile`, `--no-warn-script-location` and
`--no-cache-dir`, falsy values have to be used:

```ini
[global]
no-cache-dir = false

[install]
no-compile = no
no-warn-script-location = false
```

### Repeatable options

For options which can be repeated like `--verbose` and `--quiet`, a
non-negative integer can be used to represent the level to be specified:

```ini
[global]
quiet = 0
verbose = 2
```

It is possible to append values to a section within a configuration file. This
is applicable to appending options like `--find-links` or `--trusted-host`,
which can be written on multiple lines:

```ini
[global]
find-links =
    http://download.example.com

[install]
find-links =
    http://mirror1.example.com
    http://mirror2.example.com

trusted-host =
    mirror1.example.com
    mirror2.example.com
```

This enables users to add additional values in the order of entry for such
command line arguments.

## Environment Variables

Pip's command line options can be set with environment variables using the
format `PIP_<UPPER_LONG_NAME>` . Dashes (`-`) have to be replaced with
underscores (`_`).

- `PIP_TIMEOUT=60` is the same as `--timeout=60`
- ```
  PIP_FIND_LINKS="http://mirror1.example.com http://mirror2.example.com"
  ```

  is the same as

  ```
  --find-links=http://mirror1.example.com --find-links=http://mirror2.example.com
  ```

Repeatable options that do not take a value (such as `--verbose`) can be
specified using the number of repetitions:

- `PIP_VERBOSE=3` is the same as `pip install -vvv`

```{note}
Environment variables set to an empty string (like with `export X=` on Unix) will **not** be treated as false.
Use `no`, `false` or `0` instead.
```

## Precedence / Override order

Command line options override environment variables, which override the
values in a configuration file. Within the configuration file, values in
command-specific sections override values in the global section.

Examples:

- `--host=foo` overrides `PIP_HOST=foo`
- `PIP_HOST=foo` overrides a config file with `[global] host = foo`
- A command specific section in the config file `[<command>] host = bar`
  overrides the option with same name in the `[global]` config file section.

---

### Html Topics Dependency Resolution (`docs/html/topics/dependency-resolution.md`)

# Dependency Resolution

Pip is capable of determining and installing the dependencies of packages. The
process of determining which version of a dependency to install is known as
dependency resolution. This behaviour can be disabled by passing
{any}`--no-deps` to {any}`pip install`.

## How it works

When a user does a `pip install` (e.g. `pip install tea`), pip needs to work
out the package's dependencies (e.g. `spoon`, `hot-water`, `tea-leaves` etc.)
and what the versions of each of those dependencies it should install.

At the start of a `pip install` run, pip does not have all the dependency
information of the requested packages. It needs to work out the dependencies
of the requested packages, the dependencies of those dependencies, and so on.
Over the course of the dependency resolution process, pip will need to download
distribution files of the packages which are used to get the dependencies of a
package.

## Backtracking

```{versionchanged} 20.3
Pip's dependency resolver is now capable of backtracking.
```

During dependency resolution, pip needs to make assumptions about the package
versions it needs to install and, later, check these assumptions were not
incorrect. When pip finds that an assumption it made earlier is incorrect, it
has to backtrack, which means also discarding some of the work that has already
been done, and going back to choose another path.

This can look like pip downloading multiple versions of the same package,
since pip explicitly presents each download to the user. The backtracking of
choices made during this step is not unexpected behaviour or a bug. It is part
of how dependency resolution for Python packages works.

````{admonition} Example
The user requests `pip install tea`. The package `tea` declares a dependency on
`hot-water`, `spoon`, `cup`, amongst others.

Pip starts by picking the most recent version of `tea` and gets the list of
dependencies of that version of `tea`. It will then repeat the process for
those packages, picking the most recent version of `spoon` and then `cup`. Now,
pip notices that the version of `cup` it has chosen is not compatible with the
version of `spoon` it has chosen. Thus, pip will "go back" (backtrack) and try
to use another version of `cup`. If it is successful, it will continue onto the
next package (like `sugar`). Otherwise, it will continue to backtrack on `cup`
until it finds a version of `cup` that is compatible with all the other
packages.

This can look like:

```console
$ pip install tea
Collecting tea
  Downloading tea-1.9.8-py2.py3-none-any.whl (346 kB)
     |████████████████████████████████| 346 kB 10.4 MB/s
Collecting spoon==2.27.0
  Downloading spoon-2.27.0-py2.py3-none-any.whl (312 kB)
     |████████████████████████████████| 312 kB 19.2 MB/s
Collecting cup>=1.6.0
  Downloading cup-3.22.0-py2.py3-none-any.whl (397 kB)
     |████████████████████████████████| 397 kB 28.2 MB/s
INFO: pip is looking at multiple versions of this package to determine
which version is compatible with other requirements.
This could take a while.
  Downloading cup-3.21.0-py2.py3-none-any.whl (395 kB)
     |████████████████████████████████| 395 kB 27.0 MB/s
  Downloading cup-3.20.0-py2.py3-none-any.whl (394 kB)
     |████████████████████████████████| 394 kB 24.4 MB/s
  Downloading cup-3.19.1-py2.py3-none-any.whl (394 kB)
     |████████████████████████████████| 394 kB 21.3 MB/s
  Downloading cup-3.19.0-py2.py3-none-any.whl (394 kB)
     |████████████████████████████████| 394 kB 26.2 MB/s
  Downloading cup-3.18.0-py2.py3-none-any.whl (393 kB)
     |████████████████████████████████| 393 kB 22.1 MB/s
  Downloading cup-3.17.0-py2.py3-none-any.whl (382 kB)
     |████████████████████████████████| 382 kB 23.8 MB/s
  Downloading cup-3.16.0-py2.py3-none-any.whl (376 kB)
     |████████████████████████████████| 376 kB 27.5 MB/s
  Downloading cup-3.15.1-py2.py3-none-any.whl (385 kB)
     |████████████████████████████████| 385 kB 30.4 MB/s
INFO: pip is looking at multiple versions of this package to determine
which version is compatible with other requirements.
This could take a while.
  Downloading cup-3.15.0-py2.py3-none-any.whl (378 kB)
     |████████████████████████████████| 378 kB 21.4 MB/s
  Downloading cup-3.14.0-py2.py3-none-any.whl (372 kB)
     |████████████████████████████████| 372 kB 21.1 MB/s
```

These multiple `Downloading cup-{version}` lines show that pip is backtracking
choices it is making during dependency resolution.
````

If pip starts backtracking during dependency resolution, it does not know how
many choices it will reconsider, and how much computation would be needed.

For the user, this means it can take a long time to complete when pip starts
backtracking. In the case where a package has a lot of versions, arriving at a
good candidate can take a lot of time. The amount of time depends on the
package size, the number of versions pip must try, and various other factors.

Backtracking reduces the risk that installing a new package will accidentally
break an existing installed package, and so reduces the risk that your
environment gets messed up. To do this, pip has to do more work, to find out
which version of a package is a good candidate to install.

## Possible ways to reduce backtracking

There is no one-size-fits-all answer to situations where pip is backtracking
excessively during dependency resolution. There are ways to reduce the
degree to which pip might backtrack though. Nearly all of these approaches
require some amount of trial and error.

### Allow pip to complete its backtracking

In most cases, pip will complete the backtracking process successfully.
This could take a very long time to complete, so this may not be your
preferred option.

However, it is a possible that pip will not be able to find a set of
compatible versions. For this, pip will try every possible combination that
it needs to and determine that there is no compatible set.

If you'd prefer not to wait, you can interrupt pip (Ctrl+c) and try the
strategies listed below.

### Reduce the number of versions pip is trying to use

It is usually a good idea to add constraints the package(s) that pip is backtracking on (e.g. in the above example - `cup`).

You could try something like:

```{pip-cli}
$ pip install tea "cup >= 3.13"
```

This will reduce the number of versions of `cup` it tries, and
possibly reduce the time pip takes to install.

There is a possibility that the addition constraint is incorrect. When this
happens, the reduced search space makes it easier for pip to more quickly
determine what caused the conflict and present that to the user. It could also
result in pip backtracking on a different package due to some other conflict.

### Use constraint files or lockfiles

This option is a progression of the previous section. It requires users to know
how to inspect:

- the packages they're trying to install
- the package release frequency and compatibility policies
- their release notes and changelogs from past versions

During deployment, you can create a lockfile stating the exact package and
version number for each dependency of that package. You can create this
with [pip-tools](https://github.com/jazzband/pip-tools/).

This means the "work" is done once during development process, and thus
will avoid performing dependency resolution during deployment.

(Fixing conflicting dependencies)=

## Dealing with dependency conflicts

This section uses hypothetical packages (`package_coffee`, `package_tea`, and
`package_water`) to explain how pip resolves conflicts.

This section provides practical suggestions to pip users who encounter
a `ResolutionImpossible` error, where pip cannot install their specified
packages due to conflicting dependencies.

### Understanding your error message

When you get a `ResolutionImpossible` error, you might see something
like this:

```{pip-cli}
$ pip install package_coffee==0.44.1 package_tea==4.3.0
[regular pip output]
ERROR: Cannot install package_coffee==0.44.1 and package_tea==4.3.0 because these package versions have conflicting dependencies.

The conflict is caused by:
    package_coffee 0.44.1 depends on package_water<3.0.0,>=2.4.2
    package_tea 4.3.0 depends on package_water==2.3.1
```

In this example, pip cannot install the packages you have requested,
because they each depend on different versions of the same package
(``package_water``):

- ``package_coffee`` version ``0.44.1`` depends on a version of
  ``package_water`` that is less than ``3.0.0`` but greater than or equal to
  ``2.4.2``
- ``package_tea`` version ``4.3.0`` depends on version ``2.3.1`` of
  ``package_water``

Note: `package_coffee`, `package_tea`, and `package_water` are hypothetical
packages used only to illustrate dependency conflicts. They are not real
projects you can install.


Sometimes these messages are straightforward to read, because they use
commonly understood comparison operators to specify the required version
(e.g. `<` or `>`).

However, Python packaging also supports some more complex ways for
specifying package versions (e.g. `~=` or `*`):

| Operator | Description                                                    | Example                                              |
| -------- | -------------------------------------------------------------- | ---------------------------------------------------- |
| `>`      | Any version greater than the specified version.                | `>3.1`: any version greater than `3.1`.              |
| `<`      | Any version less than the specified version.                   | `<3.1`: any version less than `3.1`.                 |
| `<=`     | Any version less than or equal to the specified version.       | `<=3.1`: any version less than or equal to `3.1`.    |
| `>=`     | Any version greater than or equal to the specified version.    | `>=3.1`: any version greater than or equal to `3.1`. |
| `==`     | Exactly the specified version.                                 | `==3.1`: only version `3.1`.                         |
| `!=`     | Any version not equal to the specified version.                | `!=3.1`: any version other than `3.1`.               |
| `~=`     | Any compatible{sup}`1` version.                                | `~=3.1`: any version compatible{sup}`1` with `3.1`.  |
| `*`      | Can be used at the end of a version number to represent _all_. | `==3.1.*`: any version that starts with `3.1`.       |

{sup}`1` Compatible versions are higher versions that only differ in the final segment.
`~=3.1.2` is equivalent to `>=3.1.2, ==3.1.*`. `~=3.1` is equivalent to `>=3.1, ==3.*`.

The detailed specification of supported comparison operators can be
found in {pep}`440`.

### Possible solutions

The solution to your error will depend on your individual use case. Here
are some things to try:

#### Audit your top level requirements

As a first step, it is useful to audit your project and remove any
unnecessary or out of date requirements (e.g. from your `setup.py` or
`requirements.txt` files). Removing these can significantly reduce the
complexity of your dependency tree, thereby reducing opportunities for
conflicts to occur.

#### Loosen your top level requirements

Sometimes the packages that you have asked pip to install are
incompatible because you have been too strict when you specified the
package version.

In our first example both `package_coffee` and `package_tea` have been
_pinned_ to use specific versions
(`package_coffee==0.44.1 package_tea==4.3.0`).

To find a version of both `package_coffee` and `package_tea` that depend on
the same version of `package_water`, you might consider:

- Loosening the range of packages that you are prepared to install
  (e.g. `pip install "package_coffee>0.44" "package_tea>4.0.0"`)
- Asking pip to install _any_ version of `package_coffee` and `package_tea`
  by removing the version specifiers altogether (e.g.
  `pip install package_coffee package_tea`)

In the second case, pip will automatically find a version of both
`package_coffee` and `package_tea` that depend on the same version of
`package_water`, for example:

- `package_coffee 0.44.1`, which depends on `package_water 2.6.1`
- `package_tea 4.4.3`, which also depends on `package_water 2.6.1`

If you want to prioritize one package over another, you can add version
specifiers to _only_ the more important package:

```{pip-cli}
$ pip install package_coffee==0.44.1 package_tea
```

This will result in:

- `package_coffee 0.44.1`, which depends on `package_water 2.6.1`
- `package_tea 4.4.3` which _also_ depends on `package_water 2.6.1`

Now that you have resolved the issue, you can repin the compatible
package versions as required.

#### Loosen the requirements of your dependencies

Assuming that you cannot resolve the conflict by loosening the version
of the package you require (as above), you can try to fix the issue on
your _dependency_ by:

- Requesting that the package maintainers loosen _their_ dependencies
- Forking the package and loosening the dependencies yourself

```{warning}
If you choose to fork the package yourself, you are _opting out_ of
any support provided by the package maintainers. Proceed at your own risk!
```

#### All requirements are appropriate, but a solution does not exist

Sometimes it's simply impossible to find a combination of package
versions that do not conflict. Welcome to [dependency hell].

In this situation, you could consider:

- Using an alternative package, if that is acceptable for your project.
  See [Awesome Python] for similar packages.
- Refactoring your project to reduce the number of dependencies (for
  example, by breaking up a monolithic code base into smaller pieces).

## Handling Resolution Too Deep Errors

Sometimes pip's dependency resolver may exceed its search depth and terminate
with a `ResolutionTooDeepError` exception. This typically occurs when the
dependency graph is extremely complex or when there are too many package
versions to evaluate.

To address this error, consider the following strategies:

### Specify Reasonable Lower Bounds

By setting a higher lower bound for your dependencies, you narrow the search
space. This excludes older versions that might trigger excessive backtracking.
For example:

```{pip-cli}
$ pip install "package_coffee>=0.44.0" "package_tea>=4.0.0"
```

### Use the `--upgrade` Flag

The `--upgrade` flag directs pip to ignore already installed versions and
search for the latest versions that meet your requirements. This can help
avoid unnecessary resolution paths:

```{pip-cli}
$ pip install --upgrade package_coffee package_tea
```

### Utilize Constraint Files

If you need to impose additional version restrictions on transitive
dependencies (dependencies of dependencies), consider using a constraint
file. A constraint file specifies version limits for packages that are
indirectly required. For example:

```
# constraints.txt
indirect_dependency>=2.0.0
```

Then install your packages with:

```{pip-cli}
$ pip install --constraint constraints.txt package_coffee package_tea
```

### Use Upper Bounds Sparingly

Although upper bounds are generally discouraged because they can complicate
dependency management, they may be necessary when certain versions are known
to cause conflicts. Use them cautiously—for example:

```{pip-cli}
$ pip install "package_coffee>=0.44.0,<1.0.0" "package_tea>=4.0.0"
```

### Report ResolutionTooDeep Errors

If you encounter a `ResolutionTooDeep` error consider reporting it, to help
the pip team have real world examples to test against, at the dedicated
[pip issue](https://github.com/pypa/pip/issues/13281).

## Getting help

If none of the suggestions above work for you, we recommend that you ask
for help on:

- [Python user Discourse](https://discuss.python.org/c/users/7)
- [Python user forums](https://www.python.org/community/forums/)
- [Python developers Slack channel](https://pythondev.slack.com/)
- [Python IRC](https://www.python.org/community/irc/)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/python)

See ["How do I ask a good question?"] for tips on asking for help.

Unfortunately, **the pip team cannot provide support for individual
dependency conflict errors**. Please _only_ open a ticket on
[pip's issue tracker](https://github.com/pypa/pip/issues) if you believe
that your problem has exposed a bug in pip.

["how do i ask a good question?"]: https://stackoverflow.com/help/how-to-ask
[awesome python]: https://python.libhunt.com/
[dependency hell]: https://en.wikipedia.org/wiki/Dependency_hell

---

### Html Topics Https Certificates (`docs/html/topics/https-certificates.md`)

(SSL Certificate Verification)=

# HTTPS Certificates

```{versionadded} 1.3

```

By default, pip will perform SSL certificate verification for network
connections it makes over HTTPS. These serve to prevent man-in-the-middle
attacks against package downloads.

## Using a specific certificate store

The `--cert` option (and the corresponding `PIP_CERT` environment variable)
allow users to specify a different certificate store/bundle for pip to use. It
is also possible to use `REQUESTS_CA_BUNDLE` or `CURL_CA_BUNDLE` environment
variables.

If you need a specific certificate bundle, you can download the
[Mozilla CA bundle provided by the curl project](https://curl.se/docs/caextract.html).

## Using system certificate stores

```{versionadded} 24.2

```

```{note}
Versions of pip prior to v24.2 did not use system certificates by default.
To use system certificates with pip v22.2 or later, you must opt-in using the `--use-feature=truststore` CLI flag.
```

By default
system certificates are used in addition to certifi to verify HTTPS connections.
This functionality is provided through the {pypi}`truststore` package.

If you encounter a TLS/SSL error when using the `truststore` feature you should
open an issue on the [truststore GitHub issue tracker] instead of pip's issue
tracker. The maintainers of truststore will help diagnose and fix the issue.

To opt-out of using system certificates you can pass the `--use-deprecated=legacy-certs`
flag to pip.

[truststore github issue tracker]:
  https://github.com/sethmlarson/truststore/issues

---

### Html Topics Local Project Installs (`docs/html/topics/local-project-installs.md`)

# Local project installs

It is extremely common to have a project, available in a folder/directory on your computer [^1] that you wish to install.

With pip, depending on your usecase, there are two ways to do this:

- A regular install
- An editable install

## Regular installs

You can install local projects by specifying the project path to pip:

```{pip-cli}
$ pip install path/to/SomeProject
```

This will install the project into the Python that pip is associated with, in a manner similar to how it would actually be installed.

This is what should be used in CI system and for deployments, since it most closely mirrors how a package would get installed if you build a distribution and installed from it (because that's _exactly_ what it does).

(editable-installs)=

## Editable installs

You can install local projects in "editable" mode:

```{pip-cli}
$ pip install -e path/to/SomeProject
```

Editable installs allow you to install your project without copying any files. Instead, the files in the development directory are added to Python's import path. This approach is well suited for development and is also known as a "development installation".

With an editable install, you only need to perform a re-installation if you change the project metadata (eg: version, what scripts need to be generated etc). You will still need to run build commands when you need to perform a compilation for non-Python code in the project (eg: C extensions).

```{caution}
It is possible to see behaviour differences between regular installs vs editable installs. These differences depend on the build-backend, and you should check the build-backend documentation for the details. In case you distribute the project as a "distribution package", users will see the behaviour of regular installs -- thus, it is important to ensure that regular installs work correctly.
```

## Build artifacts

```{versionchanged} 21.3
The project being installed is no longer copied to a temporary directory before invoking the build system, by default. A `--use-deprecated=out-of-tree-build` option is provided as a temporary fallback to aid user migrations.
```

```{versionchanged} 22.1
The `--use-deprecated=out-of-tree-build` option has been removed.
```

When provided with a project that's in a local directory, pip will invoke the build system "in place". This behaviour has several consequences:

- Local project builds will now be significantly faster, for certain kinds of projects and on systems with slow I/O (eg: via network attached storage or overly aggressive antivirus software).
- Certain build backends (eg: `setuptools`) will litter the project directory with secondary build artifacts (eg: `.egg-info` directories).
- Certain build backends (eg: `setuptools`) may not be able to perform with parallel builds anymore, since they previously relied on the fact that pip invoked them in a separate directory for each build.

[^1]: Specifically, the current machine's filesystem.

---

### Html Topics More Dependency Resolution (`docs/html/topics/more-dependency-resolution.md`)

# More on Dependency Resolution

This article goes into more detail about pip's dependency resolution algorithm.
In certain situations, pip can take a long time to determine what to install,
and this article is intended to help readers understand what is happening
"behind the scenes" during that process.

```{note}
This document is a work in progress. The details included are accurate (at the
time of writing), but there is additional information, in particular around
pip's interface with resolvelib, which has not yet been included.

Contributions to improve this document are welcome.
```

## The dependency resolution problem

The process of finding a set of packages to install, given a set of dependencies
between them, is known to be an [NP-hard](https://en.wikipedia.org/wiki/NP-hardness)
problem. What this means in practice is roughly that the process scales
*extremely* badly as the size of the problem increases. So when you have a lot
of dependencies, working out what to install will, in the worst case, take a
very long time.

The practical implication of that is that there will always be some situations
where pip cannot determine what to install in a reasonable length of time. We
make every effort to ensure that such situations happen rarely, but eliminating
them altogether isn't even theoretically possible. We'll discuss what options
you have if you hit a problem situation like this a little later.

## Python specific issues

Many algorithms for handling dependency resolution assume that you know the
full details of the problem at the start - that is, you know all of the
dependencies up front. Unfortunately, that is not the case for Python packages.
With the current package index structure, dependency metadata is only available
by downloading the package file, and extracting the data from it. And in the
case of source distributions, the situation is even worse as the project must
be built after being downloaded in order to determine the dependencies.

Work is ongoing to try to make metadata more readily available at lower cost,
but at the time of writing, this has not been completed.

As downloading projects is a costly operation, pip cannot pre-compute the full
dependency tree. This means that we are unable to use a number of techniques
for solving the dependency resolution problem. In practice, we have to use a
*backtracking algorithm*.

## Dependency metadata

It is worth discussing precisely what metadata is needed in order to drive the
package resolution process. There are essentially three key pieces of
information:

* The project name
* The release version
* The dependencies themselves

There are other pieces of data (e.g., extras, python version restrictions, wheel
compatibility tags) which are used as well, but they do not fundamentally
alter the process, so we will ignore them here.

The most important information is the project name and version. Those two pieces
of information identify an individual "candidate" for installation, and must
uniquely identify such a candidate. Name and version must be available from the
moment the candidate object is created. This is not an issue for distribution
files (sdists and wheels) as that data is available from the filename, but for
unpackaged source trees, pip needs to call the build backend to ask for that
data. This is done before resolution proper starts.

The dependency data is *not* requested in advance (as noted above, doing so
would be prohibitively costly, and for a backtracking algorithm it isn't
needed). Instead, pip requests dependency data "on demand", as the algorithm
starts to check that particular candidate.

One particular implication of the lazy fetching of dependency data is that
often, pip *does not know* things that might be obvious to a human looking at
the dependency tree as a whole. For example, if package A depends on version
1.0 of package B, it's obvious to a human that there's no point in looking at
other versions of package B. But if pip starts looking at B before it has
considered A, it doesn't have access to A's dependency data, and so has no way
of knowing that looking at other versions of B is wasted work. And worse still,
pip cannot even know that there's vital information in A's dependencies.

This latter point is a common theme with many cases where pip takes a long time
to complete a resolution - there's information pip doesn't know at the point
where it makes a "wrong" choice. Most of the heuristics added to the resolver
to guide the algorithm are designed to guess correctly in the face of that
lack of knowledge.

## The resolver and the finder

So far, we have been talking about the "resolver" as a single entity. While that
is mostly true, the process of getting package data from an index is handled
by another component of pip, the "finder". The finder is responsible for
feeding candidates to the resolver, and has a key role to play in selecting
suitable candidates.

Note that the resolver is *only* relevant for packages fetched from an index.
Candidates coming from other sources (local source directories, {ref}`direct
URL references <pypug:dependency-specifiers>`) do *not* go through the finder,
and are merged with the candidates provided by the finder as part of the resolver's
"provider" implementation.

As well as determining what versions exist in the index for a given project,
the finder selects the best distribution file to use for that candidate. This
may be a wheel or a source distribution, and precisely what is selected is
controlled by wheel compatibility tags, pip's options (whether to prefer binary
or source) and metadata supplied by the index. In particular, if a file is
marked as only being for specific Python versions, the file will be ignored by
the finder (and the resolver may never even see that version).

The finder also provides candidates for a project to the resolver in order of
preference - the provider implements the rule that later versions are preferred
over older versions, for example.

## The resolver algorithm

The resolver itself is based on a separate package, [resolvelib](https://pypi.org/project/resolvelib/).
This implements an abstract backtracking resolution algorithm, in a way that is
independent of the specifics of Python packages - those specifics are abstracted
away by pip before calling the resolver.

Pip's interface to resolvelib is in the form of a "provider", which is the
interface between pip's model of packages and the resolution algorithm. The
provider deals in "candidates" and "requirements" and implements the following
operations:

* `identify` - implements identity for candidates and requirements. It is this
  operation that implements the rule that candidates are identified by their
  name and version, for example.
* `get_preference` - this provides information to the resolver to help it choose
  which requirement to look at "next" when working through the resolution
  process.
* `narrow_requirement_selection` - this provides a way to limit the number of
  identifiers passed to `get_preference`.
* `find_matches` - given a set of constraints, determine what candidates exist
  that satisfy them. This is essentially where the finder interacts with the
  resolver.
* `is_satisfied_by` - checks if a candidate satisfies a requirement. This is
  basically the implementation of what a requirement means.
* `get_dependencies` - get the dependency metadata for a candidate. This is
  the implementation of the process of getting and reading package metadata.

Of these methods, the only non-trivial ones are the `get_preference` and
`narrow_requirement_selection` methods. These implement heuristics used
to guide the resolution, telling it which requirement to try to satisfy next.
It's these methods that are responsible for trying to guess which route through
the dependency tree will be most productive. As noted above, it's doing this
with limited information. See the following diagram:



When the provider is asked to choose between the red requirements (A->B and
A->C) it doesn't know anything about the dependencies of B or C (i.e., the
grey parts of the graph).

Pip's current implementation of the provider implements
`narrow_requirement_selection` as follows:

* If Requires-Python is present only consider that
* If there are causes of resolution conflict (backtrack causes) then
    only consider them until there are no longer any resolution conflicts
* If any identifiers have appeared unresolved in backtrack causes at
    least 5 times, only consider those so they get pinned before other
    packages pick a version

Pip's current implementation of the provider implements `get_preference`
for known requirements with the following preferences in the following order:

* Any requirement that has appeared in repeated conflicts (see
    ``narrow_requirement_selection`` above).
* Any requirement that is "direct", e.g., points to an explicit URL.
* Any requirement that is "pinned", i.e., contains the operator ``===``
    or ``==`` without a wildcard.
* Any requirement that imposes an upper version limit, i.e., contains the
    operator ``<``, ``<=``, ``~=``, or ``==`` with a wildcard. Because
    pip prioritizes the latest version, preferring explicit upper bounds
    can rule out infeasible candidates sooner. This does not imply that
    upper bounds are good practice; they can make dependency management
    and resolution harder.
* Order user-specified requirements as they are specified, placing
    other requirements afterward.
* Any "non-free" requirement, i.e., one that contains at least one
    operator, such as ``>=`` or ``!=``.
* Alphabetical order for consistency (aids debuggability).

---

### Html Topics Python Option (`docs/html/topics/python-option.md`)

# Managing a different Python interpreter

```{versionadded} 22.3
```

Occasionally, you may want to use pip to manage a Python installation other than
the one pip is installed into. In this case, you can use the `--python` option
to specify the interpreter you want to manage. This option can take one of two
values:

1. The path to a Python executable.
2. The path to a virtual environment.

In both cases, pip will run exactly as if it had been invoked from that Python
environment.

One example of where this might be useful is to manage a virtual environment
that does not have pip installed.

```{pip-cli}
$ python -m venv .venv --without-pip
$ pip --python .venv install SomePackage
[...]
Successfully installed SomePackage
```

You could also use `--python .venv/bin/python` (or on Windows,
`--python .venv\Scripts\python.exe`) if you wanted to be explicit, but the
virtual environment name is shorter and works exactly the same.

---

### Html Topics Repeatable Installs (`docs/html/topics/repeatable-installs.md`)

(repeatability)=
# Repeatable Installs

Pip can be used to achieve various levels of repeatable environments. This page
walks through increasingly stricter definitions of what "repeatable" means.

## Pinning the package versions

Pinning package versions of your dependencies in the requirements file
protects you from bugs or incompatibilities in newly released versions:

```
SomePackage == 1.2.3
DependencyOfSomePackage == 4.5.6
```

```{note}
Pinning refers to using the `==` operator to require the package to be a
specific version.
```

A requirements file, containing pinned package versions can be generated using
{ref}`pip freeze`. This would pin not only the top-level packages, but also all of
their transitive dependencies. Performing the installation using
{ref}`--no-deps <install_--no-deps>` would provide an extra dose of insurance
against installing anything not explicitly listed.

This strategy is easy to implement and works across OSes and architectures.
However, it trusts the locations you're fetching the packages from (like PyPI)
and the certificate authority chain. It also relies on those locations not
allowing packages to change without a version increase. (PyPI does protect
against this.)

## Hash-checking

Beyond pinning version numbers, you can add hashes against which to verify
downloaded packages:

```none
FooProject == 1.2 --hash=sha256:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
```

This protects against a compromise of PyPI or the HTTPS certificate chain. It
also guards against a package changing without its version number changing (on
indexes that allow this). This approach is a good fit for automated server
deployments.

Hash-checking mode is a labour-saving alternative to running a private index
server containing approved packages: it removes the need to upload packages,
maintain ACLs, and keep an audit trail (which a VCS gives you on the
requirements file for free). It can also substitute for a vendored library,
providing easier upgrades and less VCS noise. It does not, of course,
provide the availability benefits of a private index or a vendored library.

[pip-tools] is a package that builds upon pip, and provides a good workflow for
managing and generating requirements files.

[pip-tools]: https://github.com/jazzband/pip-tools#readme

## Using a wheelhouse (AKA Installation Bundles)

{ref}`pip wheel` can be used to generate and package all of a project's
dependencies, with all the compilation performed, into a single directory that
can be converted into a single archive. This archive then allows installation
when index servers are unavailable and avoids time-consuming recompilation.

````{admonition} Example
Creating the bundle, on a modern Unix system:

```
$ tempdir=$(mktemp -d /tmp/wheelhouse-XXXXX)
$ python -m pip wheel -r requirements.txt --wheel-dir=$tempdir
$ cwd=`pwd`
$ (cd "$tempdir"; tar -cjvf "$cwd/bundled.tar.bz2" *)
```

Installing from the bundle, on a modern Unix system:

```
$ tempdir=$(mktemp -d /tmp/wheelhouse-XXXXX)
$ (cd $tempdir; tar -xvf /path/to/bundled.tar.bz2)
$ python -m pip install --force-reinstall --no-index --no-deps $tempdir/*
```
````

Note that such a wheelhouse contains compiled packages, which are typically
OS and architecture-specific, so these archives are not necessarily portable
across machines.

Hash-checking mode can also be used along with this method (since this uses a
requirements file as well), to ensure that future archives are built with
identical packages.

---

### Html Topics Secure Installs (`docs/html/topics/secure-installs.md`)

# Secure installs

By default, pip does not perform any checks to protect against remote tampering and involves running arbitrary code from distributions. It is, however, possible to use pip in a manner that changes these behaviours, to provide a more secure installation mechanism.

This can be achieved by doing the following:

- Enable {ref}`Hash-checking mode`, by passing {any}`--require-hashes`
- Disallow source distributions, by passing {any}`--only-binary :all: <--only-binary>`

(Hash-checking mode)=

## Hash-checking Mode

```{versionadded} 8.0

```

This mode uses local hashes, embedded in a requirements.txt file, to protect against remote tampering and network issues. These hashes are specified using a `--hash` [per requirement option](per-requirement-options).

Note that hash-checking is an all-or-nothing proposition. Specifying `--hash` against _any_ requirement will activate this mode globally.

To add hashes for a package, add them to line as follows:

```
FooProject == 1.2 \
  --hash=sha256:2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 \
  --hash=sha256:486ea46224d1bb4fb680f34f7c9ad96a8f24ec88be73ea8e5a6c65260e9cb8a7
```

### Additional restrictions

- Hashes are required for _all_ requirements.

  This is because a partially-hashed requirements file is of little use and thus likely an error: a malicious actor could slip bad code into the installation via one of the unhashed requirements.

  Note that hashes embedded in URL-style requirements via the `#md5=...` syntax suffice to satisfy this rule (regardless of hash strength, for legacy reasons), though you should use a stronger hash like sha256 whenever possible.

- Hashes are required for _all_ dependencies.

  If there is a dependency that is not spelled out and hashed in the requirements file, it will result in an error.

- Requirements must be pinned (either to a URL, filesystem path or using `==`).

  This prevents a surprising hash mismatch upon the release of a new version that matches the requirement specifier.

### Forcing Hash-checking mode

It is possible to force the hash checking mode to be enabled, by passing `--require-hashes` command-line option.

This can be useful in deploy scripts, to ensure that the author of the requirements file provided hashes. It is also a convenient way to bootstrap your list of hashes, since it shows the hashes of the packages it fetched. It fetches only the preferred archive for each package, so you may still need to add hashes for alternatives archives using {ref}`pip hash`: for instance if there is both a binary and a source distribution.

### Disabling automatic enforcement of hash checking mode

```{versionadded} 26.2

```

By default, when at least one requirement has hashes, hashes become required for all requirements. This behaviour notably prevents the combination of hashed requirements with local directories or VCS URLs.

To help with such use cases, a `--no-require-hashes` flag is available to disable this mechanism. Hashes are then verified only for requirements where they are provided.

### Hash algorithms

The recommended hash algorithm at the moment is sha256, but stronger ones are allowed, including all those supported by `hashlib`. However, weaker ones such as md5, sha1, and sha224 are excluded to avoid giving a false sense of security.

### Multiple hashes per package

It is possible to use multiple hashes for each package. This is important when a package offers binary distributions for a variety of platforms or when it is important to allow both binary and source distributions.

### Interaction with caching

```{versionchanged} 23.1
The {ref}`locally-built wheel cache <wheel-caching>` is used in hash-checking mode too.
```

When installing from the cache of locally built wheels in hash-checking mode, pip verifies
the hashes against those of the original source distribution that was used to build the wheel.
These original hashes are obtained from a `origin.json` file stored in each cache entry.

### Using hashes from PyPI (or other index servers)

PyPI (and certain other index servers) provides a hash for the distribution, in the fragment portion of each download URL, like `#sha256=123...`, which pip checks as a protection against download corruption.

Other hash algorithms that have guaranteed support from `hashlib` are also supported here: sha1, sha224, sha384, sha256, and sha512. Since this hash originates remotely, it is not a useful guard against tampering and thus does not satisfy the `--require-hashes` demand that every package have a local hash.

## Repeatable installs

Hash-checking mode also works with {ref}`pip download` and {ref}`pip wheel`. See {doc}`../topics/repeatable-installs` for a comparison of hash-checking mode with other repeatability strategies.

## Do not use setuptools directly

Be careful not to nullify all your security work by installing your actual project by using setuptools' deprecated interfaces directly: for example, by calling `python setup.py install`, `python setup.py develop`, or `easy_install`.

These will happily go out and download, unchecked, anything you missed in your requirements file and it’s easy to miss things as your project evolves. To be safe, install your project using pip and {any}`--no-deps`.

Instead of `python setup.py install`, use:

```{pip-cli}
$ pip install --no-deps .
```

Instead of `python setup.py develop`, use:

```{pip-cli}
$ pip install --no-deps -e .
```

---

### Html Topics Vcs Support (`docs/html/topics/vcs-support.md`)

(vcs support)=
# VCS Support

Pip supports installing from various version control systems (VCS).
This support requires a working executable to be available (for the version
control system being used). It is used through URL prefixes:

- Git -- `git+`
- Mercurial -- `hg+`
- Subversion -- `svn+`
- Bazaar -- `bzr+`

The general form of a VCS requirement is `ProjectName @ VCS_URL`, e.g.

```none
MyProject @ git+https://git.example.com/MyProject
MyProject[extra] @ git+https:/git.example.com/MyProject
```

This is the {ref}`Direct URL <pypug:dependency-specifiers>` requirement syntax.
It is also permissible to remove `MyProject @` portion is removed and provide
a bare VCS URL.

```none
git+https://git.example.com/MyProject
```

This is a pip specific extension. This form can be used as long as pip does
not need to know the project name in advance. pip is generally able to infer
the project name except in the case of {ref}`editable-vcs-installs`. In
addition, extras cannot be requested using a bare VCS URL.

## Supported VCS

### Git

The supported schemes are `git+file`, `git+https`, `git+ssh`, `git+http`,
`git+git` and `git`. Here are some of the supported forms:

```none
MyProject @ git+ssh://git@git.example.com/MyProject
MyProject @ git+file:///home/user/projects/MyProject
MyProject @ git+https://git.example.com/MyProject
```

```{warning}
The use of `git`, `git+git`, and `git+http` schemes is discouraged.
The former two use [the Git Protocol], which lacks authentication, and HTTP is
insecure due to lack of TLS based encryption.
```

[the Git Protocol]: https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols

It is also possible to specify a "git ref" such as branch name, a commit hash or
a tag name:

```none
MyProject @ git+https://git.example.com/MyProject.git@master
MyProject @ git+https://git.example.com/MyProject.git@v1.0
MyProject @ git+https://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709
MyProject @ git+https://git.example.com/MyProject.git@refs/pull/123/head
```

When passing a commit hash, specifying a full hash is preferable to a partial
hash because a full hash allows pip to operate more efficiently (e.g. by
making fewer network calls).

Pip requests partial clones by default when using Git 2.17 or later, and will
detect when git advertises support for partial clones. If a Git server or
network configuration incorrectly claims to support partial clones, but does
not do so in practice, setting `PIP_NO_PARTIAL_CLONE_FOR_BROKEN_GIT_SERVER=1`
will force pip to ignore the claim and use a full clone.

### Mercurial

The supported schemes are `hg+file`, `hg+http`, `hg+https`, `hg+ssh`
and `hg+static-http`. Here are some of the supported forms:

```
MyProject @ hg+http://hg.myproject.org/MyProject
MyProject @ hg+https://hg.myproject.org/MyProject
MyProject @ hg+ssh://hg.myproject.org/MyProject
MyProject @ hg+file:///home/user/projects/MyProject
```

It is also possible to specify a revision number, a revision hash, a tag name
or a local branch name:

```none
MyProject @ hg+http://hg.example.com/MyProject@da39a3ee5e6b
MyProject @ hg+http://hg.example.com/MyProject@2019
MyProject @ hg+http://hg.example.com/MyProject@v1.0
MyProject @ hg+http://hg.example.com/MyProject@special_feature
```

### Subversion

The supported schemes are `svn`, `svn+svn`, `svn+http`, `svn+https` and
`svn+ssh`. Here are some of the supported forms:

```none
MyProject @ svn+https://svn.example.com/MyProject
MyProject @ svn+ssh://svn.example.com/MyProject
MyProject @ svn+ssh://user@svn.example.com/MyProject
```

You can also give specific revisions to an SVN URL, like so:

```none
-e MyProject @ svn+http://svn.example.com/svn/MyProject/trunk@2019
-e MyProject @ svn+http://svn.example.com/svn/MyProject/trunk@{20080101}
```

Note that you need to use [Editable VCS installs](#editable-vcs-installs) for
using specific revisions from Subversion.

### Bazaar

The supported schemes are `bzr+http`, `bzr+https`, `bzr+ssh`, `bzr+sftp`,
`bzr+ftp` and `bzr+lp`. Here are the supported forms:

```none
MyProject @ bzr+http://bzr.example.com/MyProject/trunk
MyProject @ bzr+sftp://user@example.com/MyProject/trunk
MyProject @ bzr+ssh://user@example.com/MyProject/trunk
MyProject @ bzr+ftp://user@example.com/MyProject/trunk
MyProject @ bzr+lp:MyProject
```

Tags or revisions can be installed like so:

```none
MyProject @ bzr+https://bzr.example.com/MyProject/trunk@2019
MyProject @ bzr+http://bzr.example.com/MyProject/trunk@v1.0
```

(editable-vcs-installs)=

## Editable VCS installs

VCS projects can be installed in {ref}`editable mode <editable-installs>` (using
the {ref}`--editable <install_--editable>` option) or not.

In editable mode, the project name must be provided upfront using the Direct URL
(`MyProject @ URL`) form so pip can determine the VCS clone location.

- The default clone location (for editable installs) is:

  - `<venv path>/src/SomeProject` in virtual environments
  - `<cwd>/src/SomeProject` for global Python installs

  The {ref}`--src <install_--src>` option can be used to modify this location.

- For non-editable installs, the project is built locally in a temp dir and then
  installed normally.

Note that if a satisfactory version of the package is already installed, the
VCS source will not overwrite it without an `--upgrade` flag. Further, pip
looks at the package version, at the target revision to determine what action to
take on the VCS requirement (not the commit itself).

## URL fragments

Pip looks at the `subdirectory` fragments of VCS URLs for specifying the path to the
Python package, when it is not in the root of the VCS directory.

```{note}
Pip also supports an `egg` fragment to specify the "project name". This is a legacy
feature and its use is discouraged in favour of the
{ref}`Direct URL <pypug:dependency-specifiers>` form.

The `egg` fragment **MUST** be a bare {ref}`project name <pypug:name-normalization>`.
Anything else is not guaranteed to work.
```

````{admonition} Example
If your repository layout is:

```
pkg_dir
├── setup.py  # setup.py for package "pkg"
└── some_module.py
other_dir
└── some_file
some_other_file
```

Then, to install from this repository, the syntax would be:

```{pip-cli}
$ pip install "pkg @ vcs+protocol://repo_url/#subdirectory=pkg_dir"
```

or:

```{pip-cli}
$ pip install -e "pkg @ vcs+protocol://repo_url/#subdirectory=pkg_dir"
```
````

---

### Html Topics Workflow (`docs/html/topics/workflow.md`)

# Pip is not a workflow management tool

The core purpose of pip is to *manage the packages installed in your
environment*. Whilst package management is an important part of most Python
development workflows, it is only one part. Tasks like creating and managing
environments, configuring and running development tasks, managing the Python
interpreter itself, and managing the overall "project", are not part of pip's
scope. Managing a development workflow as a whole is a complex task and one
where there are many views on the "correct approach".

Pip has a number of features which make it useful in development workflows - for
example, the ability to install the current project via `pip install .`,
editable installs, and requirements files. However, there is no intention that
pip will manage the workflow as a whole.

As an example, pip provides the `pip wheel` command, which can be used to build
a wheel for your project. However, there is no corresponding command to build a
source distribution. This is because building a wheel is a fundamental step in
installing a package (if that package is only available as source code), whereas
building a source distribution is never needed when installing. Users who need a
tool to build their project should use a dedicated tool like `build`, which
provides commands to build wheels and source distributions.


## The role of `ensurepip`

Pip is available in a standard Python installation, via the `ensurepip` stdlib
module. This provides users with an "out of the box" installer, which can be
used to gain access to all of the various tools and libraries available on PyPI.
In particular, this enables the installation of a number of workflow tools.

This "bootstrapping" mechanism was proposed (and accepted) in [PEP
453](https://peps.python.org/pep-0453/).


## Further information

The [Packaging User Guide](https://packaging.python.org) discusses Python
project development, and includes tool recommendations for people looking for
further information on how to manage their development workflow.

---

### Html Ux Research Design Contribute (`docs/html/ux-research-design/contribute.md`)

# How to Contribute

## Participate in UX Research

It is important that we hear from pip users so that we can:

- Understand how pip is currently used by the Python community
- Understand how pip users _need_ pip to behave
- Understand how pip users _would like_ pip to behave
- Understand pip’s strengths and shortcomings
- Make useful design recommendations for improving pip

If you are interested in participating in pip user research, please [join pip’s user panel](https://mail.python.org/mailman3/lists/pip-ux-studies.python.org/).

## Test New Features

You can help the team by testing new features as they are released to the community.

## Report and Work on UX Issues

If you believe that you have found a user experience bug in pip, or you have ideas for how pip could be made better for all users, please file an issue on the [pip issue tracker](https://github.com/pypa/pip/issues/new).

You can also help improve pip’s user experience by [working on UX issues](https://github.com/pypa/pip/issues?q=is%3Aissue+label%3AUX+is%3Aopen). Issues that are ideal for new contributors are marked with “[good first issue](https://github.com/pypa/pip/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)”. Explore the
[UX Guidance](guidance.md) if you have questions.

---

### Html Ux Research Design Guidance (`docs/html/ux-research-design/guidance.md`)

# UX Guidance

This section of the documentation is intended for contributors who wish to work on improving pip's user experience, including pip's documentation.

## What is User Centered Design?

User-centered design (UCD) or human-centered design (HCD) is an iterative process in which design decisions are informed by an understanding of users and their needs. There are many terms used to describe this type of work; in this document we will use "user experience (UX) research and design".

For the pip project, UX research and design can be used to:

- Develop a deeper understanding of pip's users, the context in which they use pip and the challenges that they face
- Inform the design of new or existing pip features, so that pip us more usable and accessible. This may include improving pip's output (including error messages), controls (e.g. commands and flags) and documentation
- Help pip's development team prioritize feature requests based on user needs

At a high level, the UX research and design process is comprised of:

1. **[Research](#conducting-research-for-pip)**, where a variety of techniques are used (e.g.[surveys](#surveys) and [interviews](#interviews)) to learn about users and what they want from the tools they use
2. **[Design](#user-interface-design)**, where solutions are proposed to response to the research conducted. UX research and design is conducted iteratively, with design proposals or prototypes tested with users to validate that they are effective in meeting users' needs. Often, it is necessary to complete several cycles of research, design and validation to find a solution that works:



For more information on how this process has been applied to the pip project, see [research results](research-results/index).

See also:

- [Introduction to user centered design from the interaction design foundation](https://www.interaction-design.org/literature/topics/user-centered-design)
- [User-Centered Design Basics from usability.gov](https://www.usability.gov/what-and-why/user-centered-design.html)
- [User-centered design articles and videos from Nielson Norman Group](https://www.nngroup.com/topic/user-centered-design/)

## Conducting Research for pip

User research can be used to answer a few different types of questions:

- _Understanding the context generally_ — e.g. how is pip used by people? What different environments and contexts is pip used in?
- _Understanding the users more broadly_ — e.g. who uses pip? How much experience do they have typically? How do they learn how to use pip? Are there any common characteristics between pip users? How diverse are the needs of pip's users?
- _Evaluating a specific need or challenge_ — e.g. how are pip users encountering a given issue? When does it come up? Do pip users regularly encounter this issue? How would a new feature address this issue?

During the research process, it is important to engage users for input, and incorporate their feedback into decision making.

Input and feedback from users is as valuable to an open source project as code contributions; end users may not be ready yet to submit a pull request or make fixes into the code directly, but their feedback can help to shape pip's priorities and direction.

There are many ways to engage users in open source projects, and sometimes input from community members can feel overwhelming! Providing a structure, such as surveys and interviews, can make it easier to collect and understand feedback. Some examples of how to engage users are:

- _Surveys_ — good for targeted feedback about specific issues and broad community context and understanding
- _Interviews_ — good for in-depth conversations to understand or explore a topic
- _Testing_ — good to evaluate an issue or validate a design idea
- _Open issue queues_ (e.g. GitHub issues) & support ticket systems — great data source to understand common challenges
- _Forums or discussion tools_ — great data source to understand common challenges or engage broader community in open discussion
- _Conferences and events_ — great opportunity to go lightweight interviews or testing of specific features

When running [UX research on pip in 2020](research-results/index), we found that surveys and interviews were particularly useful tools to engage with pip's users. Some general guidelines, as well as pip-specific recommendations are below.

### Surveys

Surveys are great for collecting broad, large scale input, e.g. learning more about pip's user community as a whole, or for getting targeted feedback about a specific issue.

Surveys can also be leveraged to get in-situ feedback with early releases of new tools, e.g. prompting users on the command line if they are using a beta version of a feature or asking people for feedback on a documentation page.

As an example, in 2020, the pip UX team published several surveys to learn about pip and pip's users. This included:

- Understanding 'who uses pip'
- Collecting feedback about pip's documentation
- Collecting feedback about pip's beta release of the 2020 dependency resolver
- Asking users how specific parts of pip's 2020 dependency resolver should behave

A full list of the surveys published in 2020 and their results [can be found here](research-results/index).

#### Designing Surveys

When designing surveys, it is important to first establish what you want to learn. It can be useful to write this down as research-results/index questions. Example pip research-results/index questions [can be found here](https://github.com/pypa/pip/issues/8518).

If you find that your topic is large, or you have many research-results/index questions, consider publishing several separate surveys, as long surveys risk a low response / high dropoff rate.

Below is a brief guide to building a survey for pip:

<ol>
  <li>
    <strong>Introduce your survey</strong><br>
    Explain the motivation for the survey, or (for surveys about pip's behaviour) set the scene with a scenario.
  </li>
  <li>
    <strong>Design your questions</strong><br>
    <ul>
      <li>
        Limit the number of questions you ask to avoid a low response rate. A good rule of thumb is: 3-4 questions about the specific topic, 2-3 questions about users level of experience / what they use Python or pip for.<br>
        When asking about years of experience use the following groupings as options:
        <ul>
          <li>< 1 Year</li>
          <li>1-3 Years</li>
          <li>4-6 Years</li>
          <li>7-10 Years</li>
          <li>11-15 Years</li>
          <li>16+ Years</li>
        </ul>
      </li>
      <li>
        Use <a href="https://en.wikipedia.org/wiki/Closed-ended_question">closed questions</a> with a fixed number of possible responses (e.g. yes/no, multiple choice, checkboxes, or <a href="https://www.nngroup.com/articles/rating-scales">likert scale</a>) for measuring behaviour, opinion or preferences
      </li>
      <li>
        Use <a href="https://en.wikipedia.org/wiki/Open-ended_question">open questions</a> to learn about reasoning. If you are using a lot of closed questions in your survey, it is useful to include some open questions to "fish" for less expected answers - e.g. asking a user "why?" they chose a particular option
      </li>
    </ul>
  </li>
  <li>
    <strong>Pilot your survey and modify it based on feedback</strong><br>
    This could be as simple as sharing it with 1-2 people to see if it makes sense.
  </li>
  <li>
    <strong>Determine where to do outreach</strong><br>
    Establish who you want to hear from and where you should post the survey. Are there community members or groups that can help you reach more people?<br>
    <ul>
      <li>Does the survey need to be translated into other languages to reach a broader set of the community?</li>
      <li>Are you able to compensate people for their time?</li>
      <li>Do participants want to be acknowledged as contributors?</li>
    </ul>
  </li>
  <li>
    <strong>Launch and promote your survey</strong><br>
    See <a href="#survey-and-interview-outreach">survey and interview outreach</a> for recommendations on how to do outreach for pip based on the UX research-results/index conducted in 2020.
  </li>
</ol>

#### Survey Case Study

The process described above was followed in 2020, when we wanted to establish whether pip [should install packages with conflicting dependencies](https://github.com/pypa/pip/issues/8452).

First, we introduced the purpose of the survey, with a scenario:



Next, we asked a closed question to establish what the user prefers:



Following this, we qualified the response with an open question:



This was followed by further questions about workarounds, syntax and behaviour preferences.

Finally, we asked survey participants about themselves, including how much Python experience they have, and what they use Python for. This was to find out if different types of Python users answered the questions differently.

This survey was shared with the pip team and improved several times, before it was published and promoted using a variety of [outreach channels](#survey-and-interview-outreach).

In total, we received 415 responses, with [clear results](research-results/override-conflicting-dependencies) that helped us to make strong recommendations on how to move forward with this feature.

#### Analysing Survey Results

Surveys are particularly useful for being able to quickly understand trends from a larger population of responses. If your questions are designed well, then you should be able to easily aggregate the data and make statements such as: `X% of respondents said that Option B was the best option.`

#### Contextualizing the Responses

It's important to remember that the responses to your survey will be biased by the way that you did outreach for your survey, so unless you can be sure that the people who responded to your survey are representative of all of your users, then you need to be sure to contextualize the results to the participants. Within your survey responses it can be helpful to see if there is variation in the responses by different aspects of your users or your user community, e.g.

- By experience level — Are responses consistent across experience level or do they vary? E.g. Do newer or more junior experience users have different responses, needs or challenges?
- By background/context — Are responses consistent across background or context? E.g. Do users in a corporate context have similar responses to hobbyist/independent users? Do data analysts have similar responses to software engineers?

#### How many responses is enough?

It depends! This is a hard question to answer in research like this — Traditional statistics would suggest that "enough" depends on the total population you need the survey to represent. In UX research, the answer tends to be more around when you see variation in responses level out, and so it's more about signals and trends in the data.

If you are finding that there aren't patterns in the data, it might mean that your questions weren't clear or provided too many options, or it might mean that you need to reach out to more people.

See also:

- [28 Tips for Creating Great Qualitative Surveys from Nielson Norman Group](https://www.nngroup.com/articles/qualitative-surveys/)
- [Open vs. Closed Questions in User Research from Nielsen Norman Group](https://www.nngroup.com/videos/open-vs-closed-questions/)
- [Survey questions 101: over 70 survey question examples + types of surveys and FAQs - from HotJar](https://www.hotjar.com/blog/survey-questions/)

### Interviews

Interviews are a great way to have more in-depth conversations with users to better understand or explore a topic. Unlike surveys, they are not a great way to understand overall patterns, as it is hard to engage with a large number of people due to the time involved. It can be particularly useful to plan around conferences and events as a way to connect with many users in a more informal setting.

#### Designing Interviews

As with surveys, it's important to establish what you want to learn before you begin.

Often, interviews are conducted with a script; this helps the interview run smoothly by providing some structure. However, it is also ok to go "off script" if the conversation is moving in an interesting or insightful direction.

Below is a brief guide to running an interview for pip:

<ol>
  <li>
    <strong>Write your script</strong><br>
    This should include an introduction that sets the scene for the participant, explaining what the interview is about, how you (or observers) will take notes, how long it will take, how their feedback will be used (and shared) and any other pointers you want to share.<br>
    Next, design your questions. Limit the number of questions, so that you have enough time to cover key points and the interview does not run for too long. Like in surveys, a good rule of thumb is 2-3 questions about users' level of experience, and what they use Python/pip for, plus 3-4 questions about the specific topic.<br>
    There are <a href="https://simplysecure.org/resources/qualitative_interviewing.pdf">four different types of interview questions</a>:
    <ol>
      <li>
        <em>Descriptive</em> — This type of question gives you concrete, specific stories and details. It also helps your interviewee "arrive" at the interview, resurfacing their relevant experiences and memories. E.g.<br>
        <ul>
          <li>Tell me about a time…</li>
          <li>Tell me about the first time…</li>
          <li>Tell me about the last time…</li>
          <li>Tell me about the worst/best time…</li>
          <li>Walk me through how you…</li>
        </ul>
      </li>
      <li>
        <em>Reflective</em> — These questions allow the interviewee to revisit and think more deeply about their experiences. Helping the interviewee reflect is at the heart of your interview. Don't rush – give them lots of space to put their thoughts together.<br>
        <ul>
          <li>What do you think about…</li>
          <li>How do you feel about…</li>
          <li>Why do you do…</li>
          <li>Why do you think…</li>
          <li>What effects did it have when…</li>
          <li>How has ... changed over time?</li>
        </ul>
      </li>
      <li>
        <em>Clarifying</em> — This type of question gives interviewees the opportunity to expand on key points. Skillful clarifying questions also let you subtly direct the interviewee's storytelling towards the areas you find most intriguing and relevant.<br>
        <ul>
          <li>What do you mean when you say…</li>
          <li>So, in other words…</li>
          <li>It sounds like you're saying [...]. Is that right?</li>
          <li>Can you tell me more about that?</li>
        </ul>
      </li>
      <li>
        <em>Exploratory</em> — These questions are an invitation to the interview-ee to think creatively about their situation, and are best left for the end of the interview. Careful, though – suggestions from a single person are rarely the answer to your design problem, and you need to be clear to them that you're just collecting ideas at this point.<br/>
        <ul>
          <li>How would you change…</li>
          <li>What would happen if…</li>
          <li>If you had a magic wand...</li>
        </ul>
      </li>
    </ol>
  </li>
  <li>
    <strong>Pilot interview with 1-2 people & modify based on their feedback</strong>
  </li>
  <li>
    <strong>Determine how to do outreach for interviews</strong><br/>
    <ul>
      <li>Who do you want to be sure to hear from? Where do you need to post to contact people for interviews? Are there community members or groups that can help you reach specific people?</li>
      <li>Do the interviews need to be translated into other languages to reach a broader set of the community or a specific community?</li>
      <li>How will people sign up for your interview?</li>
      <li>Are you able to compensate people for their time?</li>
      <li>Do participants want to be acknowledged as contributors?</li>
    </ul>
  </li>
  <li>
    <strong>Start outreach!</strong><br/>
    See <a href="#survey-and-interview-outreach">survey and interview outreach</a> for recommendations on how to do outreach for pip based on the UX research conducted in 2020.
  </li>
</ol>

Here is an example user interview script used for speaking to users about pip's documentation:

> **Introduction**
>
> - Firstly thank you for giving me your time and for your continued involvement.
> - The purpose of this interview is to better understand how pip's documentation is perceived and used by Python community members
> - The interview will take approximately 30 minutes. If you don't understand any of the questions please ask me to repeat or rephrase. If you don't have a good answer, feel free to tell me to skip.
> - I will be taking notes. These will be shared on GitHub or the pip docs, but we will remove any identifying data to > protect your anonymity
> - Please be honest - your feedback can help us make pip better. I won't be offended by anything you have to say :)
> - (optional) Do you mind if I record this session?
>
> **Opening questions**
>
> - Can you tell me a bit about how you use Python?
> - How long have you been using pip?
>
> **Solving problems**
>
> - Can you tell me about a time you had a problem when using pip?
>   - What happened?
>   - What did you do?
>   - Where did you go?
>   - How did you resolve your problem?
> - Please go to[ https://pip.pypa.io/en/stable/](https://pip.pypa.io/en/stable/)
>   - Have you ever used this documentation?
>   - On a scale of 1-10 how useful was it?
>   - Why?
> - Are there any projects that you use that you'd like us to look at when thinking about improving pip's docs?
>   - What makes that documentation good/useful?
>
> **Conclusion**
>
> - What one thing could the pip team do to help users troubleshoot pip problems?
> - Do you have any questions?

#### How many interviews is enough?

This depends on the complexity of the issue you are discussing, and whether or not you feel that you have gained enough insight from the interviews you have conducted. It also depends on whether you feel you have heard from a wide enough range of people. For example, you may wish to stop interviewing only after you have heard from both expert _and_ novice pip users.

Often, conducting just a few interviews will uncover so many problems that there is enough material to make recommendations to the team.

#### Analyzing Interview Data

Formal interview analysis typically uses a process called "coding" where multiple researchers review interview transcripts and label different statements or comments based on a code system or typology that has been developed to align with the research. This is a great practice and a great way to make sure that the researchers' bias is addressed as part of the process, but most teams do not have the staffing or resources to do this practice.

Instead many smaller teams use lightweight processes of capturing interview statements into **themes**, e.g. specific topics or issue areas around needs or challenges. Interviews are also a great source for **quotes**, which can be helpful for providing an example of why something is important or when/how something comes up for users.

Interview analysis is frequently done using sticky notes, where you can write a quote, issue or finding on a sticky note and then move the sticky notes around into clusters that can be labeled or categorized into the themes. Remotely this can be facilitated by any number of tools, e.g. digital sticky board tools like [Miro](https://miro.com/) or [Mural](https://www.mural.co/), or even kanban board tools like [Trello](https://trello.com/), [Wekan](https://wekan.github.io/) or [Cryptpad](https://cryptpad.fr/), or this can be done just with text documents or spreadsheets, using lists and categories. It can be helpful to use a [worksheet for debriefing](https://simplysecure.org/resources/interview_synthesis.pdf) at the end of each interview to capture insights and themes quickly before you forget topics from the specific interview.

See also:

- [User Interviews: How, When, and Why to Conduct Them from Nielson Norman Group](https://www.nngroup.com/articles/user-interviews/)
- [Interviewing Users from Nielson Norman Group](https://www.nngroup.com/articles/interviewing-users/)

### Survey and Interview Outreach

The following is a list of outreach platforms that the pip team used when conducting research in 2020. Some were more successful than others:

#### Recommended: UX Research Panel

As part of the [2020 UX Work](research-results/index), we published a form that asked people to join a research panel and be regularly contacted about surveys and interview opportunities. This is now a [mailing list that users can sign up for](https://mail.python.org/mailman3/lists/pip-ux-studies.python.org/), and will be used in an ongoing way in addition to broad public outreach.

#### Recommended: Twitter

We found Twitter to be a very effective platform for engaging with the Python community and drive participation in UX research. We recommend:

1. Asking [ThePSF](https://twitter.com/ThePSF), [PyPA](https://twitter.com/ThePyPA) and [PyPI](https://twitter.com/pypi) to retweet calls for survey and interview participation
2. Asking specific individuals (who have reach within specific communities, or general followings within the Python community) to retweet.
3. Explicitly asking for retweets within tweets
4. Responding to users within Twitter

#### Recommended: Specific Interest Groups

We engaged with the [PyLadies](https://pyladies.com/) community via their [Slack channel](https://slackin.pyladies.com/) to drive more participation from women using pip, as we found this demographic more difficult to reach via other channels

#### Recommended: Conference Communities

Due to the 2020 Global Pandemic we were unable to engage with users via PyCon (or other regional conferences) as we would have liked. However, we would still recommend this channel as a fast and insightful way to engage with large groups of interested people.

#### Worth Exploring: Adding a prompt/path into pip's 'help' command

We didn't have a chance to explore this opportunity, but the idea came up during workshops in December 2020 with Pypa Maintainers, and could be a great way to engage users and help point them towards opportunities to contribute.

#### Not recommended: Forums (Discourse, etc)

We used [discuss.python.org](https://discuss.python.org/) several times, posting to the [packaging forum](https://discuss.python.org/c/packaging/14) to ask packaging maintainers about their views on pip's functionality. Unfortunately, this was not as fruitful as we hoped, with very few responses. We found that engaging with packaging maintainers via Twitter was more effective.

Posting surveys on Reddit was also not as useful as we had expected. If the user posting the survey or call for research participation does not have significant credit on Reddit, then the posting process itself can be challenging. Overall we did not see as much engagement in surveys or interviews come from Reddit relative to other outreach means.

## User Interface Design

Many people associate the term "user interface" with websites or applications, however it is important to remember that a CLI is a user interface too, and deserves the same design consideration as graphical user interfaces.

Designing for pip includes:

- Designing pip's _input_ - establishing the best way to group functionality under commands, and how to name those commands so that they make sense to the user
- Writing pip's _output_ - establishing how pip responds to commands and what information it provides the user. This includes writing success and error messages.
- Providing supplemental materials - e.g. documentation that helps users understand pip's operation

### Error Message Format

A good error message should mention:

* what the user has tried to do
* possible next steps to try and solve the error
  * possible steps need to go from "easiest" to "most complicated"
* why the error has happened - include a way to see more information
  about the situation

A [sample `ResolutionImpossible` error that follows this guidance
is available](resolution-impossible-example).

**Further reading**

- <https://uxplanet.org/how-to-write-good-error-messages-858e4551cd4>
- <https://www.nngroup.com/articles/error-message-guidelines/>

### Design Principles / Usability Heuristics

There are many interaction design principles that help designers design great experiences. Nielsen Norman's [10 Usability Heuristics for User Interface Design](https://www.nngroup.com/articles/ten-usability-heuristics) is a great place to start. Here are some of the ways these principles apply to pip:

- Visibility of system status: ensure all commands result in clear feedback that is relevant to the user - but do not overload the user with too much information (see "Aesthetic and minimalist design")
- Consistency and standards: when writing interfaces, strive for consistency with the rest of the Python packaging ecosystem, and (where possible) adopt familiar patterns from other CLI tools
- Aesthetic and minimalist design: remove noise from CLI output to ensure the user can find the most important information
- Help users recognize, diagnose, and recover from errors: clearly label and explain errors: what happened, why, and what the user can do to try and fix the error. Link to documentation where you need to provide a detailed explanation.
- Help and documentation: provide help in context and ensure that documentation is task-focussed

#### Additional Resources

- [Command Line Interface Guidelines](https://clig.dev)
- [10 design principles for delightful CLIs](https://blog.developer.atlassian.com/10-design-principles-for-delightful-clis/)

### Design Tools

Tools that are frequently used in the design process are personas and guidelines, but also wireframing, prototyping, and testing, as well as creating flow diagrams or models.

#### Personas

_For a more in-depth overview of personas and using them in open source projects, this [resource from Simply Secure](https://simplysecure.org/blog/personas) may be helpful._

Personas are abstractions or archetypes of people who might use your tool. It often takes the form of a quick portrait including things like — name, age range, job title, enough to give you a sense of who this person is. You can capture this information into a [persona template](https://simplysecure.org/resources/persona-template-tech.pdf) and share them with your open source community as a resource see [examples from the Gitlab UX Team](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/).

Personas are particularly useful to help ground a feature design in priorities for specific needs of specific users. This helps provide useful constraints into the design process, so that you can focus your work, and not try to make every feature a swiss army knife of solutions for every user.

In 2020, the pip UX team developed the following personas for the pip project:

- Python Software User
- Python Software Maker
- Python Package Maintainer

An in-depth write up on how the pip personas were created, and how they can be applied to future pip UX work can be [found here](research-results/personas).

#### Prototyping

In any UX project, it is important to prototype and test interfaces with real users. This provides the team with a feedback loop, and ensures that the solution shipped to the end user meets their needs.

Prototyping CLIs can be a challenge. See [Creating rapid CLI prototypes with cli-output](https://www.ei8fdb.org/prototyping-command-line-interfaces-with-cli-output/) for recommendations.

#### Copywriting Style Guides

Given pip's interface is text, it is particularly important that clear and consistent language is used.

The following copywriting Style Guides may be useful to the pip team:

- [Warehouse (PyPI) copywriting styleguide and glossary of terms](https://warehouse.pypa.io/ui-principles/#4-write-clearly-with-consistent-style-and-terminology)
- Firefox:
  - [Voice and Tone](https://meet.google.com/linkredirect?authuser=0&dest=https%3A%2F%2Fdesign.firefox.com%2Fphoton%2Fcopy%2Fvoice-and-tone.html)
  - [Writing for users](https://meet.google.com/linkredirect?authuser=0&dest=https%3A%2F%2Fdesign.firefox.com%2Fphoton%2Fcopy%2Fwriting-for-users.html)
- [Heroku CLI](https://devcenter.heroku.com/articles/cli-style-guide) (very specific to Heroku's CLI tools)
- [Redhat Pattern Fly style guide](https://www.patternfly.org/v4/ux-writing/about)
- [Writing for UIs from Simply Secure](https://simplysecure.org/blog/writing-for-uis)

### General Resources

- Heroku talk on design of their CLI tools ([video](https://www.youtube.com/watch?v=PHiDG-_XoRk) transcript)
- [Simply Secure: UX Starter Pack](https://simplysecure.org/ux-starter-pack/)
- [Simply Secure: Feedback Gathering Guide](https://simplysecure.org/blog/feedback-gathering-guide)
- [Simply Secure: Getting Quick Tool Feedback](https://simplysecure.org/blog/design-spot-tool-feedback)
- [Internews: UX Feedback Collection Guidebook](https://globaltech.internews.org/our-resources/ux-feedback-collection-guidebook)
- [Simply Secure: Knowledge Base](https://simplysecure.org/knowledge-base/)
- [Open Source Design](https://opensourcedesign.net/resources/)
- [Nielsen Norman Group](https://www.nngroup.com/articles/)
- [Interaction Design Foundation](https://www.interaction-design.org/literature)

---

### Html Ux Research Design Resolution Impossible Example (`docs/html/ux-research-design/resolution-impossible-example.md`)

---
orphan:
---

# Example error: ResolutionImpossible

## What if there are user-provided pinned packages?

Where a user wants to install packages (with 1 or more pinned version)
with default verbose level

```
$ pip install peach=1.0 apple=2.0

Due to conflicting dependencies pip cannot install Peach1.0 and Apple2.0:

* Peach 1.0 depends on Banana 3.0
* Apple2.0 depends on Banana2.0

There are a number of possible solutions. You can try:
1. removing package versions from your requirements, and letting pip try to resolve the problem for you
2. Trying  a version of Peach that depends on Banana2.0. Try `pip-search peach —dep banana2.0`
3. replacing Apple or Peach with a different package altogether
4. patching Apple2.0 to use Banana3.0
5. force installing (Be aware!)

For instructions on how to do these steps visit: https://pypa.io/SomeLink
To debug this further you can run `pip-tree` to see all of your dependencies.
```

**with verbose level -vv**

If a user ran the same pip command with more verbosity, what would they see?

**with verbose level -vvv**

If a user ran the same pip command with more verbosity, what would they see?

## What if there are no user-provided version restrictions?

NB: We are assuming this resolver behaviour gets implemented, based on [GH issues 8249](https://github.com/pypa/pip/issues/8249).

**with default verbose level**

```
$ pip install apple peach

Due to conflicting dependencies pip cannot install apple or peach. Both depend on banana, but pip can't find a version of either where they depend on the same banana version.

There are a number of possible solutions. You can try:
1. replacing apple or peach with a different package altogether
2. patching apple or peach to use the same version of banana
3. force installing (Be aware!)

To debug this further you can run pip-tree to see all of your dependencies.
```

**with verbose level -vv**

If a user ran the same pip command with more verbosity, what would they see?

**with verbose level -vvv**

If a user ran the same pip command with more verbosity, what would they see?

**What should be in the "documentation" page?**

* ways to swap a package for another
* how to patch a package to support a version (various ways)

## Recommendations

* Write official documentation / guide "How to resolve dependency conflicts" explaining:
  * Why conflicts can exist
  * How you can avoid them (pinning)
  * How you can resolve them
    * Use alternative package
    * Use older version
    * Patch package
* Introduce new commands to pip, inspired by poetry:
  * Tree: Show full tree of dependencies
  * Show `<package>` Show details of a package, including it's dependencies
  * latest - shows latest vs installed versions
  * outdated - shows only outdated versions
* Expose commands / help link in output??
  * when particular issue happens provide ways to move on (ala pipenv), e.g.
    * run this command to see X
    * is it your internet connection?
    * is it the pypi website?
* Aspirational commands
  * `pip search PackageName —dep PackageNameVersion`
    * a command that will search for a version of a package that has a dependency on another packageversion

---

### Man Commands Cache (`docs/man/commands/cache.rst`)

:orphan:

=========
pip-cache
=========

Description
***********

.. pip-command-description:: cache

Usage
*****

.. pip-command-usage:: cache

Options
*******

.. pip-command-options:: cache

---

### Man Commands Check (`docs/man/commands/check.rst`)

:orphan:

=========
pip-check
=========

Description
***********

.. pip-command-description:: check

Usage
*****

.. pip-command-usage:: check

Options
*******

.. pip-command-options:: check

---

### Man Commands Config (`docs/man/commands/config.rst`)

:orphan:

==========
pip-config
==========

Description
***********

.. pip-command-description:: config

Usage
*****

.. pip-command-usage:: config

Options
*******

.. pip-command-options:: config

---

### Man Commands Debug (`docs/man/commands/debug.rst`)

:orphan:

==========
pip-debug
==========

Description
***********

.. pip-command-description:: debug

Usage
*****

.. pip-command-usage:: debug


.. warning::
    This command is only meant for debugging.
    Its options and outputs are provisional and may change without notice.


Options
*******

.. pip-command-options:: debug

---

### Man Commands Download (`docs/man/commands/download.rst`)

:orphan:

============
pip-download
============

Description
***********

.. pip-command-description:: download

Usage
*****

.. pip-command-usage:: download

Options
*******

.. pip-command-options:: download

---

### Man Commands Freeze (`docs/man/commands/freeze.rst`)

:orphan:

==========
pip-freeze
==========

Description
***********

.. pip-command-description:: freeze

Usage
*****

.. pip-command-usage:: freeze

Options
*******

.. pip-command-options:: freeze

---

### Man Commands Hash (`docs/man/commands/hash.rst`)

:orphan:

========
pip-hash
========

Description
***********

.. pip-command-description:: hash

Usage
*****

.. pip-command-usage:: hash

Options
*******

.. pip-command-options:: hash

---

### Man Commands Help (`docs/man/commands/help.rst`)

:orphan:

========
pip-help
========

Description
***********

.. pip-command-description:: help

Usage
*****

.. pip-command-usage:: help

Options
*******

.. pip-command-options:: help

---

### Man Commands Index (`docs/man/commands/index.rst`)

:orphan:

===========
pip-index
===========

Description
***********

.. pip-command-description:: index

Usage
*****

.. pip-command-usage:: index

Options
*******

.. pip-command-options:: index

---

### Man Commands Install (`docs/man/commands/install.rst`)

:orphan:

===========
pip-install
===========

Description
***********

.. pip-command-description:: install

Usage
*****

.. pip-command-usage:: install

Options
*******

.. pip-command-options:: install

---

### Man Commands List (`docs/man/commands/list.rst`)

:orphan:

========
pip-list
========

Description
***********

.. pip-command-description:: list

Usage
*****

.. pip-command-usage:: list

Options
*******

.. pip-command-options:: list

---

### Man Commands Lock (`docs/man/commands/lock.rst`)

:orphan:

========
pip-lock
========

Description
***********

.. pip-command-description:: lock

Usage
*****

.. pip-command-usage:: lock

Options
*******

.. pip-command-options:: lock

---

### Man Commands Search (`docs/man/commands/search.rst`)

:orphan:

==========
pip-search
==========

Description
***********

.. pip-command-description:: search

Usage
*****

.. pip-command-usage:: search

Options
*******

.. pip-command-options:: search

---

### Man Commands Show (`docs/man/commands/show.rst`)

:orphan:

========
pip-show
========

Description
***********

.. pip-command-description:: show

Usage
*****

.. pip-command-usage:: show

Options
*******

.. pip-command-options:: show

---

### Man Commands Uninstall (`docs/man/commands/uninstall.rst`)

:orphan:

=============
pip-uninstall
=============

Description
***********

.. pip-command-description:: uninstall

Usage
*****

.. pip-command-usage:: uninstall

Options
*******

.. pip-command-options:: uninstall

---

### Man Commands Wheel (`docs/man/commands/wheel.rst`)

:orphan:

=========
pip-wheel
=========

Description
***********

.. pip-command-description:: wheel

Usage
*****

.. pip-command-usage:: wheel

Options
*******

.. pip-command-options:: wheel

---

### Html Development Architecture Anatomy (`docs/html/development/architecture/anatomy.rst`)

.. note::

    This section of the documentation is currently being written. pip
    developers welcome your help to complete this documentation. If you're
    interested in helping out, please let us know in the `tracking issue`_.

****************************************
Repository anatomy & directory structure
****************************************

``pip``’s codebase (`GitHub repository`_) is structured as a standard Python package.


Root and tools
==============

The ``README``, license, ``pyproject.toml``, and so on are in the top level.

* ``AUTHORS.txt``
* ``LICENSE.txt``
* ``NEWS.rst``
* ``pyproject.toml``
* ``README.rst``
* ``noxfile.py`` -- ``pip`` uses Nox, an automation tool, configured by this file. ``noxfile.py`` describes a few environments ``pip`` uses during development for simplifying how tests are run (complicated situation there). Example: ``nox -s lint``, ``nox -s test-3.10``. We can run tests for different versions of Python by changing “3.10” to “3.7” or similar.
* ``.gitattributes``
* ``.gitignore``
* ``.mailmap``
* ``docs/`` *[documentation, built with Sphinx]*

  * ``html/`` *[sources to HTML documentation avail. online]*
  * ``man/`` has man pages the distros can use by running ``man pip``
  * ``pip_sphinxext.py`` *[an extension -- pip-specific plugins to Sphinx that do not apply to other packages]*

* ``news/`` *[pip stores news fragments… Every time pip makes a user-facing change, a file is added to this directory (usually a short note referring to a GitHub issue) with the right extension & name so it gets included in changelog…. So every release the maintainers will be deleting old files in this directory? Yes - we use the towncrier automation to generate a NEWS file, and auto-delete old stuff. There’s more about this in the contributor documentation!]*

  * ``template.rst`` *[template for changelog -- this is a file towncrier uses…. Is this jinja? I don’t know, check towncrier docs]*

* ``src/`` *[source; see below]*
* ``tools/`` *[misc development workflow tools, like requirements files & CI files & helpers. For instance, automating the release.]*
* ``tests/`` -- contains tests you can run. There are instructions in :doc:`../getting-started`.

  * ``__init__.py``
  * ``conftest.py``
  * ``data/`` *[test data for running tests -- pseudo package index in it!  Lots of small packages that are invalid or are valid. Test fixtures.  Used by functional tests]*
  * ``functional/`` *[functional tests of pip’s CLI -- end-to-end, invoke pip in subprocess & check results of execution against desired result. This also is what makes test suite slow]*
  * ``lib/`` *[helpers for tests]*
  * ``unit/`` *[unit tests -- fast and small and nice!]*

* ``.github``


src directory
=============

In the root directory, the ``src/`` directory contains pip's core
source code. Within ``src/pip/``, ``_internal/`` has the pip code
that's written by pip maintainers, and ``_vendor/`` is pip's
dependencies (code from other packages).

Within ``src/``:

* ``pip/``

  * ``__init__.py``
  * ``__main__.py``
  * ``_internal/`` *[where all the pip code lives that’s written by pip maintainers -- underscore means private. pip is not a library -- it’s a command line tool! A very important distinction! People who want to install stuff with pip should not use the internals -- they should use the CLI. There’s a note on this in the docs.]*

    * ``__init__.py``
    * ``build_env.py``
    * ``cache.py`` *[has all the info for how to handle caching within pip -- cache-handling stuff. Uses cachecontrol from PyPI, vendored into pip]*
    * ``cli/`` *[subpackage containing helpers & additional code for managing the command line interface. Uses argparse from stdlib]*
    * ``commands/`` *[literally - each file is the name of the command on the pip CLI. Each has a class that defines what’s needed to set it up, what happens]*
    * ``configuration.py``
    * ``download.py``
    * ``exceptions.py``
    * ``index/``
    * ``locations/``
    * ``main.py`` *[legacy entry point]*
    * ``models/`` *[in-process refactoring! Goal: improve how pip internally models representations it has for data -- data representation. General overall cleanup. Data reps are spread throughout codebase….link is defined in a class in 1 file, and then another file imports Link from that file. Sometimes cyclic dependency?!?! To prevent future situations like this, etc., Pradyun started moving these into a models directory.]*
    * ``operations/`` -- a bit of a weird directory….. ``Freeze.py`` used to be in there. Freeze is an operation -- there was an operations.freeze. Then “prepare” got added (the operation of preparing a pkg). Then “check” got added for checking the state of an env.] [what’s a command vs an operation? Command is on CLI; an operation would be an internal bit of code that actually does some subset of the operation the command says. ``install`` command uses bits of ``check`` and ``prepare``, for instance. In the long run, Pradyun’s goal: ``prepare.py`` goes away (gets refactored into other files) such that ``operations`` is just ``check`` and ``freeze``..... … Pradyun plans to refactor this. [how does this compare to ``utils``?]

      * ``install/`` -- for modules related to installing projects of various kinds

        * ``wheel.py`` is a file that manages installation of a wheel file. This handles unpacking wheels -- “unpack and spread”. There is a package on PyPI called ``wheel`` that builds wheels -- do not confuse it with this.

    * ``pep425tags.py`` -- getting refactored into packaging.tags (a library on PyPI) which is external to pip (but vendored by pip). :pep:`425` tags: turns out lots of people want this! Compatibility tags for built distributions -> e.g., platform, Python version, etc.
    * ``pyproject.py`` -- ``pyproject.toml`` is a new standard (:pep:`518` and :pep:`517`). This file reads pyproject.toml and passes that info elsewhere. The rest of the processing happens in a different file. All the handling for 517 and 518 is in a different file.
    * ``req/`` *[*\ **A DIRECTORY THAT NEEDS REFACTORING. A LOT**\ *\ …… Remember Step 3? Dependency resolution etc.? This is that step! Each file represents … have the entire flow of installing & uninstalling, getting info about packages…. Some files here are more than 1,000 lines long! (used to be longer?!) Refactor will deeply improve developer experience. Also, we're `improving the pip dependency resolver`_ in 2020 so a bunch of this is changing.]*
    * ``utils/`` *[everything that is not “operationally” pip ….. Misc functions and files get dumped. There’s some organization here. There’s a models.py here which needs refactoring. Deprecation.py is useful, as are other things, but some things do not belong here. There ought to be some GitHub issues for refactoring some things here. Maybe a few issues with checkbox lists.]*
    * ``vcs/`` *[stands for Version Control System. Where pip handles all version control stuff -- one of the ``pip install`` arguments you can use is a version control link. Are any of these commands vendored? No, via subprocesses. For performance, it makes sense (we think) to do this instead of pygitlib2 or similar -- and has to be pure Python, can’t include C libraries, because you can’t include compiled C stuff, because you might not have it for the platform you are running on.]*

  * ``_vendor/`` *[code from other packages -- pip’s own dependencies…. Has them in its own source tree, because pip cannot depend on pip being installed on the machine already!]*

.. _`tracking issue`: https://github.com/pypa/pip/issues/6831
.. _GitHub repository: https://github.com/pypa/pip/
.. _improving the pip dependency resolver: https://github.com/pypa/pip/issues/988

---

### Html Development Architecture Command Line Interface (`docs/html/development/architecture/command-line-interface.rst`)

======================
Command Line Interface
======================

The ``pip._internal.cli`` package is responsible for processing and providing
pip's command line interface. This package handles:

* CLI option definition and parsing
* autocompletion
* dispatching to the various commands
* utilities like progress bars and spinners

.. note::

    This section of the documentation is currently being written. pip
    developers welcome your help to complete this documentation. If you're
    interested in helping out, please let us know in the
    `tracking issue <https://github.com/pypa/pip/issues/6831>`_.


.. _cli-overview:

Overview
========

A ``ConfigOptionParser`` instance is used as the "main parser",
for parsing top level args.

``Command`` then uses another ``ConfigOptionParser`` instance, to parse command-specific args.

Command structure
-----------------

This section shows the class hierarchy from which every command's class will inherit
from.

`base_command.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/base_command.py>`_
defines the base ``Command`` class, from which every other command will inherit directly or
indirectly (see the *command tree* at the end of this section).

Using the ``ConfigOptionParser`` (see `Configuration and CLI "blend" <Configuration and CLI "blend"_>`_),
this class adds the general options and instantiates the *cmd_opts* group, where every other specific
option will be added if needed on each command's class. For those commands that define specific
options, like ``--dry-run`` on ``pip install`` command, the options must be added to *cmd_opts*
this is the job of *add_options* method), which will be automatically called on ``Command``'s initialization.

The base ``Command`` has the following methods:

.. py:class:: Command

  .. py:method:: main()

    Main method of the class, it's always called (as can be seen in main.py's
    `main <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/main.py#L46>`_).
    It's in charge of calling the specific ``run`` method of the class and handling the possible errors.

  .. py:method:: run()

    Abstract method where the actual action of a command is defined.

  .. py:method:: add_options()

    Optional method to insert additional options on a class, called on ``Command`` initialization.

Some commands have more specialized behavior, (see for example ``pip index``).
These commands instead will inherit from ``IndexGroupCommand``, which inherits from ``Command``
and  ``SessionCommandMixin`` to build the pip session for the corresponding requests.

Lastly, ``RequirementCommand``, which inherits from ``IndexGroupCommand`` is the base class
for those commands which make use of requirements in any form, like ``pip install``.

In addition to the previous classes, a last mixin class must be mentioned, from which
``Command`` as well as ``SessionCommandMixin`` inherit: ``CommandContextMixIn``, in
charge of the command's context.

In the following command tree we can see the hierarchy defined for the different pip
commands, where each command is defined under the base class it inherits from:

| ``Command``
|  ├─ ``cache``, ``check``, ``completion``, ``configuration``, ``debug``, ``freeze``, ``hash``, ``help``, ``inspect``, ``show``, ``search``, ``uninstall``
|  └─ ``IndexGroupCommand``
|      ├─ ``index``, ``list``
|      └─ ``RequirementCommand``
|           └─ ``wheel``, ``download``, ``install``


Option definition
-----------------

The set of shared options are defined in `cmdoptions.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/cmdoptions.py>`_
module, as well as the *general options* and *package index options* groups of options
we see when we call a command's help, or the ``pip index``'s help message respectively.
All options are defined in terms of functions that return `optparse.Option <https://docs.python.org/3/library/optparse.html#optparse.Option>`_
instances once called, while specific groups of options, like *Config Options* for
``pip config`` are defined in each specific command file (see for example the
`configuration.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/commands/configuration.py>`_).

Argument parsing
----------------

The main entrypoint for the application is defined in the ``main`` function in the
`main.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/main.py>`_ module.
This function is in charge of the `autocompletion <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/autocompletion.py>`_,
calling the ``parse_command`` function and creating and running the subprograms
via ``create_command``, on which the ``main`` method is called.

The ``parse_command`` is defined in the `main_parser.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/main_parser.py>`_
module, which defines the following two functions:

.. py:function:: parse_command()

  Function in charge of the initial parse of ``pip``'s program. Creates the main parser (see
  the next function ``create_main_parser``) to extract the general options
  and the remaining arguments. For example, running ``pip --timeout=5 install --user INITools``
  will split ``['--timeout=5']`` as general option and  ``['install', '--user', 'INITools']``
  as the remainder.

  At this step the program deals with the options ``--python``, ``--version``, ``pip``
  or ``pip help``. If neither of the previous options is found, it tries to extract the command
  name and arguments.

.. py:function:: create_main_parser()

  Creates the main parser (type ``pip`` in the console to see the description of the
  program). The internal parser (`ConfigOptionParser <Configuration and CLI "blend"_>`_),
  adds the general option group and the list of commands coming from ``cmdoptions.py``
  at this point.

After the initial parsing is done, ``create_command`` is in charge of creating the appropriate
command using the information stored in `commands_dict <https://github.com/pypa/pip/blob/main/src/pip/_internal/commands/__init__.py>`_
variable, and calling its ``main`` method (see `Command structure <Command structure>`_).

A second argument parsing is done at each specific command (defined in the base ``Command`` class),
again using the ``ConfigOptionParser``.

Argument access
---------------

To access all the options and arguments, ``Command.run()`` takes
the options as `optparse.Values <https://docs.python.org/3/library/optparse.html#optparse.Values>`_
and a list of strings for the arguments (parsed in ``Command.main()``). The internal methods of
the base ``Command`` class are in charge of passing these variables after ``parse_args`` is
called for a specific command.

Configuration and CLI "blend"
-----------------------------

The base ``Command`` instantiates the class `ConfigOptionParser <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/parser.py>`_
which is in charge of the parsing process (via its parent class
`optparse.OptionParser <https://docs.python.org/3/library/optparse.html#optparse.OptionParser>`_).
Its main addition consists of the following function:

.. py:class:: ConfigOptionParser(OptionParser)

  .. py:method:: get_default_values()

    Overrides the original method to allow updating the defaults after the instantiation of the
    option parser.

It allows overriding the default options and arguments using the ``Configuration`` class
(more information can be found on :ref:`Configuration`) to include environment variables and
settings from configuration files.

Progress bars and spinners
--------------------------

There are two more modules in the ``cli`` subpackage in charge of showing the state of the
program.

* `progress_bars.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/progress_bars.py>`_

  This module contains the following function:

  .. py:function:: get_download_progress_renderer()

    It uses `rich <https://rich.readthedocs.io/en/stable/reference/progress.html#module-rich.progress>`_
    functionalities to render the download progress.

  This function (used in `download.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/network/download.py>`_,
  inside the ``Downloader`` class), allows watching the download process when running
  ``pip install`` on *big* packages.

* `spinner.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/cli/spinners.py>`_

  The main function of this module is:

  .. py:function:: open_spinner()

    It yields the appropriate type of spinner, which is used in ``call_subprocess``
    function, inside `subprocess.py <https://github.com/pypa/pip/blob/main/src/pip/_internal/utils/subprocess.py>`_
    module, so the user can see there is a program running.

* TODO: quirks / standard practices / broad ideas.
  (avoiding lists in option def'n, special cased option value types,
  )


Future Refactoring Ideas
========================

* Change option definition to be a more declarative, consistent, static
  data-structure, replacing the current ``partial(Option, ...)`` form
* Move progress bar and spinner to a ``cli.ui`` subpackage
* Move all ``Command`` classes into a ``cli.commands`` subpackage
  (including base classes)

---

### Html Development Architecture Configuration Files (`docs/html/development/architecture/configuration-files.rst`)

===========================
Configuration File Handling
===========================

The ``pip._internal.configuration`` module is responsible for handling
(eg. loading from and saving values to) configuration files that are used by
pip. The module's functionality is largely exposed through and coordinated by
the module's ``Configuration`` class.

.. note::

    This section of the documentation is currently being written. pip
    developers welcome your help to complete this documentation. If you're
    interested in helping out, please let us know in the
    `tracking issue <https://github.com/pypa/pip/issues/6831>`_.


.. _configuration-overview:

Overview
========

pip stores configuration files in standard OS-appropriate locations, which are
determined by ``appdirs``. These files are in the INI format and are processed
with ``RawConfigParser``.

pip uses configuration files in two operations:

* During processing of command line options.

  * Reading from *all* configuration sources

* As part of ``pip config`` command.

  * Reading from *all* configuration sources
  * Manipulating a single configuration file

Both of these operations utilize functionality provided the ``Configuration``
object, which encapsulates all the logic for handling configuration files and
provides APIs for the same.

The remainder of this section documents the ``Configuration`` class, and
discusses potential future refactoring ideas.


.. _configuration-class:

``Configuration`` class
=======================

``Configuration`` loads configuration values from sources in the local
environment: a combination of configuration files and environment variables.

It can be used in two "modes", for reading all the values from the local
environment and for manipulating a single configuration file. It differentiates
between these two modes using the ``load_only`` attribute, which can be None or
represent the :ref:`kind <config-kinds>` of the configuration file to be
manipulated.

The ``isolated`` attribute determines which sources are used when loading the
configuration. If ``isolated`` is ``True``, user-specific configuration files
and environment variables are not used.

Reading from local environment
------------------------------

``Configuration`` can be used to read from all configuration sources in the
local environment and access the values, as per the precedence logic described
in the :ref:`Config Precedence <config-precedence>` section.

For this use case, the ``Configuration.load_only`` attribute would be ``None``,
and the methods used would be:

.. py:class:: Configuration

  .. py:method:: load()

    Handles all the interactions with the environment, to load all the
    configuration data into objects in memory.

  .. py:method:: items()

    Provides key-value pairs (like ``dict.items()``) from the loaded-in-memory
    information, handling all of the override ordering logic.

  .. py:method:: get_value(key)

    Provides the value of the given key from the loaded configuration.
    The loaded configuration may have ``load_only`` be None or non-None.
    This uses the same underlying mechanism as ``Configuration.items()`` and
    does follow the precedence logic described in :ref:`Config Precedence
    <config-precedence>`.

At the time of writing, the parts of the codebase that use ``Configuration``
in this manner are: ``ConfigOptionParser``, to transparently include
configuration handling as part of the command line processing logic,
and ``pip config get``, for printing the entire configuration when no
:ref:`kind <config-kinds>` is specified via the CLI.

Manipulating a single configuration file
----------------------------------------

``Configuration`` can be used to manipulate a single configuration file,
such as to add, change or remove certain key-value pairs.

For this use case, the ``load_only`` attribute would be non-None, and would
represent the :ref:`kind <config-kinds>` of the configuration file to be
manipulated. In addition to the methods discussed in the previous section,
the methods used would be:

.. py:class:: Configuration
  :noindex:

  .. py:method:: get_file_to_edit()

    Provides the "highest priority" file, for the :ref:`kind <config-kinds>` of
    configuration file specified by ``load_only``. This requires ``load_only``
    to be non-None.

  .. py:method:: set_value(key, value)

    Provides a way to add/change a single key-value pair, in the file specified
    by ``Configuration.get_file_to_edit()``.

  .. py:method:: unset_value(key)

    Provides a way to remove a single key-value pair, in the file specified
    by ``Configuration.get_file_to_edit()``.

  .. py:method:: save()

    Saves the in-memory state of to the original files, saving any modifications
    made to the ``Configuration`` object back into the local environment.

.. _config-kinds:

kinds
=====

This is an enumeration that provides values to represent a "source" for
configuration. This includes environment variables and various types of
configuration files (global, site-specific, user_specific, specified via
``PIP_CONFIG_FILE``).

Future Refactoring Ideas
========================

* Break up the ``Configuration`` class into 2 smaller classes, by use case
    * ``Command`` use-case (read only) -- ``ConfigurationReader``
    * ``pip config`` use-case (read / write) -- ``ConfigurationModifier`` (inherit from ``ConfigurationReader``)
* Eagerly populate ``Configuration._dictionary`` on load.

---

### Html Development Architecture Index (`docs/html/development/architecture/index.rst`)

.. _architecture-pip-internals:

===============================
Architecture of pip's internals
===============================

.. note::

    This section of the documentation is currently being written. pip
    developers welcome your help to complete this documentation. If
    you're interested in helping out, please let us know in the
    `tracking issue`_, or just go ahead and submit a pull request and
    mention it in that tracking issue.

.. note::

    Direct use of pip's internals is *not supported*, and these internals
    can change at any time. For more details, see :ref:`Using pip from
    your program`.


.. toctree::
    :maxdepth: 2

    overview
    anatomy
    configuration-files
    package-finding
    command-line-interface
    upgrade-options


.. _`tracking issue`: https://github.com/pypa/pip/issues/6831

---

### Html Development Architecture Overview (`docs/html/development/architecture/overview.rst`)

.. note::

    This section of the documentation is currently being written. pip
    developers welcome your help to complete this documentation. If you're
    interested in helping out, please let us know in the `tracking issue`_.


****************************
Broad functionality overview
****************************

pip is a package installer.

pip does a lot more than installation; it also has a cache, and it has
configuration, and it has a CLI, which has its own quirks. But mainly:

Things pip does:

1. | Manages the building of packages (offloads package building to a
     backend) when that’s necessary (a source distribution package --
     this is not necessary if the package is a wheel).

   1. | By default, pip delegates package-building to setuptools, for
           backwards compatibility reasons. But thing with setuptools:
           has a ``setup.py`` file that it invokes to …… get info?

2. Decides where to install stuff. Once the package is built, the resulting
   artifact is then installed to the system in its appropriate place. :pep:`517`
   defines the interface between the build backend & installer.

Broad overview of flow
======================

In sequence, what does pip do?:

1. Get user input (user-supplied string saying what package they want)
2. Figure out what that means: exactly what the user requested --
   translate to a thing pip can operate on (user input to requirements)
3. CORE OF THE WHOLE PROCESS, MAYBE? Once you have a set of reqs from
   Step 2, you have to expand those into a concrete “things to install”
   -- Figure out what other requirements it has to install based on
   user-given requirements, and where to get them from.

   a. this step is convoluted - also exploratory, involves dependency
      resolution -- we need to get to the index, see what versions
      are available

   b. Sometimes you need to build the package itself in order to get
      dependency information, which means fetching the package from
      package index, which means knowing whether it exists. For a
      single package,

4. Install the actual items to be installed.

Why? pip installs from places other than PyPI! But also, we’ve never had
guarantees of PyPI’s JSON API before now, so no one has been getting
metadata from PyPI separate from downloading the package itself.

In terms of flow of the install process:

1. For 1 package: Get abstract requirement(s) for that package, and
   try and see what that means (this abstract requirement can take
   various forms). Define abstract dependencies.

2. Once we have a set of "this package, get it from here, this is that
   version of that package",

3. Modify the environment to install those things (which means: place
   the files in the right place). For example: if you already have
   version 6.0 of a requirement and you are installing 7.2, uninstall
   6.0 and install 7.2.

Download process
----------------

What happens in an install? Well, a subset of ``install``, a process
pip usually does during a ``pip install``, is ``download`` (also
available to the user as the :ref:`pip download` command). And we
download and INSPECT packages to get manifests. For any given package
name, we need to know what files are available and what their
filenames are.

pip can download from a Python package repository, where packages are
stored in a structured format so an installer like pip can find them.

:pep:`503` defines the API we use to talk to a Python package repository.

PyPI
^^^^

What happens if we run ``pip download somepackage`` with no other
arguments?  By default we look at `PyPI`_, which is where pip knows
where to look to get more info for what the package index knows about
``somepackage``.

``pip`` then knows: what files are available, and what their filenames
are.

IN OTHER WORDS

While all dependencies have not been resolved, do the following:

1.  Following the API defined in :pep:`503`, fetch the index page from
    `https://{pypi_index}/simple/{package_name} <https://pypi.org/simple/{package_name}>`_
2.  Parse all of the file links from the page.
3.  Select a single file to download from the list of links.
4.  Extract the metadata from the downloaded package.
5.  Update the dependency tree based on the metadata.

The package index gives pip a list of files for that package (via the existing PyPI API). The files have the version and some other info that helps pip decide whether that's something pip ought to download.

pip chooses from the list a single file to download.

It may go back and choose another file to download.

When pip looks at the package index, the place where it looks has
basically a link. The link’s text is the name of the file.

This is the `PyPI Simple API`_ (PyPI has several APIs, some are being
deprecated). pip looks at Simple API, documented initially at :pep:`503` --
packaging.python.org has PyPA specifications with more details for
Simple Repository API.

For this package name -- this is the list of files available.

Looks there for:

* The list of filenames
* Other info

Once it has those, it selects one file and downloads it.

(Question: If I want to ``pip install flask``, I think the whole list of filenames
cannot….should not be …. ? I want only the Flask …. Why am I getting the
whole list?

Answer: It's not every file, just files of Flask. No API for getting all
files on PyPI. It’s for getting all files of Flask.)

.. _`tracking issue`: https://github.com/pypa/pip/issues/6831
.. _PyPI: https://pypi.org/
.. _PyPI Simple API: https://warehouse.readthedocs.io/api-reference/legacy/

---

### Html Development Architecture Package Finding (`docs/html/development/architecture/package-finding.rst`)

Finding and choosing files (``index`` and ``PackageFinder``)
---------------------------------------------------------------

The ``pip._internal.index`` sub-package in pip is responsible for deciding
what file to download and from where, given a requirement for a project. The
package's functionality is largely exposed through and coordinated by the
package's ``PackageFinder`` class.


.. _index-overview:

Overview
********

Here is a rough description of the process that pip uses to choose what
file to download for a package, given a requirement:

1. Collect together the various network and file system locations containing
   project package files. These locations are derived, for example, from pip's
   :ref:`--index-url <install_--index-url>` (with default
   https://pypi.org/simple/ ) setting and any configured
   :ref:`--extra-index-url <install_--extra-index-url>` locations. Each of the
   project page URL's is an HTML page of anchor links, as defined in
   `PEP 503`_, the "Simple Repository API."
2. For each project page URL, fetch the HTML and parse out the anchor links,
   creating a ``Link`` object from each one. The :ref:`LinkCollector
   <link-collector-class>` class is responsible for both the previous step
   and fetching the HTML over the network.
3. Determine which of the links are minimally relevant, using the
   :ref:`LinkEvaluator <link-evaluator-class>` class.  Create an
   ``InstallationCandidate`` object (aka candidate for install) for each
   of these relevant links.
4. Further filter the collection of ``InstallationCandidate`` objects (using
   the :ref:`CandidateEvaluator <candidate-evaluator-class>` class) to a
   collection of "applicable" candidates.
5. If there are applicable candidates, choose the best candidate by sorting
   them (again using the :ref:`CandidateEvaluator
   <candidate-evaluator-class>` class).

The remainder of this section is organized by documenting some of the
classes inside the ``index`` package, in the following order:

* the main :ref:`PackageFinder <package-finder-class>` class,
* the :ref:`LinkCollector <link-collector-class>` class,
* the :ref:`LinkEvaluator <link-evaluator-class>` class,
* the :ref:`CandidateEvaluator <candidate-evaluator-class>` class,
* the :ref:`CandidatePreferences <candidate-preferences-class>` class, and
* the :ref:`BestCandidateResult <best-candidate-result-class>` class.


.. _package-finder-class:

The ``PackageFinder`` class
***************************

The ``PackageFinder`` class is the primary way through which code in pip
interacts with ``index`` package. It is an umbrella class that encapsulates and
groups together various package-finding functionality.

The ``PackageFinder`` class is responsible for searching the network and file
system for what versions of a package pip can install, and also for deciding
which version is most preferred, given the user's preferences, target Python
environment, etc.

The pip commands that use the ``PackageFinder`` class are:

* :ref:`pip download`
* :ref:`pip install`
* :ref:`pip list`
* :ref:`pip wheel`

The pip commands requiring use of the ``PackageFinder`` class generally
instantiate ``PackageFinder`` only once for the whole pip invocation. In
fact, pip creates this ``PackageFinder`` instance when command options
are first parsed.

With the exception of :ref:`pip list`, each of the above commands is
implemented as a ``Command`` class inheriting from ``RequirementCommand``
(for example :ref:`pip download` is implemented by ``DownloadCommand``), and
the ``PackageFinder`` instance is created by calling the
``RequirementCommand`` class's ``_build_package_finder()`` method. ``pip
list``, on the other hand, constructs its ``PackageFinder`` instance by
calling the ``ListCommand`` class's ``_build_package_finder()``. (This
difference may simply be historical and may not actually be necessary.)

Each of these commands also uses the ``PackageFinder`` class for pip's
"self-check," (i.e. to check whether a pip upgrade is available). In this
case, the ``PackageFinder`` instance is created by the
``self_outdated_check.py`` module's ``pip_self_version_check()`` function.

The ``PackageFinder`` class is responsible for doing all of the things listed
in the :ref:`Overview <index-overview>` section like fetching and parsing
`PEP 503`_ simple repository HTML pages, evaluating which links in the simple
repository pages are relevant for each requirement, and further filtering and
sorting by preference the candidates for install coming from the relevant
links.

One of ``PackageFinder``'s main top-level methods is
``find_best_candidate()``. This method does the following two things:

1. Calls its ``find_all_candidates()`` method, which gathers all
   possible package links by reading and parsing the index URL's and
   locations provided by the user (the :ref:`LinkCollector
   <link-collector-class>` class's ``collect_sources()`` method), constructs a
   :ref:`LinkEvaluator <link-evaluator-class>` object to filter out some of
   those links, and then returns a list of ``InstallationCandidates`` (aka
   candidates for install). This corresponds to steps 1-3 of the
   :ref:`Overview <index-overview>` above.
2. Constructs a ``CandidateEvaluator`` object and uses that to determine
   the best candidate. It does this by calling the ``CandidateEvaluator``
   class's ``compute_best_candidate()`` method on the return value of
   ``find_all_candidates()``. This corresponds to steps 4-5 of the Overview.

``PackageFinder`` also has a ``process_project_url()`` method (called by
``find_best_candidate()``) to process a `PEP 503`_ "simple repository"
project page. This method fetches and parses the HTML from a PEP 503 project
page URL, extracts the anchor elements and creates ``Link`` objects from
them, and then evaluates those links.


.. _link-collector-class:

The ``LinkCollector`` class
***************************

The :ref:`LinkCollector <link-collector-class>` class is the class
responsible for collecting the raw list of "links" to package files
(represented as ``Link`` objects) from file system locations, as well as the
`PEP 503`_ project page URL's that ``PackageFinder`` should access.

The ``LinkCollector`` class takes into account the user's :ref:`--find-links
<install_--find-links>`, :ref:`--extra-index-url <install_--extra-index-url>`,
and related options when deciding which locations to collect links from. The
class's main method is the ``collect_sources()`` method. The :ref:`PackageFinder
<package-finder-class>` class invokes this method as the first step of its
``find_all_candidates()`` method.

``LinkCollector`` also has a ``fetch_page()`` method to fetch the HTML from a
project page URL. This method is "unintelligent" in that it doesn't parse the
HTML.

The ``LinkCollector`` class is the only class in the ``index`` sub-package that
makes network requests and is the only class in the sub-package that depends
directly on ``PipSession``, which stores pip's configuration options and
state for making requests.


.. _link-evaluator-class:

The ``LinkEvaluator`` class
***************************

The ``LinkEvaluator`` class contains the business logic for determining
whether a link (e.g. in a simple repository page) satisfies minimal
conditions to be a candidate for install (resulting in an
``InstallationCandidate`` object). When making this determination, the
``LinkEvaluator`` instance uses information like the target Python
interpreter as well as user preferences like whether binary files are
allowed or preferred, etc.

Specifically, the ``LinkEvaluator`` class has an ``evaluate_link()`` method
that returns whether a link is a candidate for install.

Instances of this class are created by the ``PackageFinder`` class's
``make_link_evaluator()`` on a per-requirement basis.


.. _candidate-evaluator-class:

The ``CandidateEvaluator`` class
********************************

The ``CandidateEvaluator`` class contains the business logic for evaluating
which ``InstallationCandidate`` objects should be preferred. This can be
viewed as a determination that is finer-grained than that performed by the
``LinkEvaluator`` class.

In particular, the ``CandidateEvaluator`` class uses the whole set of
``InstallationCandidate`` objects when making its determinations, as opposed
to evaluating each candidate in isolation, as ``LinkEvaluator`` does. For
example, whether a pre-release is eligible for selection or whether a file
whose hash doesn't match is eligible depends on properties of the collection
as a whole.

The ``CandidateEvaluator`` class uses information like the list of
:ref:`platform tags <pypug:platform-compatibility-tags>`
compatible with the target Python interpreter, hashes provided by the
user, and other user preferences, etc.

Specifically, the class has a ``get_applicable_candidates()`` method.
This accepts the ``InstallationCandidate`` objects resulting from the links
accepted by the ``LinkEvaluator`` class's ``evaluate_link()`` method, filters
them to a list of "applicable" candidates and orders them by preference.

The ``CandidateEvaluator`` class also has a ``sort_best_candidate()`` method
that returns the best (i.e. most preferred) candidate.

Finally, the class has a ``compute_best_candidate()`` method that calls
``get_applicable_candidates()`` followed by ``sort_best_candidate()``, and
then returning a :ref:`BestCandidateResult <best-candidate-result-class>`
object encapsulating both the intermediate and final results of the decision.

Instances of ``CandidateEvaluator`` are created by the ``PackageFinder``
class's ``make_candidate_evaluator()`` method on a per-requirement basis.


.. _candidate-preferences-class:

The ``CandidatePreferences`` class
**********************************

The ``CandidatePreferences`` class is a simple container class that groups
together some of the user preferences that ``PackageFinder`` uses to
construct ``CandidateEvaluator`` objects (via the ``PackageFinder`` class's
``make_candidate_evaluator()`` method).

A ``PackageFinder`` instance has a ``_candidate_prefs`` attribute whose value
is a ``CandidatePreferences`` instance. Since ``PackageFinder`` has a number
of responsibilities and options that control its behavior, grouping the
preferences specific to ``CandidateEvaluator`` helps maintainers know which
attributes are needed only for ``CandidateEvaluator``.


.. _best-candidate-result-class:

The ``BestCandidateResult`` class
*********************************

The ``BestCandidateResult`` class is a convenience "container" class that
encapsulates the result of finding the best candidate for a requirement.
(By "container" we mean an object that simply contains data and has no
business logic or state-changing methods of its own.) It stores not just the
final result but also intermediate values used to determine the result.

The class is the return type of both the ``CandidateEvaluator`` class's
``compute_best_candidate()`` method and the ``PackageFinder`` class's
``find_best_candidate()`` method.


.. _`PEP 503`: https://www.python.org/dev/peps/pep-0503/

---

### Html Development Architecture Upgrade Options (`docs/html/development/architecture/upgrade-options.rst`)

=============================================
Options that control the installation process
=============================================

When installing packages, pip chooses a distribution file, and
installs it in the user's environment. There are many choices (which
are `still evolving`_) involved in deciding which file to install, and
these are controlled by a variety of options.

.. note::

    This section of the documentation needs to be updated per
    :ref:`Resolver changes 2020`.

Controlling what gets installed
===============================

These options directly affect how the resolver uses the list of available
distribution files to decide which one to install. So these modify the
resolution algorithm itself, rather than the input to that algorithm.

``--upgrade``

Allow installing a newer version of an installed package. In principle, this
option actually affects "what gets considered", in the sense that it allows
the resolver to see other versions of installed packages. Without
``--upgrade``, the resolver will only see the installed version as a
candidate.

``--upgrade-strategy``

This option affects which packages are allowed to be installed. It is only
relevant if ``--upgrade`` is specified (except for the ``to-satisfy-only``
option mentioned below). The base behaviour is to allow
packages specified on pip's command line to be upgraded. This option controls
what *other* packages can be upgraded:

* ``eager`` - all packages will be upgraded to the latest possible version.
  It should be noted here that pip's current resolution algorithm isn't even
  aware of packages other than those specified on the command line, and
  those identified as dependencies. This may or may not be true of the new
  resolver.
* ``only-if-needed`` - packages are only upgraded if they are named in the
  pip command or a requirement file (i.e, they are direct requirements), or
  an upgraded parent needs a later version of the dependency than is
  currently installed.
* ``to-satisfy-only`` (**undocumented, please avoid**) - packages are not
  upgraded (not even direct requirements) unless the currently installed
  version fails to satisfy a requirement (either explicitly specified or a
  dependency).

  * This is actually the "default" upgrade strategy when ``--upgrade`` is
    *not set*, i.e. ``pip install AlreadyInstalled`` and
    ``pip install --upgrade --upgrade-strategy=to-satisfy-only AlreadyInstalled``
    yield the same behavior.

``--force-reinstall``

Doesn't affect resolution, but if the resolved result is the same as what is
currently installed, uninstall and reinstall it rather than leaving the
current version in place. This occurs even if ``--upgrade`` is not set.

``--ignore-installed``

Act as if the currently installed version isn't there - so don't care about
``--upgrade``, and don't uninstall before (re-)installing.


Controlling what gets considered
================================

These options affect the list of distribution files that the resolver will
consider as candidates for installation. As such, they affect the data that
the resolver has to work with, rather than influencing what pip does with the
resolution result.

Prereleases

``--pre``

Source vs Binary

``--no-binary``

``--only-binary``

``--prefer-binary``

Wheel tag specification

``--platform``

``--implementation``

``--abi``

Index options

``--index-url``

``--extra-index-url``

``--no-index``

``--find-links``


Controlling dependency data
===========================

These options control what dependency data the resolver sees for any given
package (or, in the case of ``--python-version``, the environment information
the resolver uses to *check* the dependency).

``--no-deps``

``--python-version``

``--ignore-requires-python``


Special cases
=============

These need further investigation. They affect the install process, but not
necessarily resolution or what gets installed.

``--require-hashes``

``--constraint``

``--editable <LOCATION>``


.. _still evolving: https://github.com/pypa/pip/issues/8115

---

### Html Ux Research Design Research Results About Our Users (`docs/html/ux-research-design/research-results/about-our-users.md`)

# About pip's Users

## Problem

We want to understand users' background, their cultural environment, and how they experience the world, so that we can find better ways to serve them.

[Skip to recommendations](#recommendations)

## Research

To develop our understanding about pip's users, we published a "Who uses pip?" survey that asked users about:

- Their location in the world
- Their spoken language
- If they identified as members of an underrepresented group in the Python community
- Their disabilities and if those disabilities affected their usage of pip

## Results

164 people responded to the survey, with 40% of these coming from English speaking countries. 80% of participants came from Europe or North America.

Approx. 60% did not identify as members of an underrepresented group. The majority of participants who did identify as underrepresented did so for gender reasons.

The majority of participants (94%) responded that they did not have a disability. Of those that did have a disability, the majority were cognitive disabilities (Attention Deficit Hyperactivity Disorder aka ADHD, Autism, Aspergers, Dyslexia) or a hearing disability.

### Participant Demographics

#### Location

The majority of participants came from North America and Western Europe. Participation from pip users in Africa, Asia, and the Middle-East was low.



Fig. X: Global distribution of pip research participants.

| Country Name             | Number of participants |
| ------------------------ | ---------------------- |
| United States of America | 42                     |
| United Kingdom           | 17                     |
| France                   | 12                     |
| Germany                  | 11                     |
| Canada                   | 10                     |
| Netherlands              | 8                      |
| Spain                    | 6                      |
| Switzerland              | 5                      |
| Nigeria                  | 4                      |
| India                    | 4                      |
| Czech Republic           | 4                      |
| Argentina                | 4                      |
| Sweden                   | 3                      |
| Australia                | 3                      |
| Ukraine                  | 2                      |
| Taiwan                   | 2                      |
| Russia                   | 2                      |
| Greece                   | 2                      |
| Colombia                 | 2                      |
| Chile                    | 2                      |
| Brazil                   | 2                      |
| Belgium                  | 2                      |
| Uganda                   | 1                      |
| Turkey                   | 1                      |
| Singapore                | 1                      |
| Serbia                   | 1                      |
| Norway                   | 1                      |
| Luxembourg               | 1                      |
| Japan                    | 1                      |
| Italy                    | 1                      |
| Israel                   | 1                      |
| Ireland                  | 1                      |
| Hungary                  | 1                      |
| Ghana                    | 1                      |
| Finland                  | 1                      |
| Bulgaria                 | 1                      |
| Austria                  | 1                      |
| Total                    | 164                    |

#### Participant's First Language

Even though the research was carried out mainly in English, 51% of participants spoke languages other than English.

| What spoken language do you feel is your first? | Number of participants |
| ----------------------------------------------- | ---------------------- |
| English                                         | 79                     |
| French                                          | 18                     |
| Spanish                                         | 12                     |
| German                                          | 11                     |
| Russian                                         | 5                      |
| Czech                                           | 4                      |
| Italian                                         | 4                      |
| Portuguese                                      | 3                      |
| Dutch                                           | 3                      |
| Ukrainian                                       | 2                      |
| Swedish                                         | 2                      |
| Greek                                           | 2                      |
| Catalan                                         | 2                      |
| Mandarin                                        | 2                      |
| Hungarian                                       | 2                      |
| Bengali                                         | 1                      |
| Luxembourgish                                   | 1                      |
| Bulgarian                                       | 1                      |
| Romanian                                        | 1                      |
| Chinese                                         | 1                      |
| Norwegian                                       | 1                      |
| Serbian                                         | 1                      |
| Polish                                          | 1                      |
| Hebrew                                          | 1                      |
| Indonesian                                      | 1                      |
| Malayalam                                       | 1                      |

NB: English includes British English and American English. Some participants gave more than one answer, their first answer is included here.

### Participants who identified as underrepresented in the Python community

We asked research participants if they identified as members of an underrepresented group within the Python community.

The wording of this question was deliberately broad to discover participants' understanding of the term "underrepresented" - we listed gender, age, educational background, spoken language, and what they use Python for as a non-exhaustive list of examples.



Of the 22.6% that responded "Yes" the answers were classified as follows :

| Underrepresentation category | Count |
| ---------------------------- | ----- |
| Gender                       | 9     |
| Cultural                     | 3     |
| Age                          | 3     |
| Immigration status           | 2     |
| Neurodiversity               | 3     |
| Other                        | 6     |
| No answer                    | 8     |

NB: This question was included after the survey was published. Total participants was 106, as opposed to all other questions which had 164.

The majority of participants did not identify as part of an underrepresented group. However, due to the small sample size these results cannot be seen as representative of the whole pip user base.

#### Participant comments about identifying (or not) as under-represented

Here is a sample of noteworthy comments from these different groups:

##### Related to Gender

> "(I am) LGBTQ/IA+" **- Participant 242608909**

> "I am a 25 year old female Colombian developer." **- Participant 242611698**

> "Female, 39, no computer science background whatsoever, self taught." **- Participant 242614039**

##### Related to Culture

> "The hispanic community is quite underrepresented in the web in general" **- Participant 242599212**

> "I am a 1st generation Dominican-American. My parents are from the Dominican Republic." **- Participant 242769361**

##### Related to Age

> "Older age, I am 50 now." **- Participant 242769743**

##### Related to Neurodiversity

> "I'm a woman. And autistic. But the latter might not be underrepresented ;)" **- Participant 243428773**

##### Other Noteworthy Comments

> "Veterans who entered tech post-military" **- Participant 243524784**

> "I'm a young white cis male, so by far not a minority in those aspects. But at the same time I'm from a third world country, Argentina, and that sometimes (and I emphasize, only sometimes) makes me feel like a minority. When participating in our local communities (Python Argentina), I feel clearly not-minority, and with the responsibility of helping minorities, trying to build a more welcoming and fair environment for them. But when I participate in the broader global community, at times I feel underrepresented, seeing it mostly guided by english-s[p]eaking people from first world countries. But if I have to choose, I would say I mostly feel not-minority, because I mostly interact with people from our local communities, where I'm not part of a minority." **- Participant 242592869**

> "As a CIS male I conform the majoritarian group in the IT world. I'm hopeful that things are changing everywhere, and will keep changing: inclusion is getting bigger and better, more and more people are starting their careers as devs or similar, disregarding ethnicity and/or sexual orientation and that's great! And we need to keep fighting for that." **- Participant 243455292**

### Participant Disabilities

Disabilities - physical, motor, cognitive, hearing, speech - alter how people perceive and interact with the world around them - software included. We asked participants about their disabilities and how it affected their usage of pip.

Understanding these disabilities is important particularly when designing pip command structures, and designing pip output.

The majority of participants (91%) responded that they did not have a disability. Of those that told us that have a disability, the majority were cognitive disabilities (Attention Deficit Hyperactivity Disorder (ADHD), Autism, Aspergers, Dyslexia, or a hearing disability.

#### How many participants identified as having a disability?

| Do you self-identify as someone who has a disability? | Number of responses |
| ----------------------------------------------------- | ------------------- |
| No                                                    | 150                 |
| Yes                                                   | 14                  |
| Grand Total                                           | 164                 |

#### Vision

Participants who answered yes to this question were partially sighted. Their vision disability was not corrected by glasses, but did not significantly affect their usage of pip.

#### Hearing

Five participants identified as having a hearing impairment, or hearing loss. While this disability made participants lives more difficult, it did not affect their usage of pip:

> "Being hard of hearing/impaired makes my life much harder, but so far it never has impacted my usage of pip. Perhaps because I haven‘t used parts of it that would?" **- Participant 242934019**

> "Not at all given that everything happens by text in my console." **- Participant 243455292**

However it did affect the way they consume pip learning materials: if video is being used for learning or support, they should have captions/subtitles/transcriptions available.

> "any videos released, it is so helpful if there is either a) transcripts, or b) captions." **- Participant 243524784**

#### Cognitive Disabilities

Nine participants expressed cognitive disabilities including undefined mental health conditions, Attention Deficit Hyperactivity Disorder (ADHD), Autism, Aspergers, Dyslexia.

These participants did not explain how their cognitive disabilities affect their usage of pip, however there are guidelines and best practices for designing for people with cognitive disabilities.

#### Physical or Mobility Disability

One participant responded that they had a physical or mobility disability, but did not give detail about it in relation to their usage of pip.

### Participants use of Assistive Technology

The term "assistive technology" (AT) is used to describe products or systems that support and assist individuals with disabilities, restricted mobility or other impairments to perform functions that might otherwise be difficult or impossible. A subset of these are used to make computer technology - hardware and software - more accessible. Common examples of AT used with computer technology are: screen readers, text-to-speech outputs/inputs.

The majority of participants (94%) said that they have never used assistive technology.

| Do you use assistive technology (AT) when using computers? | Number of responses |
| ---------------------------------------------------------- | ------------------- |
| No, I have never used it                                   | 128                 |
| I only use it when needed                                  | 3                   |
| I use it everyday                                          | 1                   |
| I have used it in the past, but not anymore                | 4                   |

Of the eight participants who have used assistive technology, one participant uses assistive technology every day with:

- Text-to-speech output as "text to speech allow(s) me to listen and learn when my eyes get strained."
- Speech-to-text input as they like using their "tablet and makes typing easier"
- On-screen keyboards
- Input switches/touch screens

A further seven participants use assistive technology only as needed:

> "I use custom display filter software to do things like colorize key lines of output automatically (to draw my eye/attention), and provide digit dilimination (I.E. help me tell 1000 and 10000 apart) when using a text console application."

> "The standard Mac user interface design contains enough assistive technology without my needing to use any features which are specifically intended solely as assistive functions."

> "I sometimes use it to make sure that my code will work correctly with AT."

#### Operating systems used with assistive technology

Participants use assistive technology across the three most popular desktop operating systems - Linux (most popular), Windows (2nd most popular), and Mac.



#### Assistive technology when using pip

We asked participants how well their assistive technologies worked when they use pip. All participants using assistive technology with pip said it worked well for them.

We received some feedback about screen readers not coping well with long output, with users experiencing difficulties accessing content at the top of the current terminal window. Therefore, commands or actions (e.g. pip help, pip install, failed builds) that generate a lot of content can be a problem for screenreader users.

## Recommendations

### Supporting languages other than English

As 51% of participants speak a language other than English, we recommend that the pip team add localization support to the pip documentation and reach out to the community to find pip users who might be willing to contribute translations. Translators that have [contributed translations to PyPI](https://hosted.weblate.org/projects/pypa/warehouse/) may be a good starting point.

If this is not possible, we recommend linking to useful resources in languages other than English from the pip documentation, as we know from our other research that users use a mixture of the official documentation, search engine searches, Stack Overflow and blogs/websites to find solutions to their problems.

### Supporting pip users with disabilities

Pip's operation is generally very good for users with disabilities. Being a command line application there are no distracting images or ancillary content, and the user has a large amount of control on how they experience pip via customisation of interface visual preferences (to use contrasting colours, font size and type) and visual and auditory alerts.

To better support pip's users with disabilities, the pip team should:

- Ensure any future video or audio support materials are provided with captions
- Improve pip's output (see below)

### Improving pip output

Pip's output is currently too verbose, generating an unhelpful amount of output during its operation. This causes usability issues for all users - especially users with cognitive disabilities.

Pip's output should be improved by:

- Retaining only the information that is important to users in their current moment (e.g. at install of a package)
- Removing unimportant information from the terminal output. The information can still be logged to the log files if needed.
- Reducing the number of verbosity levels to three. Right now there are seven levels of verbosity, which is overwhelming and in no way useful. We recommend:
  - Verbosity 0 - shows only what packages are to be installed, notifications identified as important about the operation, any errors and the final outcome
  - Verbosity 1 - shows more detail about the packages being installed
  - Verbosity 2 - shows full information which is also logged to logfiles

## Further reading

Designing for people with disabilities:

- [An Introduction to inclusive design](https://www.nomensa.com/blog/2011/introduction-inclusive-design)
- [How ADHD and dyslexia teach you to do better UX design](https://themasters.io/blog/posts/how-adhd-dyslexia-teach-better-ux-design)
- [Improve User Experience by Designing with Cognitive Differences in Mind](https://noti.st/elizabethschafer/fg3BR4)
- [Designing accessible software - guidelines for different disabilities](https://ukhomeoffice.github.io/accessibility-posters/)
- [Designing for Children with ADHD: The Search for Guidelines for Non-Experts](https://uxpamagazine.org/designing_children_adhd/) (written for children however applicable generally)
- [Designing for dyslexia](https://uxplanet.org/designing-for-dyslexia-6d12e8c41cd7)

---

### Html Ux Research Design Research Results Ci Cd (`docs/html/ux-research-design/research-results/ci-cd.md`)

# How pip is used in interactive environments (i.e. CI, CD)

## Problem

We want to know about the contexts in which pip users use pip - interactively (i.e. typing pip commands at the command line terminal) and in an automated environment (i.e. as part of continuous software integration or continuous software development pipelines).

Different contexts of use mean that users have different important and common tasks; it means when, where and how they complete these tasks are different.

Each of these contexts bring different needs: interactive usage requires the right feedback/output at the right time, whereas an automated environment requires little or no feedback in the moment but detailed feedback after the task has finished.

We also wanted to know what users used pip for - as part of their software development toolchain, or purely as a software installer (analogous to Ubuntu Aptitude or Mac Appstore). We also asked about their need for pip to build packages from source.

## Research

We created a survey and asked users to give answers to the following statements:

- I use pip in an automated environment (e.g. CI/CD pipelines)
- I have problems with pip in CI/CD pipelines
- I use pip interactively (e.g. typing pip commands on the commandline)
- I make software and use pip as part of my software development workflow
- I use pip only to install and use Python packages
- I need pip to build software packages from source

## Results

Using pip interactively makes up the majority of pip usage (91%), the majority (73%) of this usage is basic usage - to only install and use Python packages.

Half (51%) of all participants used pip in an automated environment, with only 9% having issues with pip in that automated environment. This points to a good use experience for these users.

71% use pip as part of their software toolchain, only 29% needing pip to build from source.

These results show that the main context of use is interactive - users either writing code, installing software at the command line and we know from other research that interactive usage has its issues e.g. pip output being too verbose.

While it is important to provide automated environment users with a good experience, interactive mode users are being underserved.





91% of users said they used pip interactively. This does not preclude them from automated usage.

---

### Html Ux Research Design Research Results Improving Pips Documentation (`docs/html/ux-research-design/research-results/improving-pips-documentation.md`)

# Improving pip's Documentation

## Problem

We want to establish whether or not the [official pip documentation](https://pip.pypa.io/en/stable/) helps users to solve their pip problems. We also want to identify possible improvements to the content and structure of the docs.

[Skip to recommendations](#recommendations)

## Research

### Interviews

We conducted interviews with pip users specifically discussing documentation. During these interviews we asked about:

- Problems they had experienced while using pip, and how they solved them (with a focus on what information sources they used)
- How they rate pip's documentation, and what we could do to make the docs more useful
- What documentation (from other projects or languages) they find valuable, and why

### Surveys

We collected documentation feedback via two surveys:

- In our survey that profiled pip users, we asked "What would be your ideal way of getting help with pip?"
- We also published a survey specific to pip's docs:



### Keyword research

We used keyword research tools to understand what words ("keywords") people use when using search engines to troubleshoot pip problems.

### Other research methods

We also:

1. Asked for volunteers to participate in a diary study, documenting their experience solving pip problems. Unfortunately this was not completed due to lack of interest from the community.
2. Asked for user feedback on the pip documentation site:
   
   Unfortunately, we did not gather any useful feedback via this effort
3. [Installed analytics on the pip docs](https://github.com/pypa/pip/pull/9146). We are waiting for this to be merged and start providing useful data.

## Results

In total, we:

- Conducted 5 user interviews about pip's documentation
- Received 141 responses to the question "What would be your ideal way of getting help with pip?"
- Received 159 responses to the documentation survey

In general, we found that pip's documentation is underutilized by the community, with many users not knowing that it exists. Instead, most users turn to common tools (Google, Stack Overflow) to solve their pip problems.

In response to the question "When you have a problem using pip, what do you do?" (multiselect):

- 81.9% of respondents Google it
- 56.9% of respondents search or ask on Stack Overflow
- 33.8% of respondents use pip help from the command line
- **25.6% of respondents go to the pip docs**
- 20.6% of respondents go the the Python Packaging User Guide
- 8.1% of respondents ask on a forum, community board, or chat channel



Based on survey results, users find pip's docs:

- Marginally more useful than not useful
- Marginally more clear than unclear
- Not opinionated enough

Common feedback that emerged from both surveys and user interviews includes:

- The documentation performs poorly in search engine results
- The style and layout is dated (note: this feedback was collected before the [new theme was deployed](https://github.com/pypa/pip/pull/9012))
- There is not enough guidance/examples on how to resolve common problems, or achieve specific goals
- The documentation information architecture is difficult to navigate (the monolithic structure of the user guide is a problem) and does not prioritise the most useful content
- There should be more instructions specific to each user's different situation (e.g. what operating system they are using)
- The scope of the documentation is unclear
- The documentation should recognise that pip exists within an ecosystem of other packaging tools
- ["There should be one-- and preferably only one --obvious way to do it."](https://www.python.org/dev/peps/pep-0020/) - i.e. the documentation should provide stronger recommendations

While some users mentioned that video would be helpful, more said that video was too long, or inappropriate for the kind of problems they experience using pip.

Some users mentioned that in person support, forums or chat would be helpful, with many unaware of existing support / community channels.

Several users also noted that improving pip's error messages would reduce the need for better documentation.

From our keyword research we identified seven _query types_: "about pip", "install pip", "uninstall pip" "update pip", "using pip", "errors", and "other".

<details><summary> See keyword research results</summary>

### About pip

- what is pip
- what is pip in python
- what is pip python
- what does pip mean
- what does pip stand for
- what does pip stand for python
- pip meaning

### Install pip

- get pip
- python install pip
- install pip
- installing pip
- how to install pip python
- how to install pip
- how to download pip
- how to get pip
- how to check if pip is installed
- install pip mac
- how to install pip on mac
- install pip on mac
- install pip linux
- how to install pip linux
- how to install pip on linux
- how to install pip in ubuntu
- how to install pip ubuntu
- install pip ubuntu
- ubuntu install pip
- pip windows
- install pip windows
- pip install windows
- how to install pip windows
- how to install pip in windows
- how to install pip on windows
- how to pip install on windows
- how to install pip on windows 10
- how to run pip on windows

### Uninstall pip

- how to uninstall pip
- uninstall pip
- pip uninstall

### Update pip

- how to update pip
- how to upgrade pip
- pip update
- pip upgrade
- upgrade pip
- how to upgrade pip on windows

### Using pip

- how to use pip
- how to use pip install
- how to pip install
- how to use pip python
- how to install with pip
- how to run pip
- python how to use pip
- pip install requirements.txt
- pip requirements.txt
- pip freeze
- pip update package
- pip install specific version
- pip upgrade package
- pip uninstall package

### Errors

- no module named pip
- pip command not found
- pip is not recognized
- 'pip' is not recognized as an internal or external command, operable program or batch file.
- -bash: pip: command not found
- pip is not recognized as an internal or external command
- pip install invalid syntax

### Other

- how to add pip to path
- how to check pip version
- how does pip work
- where does pip install packages
- pip vs pip3
- where is pip installed

</details>
<br/>

The prevalence of "install pip" queries strongly suggests that the current installation documentation should be improved and that users are searching for solutions specific to their operating system.

The "about pip" queries also suggest that beginners would benefit from documentation that better explains pip basics - e.g. what pip is and what it does.

## Recommendations

Based on our research, we recommend that the pip team:

- Revise the structure of the documentation:
  - Break monolithic pages into standalone pages on different subjects, with appropriate meta tags. This will help the docs appear higher in search results for the 81.9% of users who use Google to troubleshoot their pip problems.
  - Prioritise most used features (see "[buy a feature](prioritizing-features)" results for guidance)
- Add a "troubleshooting" section to the documentation that addresses common questions, explains error messages and tells users where they can find more help
- Provide more context about pip's role in the Python packaging ecosystem by:
  - Introducing packaging concepts that users need to understand in order to use pip
  - Explaining pip's role/scope within the packaging ecosystem
  - Comparing pip to other tools
- Develop a beginner's guide that walks new pip users through everything they need to know to use pip's most basic functionality. This should include addressing concepts outside of pip's scope (e.g. how to open and use a terminal, how to set up a virtual environment), that may block users from being successful
- For each page, (where appropriate), add sections for:
  - "tips and tricks" - things to know / gotchas
  - "troubleshooting" - possible error messages and recommended solutions. Where appropriate, this should link to content in the troubleshooting section.
  - "see also" (links to external resources - e.g. useful stack overflow questions, blog articles, etc.)
- In general, write content that:
  - Is opinionated. Prioritize solutions that will work in the majority of cases, while pointing to possible edge cases and workarounds in "tips and tricks", "troubleshooting" and "see also" content
  - Uses keywords to increase search results visibility
  - Provides instructions for different contexts - e.g. for users on Windows, Linux, MacOSX
  - Increases interlinking with external sources, including packaging.python.org

### Suggested site map

Based on the above user input, we have developed a proposed [site map](https://i.imgur.com/UP5q09W.png) (link opens larger format image) to help guide the redevelopment of pip's documentation in line with the above recommendations.



<details><summary> See notes for this site map</summary>

#### Node 1.0: Quick reference

_Page purpose:_

- To give pip users a quick overview of how to install pip, and use pip's main functionality
- To link to other (more detailed) areas of the documentation

_Suggested content:_

- Quick installation guide, including how to use a virtual environment. This is necessary for user who want to install more than one Python project on their machine.
- Common commands / tasks (based on [buy a feature](prioritizing-features) data)

---

#### Node 2.0: About pip

_Page purpose:_

- To introduce pip to new users

_Suggested content:_

- Introduce pip as a command line program
- Explain what the command line is and how to use it in different operating systems
- Explain what pip is/does, and what it stands for
- Link to packaging concepts (node 2.1)
- Explain pip's scope (e.g. to install and uninstall packages) and link to other tools (node 2.2)

#### Node 2.1: Packaging concepts

_Page purpose:_

- To introduce packaging concepts for new pip users

_Suggested content:_

- What is a package?
- What types of packages are there? e.g. file types
- What is package versioning / what are requirement specifiers? (note: talk about potential dependency conflicts here)
- Where do I get packages from?
- How should I control how packages are installed on my system (e.g. virtualenv and environment isolation)
- How can I reproduce an environment / ensure repeatability? (e.g requirements files)
- What do I need to know about security? (e.g. hash checking, PyPI name squatting)
- Link to node 2.2 ("pip vs other packaging tools")

#### Node 2.2: pip vs other packaging tools

_Page purpose:_

- To compare pip to other tools with the same scope
- To highlight that pip exists within a _packaging ecosystem_ and link to other packaging tools

_Suggested content:_

- Compare pip to other installation tools - e.g. poetry, pipenv, conda. What are the features, pros and cons of each? Why do packaging users choose one over the other?
- Briefly introduce other packaging projects. Link to https://packaging.python.org/key_projects/

---

#### Node 3.0: Installing pip

_Page purpose:_

- To help pip users install pip

_Suggested content:_

- Refactor current page, emphasising pathways for different operating systems
- Add "tips and tricks", "troubleshooting" and "see also" (link to external resources) sections to provide additional help

---

#### Node 4.0: Tutorials

_Page purpose:_

- To provide a jumping off place into pip's tutorials

_Suggested content:_

- Link to tutorials, including sub pages, where appropriate

#### Node 4.1: Using pip to install your first package

_Page purpose:_

- To help new pip users get started with pip

_Suggested content:_
Step by step tutorial (possibly broken into several pages) that covers:

- Using the command line
- Installing pip (or checking pip is installed)
- Creating/activating a virtual env (use venv for this, but point to alternatives)
- Installing a package
- Showing where the package has been installed
- Deactivating/reactivating virtualenv
- Uninstalling a package

#### Node 4.2: Advanced tutorial - using pip behind a proxy

_Page purpose:_

- To help advanced pip users achieve specific goals

_Suggested content:_

- Step by step tutorial for using pip behind a proxy

NB: other advanced tutorials should be added as identified by the team and/or requested by the community.

---

#### 5.0: Using pip

_Page purpose:_

- To provide a jumping off point for the user guide and reference guide

_Suggested content:_

- Link to each subject in the user guide
- Link to reference guide

#### 5.1: User guide

_Page purpose:_

- To provide users with specific detailed instructions on pip's key features

_Suggested content:_
Break down current user guide into separate pages, or pages linked by subject. Suggested order:

- Running pip
- Installing Packages
- Uninstalling Packages
- Environment recreation with requirements files
  - sub heading: "pinned version numbers"
  - sub heading: "hash checking mode"
- Listing Packages
- Searching for Packages
- Installing from local packages
- Installing from Wheels
- Wheel bundles
- “Only if needed” Recursive Upgrade
- Configuration
- User Installs
- Command Completion
- Basic Authentication Credentials
- Using a Proxy Server (includes link to tutorial)
- Constraints Files
- Using pip from your program

Where possible, each page should include:

- "tips and tricks" for workarounds, common _gotchas_ and edge use cases
- "troubleshooting" information, linking to content in node 6.2 ("Troubleshooting error messages") where applicable
- "see also", linking to external resources (e.g. stack overflow questions, useful threads on message boards, blogs posts, etc.

Note: the following content should be moved:

- Fixing conflicting dependencies (move to node 6.2 - "Troubleshooting error messages")
- Dependency resolution backtracking (move to node 6.2 - "Troubleshooting error messages")
- Changes to the pip dependency resolver in 20.3 (move to node 7.0 - "News, changelog and roadmap")

#### 5.2: Reference guide

_Page purpose:_

- To document pip's CLI

_Suggested content:_

- https://pip.pypa.io/en/stable/reference/

---

#### 6.0: Help

_Page purpose:_

- To provide a jumping off place for users to find answers to their pip questions

_Suggested content:_

- Links to
  - 6.1 "FAQs"
  - 6.2 "Troubleshooting error messages"
  - 6.3 "Finding more help"

#### 6.1: FAQs

_Page purpose:_

- To answer common pip questions / search terms

_Suggested content:_

- What is the difference between pip and pip3?
- Where does pip install packages?
- How can I check pip's version?
- How can I add pip to my path?
- Where is pip installed?
- What does pip stand for?

See [popular questions on Stack Overflow](https://stackoverflow.com/search?q=pip&s=ec4ee117-277a-4c5d-a3f5-c921ca6c5da6) for more examples.

#### 6.2: Troubleshooting error messages

_Page purpose:_

- To help pip users solve their problem when they experience an error using pip

_Suggested content:_
For each (common) error message:

- Explain what happened
- Explain why it happened
- Explain what the user can do to resolve the problem

Note: the [ResolutionImpossible](https://pip.pypa.io/en/stable/user_guide/#fixing-conflicting-dependencies) and [dependency resolution backtracking](https://pip.pypa.io/en/stable/user_guide/#dependency-resolution-backtracking)
documentation should both be moved here.

#### 6.3: Finding more help

_Page purpose:_

- To point pip users to other resources if they cannot find the information they need within the pip documentation

_Suggested content:_

- See [getting help](https://pip.pypa.io/en/stable/user_guide/#getting-help)

---

#### 7.0: News, changelog and roadmap

_Page purpose:_

- To share information about:
  - Recent changes to pip
  - Upcoming changes to pip
  - Ideas for improving pip, specifically highlighting where funding would be useful

_Suggested content:_

- [Changes to the pip dependency resolver in 20.3 (2020)](https://pip.pypa.io/en/stable/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020)
- Links to PSF blog posts about pip
- Link to [fundable packaging improvements](https://github.com/psf/fundable-packaging-improvements/blob/master/FUNDABLES.md)

---

#### 8.0: Contributing

_Page purpose:_

- To encourage new people to contribute to the pip project
- To demonstrate that the project values different _types_ of contributions, e.g. not just development
- To recognise past and current contributors

_Suggested content:_

- Introduction to pip as an open source project
- Contributors code of conduct
- Recognition of the different types of contributions that are valued
- Credit list of contributors, including pip maintainers

#### 8.1: Development

_Page purpose:_

- To onboard people who want to contribute code to pip

_Suggested content:_

- https://pip.pypa.io/en/stable/development/

#### 8.2: UX design

_Page purpose:_

- To onboard people who want to contribute UX (research or design) to pip
- To share UX knowledge and research results with the pip team

_Suggested content:_

- UX guidelines, and how they apply to the pip project
- Current UX initiatives (e.g. open surveys, interview slots, etc.)
- Previous research and results, including UX artifacts (e.g. personas)

#### 8.3: Documentation

_Page purpose:_

- To onboard people who want to contribute to pip's docs
- To share previous research and recommendations related to pip's docs

_Suggested content:_

- This guide
- Writing styleguide / glossary of terms - see the [Warehouse documentation](https://warehouse.pypa.io/ui-principles/#4-write-clearly-with-consistent-style-and-terminology) for an example.

</details>

### Future research suggestions

To continue to improve pip's documentation, we suggest:

- Conducting [card sorting](https://www.nngroup.com/articles/card-sorting-definition/) with pip users to establish the ideal order and grouping of pages
- Regularly reviewing the documentation analytics, to understand those pages which are most/least visited
- Regularly reviewing Stack Overflow to identify questions for the FAQ
- Setting up a mechanism for collecting user feedback while users are on the documentation site

---

### Html Ux Research Design Research Results Mental Models (`docs/html/ux-research-design/research-results/mental-models.md`)

# How Users Understand pip

## Problem

We want to understand how pip's users understand pip as a tool: what they think it is and what it does.

[Skip to recommendations](#recommendations)

## Research

In order to capture participants mental models of pip and how package management works, we asked participants the following questions:

- In your own words, explain what pip is
- In your own words, explain what happens when pip installs a software package
- In your own words, explain what a Python package dependency is

When we talk about mental models, we talk about "deep" or "shallow" mental models. When a user has a deep mental models of something, their have a deep understanding with a lot of detail, shallow models are the opposite.

In order to evaluate those mental models - do they match the reality of pip and package management - we worked with the maintainers to identify 1. pip's behaviours and activities (18 aspects), and 2. the aspects of package dependencies (13), and what a Python package dependency is (10). We then scored participants' answers against those.

## Results

The analysis focused on participants with between 2 and 10 years of Python experience.

Over 90% of participants did not have a deep understanding of pip - with limited understanding of what pip is, what it does during the install process, and of package management in general.
However, while participants' understanding was low, only 4 participants had factually incorrect understandings of what pip is and does.

Participants had a slightly deeper understanding of what happens during a pip install process. The most in depth answer included 7 of the 13 identified aspects. The median was 3. Answers focused on resolving dependencies, finding possible package names, downloading assets and installing the package.

Participants' understanding of software dependencies was again shallow - the most in depth answer included 8 identified aspects. The median was 3. Answers focused on the fact that software dependencies were a result of code reuse, that constraining package versions reduced the possibility of dependency conflicts.

The full data is available in[ this spreadsheet](https://docs.google.com/spreadsheets/d/1HBiNyehaILxhzZKWcBavkKXDzJr6gIt_Y8Jm8RRgJYg/edit#gid=0).

### Responses to "In your own words, explain what pip is"

> "pip is a standard command-line tool for managing python packages. It has three primary functions: (1) obtaining & caching python packages and/or their dependencies from a repository (typically pypi), (2) building (if needed) and installing python packages--and related dependencies--to a 'site-packages' location in the python path, and (optionally) (3) uninstalling previously-installed packages." **- participant 242608909 (Scientist, Professor in the Earth and Atmospheric Sciences Department, using Python for 7 - 10 years)**

> "Pip is a package management system for python. Kind of like apt in linux, it can be used to install packages in public or private repositories into the current version or environment of Python that invoked the pip command." **- participant 240364032 (Professional software developer using Python for 7-10 years)**

> "pip allows to install/update remove python libraries in your environment. pip manage the library. you will need something else to manage your environment. To use it the easiest is pip install `package-name` I recommend using a requirements.txt and add as you go the library and do pip install -r requirements.txt each time. it avoid to forget a library at the end of the project :)" **- participant 241178995 (Data scientist working in software engineering)**

> "python's npm/cargo/opam... dedicated package manager and ecosystem for python libraries and applications" **- participant 240306262 (self-taught Python creative artist and web developer, using Python for 5-6 years)**

> "A tool to download & install packages and resolve dependencies. I see it in the same area as yum, zypper or apt-get install in the Linux world." **- participant 240306204 (Using Python for scientific research and data analysis for 3 - 4 years)**

> "Pip is the tool primarily used in the Python community to install packages. ("Package" means two different things in Python; it can be a target of the `import` statement that includes modules and other packages, or it can mean a collection of code with a defined interface that can be installed for reuse. I'm referring to the second thing here.) Pip's implementation defines what it means for a package to be installed in a Python environment. Any other tool that wishes to install software into a Python environment (e.g. conda) must match Pip's implementation." **- participant 240313922 (Computer security researcher at a university, using Python for 7-10 years)**

### Responses to "In your own words, explain what happens when pip installs a software package"

> "I think pip looks up package "tea" in the repository of packages (PyPI by default, but can be changed). If it doesn't find it, it gives an error. If it exists, it downloads some information about the package, like what form it exists in. This can be a wheel, or a package that needs to be built. If it is a wheel, it checks the dependencies and installs them, then it installs the wheel (not sure what this means, probably it extracts it). The wheel is specific to a python distribution and base OS, so it might be available on certain platforms but not others. If it is a package that needs to be built, pip downloads the package source (or clones the repository), and runs setup.py, which installs dependencies and other packages, then the package itself. I forgot to mention that before installing there is some check for checking compatibility of the version required and the versions required by other packages." **- participant 240426799 (Scientific researcher - data analysis and computer vision models, using Python for 5-6 years)**

> "pip searches for a package source (and for me uses the default, so Pypi), then ask the package source for a package with the given name and versions (if specified), then if the package is available download the package in the most appropriate format (depending on my platform), then unzip the package and runs the installer (most probably calls setuptools with the included setup.py file) which will perform the required installation steps. This installation process may contain dependencies (typically specified in setup.py), which will trigger the same process for the dependencies, and so on until all dependencies are installed (if everything is OK)." **- participant 240670292 (Software developer industrial systems control, using Python for 5-6 years)**

> "Pip checks PyPI (default package index, assuming that wasn't overridden) for the package matching `tea`. It uses the various specifiers (eg. OS compatibility, Python compatibility, etc) to find the latest version of `tea` compatible with my system. Within that version, it finds the best possible installation match (eg. a `wheel`, if supported on my system and my version of `pip` contains the relevant versioned support [eg. most recently manylinux2010], potentially falling back all the way to a source distribution). After downloading the relevant distribution, it performs the same operations recursively up the dependency chain as specified by the `install_requires` of the `setuptools.setup()` method. After grabbing all relevant packages, it performs the installations as specified in their setup methods -- generally, this involves extracting python files to specific system paths, but various levels of complexity may be added as need be such as compilations, system library bindings, etc. I believe the new resolver changes the above by performing all the lookups simultaneously (eg. by building and solving a dependency graph rather than traversing incrementally) but have not yet read the PEP to learn more. I've answered the above with setuptools in mind -- I believe there was a step added recently to check pyproject.toml first to allow for alternate systems here, but I find the added customization to be a net negative to the ecosystem and have not yet played with it -- the entire Poetry/Pipenv/Pipfile.lock/Flit thing just seems to be adding unnecessary complexity; users who know what they're doing have solved all these issues years ago for their packages and users who find the porcelain makes their lives easier are likely going to run into UX trouble no matter the veneer." **- participant 241463652 (Using Python for 5-6 years)**

> "pip accesses the tea package from pypi (guessing that's where, online at least) and downloads a copy of the files into my local venv" **- participant 243434435 (Data analysis & machine learning, using Python for 1-2 years)**

> "Looking up the latest version of of the package from pypi" **- participant 243897973 (Software testing/writing automated tests using Python 3 - 4 years)**

> "Download, unpack, sometimes compile a module for my target arch" **- participant 243428875 (System administration using Python 7 - 10 years)**

## Recommendations

It's difficult to know what to recommend. Some ideas:

- Question: Is it actually necessary for users to know everything that pip is doing?
- Better documentation:
  - Describing the "blocks of functionality" that pip carries out and how to deal with them when it breaks
  - Curating package manager training and help
  - Improving pip output to expose the different pip functionality blocks

---

### Html Ux Research Design Research Results Override Conflicting Dependencies (`docs/html/ux-research-design/research-results/override-conflicting-dependencies.md`)

# Providing an override to install packages with conflicting dependencies

## Problem

Currently, when a user has dependency conflicts in their project they may be unaware there is a problem, because pip will install conflicting packages without raising an error.

The new pip resolver is more strict and will no longer allow users to install packages that have conflicting dependencies.

As a result, some users may feel that newer versions of pip are "broken" when pip refuses to install conflicting packages.

For this reason, the pip team wanted to know if they should provide an override that allows users to install conflicting packages.

[Skip to recommendations](#recommendations)

## Research

We published a survey with the following introduction:

<blockquote>
Imagine you have packages tea and coffee:

tea 1.0.0 depends on water <1.12.<br>
coffee 1.0.0 depends on water>=1.12<br>

Installing tea 1.0.0 and coffee 1.0.0 will cause a conflict because they each rely on different versions of water - this is known as a "dependency conflict".

The pip team has recently changed the way that pip resolves dependency conflicts. The new implementation is stricter than before: pip will no longer install packages where there is a dependency conflict - instead it will show an error.

The purpose of this survey is to gather feedback on providing a way to override this behaviour.

All questions are optional - please provide as much information as you can.

</blockquote>

We then asked users:

- If pip should provide an override that allows users to install packages when there are dependency conflicts
- Why they answered yes or no
- For users that answered yes, we asked:
  - When they would use the override
  - How often they would use the override
  - How easy it would be to find a workaround, if pip did not provide an override
  - What syntax they prefer

## Results

In total, we received 415 responses to the survey.

An overwhelming majority (>70%) of respondents indicated that they want some kind of override that allows them to install packages when there are dependency conflicts. Despite desiring this feature, most respondents said if it exists they would use it "not often" — this indicates that it is an advanced feature that is not critical to day-to-day usage. Nevertheless, because it would be difficult or very difficult to find a workaround (>60%), we suggest that pip should offer a override feature (see recommendations, below).

Over half of the respondents said that `pip install tea coffee --ignore-conflicts` was the most ideal syntax for this command when installing multiple packages at once with a conflicting dependency. When using the `pip install --ignore-conflicts` command, a majority (>48%) of respondents said they would prefer pip to install to the most recent version of the conflicted dependency.

Most respondents suggested that installing the latest version by default is safer, because it could include security fixes or features that would be difficult to replicate on their own. They also trust that dependencies will be largely backwards-compatible. However, they said it was very important that it is necessary to have a way to override this default behavior, in case they need to use an older version of the conflicted package.

## Recommendations

Based on this research we recommend that the pip team:

- Implement an `--ignore-conflicts` option, that allows users to install packages with conflicting dependencies
- Ensure that `--ignore-conflicts` installs the most recent version of the conflicting package. For example, for conflicting package `water<1.1.2` and `water≥1.1.2`, pip should prefer to install `water≥1.1.2`.
- Allow users to override this default behavior by specifying the version of the conflicting packages. For example, `pip install tea coffee water==1.1.1 --ignore-conflicts`
- Warn users that they used the `--ignore-conflicts` flag and that this may cause unexpected behavior in their program

---

### Html Ux Research Design Research Results Personas (`docs/html/ux-research-design/research-results/personas.md`)

# pip Personas

## Problem

We want to develop personas for pip's user to facilitate faster user-centered decision making for the pip development team.

[Skip to recommendations](#recommendations)

## Research

From early interviews with pip users, and from desk research into the different communities that use Python, it was our expectation that there were large communities who were not professional software developers. For example the SciPy library is widely used in the science and engineering communities for mathematical analysis, signal and image processing.

Based on this, we expected a lot of these users would have different expectations, challenges and needs from pip.

Our hypothesis was that:

1. Python users fall into 3 main user types - a software user, a software maker and a software/package maintainer
2. That the majority (over 60%) would define themselves as Python software users
3. That the minority would define themselves as Python software maintainers

### Usertype definitions

During the research we've met different user types in the Python community. The 3 types of Python users, we proposed were:

#### The Python Software User

"I use Python software mainly as a tool to help me do what I want to do. This might be running scientific experiments, making music or analysing data with Python software I install with pip. I don't write Python software for others."

#### The Python Software Maker

"I use the Python software language and Python software packages to make software for others, mostly for other people. An example might be - building web applications for my customers. To make this web application I might use the Django framework, and a number of Python packages and libraries."

#### The Python Package Maintainer

"I spend a lot of my time creating Python software packages and libraries for other people to use in the software they make. I might make Python packages and libraries and then publish them on pypi.org or other software repositories."

## Results

During our research we found that these user types did fit with participants' sense of their usage of Python. Participants did not identify significantly different Python user types when asked.

Each of these user types is a spectrum. Some Python users after time, and with experience/training, a need to use code more than once, started to make their own Python software.

Identifying as one of these user types does not preclude users from also being another user type. Python users were more likely to Python software makers, but rarely Python software maintainers.

Most (86%) participants identified as being a Python software user. This ranged a) from using Python applications - SciPy, Scikit-Learn - as a tool, with no knowledge, or interest to do more, to b) more advanced usage of Python involving modifying others code/scripts, possibly using libraries to create code specifically for their needs.

75% identified as a Python software maker - as with Python software user, this ranged from writing basic scripts, code, to being a professional software developer.

40% identified as a Python software maintainer - the activities of a maintainer were seen as only available to someone who had many years of Python experience, was heavily involved in a particular package or application, or did it as part of their job.

### I am a Python software user

As expected, almost all participants identified as a Python software user (86%). This was the most fundamental user type - both trained software developers and those who came to Python as a result of their job were users.

Non-software developer users identified Python as a language to get stuff done -

> "Almost everyone falls into the user (category) - that’s the target. It's not an obscure language that's meant for specific domains - it's a broad general purpose language designed to get stuff done. It's used by many who don't know other languages, they just need a language to get what they're doing finished." **- Participant 240312164**

However, "using Python software" meant different things depending on who you ask - participants identified as a Python software user on a spectrum.

<table>
  <thead>
    <tr>
     <th>I am a Python software user</th>
     <th>Number of responses</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>I agree</td>
      <td>50</td>
    </tr>
    <tr>
      <td>I disagree</td>
      <td>4</td>
    </tr>
    <tr>
      <td>I have no opinion</td>
      <td>11</td>
    </tr>
    <tr>
      <td>I strongly agree</td>
      <td>70</td>
    </tr>
    <tr>
      <td>I strongly disagree</td>
      <td>4</td>
    </tr>
    <tr>
      <td><strong>Grand Total</strong></td>
      <td><strong>140</strong></td>
    </tr>
  </tbody>
</table>



#### Low end of the spectrum

Python software applications were identified by some as a tool they use to do their "actual" work - the scientist, the data analyst, the engineer, the journalist.

Here, they were "using" Python applications like SciPy, PsychPi, NumPy, to run scientific experiments, to gather data, to analyse data, with the objective of creating knowledge to make decisions, to identify what to do next.

These were users who 1) who were new to Python software, 2) came across these Python applications in their profession, and used them as tools.

They describe NumPy, or SciPy as a Python software application in itself, analogous to being a Windows user, or a Mac user.

These users are not "classically trained programmers" as one participant identified themselves. As a result, they may not have the training, or knowledge about programming concepts like software dependencies. When they are expected to deal with complex or confusing error messages or instructions they have problems, often stopping them.

#### High-end of the spectrum

Python users who "move up the spectrum" to more advanced Python usage had been using Python for longer periods - many years.

Again they may not have been classically trained developers, but through exposure - from work colleagues and their own usage - they started to experiment. This experimentation was in the form of modifying others scripts, taking classes, reading books so they could use code for other purposes.

This was _making_ software - this software could be used by them as part of their day-job, but it could also be used by many others.

We asked participants to explain the progression on this user spectrum - what is the difference between a user and a maker?

Participants spoke about "are you working on something reusable or are you using the tools to achieve a one time task?"

> "I didn't have classic software development training, more statistical analysis experience. I was clueless to the idea that it was a repository that anyone could upload packages to and become a maintainer." **- Participant \_240396891 (Data scientist at an applied research lab using Python do to network traffic analysis/parsing or Machine Learning)**

> "Firstly I use my own software written in Python, I use Python libraries from pip. I use Django, Flask, libraries like requests." **- Participant 240302171**

> "I am not a classically trained programmer, so it's a great way for me to learn and keep current in techniques. Not being a classically trained programmer, in some cases it detracts, I have a reasonable knowledge of the way to use hashes, but if I wanted to change Python's hash I'd have to read books. I can find information out there." **- Participant 240312164 (Nuclear physicist using Python for computer simulations, designing experimental methods)**

### I am a Python software maker

Being a "Python software maker" was a natural progression for some Python users, particularly those who had software development training - either on the job, personal learning or formal education. This training was important to understand fundamental programming concepts.

As discussed earlier, some participants identified as "advanced" Python users, using Python software to modify or create other software. These users were likely to progress onto being software makers.

55% of participants who identified as a software maker had between 5-20+ years of experience with Python. Only 18% of software makers had less than 2 years of experience.



We did not ask these participants about the "quality" of the software they created, but apart from the professional software developers, the opinion of these users was they were not software developers.

<table>
  <thead>
    <tr>
     <th>I am a Python software user</th>
     <th>Number of responses</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>I agree</td>
      <td>50</td>
    </tr>
    <tr>
      <td>I disagree</td>
      <td>9</td>
    </tr>
    <tr>
      <td>I have no opinion</td>
      <td>14</td>
    </tr>
    <tr>
      <td>I strongly agree</td>
      <td>56</td>
    </tr>
    <tr>
      <td>I strongly disagree</td>
      <td>10</td>
    </tr>
    <tr>
     <td><strong>Grand Total</strong></td>
     <td><strong>140</strong></td>
    </tr>
  </tbody>
</table>

Making software was as defined earlier as "are you working on something reusable or are you using the tools to achieve a one time task?"

> "I'm using Python software and libraries to make this product I'm working on, it's foundation is based on Python, with React, D3 and all built on Python. The cloud assets are Python and testing is Python." **- Participant 240315927 (a professional IT developer building a Python based data analysis application)**

> "I make software in Python. My day job is making software in python. Mainly Django web design. I work for a retail company, where I write calculating orders, creating data in other inventory management systems. Data analysis." **- Participant 240393825**

> "I have written software, sometimes for business and personal reasons. At one point I worked on a django website project, that was being used by 1000s of people. I don't think any of my live projects are based.

> "Most of it is for sysadmin, automation. I [like] to use python instead of shell scripting. I manage a server with wordpress sites. I wrote a script to update these sites, mailman list and sql DB management, and for different utilities." **- Participant 240313542**

> "I use Python for creating things - like outputs for data scientist, software engineer. I make software to look at patterns, and analyse stuff. I think I'm a maker because someone else is using - they are colleagues. Usually its non-technical colleagues. I produce outputs - make data understandable. They use the results, or a package it behind a flask app. Or analyse graphs." **- Participant 240426799**

### I am a Python software maintainer

The Python software/package maintainer user type was seen as requiring a significant amount of time and experience - domain experience as the software could be very specific (e.g. SciKit Learn, SciPy, etc), technical/coding experience, and experience in the community. You need to have spent time in doing the other jobs, before you could become a maintainer.

For large projects it was seen as necessary to have core code contributors, and maintainers. Maintainers did not always write code - they could be more involved with technical architecture, technical design, than writing code.

An aspect of the software maintainer role that wasn’t mentioned a lot was the community management aspect.



<table>
  <thead>
    <tr>
      <th>I am a Python package maintainer</th>
      <th>Number of responses</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>I agree</td>
      <td>39</td>
    </tr>
    <tr>
      <td>I disagree</td>
      <td>24</td>
    </tr>
    <tr>
      <td>I have no opinion</td>
      <td>20</td>
    </tr>
    <tr>
      <td>I strongly agree</td>
      <td>18</td>
    </tr>
    <tr>
      <td>I strongly disagree</td>
      <td>38</td>
    </tr>
    <tr>
     <td><strong>Grand Total</strong></td>
     <td><strong>140</strong></td>
    </tr>
  </tbody>
</table>

> "You can become a maintainer once you get past a certain level of experience." **- Participant 240278297**

> "To be a package maintainer, you'd have to spend a lot of time fixing issues, e.g. your package is on Github and you'd be looking at issues, reviewing PRs, writing documentation. A package maintainer is someone heavily involved in the project. They deal with more support calls, they do more thinking about issues to get your package into multiple environments. That's the good thing about the Python community - I was trying to use a Python package but there was an issue with the documentation. I said, there's a better way of doing this example. They answered and said "great, do you want to do it? Doing package maintaining, it doesn't interest me, I don't have time for it really - if I have a specific issue I will focus on it. It'd be nice (to do more)." **- Participant 240278297 (professional Python software developer)**

> "I am a core developer of scikit-learn, I spend time writing code. These days strictly speaking - writing code is the least thing I do - mostly I do reviews of other people's code. There is a lot of API design work, it can translate into writing code. I may be the one writing the code or not. I am involved with the CI every now and then. [...] I have been the release manager for the last 2 releases. There are different types of maintainer - writing code maintainers, but you do need core devs writing code. But being a maintainer and building a community -that is about communication and PRs, and mentoring people." **- Participant 240306385 (core maintainer of SciKit-Learn)**

## Recommendations

### Provide documentation recommending "best/recommended ways"

The majority of participants were using Python as a tool, as a participant said: "it's a broad general purpose language designed to get stuff done."

The majority of participants - scientists, product/electronic engineers, data analysts, nuclear physicists - used Python for their work - they may write Python software, for themselves, possibly for colleagues. A smaller number are maintainers of widely used Python packages.

As a result they are not classically trained software developers and so may not have "the right" understanding of important software programming concepts.

Users of all types, and experience struggled with knowing the "right" way to do something. They often spoke about the "recommended way" to do something - to start a new project, to make a package:

> "As a new comer, it's not easy to figure out what should be in the right way to structure a _setup.py_ or _pyproject.toml_. There is a good guide, but it's not easy to figure out what to use. I wish there was a guide like 'Make an application (or library) in 30 minutes'."

---

### Html Ux Research Design Research Results Pip Force Reinstall (`docs/html/ux-research-design/research-results/pip-force-reinstall.md`)

# pip --force-reinstall

## Problem

Currently, when `pip install [package-name] --force-reinstall` is executed, instead of reinstalling the package at the version previously installed, pip installs the package at the newest version available.

i.e. `pip install [package name] --force-reinstall` acts as `pip [package name] --upgrade`

We want to find out if users understand (or desire) this implicit behaviour.

More information can be found on [this GitHub issue](https://github.com/pypa/pip/issues/8238).

[Skip to recommendations](#recommendations)

## Research

To help us understand what users want from the `--force-reinstall` option, we launched a survey with the following scenario:

<blockquote>
You have the requests package and its dependencies installed:

requests==2.22.0<br>
asgiref==3.2.10<br>
certifi==2020.6.20<br>
chardet==3.0.4<br>
Django==3.1<br>
idna==2.8<br>
pytz==2020.1<br>
sqlparse==0.3.1<br>
urllib3==1.25.10<br>

You run 'pip install requests --force-reinstall'. What should happen?

</blockquote>

Respondents could choose from one of the following options:

- pip reinstalls the same version of requests. pip does not reinstall request's dependencies.
- pip reinstalls requests and its dependencies, updating all these packages to the latest compatible versions
- pip reinstalls requests and its dependencies, keeping every package on the same version
- pip reinstalls requests, updating it to the latest version. pip updates request's dependencies where necessary to support the newer version.
- I don't know what pip should do
- I don't understand the question
- Other (allows respondent to provide their own answer)

We also asked how useful `pip --force-reinstall` is, and how often it is used.

## Results

In total we received 190 responses to our survey, with 186 people telling us what pip should do when the `--force-reinstall` option is executed.



- **31.7%** (59/186) of respondents said that pip should reinstall requests and its dependencies, keeping every package on the same version
- **28%** (52/186) of respondents said that pip should reinstall requests, updating it to the latest version, with pip updating request's dependencies where necessary to support the newer version.
- **15.6%** (29/186) of respondents said that pip should reinstall requests and its dependencies, updating all these packages to the latest compatible versions
- **14%** (26/186) of respondents said that pip should reinstall the same version of requests, and not reinstall request's dependencies

If we group responses into "upgrade" or "do not upgrade" (ignoring responses that could not be grouped), we find:

- 46.32% (88/186) of respondents thought that pip should install the same version of requests - i.e. that `--force-reinstall` should _not_ implicitly upgrade
- 43.16% (82/186) of respondents thought that pip should upgrade requests to the latest version - i.e that `--force-reinstall` _should_ implicitly upgrade

Most respondents use `--force-reinstall` "almost never" (65.6%):




Amongst respondents who said they use `--force-reinstall` often or very often:

- 54.54% (6/11) of respondents thought that pip should install the same version of requests - i.e. that `--force-reinstall` should _not_ implicitly upgrade
- 45.45% (5/11) of respondents thought that pip should upgrade requests to the latest version - i.e that `--force-reinstall` _should_ implicitly upgrade

Respondents find `--force-reinstall` less useful than useful:




Amongst respondents who said they find `--force-reinstall` useful or very useful:

- 38.46% (20/52) of respondents thought that pip should install the same version of requests - i.e. that `--force-reinstall` should _not_ implicitly upgrade
- 50% (26/52) of respondents thought that pip should upgrade requests to the latest version - i.e that `--force-reinstall` _should_ implicitly upgrade

## Recommendations

Given that this option is not regularly used and not strongly rated as useful, we recommend that the development team consider removing `--force-reinstall` _should they wish to reduce maintenance overhead_.

In this case, we recommend showing the following message when a user tries to use `--force-reinstall`:

> Error: the pip install --force-reinstall option no longer exists. Use pip uninstall then pip install to replace up-to-date packages, or pip install --upgrade to update your packages to the latest available versions.

Should the pip development team wish to keep `--force-reinstall`, we recommend maintaining the current (implicit upgrade) behaviour, as pip's users have not expressed a clear preference for a different behaviour.

In this case, we recommend upgrading the [help text](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-force-reinstall) to be more explicit:

Old help text:

> Reinstall all packages even if they are already up-to-date.

New help text:

> Reinstall package(s), and their dependencies, even if they are already up-to-date. Where package(s) are not up-to-date, upgrade these to the latest version (unless version specifiers are used).

---

### Html Ux Research Design Research Results Pip Search (`docs/html/ux-research-design/research-results/pip-search.md`)

# pip search

## Problem

By default, `pip search` searches packages on PyPI.org from the command line. However, the team are [considering removing it](https://github.com/pypa/pip/issues/5216), because they think it's not that useful and using too many resources on PyPI ([PyPI XMLRPC search has been disabled](https://status.python.org/incidents/grk0k7sz6zkp) because of abuse/overuse).

[Skip to recommendations](#recommendations)

## Research

Prior to PyPI XMLRPC search being disabled, we:

- Gathered feedback on pip search via the "buy a feature" survey
- Published a survey specifically about pip search, asking users about:
  - Their current use of pip search
  - How useful they find pip search results
  - How clear they find pip search results
  - Where users expect pip to search (e.g. PyPI vs private index)
  - What data pip should search _other_ than project name
  - What changes or additions they would make to pip search

## Results

In total, we received 1070 responses to the buy a feature survey, with 541 (50.4%) respondents selecting "Search pypi.org for packages" in their top 10 features.

However, search ranked lower than the following features:

1. Run pip without requiring any user input (e.g. in CI) _718_
2. Show information about all installed packages _707_
3. Show information about a single installed package _596_

We received 302 responses to the pip search survey, with 62 of the 302 (20.5%) respondents either not knowing that the command existed, never using it, or using it "rarely".

We found that the remaining ~80% of respondents who do use pip search use it to:

- Find/search for the right/new/alternate packages to install:
  - Checking package name (verify correct spelling)
  - Assessing functionality (check a package's description)
  - Verifying availability (check if such package exists)
- Search for the latest version of a package (verify version)
- Find package libraries and new modules

In general, pip search is regarded as:

- more useful than not useful
- more clear than not clear

When asked if pip should search on items _other_ than the package name, respondents most commonly asked to search the package description:



Some users also mentioned that they would like the search to be configurable, e.g. by passing flags/options.

When asked how they would improve pip search, users said they would improve:

**1. Search methods:**

- fuzzy search and insensitive case should be acceptable
- users should have the option to filter/sort by description, name, tag

**2. Search results:**

- relevancy: the results should show both the exact match and closest match
- order/category: the result should display items in a certain order, e.g highest number of downloads (popularity), development status (last updated/latest version), etc.
- there should be a limited number of search results

**3. User interface:**

- link package to pypi page
- use color coding / system for better clarity
- distinguish exact match search results from others: by highlighting, or using a different color
- indicate version compatibility

## Recommendations

### Deprecation strategy

Given that the [PyPI](https://pypi.org/pypi) search API is currently disabled (as of 1st Jan, 2021) for technical and sustainability reasons, we recommend that the pip team display a clear error message to users who use the command:

```
The PyPI search API has been disabled due to unmanageable load.
To search PyPI, open your browser to search for packages at https://pypi.org
Alternatively, you can search a different index using the --index command.
```

In the longer term, **we recommend that the PyPI team investigate alternative methods of serving search results (e.g. via caching)** that would enable pip search to work again. This recommendation is supported by our research which suggests that many pip users find this functionality useful.

If this is not possible, the pip team should create clear instructions that tells users what to use instead. Some suggestions (based on common user flows) are listed below:

#### Finding a new package based on tags and keywords

This is the most common feature that you would expect from `pip search` and likely the hardest to replace after deprecation.

As mentioned above, the pip CLI should - as soon as possible - hide the full-trace error message present when a user types `pip search`. Instead, pip should show a message that encourages users to use the search index on the website itself (in their browser) by providing a link directly to [https://pypi.org](https://pypi.org). Also, pip should provide a short hint on how to use an alternative index.

```
$ pip search pytest

The PyPI search API has been disabled due to unmanageable load.

Please open your browser to search for packages at https://pypi.org

Alternatively, you can use a different index using the --index command.

   pip search pytest --index <URL>
```

In addition, the pip team could implement an alternative to the PyPI search API that works without a hard dependency on a centralized service. Similar to other distribution systems like `apt` and `yum`, the metadata of all package names could be downloaded on the user's machine with an opt-in workflow:

```
$ pip search pytest
Using pip search on the command line requires you to download the index first.
Alternatively, you can open your browser to search for packages at https://pypi.org

Download the index to /System/Library/Frameworks/Python.framework/
Versions/2.7/Resources/Python.app/Contents/MacOS/search.db? (y/n) y
......... done!

<results>

$ pip search pytest
<results>
```

This is a more complex route that will require more engineering time, but can aim to provide command line users with a similar functionality to the old `pip search` command. It can also check the age of the local index and show a warning if it is getting old.

#### Verifying the latest version of a package

Users also use the `pip search` command to find or verify a particular package's version.

As a replacement, the pip team could do either of the following:

1. Extend the `pip show` feature to include known latest versions of the package;
2. Create a `pip outdated` command which scans the current dependency tree and outputs the packages that are outdated (compared to the latest versions on the configured index).

### UX improvements

Should it be possible to continue to support pip search, we strongly recommend the following UX improvements:

- Adding support for [fuzzy search](https://en.wikipedia.org/wiki/Approximate_string_matching), or suggesting alternative/related search terms
- Adding support for case insensitive search
- Searching based on a package's description
- Linking search results to a package's PyPI page (where appropriate)

Other user feedback (as detailed above) should also be considered by the team on a case-by-case basis.

---

### Html Ux Research Design Research Results Pip Upgrade Conflict (`docs/html/ux-research-design/research-results/pip-upgrade-conflict.md`)

# pip Upgrade Conflict

## Problem

Currently, pip does _not_ take into account packages that are already installed when a user asks pip to upgrade a package. This can cause dependency conflicts for pip's users.

[Skip to recommendations](#recommendations)

## Research

We published a [survey](https://bit.ly/2ZqJijr) asking users how they would solve the following scenario:

<blockquote>
Imagine you have package tea and coffee with the following dependencies:

tea 1.0.0 - depends on water<1.12<br>
tea 2.0.0 - depends on water>=1.12<br>
coffee 1.0.0 - depends on water<1.12<br>
coffee 2.0.0 - depends on water>=1.12<br>

You have the following packages installed:

tea 1.0.0<br>
coffee 1.0.0<br>
water 1.11.0<br>

You ask pip to upgrade tea. What should pip do?

If pip upgrades tea to 2.0.0, water needs to be upgraded as well, creating a conflict with coffee...

</blockquote>

We gave users four choices:

1. Upgrade tea and water. Show a warning explaining that coffee now has unsatisfied requirements.
2. Upgrade coffee automatically to 2.0.0
3. Install nothing. Tell the user that everything is up-to-date (since the version of tea they have installed is the latest version without conflicts).
4. Install nothing. Show an error explaining that the upgrade would cause incompatibilities.

We allowed users to post their own solution, and asked why they came to their decision.

## Results

In total, we received 693 responses, 407 of which included an explanation of why a particular solution was best.



- 497 responses (71.7%) preferred option 4: that pip should install nothing and raise an error message
- 102 responses (14.7%) preferred option 2: that pip should upgrade package_coffee
- 79 responses (11.4%) preferred option 1: that pip should upgrade tea and water
- 15 responses (2.2%) preferred option 3: that pip should install nothing and tell the user that everything is up to date

From the 407 responses that answered "why" a particular solution was best, the following key themes emerged:

- "explicit is better than implicit" - pip should not create "side effects" that the user does not understand, has not anticipated, and has not consented to
- pip should do everything in its power to avoid introducing conflicts (pip should not "break" the development environment)
- Telling the user that everything is up to date (option 3) is misleading / dishonest
- pip could be more flexible by:
  - allowing the user to choose how they want to resolve the situation
  - allowing the user to override the default behaviour (using flags)

## Recommendations

Based on the results of this research, the pip UX team has made the following recommendations to the development team:

- While the current behaviour exists, [warn the user when conflicts are introduced](https://github.com/pypa/pip/issues/7744#issuecomment-717573440)
- [Change the current behaviour](https://github.com/pypa/pip/issues/9094), so that pip takes into account packages that are already installed when upgrading other packages. Show the user a warning when pip anticipates a dependency conflict (as per option 4)
- Explore [the possibility of adding additional flags to the upgrade command](https://github.com/pypa/pip/issues/9095), to give users more control

---

### Html Ux Research Design Research Results Prioritizing Features (`docs/html/ux-research-design/research-results/prioritizing-features.md`)

# Prioritizing pip Features

## Problem

The pip development team is small, and has limited time and energy to work on issues reported via the [issue tracker](https://github.com/pypa/pip/issues). There is also a significant backlog of issues (782 as of November, 2020) for the team to respond to.
For the team to prioritize their work based on what will have the most impact, we need to develop a better understanding of what users want from pip.

[Skip to recommendations](#recommendations)

## Research

To help answer this question, we developed a "buy a feature" survey, with the following scenario:

<blockquote>
Help us to understand what's important to you by participating in our "buy a feature" game:

You have an allocated budget of $200 to spend on redesigning pip.

With your $200 budget, "buy" the functionality you'd most like to keep.

You don't have to spend the whole $200, but you should also not overspend your budget!

</blockquote>

We asked users to spend their first $100 on features related to `pip install`, and to spend their remaining $100 on other pip features. We also gave users an additional $10 to suggest a new feature:







## Results

We received 1076 responses, 1070 of which were valid. The most popular features included the core competencies of pip:

- Recreating an environment from a list of installed dependencies;
- Install, uninstall, and upgrade packages from a virtual control system, file, or local directory;
- Warn about broken or conflicting dependencies.

### pip install

The top ten features related to pip install were:



1. Install and uninstall packages
2. Upgrade packages to the latest version
3. Warn about broken dependencies
4. Install a package from a version control system (e.g. Git, Mercurial, etc.)
5. Install packages as specified in a file
6. Install a package from a local directory
7. Verify downloaded packages against hashes
8. Install packages from an alternative package index, or indexes (default is PyPI only)
9. Install a package from wheels (no need for compiling code)
10. Control where you want your installed package to live on your computer

### Other pip functionality

The top ten features related to other pip functionality were:



1. Generate a list of installed packages that can be used to recreate the environment
2. Check that your installed packages do not have dependency conflicts
3. Run pip without requiring any user input (e.g. in CI)
4. Show information about all installed packages
5. Show information about a single installed package
6. Search pypi.org for packages
7. Show information about pip (version information, help information, etc.)
8. Download packages, build wheels and keep them in a directory for offline use
9. Manage pip's default configuration (e.g. by using configuration files)
10. Customise pip's output (e.g. reduce or increase verbosity, suppress colors, send output to a log)

Results varied by the amount of Python experience the user had.

<details>
<summary>See how likely users are to select a feature based on their experience level</summary>

#### Verify downloaded packages against hashes



#### Warn about broken dependencies



#### Upgrade packages to the latest version



#### Install packages from an alternative package index, or indexes



#### Install packages as specified in a file



#### Install and uninstall packages



#### Install packages from a version control system



#### Install a package from wheels



#### Install a package from a local directory



#### Control where you want your installed package to live on your computer



</details>

## Recommendations

### Environment recreation

Environment recreation is already included in pip as part of the `requirements.txt` feature; however, with it's popularity and demand, we recommend that **pip should improve it's support of this feature.**

- Improve environment recreation user output and help guides directly in the pip CLI;
- Improve pip documentation & user guide to prominently feature environment recreation as a core feature of pip;
- Improve environment recreation process itself by considering virtual environments as a core competency "built-in" to pip.

**Recreating an environment from a list of installed dependencies was the most valued feature request overall** as well as in each user group, _except for those with less than 6 months of experience and those with 16-19 years of experience (for which it was the second most valued)._

When asked to enter a feature request with freetext, users placed the words 'built-in,' 'virtual,' 'automatic,' and 'isolation' alongside the word 'environment,' which suggest that users expect pip to recreate environments with a high level of intelligence and usability.

**Selected direct quotes**

> Make pip warn you when you are not in virtualenv

> Automatic virtual env creation with a command line argument

> Eliminate virtual environments. Just use ./python_modules/ like everyone else

> I would love to see pip manage the python version and virtual env similar to the minicona

> Would spend all my $200 on this: Integrate pipenv or venv into pip so installing an application doesn't install it's dependencies in the system package store. And allow pinning dependency versions for application packages (like how pip-compile does it)

### Dependency management

We recommend that the pip team improve warning and error messages related to dependencies (e.g., conflicts) with practical hints for resolution. This can be rolled out in multiple timescales, including:

- Give hints to the user on how to resolve this issue directly alongside the error message;
- Prominently include virtual environment creation in the documentation, upon `pip install` conflict errors, and if possible as a built-in feature of pip;
- Upgrading the dependency resolver (in progress).

It is clear that dependency management, including warning about conflicting packages and upgrades, is important for pip users. By helping users better manage their dependencies through virtual environments, pip can reduce the overall warnings and conflict messages that users encounter.

---

### Html Ux Research Design Research Results Users And Security (`docs/html/ux-research-design/research-results/users-and-security.md`)

# How pip users think about security

## Problem

We wanted to understand how pip users think about security when installing packages with pip.

[Skip to recommendations](#recommendations)

## Research

We asked participants about their behaviours and practices in terms of the security and integrity of the Python packages they install with pip, and of the software they create.

We asked participants to tell us how often they:

1. Carry out a code audit of the Python software they install with pip
2. Think about the security and integrity of the (Python) software they install (with pip)
3. Think about the security and integrity of the (Python) code they create

## Results

While the security and integrity of the software users install (51%) and make (71%) is important to research participants, less than 7% do code audits of the packages or code they install with pip.

This is due to lack of time to audit large packages, lack of expertise, reliance on widely adopted Python packages, the expectation that pip automatically checks hashes, and reliance of the wider Python community to act as canary in the coalmine.

This behaviour was common across all user types, and baselines of software development experience.

These results - particularly the lack of expertise in auditing packages fits in with the overall findings that the majority of pip users are not "classically trained" (i.e. having formally learned software development) software developers and so lack the expertise and/or formal training in software development practices.

There is a gulf between what the maintainers expect users to think, and worry about, and what the users actually worry and think about. Right now, pip leaves users to "fend for themselves" in terms of providing them with assurance of the software they install. This isn't meant as a criticism, but an observation.

### Responses to question: before I install any Python software with pip, I carry out a code audit

The vast majority of participants, 82%, do not (rarely or never) do a code audit of the software packages they install using pip, the reasons are explained below.

| Before I install any Python software with pip, I carry out a code audit: | Number of responses |
| ------------------------------------------------------------------------ | ------------------- |
| Always                                                                   | 3                   |
| Frequently                                                               | 9                   |
| Rarely                                                                   | 66                  |
| Never                                                                    | 68                  |
| I'm not sure what this means                                             | 5                   |
| No opinion                                                               | 13                  |
| **Total number of participants**                                         | **164**             |

### Responses to question: I think about the security and integrity of the software I install



The vast majority of participants did think about the security and integrity of the software they installed - and unlike responses about code audits, in some cases participants made attempts to verify the security and integrity of the software they installed.

Most attempts were made by those who had experience in software development, however in some cases, people gave up.

Those who were not classically trained software developers did not know where to start.

Both of these groups identified their "sphere of influence" and did their best to cover this.

### User thoughts about security

Selected quotes from research participants

#### Responsibility as author

Participants who spent a lot of their time writing Python code - either for community or as part of their job - expressed a responsibility to their users for the code they wrote - people who wrote code which was made public expressed a stronger responsibility.

They thought about where the software would be used, who would use it, and possible attack surfaces.

> "On the basic point, I have to think about attack surfaces. If I am writing the thing (software), I have to give a crap. I have to answer the emails! In the code I push to[ pypi.org](http://pypi.org/) I think about it doubley. What could people do with this code? Whether I do a good job, that's different! I am aware of it when publishing it or making it [publicly] available. Whether I do a good job, that's different! I am aware of it when publishing it or making it [publicly] available. I rely on community resources - Python security related, I follow security people blogs, Twitter. I use Hypothesis for fuzz-testing. I also rely on having security policies in place and a reporting mechanism. I steer clear of crypto, I rely on other peoples. There's a certain amount of knowledge in the Python community, I am actively involved in it. If something happens, I will hear about it. I use Twitter, if something happens, in the morning it can take me awhile to figure out what's happened. I have a lot of trust in the ecosystem to be self healing. As long as you don't stray too far-off the reservation (into using odd or uncommon or new packages), it's a better sense of security." **- Participant (data scientist turned Python developer)**

> Yes, because I'm liable for that. If the problem is my code, and I deliver something and they get attacked. I'm screwed. **- Participant (professional Python developer and trainer)**

#### Reliance on software packages

Participants also explained they rely on code security scanning and checking software packages.

> "I use linters (Bandit), I scan the code I have created and when there is an issue I raise a red flag."

> "I use Hypothesis for fuzz-testing."

#### Reliance on good software development practices

A small number of participants explained they have good software practices in place, which help with writing secure software.

> "We have a book about ethics of code - we have mandatory certification."

> "I also rely on having security policies in place and a reporting mechanism. I steer clear of crypto, I rely on other peoples."

Of the users who have used pip's hash checking functionality:

- One finds the error messages "too annoying and loud", and has difficulty matching the file name to the hash
- Another finds the process of explicitly pinning hashes to be too tiresome (especially for dependencies)

One user mentioned that he likes [NPM audit](https://docs.npmjs.com/cli/v6/commands/npm-audit) and would like to see something similar in the Python ecosystem.

#### Lack of time

The lack of time to carry out the audit of the package code, and that of the dependencies, was cited as a very common reason. In most cases participants used Python code as a means to achieving their goal.

#### Lack of expertise to carry out the audit

The lack of expertise or knowledge of auditing software was mainly due to participants expertise not being software development. However, in the case participants were "classically" software developers, lack of expertise was also a commonly given reason for not carrying out audits.

#### Use of only widely used, well-established packages

Use of well-established, high-quality packages was a common reason amongst all types of participants - professional Python software developers and those who used Python as a tool.

"Well-established, high-quality packages" were defined by users as packages that:

- have been in existence for many years
- are popular, or commonly used by those in their community or industry
- have responsive maintainers
- maintained by people the participant has heard of
- have many hundreds or thousands of users
- are in active development (many open issues, many forks, Github stars)
- are developed in the open, and transparently
- their history is known, or can be found out publicly

#### Reliance on the Python community to find issues

There was a reliance on the community to find issues and make them know publicly - "Many eyes shallow bugs".

> "I rarely do code audits. Most of the time I rely on the opinions of the community. I look at how many maintainers there are. Maybe it's not good practice but I don't have time to go through the code." **- Participant 240315091**

#### Use of only internal packages

> "I only install internal packages, so I don't need to worry about this."

This theme was not that common, mainly in large software development environments or where security was of high importance.

#### Expectation that pip audits packages

Some users expect/assume that pip (and PyPI) should "protect" them from malicious actors - e.g. by automatically checking hashes, or detecting malicious packages.

> "If I was downloading a package on my own I check the hash, if it's installed by pip, then no. I expect pip to do it. If it doesn't do it, it does surprise me. Every package manager checks the hash against what it downloads. The hashes are already known on pypi." **- Participant 240312164 (Nuclear physicist)**

#### Other notable comments

> "Never. I should but I never do [audit code]. I don't stray, I am risk adverse. I install packages that are good already. I consider my risk surface small. I don't have time or resources to audit them. I have sufficient faith in the ecosystem to be self-auditing. If something turned up in a well known package, the community is well known for making a stink. And anyway a code audit wouldn't pick it up." **- Participant 240326752 (professional Python developer)**

> "On the private level (work) the code is developed internally. I don't audit the code on pypi - due to lack of time auditing the dependencies, and I trust it. I know they had a security breach a few years ago, but it doesn't happen that often. I know they don't audit anything but I still don't audit the code."

> "I wouldn't know how to [audit code], also I'm writing this stuff for myself. It'll work or not. Sometimes I end up installing 2 or 3 packages and find out that I need to install something else. I move on if it doesn't work. The last resort is I will write the code myself."

> "I'm quite trusting - Python is open source, I'm assuming that if a package is on[ pypi.org](http://pypi.org/) - it must be alright. I install the package first, then I look at it. I find a package by figuring out - we need to do a certain task, we search for it on the Internet, look at the documentation, we install it and then see if it is what we want" **- Participant 240278297**

> "If I want to install a package, it's for a reason. I want to calculate the azimuth and elevation of the moon with PyEphem. Do a code audit? Pffff. Most of the stuff I do is banal. It needs to meet a dependency, so I install it. I'm not going to do a code audit. I don't care. Never, but this is one of the things - is the package on pypi the exact source I see on Github? You could end up with files that are distributed differently. Probably (I don't do it) because I am too scared to look. There is this thing that pip verifies (the packages) hash - so that is a feature to guard against this. What is the hash of? No idea. It's located in the local python install." **- Participant 240426799 (systems administrator)**

> "No [I don't audit code]. [laughs] Coz, I'm not going to read thousands of lines of code before I install a package. Oh my God. [..] I wouldn't be able to find it. I'm trading off - honestly how popular the package is, number of stars on GH. pypi doesn't have any UI way to tell me how many downloads it has. If it did I would use that." **- Participant 240386315 (IT administrator)**

> "Well, I don't have the background to do a code audit of something like Numerical Python. Most packages I use are huge. Most people aren't doing code of those packages, except the maintainer. I am relying on whatever is built into pip to do package security. I also assume if there is an exploit someone will find it and let the world now. I'm really lazy." **- Participant 240312164 (Nuclear physicist)**

> "I would like some security advisor, [like in npm](https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities) - it works very well, when you install a package "there are security vulns. with this package - 1 low, 5 medium, 8 high. I haven't come across security issues with Python packages." **- CZI convening research participant**

## Recommendations

### Provide package security guidance or auditing mechanism

A small number of participants (3-4) over the research period mentioned the[ NPM audit command](https://docs.npmjs.com/auditing-package-dependencies-for-security-vulnerabilities) as an example of a good way to assess package security. It may provide a model for how to approach this user need.

### Automatically check package hashes

pip should **by default** check packages hashes during install, providing a way for users to turn this behaviour off.

In the case of no hash being available, pip should warn users and provide recommendations for users - from simplest to most advanced.

### Mechanism to report suspicious packages

Users should have a mechanism to report suspicious, or malicious, packages/behaviour. Where this mechanism should exist is open to discussion. The minimum should be a mechanism for users to flag packages on pypi.org.

### Improve the output of pips activities easier to understand

Right now pip's output is overwhelming and while it contains a lot of information, little of it is perceivable to the user - meaning is lost in "the wall of text".

Pip's output must be redesigned to provide users with the right information - including security warnings - at the right time.

---

--- METRICS ---
- Files Extracted: 108
- Estimated Token Budget: ~115298 tokens
- Canonical Reference: https://codewiki.google/github.com/pypa/pip
