diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0afa776e702..0521f261f7b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,6 @@ repos: - id: black exclude: | (?x) - ^docs/| ^src/pip/_internal/commands| ^src/pip/_internal/index| ^src/pip/_internal/models| diff --git a/MANIFEST.in b/MANIFEST.in index 24d4553785b..9148af0b652 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -22,7 +22,7 @@ exclude noxfile.py recursive-include src/pip/_vendor *.pem recursive-include src/pip/_vendor py.typed -recursive-include docs *.css *.rst *.py +recursive-include docs *.css *.py *.rst *.md exclude src/pip/_vendor/six exclude src/pip/_vendor/six/moves diff --git a/docs/docs_feedback_sphinxext.py b/docs/docs_feedback_sphinxext.py deleted file mode 100644 index d0ff1f03da1..00000000000 --- a/docs/docs_feedback_sphinxext.py +++ /dev/null @@ -1,160 +0,0 @@ -"""A sphinx extension for collecting per doc feedback.""" - -from __future__ import annotations - -from itertools import chain -from typing import Dict, List, Union - -from sphinx.application import Sphinx - -DEFAULT_DOC_LINES_THRESHOLD = 250 -RST_INDENT = 4 -EMAIL_INDENT = 6 - - -def _modify_rst_document_source_on_read( - app: Sphinx, - docname: str, - source: List[str], -) -> None: - """Add info block to top and bottom of each document source. - - This function modifies RST source in-place by adding an admonition - block at the top and the bottom of each document right after it's - been read from disk preserving :orphan: at top, if present. - """ - admonition_type = app.config.docs_feedback_admonition_type - big_doc_lines = app.config.docs_feedback_big_doc_lines - escaped_email = app.config.docs_feedback_email.replace(' ', r'\ ') - excluded_documents = set(app.config.docs_feedback_excluded_documents) - questions_list = app.config.docs_feedback_questions_list - - valid_admonitions = { - 'attention', 'caution', 'danger', 'error', 'hint', - 'important', 'note', 'tip', 'warning', 'admonition', - } - - if admonition_type not in valid_admonitions: - raise ValueError( - 'Expected `docs_feedback_admonition_type` to be one of ' - f'{valid_admonitions} but got {admonition_type}.' - ) - - if not questions_list: - raise ValueError( - 'Expected `docs_feedback_questions_list` to list questions ' - 'but got none.' - ) - - if docname in excluded_documents: - # NOTE: Completely ignore any document - # NOTE: listed in 'docs_feedback_excluded_documents'. - return - - is_doc_big = source[0].count('\n') >= big_doc_lines - - questions_list_rst = '\n'.join( - f'{" " * RST_INDENT}{number!s}. {question}' - for number, question in enumerate(questions_list, 1) - ) - questions_list_urlencoded = ( - '\n'.join( - f'\n{" " * RST_INDENT}{number!s}. {question} ' - for number, question in enumerate( - chain( - (f'Document: {docname}. Page URL: https://', ), - questions_list, - ), - ) - ). - rstrip('\r\n\t '). - replace('\r', '%0D'). - replace('\n', '%0A'). - replace(' ', '%20') - ) - - admonition_msg = rf""" - **Did this article help?** - - We are currently doing research to improve pip's documentation - and would love your feedback. - Please `email us`_ and let us know{{let_us_know_ending}} - -{{questions_list_rst}} - - .. _email us: - mailto:{escaped_email}\ - ?subject=[Doc:\ {docname}]\ Pip\ docs\ feedback\ \ - (URL\:\ https\://)\ - &body={questions_list_urlencoded} - """ - let_us_know_ending = ':' - - info_block_bottom = ( - f'.. {admonition_type}::\n\t\t{admonition_msg.format_map(locals())}\n' - ) - - questions_list_rst = '' - let_us_know_ending = ( - ' why you came to this page and what on it helped ' - 'you and what did not. ' - '(:issue:`Read more about this research <8517>`)' - ) - info_block_top = '' if is_doc_big else ( - f'.. {admonition_type}::\n\t\t{admonition_msg.format_map(locals())}\n' - ) - - orphan_mark = ':orphan:' - is_orphan = orphan_mark in source[0] - if is_orphan: - source[0] = source[0].replace(orphan_mark, '') - else: - orphan_mark = '' - - source[0] = '\n\n'.join(( - orphan_mark, info_block_top, source[0], info_block_bottom, - )) - - -def setup(app: Sphinx) -> Dict[str, Union[bool, str]]: - """Initialize the Sphinx extension. - - This function adds a callback for modifying the document sources - in-place on read. - - It also declares the extension settings changable via :file:`conf.py`. - """ - rebuild_trigger = 'html' # rebuild full html on settings change - app.add_config_value( - 'docs_feedback_admonition_type', - default='important', - rebuild=rebuild_trigger, - ) - app.add_config_value( - 'docs_feedback_big_doc_lines', - default=DEFAULT_DOC_LINES_THRESHOLD, - rebuild=rebuild_trigger, - ) - app.add_config_value( - 'docs_feedback_email', - default='Docs UX Team ', - rebuild=rebuild_trigger, - ) - app.add_config_value( - 'docs_feedback_excluded_documents', - default=set(), - rebuild=rebuild_trigger, - ) - app.add_config_value( - 'docs_feedback_questions_list', - default=(), - rebuild=rebuild_trigger, - ) - - app.connect('source-read', _modify_rst_document_source_on_read) - - return { - 'parallel_read_safe': True, - 'parallel_write_safe': True, - 'version': 'builtin', - } diff --git a/docs/html/architecture/configuration.md b/docs/html/architecture/configuration.md new file mode 100644 index 00000000000..42db2dc4694 --- /dev/null +++ b/docs/html/architecture/configuration.md @@ -0,0 +1,134 @@ +# Configuration File Handling + +Last updated: 21 Feb 2021 + +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. + +## 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` 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 ` 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 ` section. + +For this use case, the `Configuration.load_only` attribute would be `None`, +and the methods used would be: + +```{eval-rst} +.. py:class:: Configuration + :noindex: + + .. 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 + `. +``` + +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 +* `pip config get`, for printing the entire configuration when no + {ref}`kind ` 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 ` of the configuration file to be +manipulated. In addition to the methods discussed in the previous section, +the methods used would be: + +```{eval-rst} +.. py:class:: Configuration + :noindex: + + .. py:method:: get_file_to_edit() + + Provides the "highest priority" file, for the {ref}`kind ` 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. +``` + +## 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. diff --git a/docs/html/architecture/index.md b/docs/html/architecture/index.md new file mode 100644 index 00000000000..cd53349d9f0 --- /dev/null +++ b/docs/html/architecture/index.md @@ -0,0 +1,7 @@ +# Architecture + +Implementation details and stuff related to that. + +```{toctree} +configuration +``` diff --git a/docs/html/cli/index.md b/docs/html/cli/index.md new file mode 100644 index 00000000000..2cce5ba8861 --- /dev/null +++ b/docs/html/cli/index.md @@ -0,0 +1,47 @@ +# Commands + +```{toctree} +:maxdepth: 1 +:hidden: + +pip +``` + +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 +:caption: Environment management and introspection + +pip_install +pip_uninstall +pip_list +pip_freeze +pip_check +``` + +```{toctree} +:maxdepth: 1 +:caption: Fetching/Generating distributions + +pip_download +pip_wheel +pip_hash +``` + +```{toctree} +:maxdepth: 1 +:caption: Package Index information + +pip_show +pip_search +``` + +```{toctree} +:maxdepth: 1 +:caption: Managing pip itself + +pip_cache +pip_config +pip_debug +``` diff --git a/docs/html/reference/pip.rst b/docs/html/cli/pip.rst similarity index 100% rename from docs/html/reference/pip.rst rename to docs/html/cli/pip.rst diff --git a/docs/html/reference/pip_cache.rst b/docs/html/cli/pip_cache.rst similarity index 100% rename from docs/html/reference/pip_cache.rst rename to docs/html/cli/pip_cache.rst diff --git a/docs/html/reference/pip_check.rst b/docs/html/cli/pip_check.rst similarity index 100% rename from docs/html/reference/pip_check.rst rename to docs/html/cli/pip_check.rst diff --git a/docs/html/reference/pip_config.rst b/docs/html/cli/pip_config.rst similarity index 100% rename from docs/html/reference/pip_config.rst rename to docs/html/cli/pip_config.rst diff --git a/docs/html/reference/pip_debug.rst b/docs/html/cli/pip_debug.rst similarity index 100% rename from docs/html/reference/pip_debug.rst rename to docs/html/cli/pip_debug.rst diff --git a/docs/html/reference/pip_download.rst b/docs/html/cli/pip_download.rst similarity index 100% rename from docs/html/reference/pip_download.rst rename to docs/html/cli/pip_download.rst diff --git a/docs/html/reference/pip_freeze.rst b/docs/html/cli/pip_freeze.rst similarity index 100% rename from docs/html/reference/pip_freeze.rst rename to docs/html/cli/pip_freeze.rst diff --git a/docs/html/reference/pip_hash.rst b/docs/html/cli/pip_hash.rst similarity index 100% rename from docs/html/reference/pip_hash.rst rename to docs/html/cli/pip_hash.rst diff --git a/docs/html/reference/pip_install.rst b/docs/html/cli/pip_install.rst similarity index 66% rename from docs/html/reference/pip_install.rst rename to docs/html/cli/pip_install.rst index 2a60e7188b4..41b8607305c 100644 --- a/docs/html/reference/pip_install.rst +++ b/docs/html/cli/pip_install.rst @@ -149,121 +149,6 @@ profile: ``setup_requires``. -.. _`Requirements File Format`: - -Requirements File Format ------------------------- - -Each line of the requirements file indicates something to be installed, -and like arguments to :ref:`pip install`, the following forms are supported:: - - [[--option]...] - [; markers] [[--option]...] - - [-e] - [-e] - -For details on requirement specifiers, see :ref:`Requirement Specifiers`. - -See the :ref:`pip install Examples` for examples of all these forms. - -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. - -A line ending in an unescaped ``\`` is treated as a line continuation -and the newline following it is effectively ignored. - -Comments are stripped *after* line continuations are processed. - -To interpret the requirements file in UTF-8 format add a comment -``# -*- coding: utf-8 -*-`` to the first or second line of the file. - -The following options are supported: - -.. pip-requirements-file-options-ref-list:: - -Please note that the above options are global options, and should be specified on their individual lines. -The options which can be applied to individual requirements are -:ref:`--install-option `, :ref:`--global-option ` and ``--hash``. - -For example, to specify :ref:`--pre `, :ref:`--no-index ` and two -:ref:`--find-links ` locations: - -:: - ---pre ---no-index ---find-links /my/local/archives ---find-links http://some.archives.com/archives - - -If you wish, you can refer to other requirements files, like this:: - - -r more_requirements.txt - -You can also refer to :ref:`constraints files `, like this:: - - -c some_constraints.txt - -.. _`Using Environment Variables`: - -Using Environment Variables -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Since version 10, pip supports the use of environment variables inside the -requirements file. 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 `_. - -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%``. - - -.. _`Example Requirements File`: - -Example Requirements File -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Use ``pip install -r example-requirements.txt`` to install:: - - # - ####### example-requirements.txt ####### - # - ###### Requirements without Version Specifiers ###### - nose - nose-cov - beautifulsoup4 - # - ###### Requirements with Version Specifiers ###### - # See https://www.python.org/dev/peps/pep-0440/#version-specifiers - docopt == 0.6.1 # Version Matching. Must be version 0.6.1 - keyring >= 4.1.1 # Minimum version 4.1.1 - coverage != 3.5 # Version Exclusion. Anything except version 3.5 - Mopidy-Dirble ~= 1.1 # Compatible release. Same as >= 1.1, == 1.* - # - ###### Refer to other requirements files ###### - -r other-requirements.txt - # - # - ###### A particular file ###### - ./downloads/numpy-1.9.2-cp34-none-win32.whl - http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl - # - ###### Additional Requirements without Version Specifiers ###### - # Same as 1st section, just here to show that you can put things in any order. - rejected - green - # - .. _`Requirement Specifiers`: Requirement Specifiers @@ -309,44 +194,6 @@ Environment markers are supported in the command line and in requirements files. using environment markers. Don't use quotes in requirement files. [1]_ -.. _`Per-requirement Overrides`: - -Per-requirement Overrides -------------------------- - -Since version 7.0 pip supports controlling the command line options given to -``setup.py`` via requirements files. This disables the use of wheels (cached or -otherwise) for that package, as ``setup.py`` does not exist for wheels. - -The ``--global-option`` and ``--install-option`` options are used to pass -options to ``setup.py``. For example: - - :: - - FooProject >= 1.2 --global-option="--no-user-cfg" \ - --install-option="--prefix='/usr/local'" \ - --install-option="--no-compile" - -The above translates roughly into running FooProject's ``setup.py`` -script as: - - :: - - python setup.py --no-user-cfg install --prefix='/usr/local' --no-compile - -Note that the only way of giving more than one option to ``setup.py`` -is through multiple ``--global-option`` and ``--install-option`` -options, as shown in the example above. The value of each option is -passed as a single argument to the ``setup.py`` script. Therefore, a -line such as the following is invalid and would result in an -installation error. - -:: - - # Invalid. Please use '--install-option' twice as shown above. - FooProject >= 1.2 --install-option="--prefix=/usr/local --no-compile" - - .. _`Pre Release Versions`: Pre-release Versions @@ -367,158 +214,6 @@ that enables installation of pre-releases and development releases. .. _pre-releases: https://www.python.org/dev/peps/pep-0440/#handling-of-pre-releases -.. _`VCS Support`: - -VCS Support ------------ - -pip supports installing from Git, Mercurial, Subversion and Bazaar, and detects -the type of VCS using URL prefixes: ``git+``, ``hg+``, ``svn+``, and ``bzr+``. - -pip requires a working VCS command on your path: ``git``, ``hg``, ``svn``, or -``bzr``. - -VCS projects can be installed in :ref:`editable mode ` (using -the :ref:`--editable ` option) or not. - -* For editable installs, the clone location by default is ``/src/SomeProject`` in virtual environments, and - ``/src/SomeProject`` - for global installs. The :ref:`--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. VCS requirements pin the package version (specified - in the ``setup.py`` file) of the target commit, not necessarily the commit - itself. -* The :ref:`pip freeze` subcommand will record the VCS requirement specifier - (referencing a specific commit) if and only if the install is done using the - editable option. - -The "project name" component of the URL suffix ``egg=`` -is used by pip in its dependency logic to identify the project prior -to pip downloading and analyzing the metadata. For projects -where ``setup.py`` is not in the root of project, the "subdirectory" component -is used. The value of the "subdirectory" component should be a path starting -from the root of the project to where ``setup.py`` is located. - -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: - -.. tab:: Unix/macOS - - .. code-block:: shell - - python -m pip install -e "vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir" - -.. tab:: Windows - - .. code-block:: shell - - py -m pip install -e "vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir" - - -Git -^^^ - -pip currently supports cloning over ``git``, ``git+http``, ``git+https``, -``git+ssh``, ``git+git`` and ``git+file``. - -.. warning:: - - Note that the use of ``git``, ``git+git``, and ``git+http`` is discouraged. - The former two use `the Git Protocol`_, which lacks authentication, and HTTP is - insecure due to lack of TLS based encryption. - -Here are the supported forms:: - - [-e] git+http://git.example.com/MyProject#egg=MyProject - [-e] git+https://git.example.com/MyProject#egg=MyProject - [-e] git+ssh://git.example.com/MyProject#egg=MyProject - [-e] git+file:///home/user/projects/MyProject#egg=MyProject - -Passing a branch name, a commit hash, a tag name or a git ref is possible like so:: - - [-e] git+https://git.example.com/MyProject.git@master#egg=MyProject - [-e] git+https://git.example.com/MyProject.git@v1.0#egg=MyProject - [-e] git+https://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject - [-e] git+https://git.example.com/MyProject.git@refs/pull/123/head#egg=MyProject - -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). - -.. _`the Git Protocol`: https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols - -Mercurial -^^^^^^^^^ - -The supported schemes are: ``hg+file``, ``hg+http``, ``hg+https``, -``hg+static-http``, and ``hg+ssh``. - -Here are the supported forms:: - - [-e] hg+http://hg.myproject.org/MyProject#egg=MyProject - [-e] hg+https://hg.myproject.org/MyProject#egg=MyProject - [-e] hg+ssh://hg.myproject.org/MyProject#egg=MyProject - [-e] hg+file:///home/user/projects/MyProject#egg=MyProject - -You can also specify a revision number, a revision hash, a tag name or a local -branch name like so:: - - [-e] hg+http://hg.example.com/MyProject@da39a3ee5e6b#egg=MyProject - [-e] hg+http://hg.example.com/MyProject@2019#egg=MyProject - [-e] hg+http://hg.example.com/MyProject@v1.0#egg=MyProject - [-e] hg+http://hg.example.com/MyProject@special_feature#egg=MyProject - -Subversion -^^^^^^^^^^ - -pip supports the URL schemes ``svn``, ``svn+svn``, ``svn+http``, ``svn+https``, ``svn+ssh``. - -Here are some of the supported forms:: - - [-e] svn+https://svn.example.com/MyProject#egg=MyProject - [-e] svn+ssh://svn.example.com/MyProject#egg=MyProject - [-e] svn+ssh://user@svn.example.com/MyProject#egg=MyProject - -You can also give specific revisions to an SVN URL, like so:: - - [-e] svn+svn://svn.example.com/svn/MyProject#egg=MyProject - [-e] svn+http://svn.example.com/svn/MyProject/trunk@2019#egg=MyProject - -which will check out revision 2019. ``@{20080101}`` would also check -out the revision from 2008-01-01. You can only check out specific -revisions using ``-e svn+...``. - -Bazaar -^^^^^^ - -pip supports Bazaar using the ``bzr+http``, ``bzr+https``, ``bzr+ssh``, -``bzr+sftp``, ``bzr+ftp`` and ``bzr+lp`` schemes. - -Here are the supported forms:: - - [-e] bzr+http://bzr.example.com/MyProject/trunk#egg=MyProject - [-e] bzr+sftp://user@example.com/MyProject/trunk#egg=MyProject - [-e] bzr+ssh://user@example.com/MyProject/trunk#egg=MyProject - [-e] bzr+ftp://user@example.com/MyProject/trunk#egg=MyProject - [-e] bzr+lp:MyProject#egg=MyProject - -Tags or revisions can be installed like so:: - - [-e] bzr+https://bzr.example.com/MyProject/trunk@2019#egg=MyProject - [-e] bzr+http://bzr.example.com/MyProject/trunk@v1.0#egg=MyProject - Using Environment Variables ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -569,68 +264,6 @@ overridden by using ``--cert`` option or by using ``PIP_CERT``, ``REQUESTS_CA_BUNDLE``, or ``CURL_CA_BUNDLE`` environment variables. -.. _`Caching`: - -Caching -------- - -Starting with v6.0, pip provides an on-by-default cache which functions -similarly to that of a web browser. While the cache is on by default and is -designed do the right thing by default you can disable the cache and always -access PyPI by utilizing the ``--no-cache-dir`` option. - -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 simply returns that response and doesn't make the request. - -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`. - -The default location for the cache directory depends on the operating system: - -Unix - :file:`~/.cache/pip` and it respects the ``XDG_CACHE_HOME`` directory. -macOS - :file:`~/Library/Caches/pip`. -Windows - :file:`\\pip\\Cache` - -Run ``pip cache dir`` to show the cache directory and see :ref:`pip cache` to -inspect and manage pip’s cache. - - -.. _`Wheel cache`: - -Wheel Cache -^^^^^^^^^^^ - -pip will read from the subdirectory ``wheels`` within the pip cache directory -and use any packages found there. This is disabled via the same -``--no-cache-dir`` option that disables the HTTP cache. The internal structure -of that is not part of the pip API. As of 7.0, pip makes a subdirectory for -each sdist that wheels are built from and places the resulting wheels inside. - -As of version 20.0, pip also caches wheels when building from an immutable Git -reference (i.e. a commit hash). - -pip attempts to choose the best wheels from those built in preference to -building a new wheel. Note that this means when a package has both optional -C extensions and builds ``py`` tagged wheels when the C extension can't be built -that pip will not attempt to build a better wheel for Pythons that would have -supported it, once any generic wheel is built. To correct this, make sure that -the wheels are built with Python specific tags - e.g. pp on PyPy. - -When no wheels are found for an sdist, pip will attempt to build a wheel -automatically and insert it into the wheel cache. - - .. _`hash-checking mode`: Hash-Checking Mode @@ -823,39 +456,6 @@ To opt in to the future behavior, specify the ``--use-feature=in-tree-build`` option in pip's command line. -.. _`editable-installs`: - -"Editable" Installs -^^^^^^^^^^^^^^^^^^^ - -"Editable" installs are fundamentally `"setuptools develop mode" -`_ -installs. - -You can install local projects or VCS projects in "editable" mode: - -.. tab:: Unix/macOS - - .. code-block:: shell - - python -m pip install -e path/to/SomeProject - python -m pip install -e git+http://repo/my_project.git#egg=SomeProject - -.. tab:: Windows - - .. code-block:: shell - - py -m pip install -e path/to/SomeProject - py -m pip install -e git+http://repo/my_project.git#egg=SomeProject - - -(See the :ref:`VCS Support` section above for more information on VCS-related syntax.) - -For local projects, the "SomeProject.egg-info" directory is created relative to -the project path. This is one advantage over just using ``setup.py develop``, -which creates the "egg-info" directly relative the current working directory. - - .. _`controlling-setup-requires`: Controlling setup_requires diff --git a/docs/html/reference/pip_list.rst b/docs/html/cli/pip_list.rst similarity index 100% rename from docs/html/reference/pip_list.rst rename to docs/html/cli/pip_list.rst diff --git a/docs/html/reference/pip_search.rst b/docs/html/cli/pip_search.rst similarity index 100% rename from docs/html/reference/pip_search.rst rename to docs/html/cli/pip_search.rst diff --git a/docs/html/reference/pip_show.rst b/docs/html/cli/pip_show.rst similarity index 100% rename from docs/html/reference/pip_show.rst rename to docs/html/cli/pip_show.rst diff --git a/docs/html/reference/pip_uninstall.rst b/docs/html/cli/pip_uninstall.rst similarity index 100% rename from docs/html/reference/pip_uninstall.rst rename to docs/html/cli/pip_uninstall.rst diff --git a/docs/html/reference/pip_wheel.rst b/docs/html/cli/pip_wheel.rst similarity index 100% rename from docs/html/reference/pip_wheel.rst rename to docs/html/cli/pip_wheel.rst diff --git a/docs/html/conf.py b/docs/html/conf.py index 2efb7135892..be09055c13a 100644 --- a/docs/html/conf.py +++ b/docs/html/conf.py @@ -1,13 +1,4 @@ -# pip documentation build configuration file, created by -# sphinx-quickstart on Tue Apr 22 22:08:49 2008 -# -# This file is execfile()d with the current directory set to its containing dir -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. +"""Sphinx configuration file for pip's documentation.""" import glob import os @@ -15,311 +6,128 @@ import re import sys -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - +# Add the docs/ directory to sys.path, because pip_sphinxext.py is there. docs_dir = os.path.dirname(os.path.dirname(__file__)) -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, docs_dir) -# sys.path.append(os.path.join(os.path.dirname(__file__), '../')) -# -- General configuration ---------------------------------------------------- +# -- General configuration ------------------------------------------------------------ -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -# extensions = ['sphinx.ext.autodoc'] extensions = [ - # native: - 'sphinx.ext.extlinks', - 'sphinx.ext.intersphinx', - # third-party: - 'sphinx_inline_tabs', - 'sphinxcontrib.towncrier', - # in-tree: - 'docs_feedback_sphinxext', - 'pip_sphinxext', + # first-party extensions + "sphinx.ext.autodoc", + "sphinx.ext.todo", + "sphinx.ext.extlinks", + "sphinx.ext.intersphinx", + # our extensions + "pip_sphinxext", + # third-party extensions + "myst_parser", + "sphinx_copybutton", + "sphinx_inline_tabs", + "sphinxcontrib.towncrier", ] -# intersphinx -intersphinx_cache_limit = 0 -intersphinx_mapping = { - 'pypug': ('https://packaging.python.org/', None), - 'pypa': ('https://www.pypa.io/en/latest/', None), -} - - -# Add any paths that contain templates here, relative to this directory. -templates_path = [] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - # General information about the project. -project = 'pip' -copyright = '2008-2020, PyPA' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. - -version = release = 'dev' - -# Readthedocs seems to install pip as an egg (via setup.py install) which -# is somehow resulting in "import pip" picking up an older copy of pip. -# Rather than trying to force RTD to install pip properly, we'll simply -# read the version direct from the __init__.py file. (Yes, this is -# fragile, but it works...) - -pip_init = os.path.join(docs_dir, '..', 'src', 'pip', '__init__.py') -with open(pip_init) as f: +project = "pip" +copyright = "2008-2020, PyPA" + +# Find the version and release information. +# We have a single source of truth for our version number: pip's __init__.py file. +# This next bit of code reads from it. +file_with_version = os.path.join(docs_dir, "..", "src", "pip", "__init__.py") +with open(file_with_version) as f: for line in f: m = re.match(r'__version__ = "(.*)"', line) if m: __version__ = m.group(1) # The short X.Y version. - version = '.'.join(__version__.split('.')[:2]) + version = ".".join(__version__.split(".")[:2]) # The full version, including alpha/beta/rc tags. release = __version__ break + else: # AKA no-break + version = release = "dev" -# We have this here because readthedocs plays tricks sometimes and there seems -# to be a heisenbug, related to the version of pip discovered. This is here to -# help debug that if someone decides to do that in the future. print("pip version:", version) print("pip release:", release) -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -# unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_patterns = ['build/'] +# -- Options for smartquotes ---------------------------------------------------------- -# The reST default role (used for this markup: `text`) to use for all documents -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True +# Disable the conversion of dashes so that long options like "--find-links" won't +# render as "-find-links" if included in the text.The default of "qDe" converts normal +# quote characters ('"' and "'"), en and em dashes ("--" and "---"), and ellipses "..." +smartquotes_action = "qe" -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True +# -- Options for intersphinx ---------------------------------------------------------- -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), + "pypug": ("https://packaging.python.org", None), +} -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] +# -- Options for extlinks ------------------------------------------------------------- extlinks = { - 'issue': ('https://github.com/pypa/pip/issues/%s', '#'), - 'pull': ('https://github.com/pypa/pip/pull/%s', 'PR #'), - 'pypi': ('https://pypi.org/project/%s/', ''), + "issue": ("https://github.com/pypa/pip/issues/%s", "#"), + "pull": ("https://github.com/pypa/pip/pull/%s", "PR #"), + "pypi": ("https://pypi.org/project/%s/", ""), } -# Turn off sphinx build warnings because of sphinx tabs during man pages build -sphinx_tabs_nowarn = True +# -- Options for towncrier_draft extension -------------------------------------------- -# -- Options for HTML output -------------------------------------------------- +towncrier_draft_autoversion_mode = "draft" # or: 'sphinx-release', 'sphinx-version' +towncrier_draft_include_empty = True +towncrier_draft_working_directory = pathlib.Path(docs_dir).parent +# Not yet supported: towncrier_draft_config_path = 'pyproject.toml' # relative to cwd -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = "furo" +# -- Options for myst-parser ---------------------------------------------------------- -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme_options = {} +myst_enable_extensions = ["deflist"] +myst_url_schemes = ("http", "https", "mailto") +myst_heading_anchors = 2 -# Add any paths that contain custom themes here, relative to this directory. +# -- Options for HTML ----------------------------------------------------------------- -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". +html_theme = "furo" html_title = f"{project} documentation v{release}" -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = '_static/piplogo.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = 'favicon.png' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, the Docutils Smart Quotes transform (originally based on -# SmartyPants) will be used to convert characters like quotes and dashes -# to typographically correct entities. The default is True. -smartquotes = True - -# This string, for use with Docutils 0.14 or later, customizes the -# SmartQuotes transform. The default of "qDe" converts normal quote -# characters ('"' and "'"), en and em dashes ("--" and "---"), and -# ellipses "...". -# For now, we disable the conversion of dashes so that long options -# like "--find-links" won't render as "-find-links" if included in the -# text in places where monospaced type can't be used. For example, backticks -# can't be used inside roles like :ref:`--no-index <--no-index>` because -# of nesting. -smartquotes_action = "qe" - -# Custom sidebar templates, maps document names to template names. -html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. +# Disable the generation of the various indexes html_use_modindex = False - -# If false, no index is generated. html_use_index = False -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'pipdocs' - - -# -- Options for LaTeX output ------------------------------------------------- - -# The paper size ('letter' or 'a4'). -# latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -# latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]) -latex_documents = [ - ( - 'index', - 'pip.tex', - 'pip Documentation', - 'pip developers', - 'manual', - ), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -# latex_preamble = '' +# -- Options for Manual Pages --------------------------------------------------------- -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_use_modindex = True - -# -- Options for Manual Pages ------------------------------------------------- # List of manual pages generated -man_pages = [ - ( - 'index', - 'pip', - 'package manager for Python packages', - 'pip developers', - 1 - ) -] - - -def to_document_name(path, base_dir): - """Convert a provided path to a Sphinx "document name". - """ - relative_path = os.path.relpath(path, base_dir) - root, _ = os.path.splitext(relative_path) - return root.replace(os.sep, '/') - - -# Here, we crawl the entire man/commands/ directory and list every file with -# appropriate name and details -man_dir = os.path.join(docs_dir, 'man') -raw_subcommands = glob.glob(os.path.join(man_dir, 'commands/*.rst')) -if not raw_subcommands: - raise FileNotFoundError( - 'The individual subcommand manpages could not be found!' - ) -for fname in raw_subcommands: - fname_base = to_document_name(fname, man_dir) - outname = 'pip-' + fname_base.split('/')[1] - description = 'description of {} command'.format( - outname.replace('-', ' ') - ) - - man_pages.append((fname_base, outname, description, 'pip developers', 1)) - -# -- Options for docs_feedback_sphinxext -------------------------------------- - -# NOTE: Must be one of 'attention', 'caution', 'danger', 'error', 'hint', -# NOTE: 'important', 'note', 'tip', 'warning' or 'admonition'. -docs_feedback_admonition_type = 'important' -docs_feedback_big_doc_lines = 50 # bigger docs will have a banner on top -docs_feedback_email = 'Docs UX Team ' -docs_feedback_excluded_documents = { # these won't have any banners - 'news', 'reference/index', -} -docs_feedback_questions_list = ( - 'What problem were you trying to solve when you came to this page?', - 'What content was useful?', - 'What content was not useful?', -) - -# -- Options for towncrier_draft extension ----------------------------------- - -towncrier_draft_autoversion_mode = 'draft' # or: 'sphinx-release', 'sphinx-version' -towncrier_draft_include_empty = False -towncrier_draft_working_directory = pathlib.Path(docs_dir).parent -# Not yet supported: towncrier_draft_config_path = 'pyproject.toml' # relative to cwd +def determine_man_pages(): + """Determine which man pages need to be generated.""" + + def to_document_name(path, base_dir): + """Convert a provided path to a Sphinx "document name".""" + relative_path = os.path.relpath(path, base_dir) + root, _ = os.path.splitext(relative_path) + return root.replace(os.sep, "/") + + # Crawl the entire man/commands/ directory and list every file with appropriate + # name and details. + man_dir = os.path.join(docs_dir, "man") + raw_subcommands = glob.glob(os.path.join(man_dir, "commands/*.rst")) + if not raw_subcommands: + raise FileNotFoundError( + "The individual subcommand manpages could not be found!" + ) + + retval = [ + ("index", "pip", "package manager for Python packages", "pip developers", 1), + ] + for fname in raw_subcommands: + fname_base = to_document_name(fname, man_dir) + outname = "pip-" + fname_base.split("/")[1] + description = "description of {} command".format(outname.replace("-", " ")) + + retval.append((fname_base, outname, description, "pip developers", 1)) + + return retval + + +man_pages = determine_man_pages() diff --git a/docs/html/contributing/index.md b/docs/html/contributing/index.md new file mode 100644 index 00000000000..f40868e6283 --- /dev/null +++ b/docs/html/contributing/index.md @@ -0,0 +1,6 @@ +# Contributing + +Documentation written by pip's maintainers, for pip's contributorss. + +```{toctree} +``` diff --git a/docs/html/development/architecture/configuration-files.rst b/docs/html/development/architecture/configuration-files.rst deleted file mode 100644 index 2f96ea5ca50..00000000000 --- a/docs/html/development/architecture/configuration-files.rst +++ /dev/null @@ -1,151 +0,0 @@ -=========================== -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 `_. - - -.. _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 ` 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 ` 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 - `. - -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 ` 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 ` 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 ` 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. diff --git a/docs/html/explanations/authentication.md b/docs/html/explanations/authentication.md new file mode 100644 index 00000000000..c08aca859a3 --- /dev/null +++ b/docs/html/explanations/authentication.md @@ -0,0 +1,86 @@ +# 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 + +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 + +```{important} +Support for percent-encoded authentication in index URLs was added in pip 10.0 +(in {pull}`3236`). Users with older versions of pip need to upgrade to a newer +version of pip, to be able to use characters that need to be percent-encoded. +``` + +## 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. + +```bash +$ pip install keyring # install keyring from PyPI +$ echo "your-password" | keyring set pypi.company.com your-username +$ pip install your-package --index-url https://pypi.company.com/ +``` + +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` in their Python +environment. diff --git a/docs/html/explanations/caching.md b/docs/html/explanations/caching.md new file mode 100644 index 00000000000..3b282aa9667 --- /dev/null +++ b/docs/html/explanations/caching.md @@ -0,0 +1,61 @@ +# Caching + +pip provides an on-by-default caching, designed to reduce the amount of time +spent on duplicate downloads and builds. pip's caching behaviour is disabled +via the ``--no-cache-dir`` option. + +## 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`. + +### Locally built wheels + +pip attempts to use wheels from its local wheel cache whenever possible. + +pip attempts to choose the best wheels from those built in preference to +building a new wheel. Note that this means when a package has both optional +C extensions and builds ``py`` tagged wheels when the C extension can't be built +that pip will not attempt to build a better wheel for Pythons that would have +supported it, once any generic wheel is built. To correct this, make sure that +the wheels are built with Python specific tags - e.g. pp on PyPy. + +When no wheels are found for an sdist, 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. + +```{note} +The structure of pip's wheel cache is not considered public API and may change +between any two versions of pip. +``` + +```{versionchanged} 7.0 +pip now makes a subdirectory for each sdist that wheels are built +from and places the resulting wheels inside. +``` + +```{versionchanged} 20.0 +pip now caches wheels when building from an immutable Git reference +(i.e. a commit hash). +``` + +## Cache management + +pip provides a {ref}`pip cache` command to aid with managing pip's cache. + +[TODO: Expand this section with descriptions of how to use pip cache] diff --git a/docs/html/explanations/configuration.md b/docs/html/explanations/configuration.md new file mode 100644 index 00000000000..90799d574c0 --- /dev/null +++ b/docs/html/explanations/configuration.md @@ -0,0 +1,226 @@ +# 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. + +## Configuration Files + +Configuration files can change the default values for command line option. +They are written using a standard INI style configuration files. + +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. + +### 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. + +```{tab} Unix + +Global +: {file}`/etc/pip.conf` + + Alternatively, it may be 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`. + +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` +``` + +```{tab} MacOS + +Global +: {file}`/Library/Application Support/pip/pip.conf` + +User +: {file}`$HOME/Library/Application Support/pip/pip.conf` + if directory `$HOME/Library/Application Support/pip` exists + else {file}`$HOME/.config/pip/pip.conf` + + The legacy "per-user" configuration file is also loaded, if it exists: {file}`$HOME/.pip/pip.conf`. + +Site +: {file}`$VIRTUAL_ENV/pip.conf` +``` + +```{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` +``` + +### `PIP_CONFIG_FILE` + +Additionally, the environment variable `PIP_CONFIG_FILE` can be used to specify +a configuration file that's loaded first, and whose values are overridden by +the values set in the aforementioned files. Setting this to {ref}`os.devnull` +disables the loading of _all_ configuration files. + +### Loading order + +When multiple configuration files are found, pip combines them in the following +order: + +- `PIP_CONFIG_FILE`, if given. +- Global +- User +- Site + +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 (`--default-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_` . Dashes (`-`) have to be replaced with +underscores (`_`). + +- `PIP_DEFAULT_TIMEOUT=60` is the same as `--default-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 have override environment variables, which override the +values in a configuration file. Within the configuration file, values in +command-specific sections over 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 `[] host = bar` + overrides the option with same name in the `[global]` config file section. diff --git a/docs/html/explanations/custom-install-options.md b/docs/html/explanations/custom-install-options.md new file mode 100644 index 00000000000..122deafdb2d --- /dev/null +++ b/docs/html/explanations/custom-install-options.md @@ -0,0 +1,43 @@ +# Custom Install Options + +```{versionadded} 7.0 +``` + +```{caution} +Using this mechanism `--global-option` and `--install-option` disables the use +of wheels *and* is incompatible with pip's current implementation for +interacting with the build-backend as described in PEP 517. +``` + +pip supports controlling the command line options given to `setup.py` via +requirements files. This disables the use of wheels (cached or otherwise) for +that package, as `setup.py` does not exist for wheels. + +The `--global-option` and `--install-option` options are used to pass +options to `setup.py`. For example: + +```text +FooProject >= 1.2 \ + --global-option="--no-user-cfg" \ + --install-option="--prefix='/usr/local'" \ + --install-option="--no-compile" +``` + +The above translates roughly into running FooProject's `setup.py` +script as: + +``` +python setup.py --no-user-cfg install --prefix='/usr/local' --no-compile +``` + +Note that the only way of giving more than one option to `setup.py` +is through multiple `--global-option` and `--install-option` +options, as shown in the example above. The value of each option is +passed as a single argument to the `setup.py` script. Therefore, a +line such as the following is invalid and would result in an +installation error. + +```text +# THIS IS NOT VALID: use '--install-option' twice as shown above. +FooProject >= 1.2 --install-option="--prefix=/usr/local --no-compile" +``` diff --git a/docs/html/explanations/editable-installs.md b/docs/html/explanations/editable-installs.md new file mode 100644 index 00000000000..e8e41ceaeb5 --- /dev/null +++ b/docs/html/explanations/editable-installs.md @@ -0,0 +1,30 @@ +# Editable Installs + +Editable installs are a mechanism to circumvent the need of (re)installing a +package on every change during development. With an editable install, changes +made to the package source (in its checkout directory) will be reflected in the +package visible to Python, without needing a reinstall. + +pip only supports editable installs via [setuptools's "development mode"][1] +installs. You can install local projects or VCS projects in "editable" mode: + +```{pip-cli} +$ pip install -e path/to/SomeProject +$ pip install -e git+http://repo/my_project.git#egg=SomeProject +``` + +For local projects, the "SomeProject.egg-info" directory is created relative to +the project path. This is one advantage over just using ``setup.py develop``, +which creates the "egg-info" directly relative the current working directory. + +```{seealso} +{ref}`VCS Support` section for more information on VCS-related syntax. +``` + +```{important} +As of 30 Dec 2020, PEP 517 does not support editable installs. Various members +of the Python community are working on a new standard to [address this +limitation](https://discuss.python.org/t/4098). +``` + +[1]: https://setuptools.readthedocs.io/en/latest/userguide/development_mode.html#development-mode diff --git a/docs/html/explanations/index.md b/docs/html/explanations/index.md new file mode 100644 index 00000000000..e2f9db91611 --- /dev/null +++ b/docs/html/explanations/index.md @@ -0,0 +1,15 @@ +# Explanations + +Explanations provide detailed information on key topics and concepts. + +```{toctree} +authentication +caching +configuration +custom-install-options +editable-installs +repeatable-installs +requirements-files +user-installs +vcs-support +``` diff --git a/docs/html/explanations/repeatable-installs.md b/docs/html/explanations/repeatable-installs.md new file mode 100644 index 00000000000..efd6a851cdd --- /dev/null +++ b/docs/html/explanations/repeatable-installs.md @@ -0,0 +1,98 @@ +# 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 not only the top-level packages, but also all of +their transitive dependencies. Performing the installation using +{ref}`--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: + +``` +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. + +```{warning} +Beware of the `setup_requires` keyword arg in {file}`setup.py`. The (rare) +packages that use it will cause those dependencies to be downloaded by +setuptools directly, skipping pip's protections. If you need to use such a +package, see {ref}`Controlling setup_requires `. +``` diff --git a/docs/html/explanations/requirements-files.md b/docs/html/explanations/requirements-files.md new file mode 100644 index 00000000000..d6687b1442d --- /dev/null +++ b/docs/html/explanations/requirements-files.md @@ -0,0 +1,84 @@ +# Requirements Files + +Requirements files contain a list of items to be installed using +{ref}`pip install`. + +``` +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. You should not rely on the items in the file being installed +by pip in any particular order. + +## What requirements files are for + +```{seealso} +Donald Stufft's article on ["setup.py vs requirements.txt"][setup-vs-req] +discusses an important concept: "abstract" vs "concrete" dependencies. +``` + +[setup-vs-req]: https://caremad.io/2013/07/setup-vs-requirement/ + +### Repeatable installs + +Requirements files can be used to hold the result from {ref}`pip freeze` for the +purpose of achieving {ref}`repeatable installations `. + +In this case, your requirements file contains a pinned version of everything +that was installed when `pip freeze` was run. + +``` +pip freeze > requirements.txt +pip install -r requirements.txt +``` + +### Forcing an alternate version of a subdependency + +Requirements files can be 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 +``` + +### Overriding a dependencies with a patched variant + +Requirements files can be used to override a dependency, with a patched variant +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 source code, make +the fix, and place it in a VCS with the tag `sometag`. It is now possible to +reference it in your requirements file with a line like: + +``` +git+https://myvcs.com/some_dependency@sometag#egg=SomeDependency +``` + +```{note} +* If `SomeDependency` was previously a "top-level" requirement in your + requirements file (i.e. directly mentioned), then **replace** that with the + new line referencing the VCS variant. +* If `SomeDependency` is a sub-dependency, then **add** the new line. +``` + +### Forcing pip to resolve dependencies a certain way + +Requirements files were used to force pip to properly resolve dependencies. +This was especially relevant in pip 20.2 and earlier, which [did not have true +dependency resolution][gh-988]. The dependency resolution process in those +versions "simply" used the first specification it found for a package. + +Note that pip determines package dependencies using a package's +[`Requires-Dist` metadata][requires-dist], not by discovering/looking for +`requirements.txt` files embedded in them. + +[gh-988]: https://github.com/pypa/pip/issues/988 +[requires-dist]: https://packaging.python.org/specifications/core-metadata/#requires-dist-multiple-use diff --git a/docs/html/explanations/user-installs.md b/docs/html/explanations/user-installs.md new file mode 100644 index 00000000000..39a11e2a418 --- /dev/null +++ b/docs/html/explanations/user-installs.md @@ -0,0 +1,93 @@ +# User Installs + +In Python 2.6, a ["user scheme"][python-user-scheme] was added. This provided +an alternative install location for Python packages that is (as the name +suggests) user-specific. + +[python-user-scheme]: https://docs.python.org/3/install/index.html#alternate-installation-the-user-scheme + +This allows users to install packages in a location where they will have the +required filesystem permissions to do so and to avoid modifying a interpreter's +`site-packages` which might be used by other users (on shared machines) or other +programs (like their OS's programs on Linux). + +```{important} +This mechanism does not substitute the use of virtual environments, which are +mainly for isolating the dependency graphs across multiple projects *and* +(optionally) for isolating from the interpreter's `site-packages`. +``` + +## How it works + +pip supports installing into the user scheme and does so automatically when the +user does not have write permissions to the per-interpreter `site-packages` +folder (which is the default). It is also possible to force this behaviour, +by passing the [`--user`](install_--user) flag to `pip install`. + +`pip install --user` follows four rules: + +1. When globally installed packages are on the python path, and they *conflict* + with the installation requirements, they are ignored, and *not* + uninstalled. +2. 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). +3. 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. +4. 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. + +## Examples + +### With a virtual environment + +In a `--no-site-packages` virtual environment (i.e. the default kind): + +```{pip-cli} in-a-venv +$ pip install --user SomePackage +Can not perform a '--user' install. User site-packages are not visible in this virtual environment. +``` + +In a `--system-site-packages` virtual environment where `SomePackage==0.3` +is already installed in the virtual environment: + +```{pip-cli} in-a-venv +$ pip install --user SomePackage==0.4 +Will not install to the user site because it will lack sys.path precedence. +``` + +### Without a virtual environment + +`SomePackage` is *not* installed globally: + +```{pip-cli} +$ pip install --user SomePackage +[...] +Successfully installed SomePackage +``` + +`SomePackage` *is* installed globally, but is *not* the latest version: + +```{pip-cli} +$ pip install --user SomePackage +[...] +Requirement already satisfied (use --upgrade to upgrade) +$ pip install --user --upgrade SomePackage +[...] +Successfully installed SomePackage +``` + +`SomePackage` *is* installed globally, and is the latest version: + +```{pip-cli} +$ pip install --user SomePackage +[...] +Requirement already satisfied +$ pip install --user --upgrade SomePackage +[...] +Requirement already up-to-date: SomePackage +``` diff --git a/docs/html/explanations/vcs-support.md b/docs/html/explanations/vcs-support.md new file mode 100644 index 00000000000..e5cc7f43136 --- /dev/null +++ b/docs/html/explanations/vcs-support.md @@ -0,0 +1,162 @@ +# 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+` + +## 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 +git+ssh://git.example.com/MyProject#egg=MyProject +git+file:///home/user/projects/MyProject#egg=MyProject +git+https://git.example.com/MyProject#egg=MyProject +git+http://git.example.com/MyProject#egg=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 +git+https://git.example.com/MyProject.git@master#egg=MyProject +git+https://git.example.com/MyProject.git@v1.0#egg=MyProject +git+https://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject +git+https://git.example.com/MyProject.git@refs/pull/123/head#egg=MyProject +``` + +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). + +### Mercurial + +The supported schemes are `hg+file`, `hg+http`, `hg+https`, `hg+ssh` +and `hg+static-http`. Here are some of the supported forms: + +``` +hg+http://hg.myproject.org/MyProject#egg=MyProject +hg+https://hg.myproject.org/MyProject#egg=MyProject +hg+ssh://hg.myproject.org/MyProject#egg=MyProject +hg+file:///home/user/projects/MyProject#egg=MyProject +``` + +It is also possible to specify a revision number, a revision hash, a tag name +or a local branch name: + +```none +hg+http://hg.example.com/MyProject@da39a3ee5e6b#egg=MyProject +hg+http://hg.example.com/MyProject@2019#egg=MyProject +hg+http://hg.example.com/MyProject@v1.0#egg=MyProject +hg+http://hg.example.com/MyProject@special_feature#egg=MyProject +``` + +### Subversion + +The supported schemes are `svn`, `svn+svn`, `svn+http`, `svn+https` and +`svn+ssh`. Here are some of the supported forms: + +```none +svn+https://svn.example.com/MyProject#egg=MyProject +svn+ssh://svn.example.com/MyProject#egg=MyProject +svn+ssh://user@svn.example.com/MyProject#egg=MyProject +``` + +You can also give specific revisions to an SVN URL, like so: + +```none +-e svn+http://svn.example.com/svn/MyProject/trunk@2019#egg=MyProject +-e svn+http://svn.example.com/svn/MyProject/trunk@{20080101}#egg=MyProject +``` + +Note that you need to use {ref}`Editable VCS installs` for using specific +revisions. + +### Bazaar + +The supported schemes are `bzr+http`, `bzr+https`, `bzr+ssh`, `bzr+sftp`, +`bzr+ftp` and `bzr+lp`. Here are the supported forms: + +```none +bzr+http://bzr.example.com/MyProject/trunk#egg=MyProject +bzr+sftp://user@example.com/MyProject/trunk#egg=MyProject +bzr+ssh://user@example.com/MyProject/trunk#egg=MyProject +bzr+ftp://user@example.com/MyProject/trunk#egg=MyProject +bzr+lp:MyProject#egg=MyProject +``` + +Tags or revisions can be installed like so: + +```none +bzr+https://bzr.example.com/MyProject/trunk@2019#egg=MyProject +bzr+http://bzr.example.com/MyProject/trunk@v1.0#egg=MyProject +``` + +## Editable VCS installs + +VCS projects can be installed in {ref}`editable mode ` (using +the {ref}`--editable ` option) or not. + +- The default clone location (for editable installs) is: + + - `/src/SomeProject` in virtual environments + - `/src/SomeProject` for global Python installs + + The {ref}`--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 (specified in the `setup.py` file) of the target +commit to determine what action to take on the VCS requirement (not the commit +itself). + +The {ref}`pip freeze` subcommand will record the VCS requirement specifier +(referencing a specific commit) only if the install is done with the editable +option. + +## URL fragments + +pip looks at 2 fragments for VCS URLs: + +- `egg`: For specifying the "project name" for use in pip's dependency + resolution logic. eg: `egg=project_name` +- `subdirectory`: For specifying the path to the Python package, when it is not + in the root of the VCS directory. eg: `pkg_dir` + +````{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 -e "vcs+protocol://repo_url/#egg=pkg&subdirectory=pkg_dir" +``` +```` diff --git a/docs/html/getting-started.md b/docs/html/getting-started.md new file mode 100644 index 00000000000..13d2cf5e6be --- /dev/null +++ b/docs/html/getting-started.md @@ -0,0 +1,105 @@ +# Getting Started + +To get started with using pip, you should install Python on your system. + +## Installation + +pip is already installed if you are: + +- working in a + [virtual environment](pypug:Creating\ and\ using\ Virtual\ Environments) + created by [venv](pypug:venv) or [virtualenv](pypug:virtualenv). +- using Python, downloaded from [python.org](https://www.python.org) +- using Python, that has not been patched by a redistributor to remove pip and + `ensurepip`. + +## Compatibility + +The current version of pip works on: + +- Windows, Linux/Unix and MacOS. +- (C)Python 3.6, 3.7, 3.8 and 3.9 and PyPy3 as well. + +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. + +```{note} +If you're using an older version of pip or Python, it is possible that +the instructions on this page would not work for you. Please refer to the +provider / redistributor of those older versions of pip/Python +(eg: your Linux distribution) for support regarding them. +``` + +### Checking if you have a working pip + +The best way to check if you have a working pip installation is to run: + +```{pip-cli} +$ pip --version +pip X.Y.Z from .../site-packages/pip (python X.Y) +``` + +If that worked, congratulations! You have a working pip in your environment. +Skip ahead to the [Next steps](#next-steps) section on this page. + +If you got output that does not look like the sample above, read on -- the rest +of this page has information about how to install pip within a Python +environment. + +## Supported installation methods + +If your Python environment does not have pip, there are 2 supported installation +methods: + +- {mod}`ensurepip`, a bootstrapper that is part of the Python standard library +- `get-pip.py`, a bootstrapper script for pip + +### ensurepip + +Python >= 3.4 can self-bootstrap pip with the built-in {mod}`ensurepip` module. +To install pip using {mod}`ensurepip`, run: + +```{pip-cli} +$ python -m ensurepip --upgrade +``` + +```{note} +It is strongly recommended to upgrade to the current version of pip using +`--upgrade` when calling ensurepip. It is possible to skip this flag, which +also means that the process would not access the internet. +``` + +More details about how {mod}`ensurepip` works and can be used, is available in +the standard library documentation. + +### get-pip.py + +`get-pip.py` is a bootstrapper script, that is capable of installing pip in an +environment. To install pip using `get-pip.py`, you'll want to: + +- Download the `get-pip.py` script, from . + + On most Linux/MacOS machines, this can be done using the command: + + ``` + $ curl -sSL https://bootstrap.pypa.io/get-pip.py -o get-pip.py + ``` + +- Open the terminal/command prompt on your OS, in 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 + +## Next Steps + +As a next step, you'll want to read the +["Installing Packages"](pypug:tutorials/installing-packages) tutorial on +packaging.python.org. That tutorial will guide you through the basics of using +pip for installing packages. diff --git a/docs/html/index.md b/docs/html/index.md new file mode 100644 index 00000000000..6915e8dcf16 --- /dev/null +++ b/docs/html/index.md @@ -0,0 +1,38 @@ +# Welcome to pip's documentation! + +pip is the [standard package installer][recommendations] for Python. + +```{toctree} +:hidden: + +getting-started +explanations/index +reference/index +cli/index +news +``` + +```{toctree} +:caption: Troubleshooting +:hidden: +:glob: + +troubleshooting/* +``` + +```{toctree} +:caption: Project +:hidden: + +contributing/index +architecture/index +maintainance/index +ux_research_design +GitHub +``` + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the [PSF Code of Conduct][coc]. + +[recommendations]: https://packaging.python.org/guides/tool-recommendations/ +[coc]: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md diff --git a/docs/html/index.rst b/docs/html/index.rst deleted file mode 100644 index b92a23e020a..00000000000 --- a/docs/html/index.rst +++ /dev/null @@ -1,63 +0,0 @@ -================================== -pip - The Python Package Installer -================================== - -pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. - -Please take a look at our documentation for how to install and use pip: - -.. toctree:: - :maxdepth: 1 - - quickstart - installing - user_guide - reference/index - development/index - ux_research_design - news - -.. warning:: - - In pip 20.3, we've `made a big improvement to the heart of pip`_; - :ref:`Resolver changes 2020`. We want your input, so `sign up for - our user experience research studies`_ to help us do it right. - -.. warning:: - - pip 21.0, in January 2021, removed Python 2 support, per pip's - :ref:`Python 2 Support` policy. Please migrate to Python 3. - -If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: - -* `Issue tracking`_ -* `Discourse channel`_ -* `User IRC`_ - -If you want to get involved, head over to GitHub to get the source code, and feel free to jump on the developer mailing lists and chat rooms: - -* `GitHub page`_ -* `Development mailing list`_ -* `Development IRC`_ - - -Code of Conduct -=============== - -Everyone interacting in the pip project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. - -.. _package installer: https://packaging.python.org/guides/tool-recommendations/ -.. _Python Package Index: https://pypi.org -.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html -.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html -.. _Installation: https://pip.pypa.io/en/stable/installing.html -.. _Documentation: https://pip.pypa.io/en/stable/ -.. _Changelog: https://pip.pypa.io/en/stable/news.html -.. _GitHub page: https://github.com/pypa/pip -.. _Issue tracking: https://github.com/pypa/pip/issues -.. _Discourse channel: https://discuss.python.org/c/packaging -.. _Development mailing list: https://mail.python.org/mailman3/lists/distutils-sig.python.org/ -.. _User IRC: https://webchat.freenode.net/?channels=%23pypa -.. _Development IRC: https://webchat.freenode.net/?channels=%23pypa-dev -.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md diff --git a/docs/html/installing.rst b/docs/html/installing.rst index 95b21899dc6..790bfd5e67b 100644 --- a/docs/html/installing.rst +++ b/docs/html/installing.rst @@ -201,19 +201,6 @@ Upgrading pip py -m pip install -U pip -.. _compatibility-requirements: - -Python and OS Compatibility -=========================== - -pip works with CPython versions 3.6, 3.7, 3.8, 3.9 and also PyPy. - -This means pip works on the latest patch version of each of these minor -versions. Previous patch versions are supported on a best effort approach. - -pip works on Unix/Linux, macOS, and Windows. - - ---- .. [1] "Secure" in this context means using a modern browser or a diff --git a/docs/html/maintainance/index.md b/docs/html/maintainance/index.md new file mode 100644 index 00000000000..a5552bfbd84 --- /dev/null +++ b/docs/html/maintainance/index.md @@ -0,0 +1,6 @@ +# Maintainance + +Documentation written by pip's maintainers, for pip's maintainers. + +```{toctree} +``` diff --git a/docs/html/news.md b/docs/html/news.md new file mode 100644 index 00000000000..4796649a4fd --- /dev/null +++ b/docs/html/news.md @@ -0,0 +1,12 @@ +# Changelog + +```{attention} +Major and minor releases of pip also include changes listed within prior beta +releases. +``` + +```{eval-rst} +.. towncrier-draft-entries:: |release|, unreleased as on + +.. include:: ../../NEWS.rst +``` diff --git a/docs/html/news.rst b/docs/html/news.rst deleted file mode 100644 index 8b54a02e637..00000000000 --- a/docs/html/news.rst +++ /dev/null @@ -1,12 +0,0 @@ -========= -Changelog -========= - -.. attention:: - - Major and minor releases of pip also include changes listed within - prior beta releases. - -.. towncrier-draft-entries:: |release|, unreleased as on - -.. include:: ../../NEWS.rst diff --git a/docs/html/quickstart.md b/docs/html/quickstart.md new file mode 100644 index 00000000000..27cd3a7137d --- /dev/null +++ b/docs/html/quickstart.md @@ -0,0 +1,9 @@ +--- +orphan: true +--- + +# Quickstart + +This is now covered in a [packaging.python.org tutorial][tutorial]. + +[tutorial]: pypug:tutorials/installing-packages diff --git a/docs/html/quickstart.rst b/docs/html/quickstart.rst deleted file mode 100644 index 96602a7b316..00000000000 --- a/docs/html/quickstart.rst +++ /dev/null @@ -1,136 +0,0 @@ -========== -Quickstart -========== - -First, :doc:`install pip `. - -Install a package from `PyPI`_: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip install SomePackage - [...] - Successfully installed SomePackage - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip install SomePackage - [...] - Successfully installed SomePackage - - -Install a package that's already been downloaded from `PyPI`_ or -obtained from elsewhere. This is useful if the target machine does not have a -network connection: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip install SomePackage-1.0-py2.py3-none-any.whl - [...] - Successfully installed SomePackage - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip install SomePackage-1.0-py2.py3-none-any.whl - [...] - Successfully installed SomePackage - -Show what files were installed: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip show --files SomePackage - Name: SomePackage - Version: 1.0 - Location: /my/env/lib/pythonx.x/site-packages - Files: - ../somepackage/__init__.py - [...] - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip show --files SomePackage - Name: SomePackage - Version: 1.0 - Location: /my/env/lib/pythonx.x/site-packages - Files: - ../somepackage/__init__.py - [...] - -List what packages are outdated: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip list --outdated - SomePackage (Current: 1.0 Latest: 2.0) - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip list --outdated - SomePackage (Current: 1.0 Latest: 2.0) - -Upgrade a package: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip install --upgrade SomePackage - [...] - Found existing installation: SomePackage 1.0 - Uninstalling SomePackage: - Successfully uninstalled SomePackage - Running setup.py install for SomePackage - Successfully installed SomePackage - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip install --upgrade SomePackage - [...] - Found existing installation: SomePackage 1.0 - Uninstalling SomePackage: - Successfully uninstalled SomePackage - Running setup.py install for SomePackage - Successfully installed SomePackage - -Uninstall a package: - -.. tab:: Unix/macOS - - .. code-block:: console - - $ python -m pip uninstall SomePackage - Uninstalling SomePackage: - /my/env/lib/pythonx.x/site-packages/somepackage - Proceed (y/n)? y - Successfully uninstalled SomePackage - -.. tab:: Windows - - .. code-block:: console - - C:\> py -m pip uninstall SomePackage - Uninstalling SomePackage: - /my/env/lib/pythonx.x/site-packages/somepackage - Proceed (y/n)? y - Successfully uninstalled SomePackage - -.. _PyPI: https://pypi.org/ diff --git a/docs/html/reference/index.md b/docs/html/reference/index.md new file mode 100644 index 00000000000..a44ef91263e --- /dev/null +++ b/docs/html/reference/index.md @@ -0,0 +1,8 @@ +# Reference + +Reference provides information about various file formats, interfaces and +interoperability standards that pip utilises/implements. + +```{toctree} +requirements-files +``` diff --git a/docs/html/reference/index.rst b/docs/html/reference/index.rst deleted file mode 100644 index d21b7a9801a..00000000000 --- a/docs/html/reference/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -=============== -Reference Guide -=============== - -.. toctree:: - :maxdepth: 2 - - pip - pip_install - pip_download - pip_uninstall - pip_freeze - pip_list - pip_show - pip_search - pip_cache - pip_check - pip_config - pip_wheel - pip_hash - pip_debug diff --git a/docs/html/reference/requirements-files.md b/docs/html/reference/requirements-files.md new file mode 100644 index 00000000000..2e13c5522fe --- /dev/null +++ b/docs/html/reference/requirements-files.md @@ -0,0 +1,136 @@ +# Requirements File Format + +Requirements files contain a list of items to be installed using +{ref}`pip install`. This page serves as the description of the format. + +```{caution} +This format is purely implementation defined and depends on various +internal details of how pip works (eg: pip's CLI options). +``` + +## Structure + +Each line of the requirements file indicates something to be installed, +or arguments to {ref}`pip install`. The following forms are supported: + +- `[[--option]...]` +- ` [; markers] [[--option]...]` +- `` +- `[-e] ` +- `[-e] ` + +For details on requirement specifiers, see {ref}`Requirement Specifiers`. For +examples of all these forms, see {ref}`pip install Examples`. + +### Encoding + +Requirements files are `utf-8` encoding by default and also support +{pep}`263` style comments to change the encoding (i.e. +`# -*- coding: -*-`). + +### 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 `, {ref}`--no-index ` +and two {ref}`--find-links ` locations: + +``` +--pre +--no-index +--find-links /my/local/archives +--find-links http://some.archives.com/archives +``` +```` + +### Per-requirement options + +The options which can be applied to individual requirements are: + +- {ref}`--install-option ` +- {ref}`--global-option ` +- `--hash` (for {ref}`Hash-Checking mode`) + +If you wish, you can refer to other requirements files, like this: + +``` +-r more_requirements.txt +``` + +You can also refer to {ref}`constraints files `, like this: + +``` +-c some_constraints.txt +``` + +## Using environment variables + +Since pip 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). + +## Example + +``` +###### Requirements without Version Specifiers ###### +pytest +pytest-cov +beautifulsoup4 + +###### Requirements with Version Specifiers ###### +# See https://www.python.org/dev/peps/pep-0440/#version-specifiers +docopt == 0.6.1 # Version Matching. Must be version 0.6.1 +keyring >= 4.1.1 # Minimum version 4.1.1 +coverage != 3.5 # Version Exclusion. Anything except version 3.5 +Mopidy-Dirble ~= 1.1 # Compatible release. Same as >= 1.1, == 1.* + +###### Refer to other requirements files ###### +-r other-requirements.txt + +###### A particular file ###### +./downloads/numpy-1.9.2-cp34-none-win32.whl +http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl + +###### Additional Requirements without Version Specifiers ###### +# Same as 1st section, just here to show that you can put things in any order. +rejected +green +``` diff --git a/docs/html/troubleshooting/common-errors.md b/docs/html/troubleshooting/common-errors.md new file mode 100644 index 00000000000..2a74a8c5706 --- /dev/null +++ b/docs/html/troubleshooting/common-errors.md @@ -0,0 +1,3 @@ +# Common Errors + +Answers to common errors that pip's user would see, and how to resolve them. diff --git a/docs/html/troubleshooting/faq.md b/docs/html/troubleshooting/faq.md new file mode 100644 index 00000000000..d73322e3775 --- /dev/null +++ b/docs/html/troubleshooting/faq.md @@ -0,0 +1,3 @@ +# FAQ + +Q&A style answers, for more... non-technical questions about pip. diff --git a/docs/html/user_guide.rst b/docs/html/user_guide.rst index 61e0cdf0769..23893d7b642 100644 --- a/docs/html/user_guide.rst +++ b/docs/html/user_guide.rst @@ -60,76 +60,6 @@ For more information and examples, see the :ref:`pip install` reference. .. _PyPI: https://pypi.org/ -Basic Authentication Credentials -================================ - -pip supports basic authentication credentials. Basically, in the URL there is -a username and password separated by ``:``. - -``https://[username[:password]@]pypi.company.com/simple`` - -Certain special characters are not valid in the authentication part of URLs. -If the user or password part of your login credentials contain any of the -special characters -`here `_ -then they must be percent-encoded. For example, for a -user with username "user" and password "he//o" accessing a repository at -pypi.company.com, the index URL with credentials would look like: - -``https://user:he%2F%2Fo@pypi.company.com`` - -Support for percent-encoded authentication in index URLs was added in pip 10.0.0 -(in `#3236 `_). Users that must use authentication -for their Python repository on systems with older pip versions should make the latest -get-pip.py available in their environment to bootstrap pip to a recent-enough version. - -For indexes that only require single-part authentication tokens, provide the token -as the "username" and do not provide a password, for example - - -``https://0123456789abcdef@pypi.company.com`` - - -netrc Support -------------- - -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 `requests`_ which in turn delegates it to the `Python standard library`_. - -The .netrc file contains login and initialization information used by the auto-login process. -It resides in the user's home directory. The .netrc file format is simple. You specify lines -with a machine name and follow that with lines for the login and password that are -associated with that machine. Machine name is the hostname in your URL. - -An example .netrc for the host example.com with a user named 'daniel', using the password -'qwerty' would look like: - -.. code-block:: shell - - machine example.com - login daniel - password qwerty - -As mentioned in the `standard library docs `_, -only ASCII characters are allowed. Whitespace and non-printable characters are not allowed in passwords. - - -Keyring Support ---------------- - -pip also supports credentials stored in your keyring using the `keyring`_ -library. Note that ``keyring`` will need to be installed separately, as pip -does not come with it included. - -.. code-block:: shell - - pip install keyring - echo your-password | keyring set pypi.company.com your-username - pip install your-package --extra-index-url https://pypi.company.com/ - -.. _keyring: https://pypi.org/project/keyring/ - - Using a Proxy Server ==================== @@ -147,105 +77,6 @@ pip can be configured to connect through a proxy server in various ways: 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. - -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 :ref:`repeatable installations `. 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 - `_, 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:: - - git+https://myvcs.com/some_dependency@sometag#egg=SomeDependency - - 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 -`install_requires metadata -`_, -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) - `_ - - .. _`Constraints Files`: @@ -484,249 +315,6 @@ packages. For more information and examples, see the :ref:`pip search` reference. -.. _`Configuration`: - - -Configuration -============= - -.. _config-file: - -Config file ------------ - -pip allows you to set all command line option defaults in a standard ini -style config file. - -The names and locations of the configuration files vary slightly across -platforms. You may have per-user, per-virtualenv or global (shared amongst -all users) configuration: - -**Per-user**: - -* On Unix the default configuration file is: :file:`$HOME/.config/pip/pip.conf` - which respects the ``XDG_CONFIG_HOME`` environment variable. -* On macOS the configuration file is - :file:`$HOME/Library/Application Support/pip/pip.conf` - if directory ``$HOME/Library/Application Support/pip`` exists - else :file:`$HOME/.config/pip/pip.conf`. -* On Windows the configuration file is :file:`%APPDATA%\\pip\\pip.ini`. - -There is also a legacy per-user configuration file which is also respected. -To find its location: - -* On Unix and macOS the configuration file is: :file:`$HOME/.pip/pip.conf` -* On Windows the configuration file is: :file:`%HOME%\\pip\\pip.ini` - -You can set a custom path location for this config file using the environment -variable ``PIP_CONFIG_FILE``. - -**Inside a virtualenv**: - -* On Unix and macOS the file is :file:`$VIRTUAL_ENV/pip.conf` -* On Windows the file is: :file:`%VIRTUAL_ENV%\\pip.ini` - -**Global**: - -* On Unix the file may be located in :file:`/etc/pip.conf`. Alternatively - it may be 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`. -* On macOS the file is: :file:`/Library/Application Support/pip/pip.conf` -* On Windows XP the file is: - :file:`C:\\Documents and Settings\\All Users\\Application Data\\pip\\pip.ini` -* On Windows 7 and later the file is hidden, but writeable at - :file:`C:\\ProgramData\\pip\\pip.ini` -* Global configuration is not supported on Windows Vista. - -The global configuration file is shared by all Python installations. - -If multiple configuration files are found by pip then they are combined in -the following order: - -1. The global file is read -2. The per-user file is read -3. The virtualenv-specific file is read - -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. - -The names of the settings are derived from the long command line option, e.g. -if you want to use a different package index (``--index-url``) and set the -HTTP timeout (``--default-timeout``) to 60 seconds your config file would -look like this: - -.. code-block:: ini - - [global] - timeout = 60 - index-url = https://download.zope.org/ppix - -Each subcommand can be configured optionally in its own section so that every -global setting with the same name will be overridden; e.g. decreasing the -``timeout`` to ``10`` seconds when running the ``freeze`` -(:ref:`pip freeze`) command and using -``60`` seconds for all other commands is possible with: - -.. code-block:: ini - - [global] - timeout = 60 - - [freeze] - timeout = 10 - - -Boolean options like ``--ignore-installed`` or ``--no-dependencies`` can be -set like this: - -.. code-block:: 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: - -.. code-block:: ini - - [global] - no-cache-dir = false - - [install] - no-compile = no - no-warn-script-location = false - -For options which can be repeated like ``--verbose`` and ``--quiet``, -a non-negative integer can be used to represent the level to be specified: - -.. code-block:: ini - - [global] - quiet = 0 - verbose = 2 - -It is possible to append values to a section within a configuration file such as the pip.ini file. -This is applicable to appending options like ``--find-links`` or ``--trusted-host``, -which can be written on multiple lines: - -.. code-block:: 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_`` . Dashes (``-``) have to be replaced with -underscores (``_``). - -For example, to set the default timeout: - -.. tab:: Unix/macOS - - .. code-block:: shell - - export PIP_DEFAULT_TIMEOUT=60 - -.. tab:: Windows - - .. code-block:: shell - - set PIP_DEFAULT_TIMEOUT=60 - -This is the same as passing the option to pip directly: - -.. tab:: Unix/macOS - - .. code-block:: shell - - python -m pip --default-timeout=60 [...] - -.. tab:: Windows - - .. code-block:: shell - - py -m pip --default-timeout=60 [...] - -For command line options which can be repeated, use a space to separate -multiple values. For example: - -.. tab:: Unix/macOS - - .. code-block:: shell - - export PIP_FIND_LINKS="http://mirror1.example.com http://mirror2.example.com" - -.. tab:: Windows - - .. code-block:: shell - - set PIP_FIND_LINKS="http://mirror1.example.com http://mirror2.example.com" - -is the same as calling: - -.. tab:: Unix/macOS - - .. code-block:: shell - - python -m pip install --find-links=http://mirror1.example.com --find-links=http://mirror2.example.com - -.. tab:: Windows - - .. code-block:: shell - - py -m pip install --find-links=http://mirror1.example.com --find-links=http://mirror2.example.com - -Options that do not take a value, but can be repeated (such as ``--verbose``) -can be specified using the number of repetitions, so:: - - export PIP_VERBOSE=3 - -is the same as calling:: - - pip install -vvv - -.. note:: - - Environment variables set to be empty string will not be treated as false. - Please use ``no``, ``false`` or ``0`` instead. - - -.. _config-precedence: - -Config Precedence ------------------ - -Command line options have precedence over environment variables, which have -precedence over the config file. - -Within the config file, command specific sections have precedence over 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 ``[] host = bar`` - overrides the option with same name in the ``[global]`` config file section - Command Completion ================== @@ -847,256 +435,6 @@ 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 -`_, -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 -`_ variable. -This mode of installation can be turned on by specifying the :ref:`--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 - -.. _`Repeatability`: - - -Ensuring Repeatability -====================== - -pip can achieve various levels of repeatability: - -Pinned Version Numbers ----------------------- - -Pinning the 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 - -Using :ref:`pip freeze` to generate the requirements file will ensure that not -only the top-level dependencies are included but their sub-dependencies as -well, and so on. Perform the installation using :ref:`--no-deps -` for 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 PyPI and the certificate authority chain. It -also relies on indices and find-links locations not allowing -packages to change without a version increase. (PyPI does protect -against this.) - -Hash-checking Mode ------------------- - -Beyond pinning version numbers, you can add hashes against which to verify -downloaded packages:: - - 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 labor-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 vendor library, -providing easier upgrades and less VCS noise. It does not, of course, -provide the availability benefits of a private index or a vendor library. - -For more, see -:ref:`pip install\'s discussion of hash-checking mode `. - -.. _`Installation Bundle`: - -Installation Bundles --------------------- - -Using :ref:`pip wheel`, you can bundle up all of a project's dependencies, with -any compilation done, into a single archive. This allows installation when -index servers are unavailable and avoids time-consuming recompilation. Create -an archive like this:: - - $ 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" *) - -You can then install from the archive like this:: - - $ tempdir=$(mktemp -d /tmp/wheelhouse-XXXXX) - $ (cd $tempdir; tar -xvf /path/to/bundled.tar.bz2) - $ python -m pip install --force-reinstall --ignore-installed --upgrade --no-index --no-deps $tempdir/* - -Note that compiled packages are typically OS- and architecture-specific, so -these archives are not necessarily portable across machines. - -Hash-checking mode can be used along with this method to ensure that future -archives are built with identical packages. - -.. warning:: - - Finally, beware of the ``setup_requires`` keyword arg in :file:`setup.py`. - The (rare) packages that use it will cause those dependencies to be - downloaded by setuptools directly, skipping pip's protections. If you need - to use such a package, see :ref:`Controlling - setup_requires`. - .. _`Fixing conflicting dependencies`: Fixing conflicting dependencies @@ -1887,6 +1225,4 @@ announcements on the `low-traffic packaging announcements list`_ and .. _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/ -.. _requests: https://requests.readthedocs.io/en/master/user/authentication/#netrc-authentication -.. _Python standard library: https://docs.python.org/3/library/netrc.html .. _Python Windows launcher: https://docs.python.org/3/using/windows.html#launcher diff --git a/docs/pip_sphinxext.py b/docs/pip_sphinxext.py index 1ce526e0d6c..8865afa30b6 100644 --- a/docs/pip_sphinxext.py +++ b/docs/pip_sphinxext.py @@ -1,12 +1,13 @@ """pip sphinx extensions""" import optparse +import re import sys from textwrap import dedent from docutils import nodes from docutils.parsers import rst -from docutils.statemachine import ViewList +from docutils.statemachine import StringList, ViewList from pip._internal.cli import cmdoptions from pip._internal.commands import commands_dict, create_command @@ -19,14 +20,12 @@ class PipCommandUsage(rst.Directive): def run(self): cmd = create_command(self.arguments[0]) - cmd_prefix = 'python -m pip' + cmd_prefix = "python -m pip" if len(self.arguments) > 1: cmd_prefix = " ".join(self.arguments[1:]) cmd_prefix = cmd_prefix.strip('"') cmd_prefix = cmd_prefix.strip("'") - usage = dedent( - cmd.usage.replace('%prog', f'{cmd_prefix} {cmd.name}') - ).strip() + usage = dedent(cmd.usage.replace("%prog", f"{cmd_prefix} {cmd.name}")).strip() node = nodes.literal_block(usage, usage) return [node] @@ -40,20 +39,19 @@ def run(self): desc = ViewList() cmd = create_command(self.arguments[0]) description = dedent(cmd.__doc__) - for line in description.split('\n'): + for line in description.split("\n"): desc.append(line, "") self.state.nested_parse(desc, 0, node) return [node] class PipOptions(rst.Directive): - def _format_option(self, option, cmd_name=None): bookmark_line = ( - f".. _`{cmd_name}_{option._long_opts[0]}`:" - if cmd_name else - f".. _`{option._long_opts[0]}`:" - ) + ".. _`{cmd_name}_{option._long_opts[0]}`:" + if cmd_name + else ".. _`{option._long_opts[0]}`:" + ).format(**locals()) line = ".. option:: " if option._short_opts: line += option._short_opts[0] @@ -65,7 +63,7 @@ def _format_option(self, option, cmd_name=None): metavar = option.metavar or option.dest.lower() line += f" <{metavar.lower()}>" # fix defaults - opt_help = option.help.replace('%default', str(option.default)) + opt_help = option.help.replace("%default", str(option.default)) # fix paths with sys.prefix opt_help = opt_help.replace(sys.prefix, "") return [bookmark_line, "", line, "", " " + opt_help, ""] @@ -88,9 +86,7 @@ def run(self): class PipGeneralOptions(PipOptions): def process_options(self): - self._format_options( - [o() for o in cmdoptions.general_group['options']] - ) + self._format_options([o() for o in cmdoptions.general_group["options"]]) class PipIndexOptions(PipOptions): @@ -99,7 +95,7 @@ class PipIndexOptions(PipOptions): def process_options(self): cmd_name = self.arguments[0] self._format_options( - [o() for o in cmdoptions.index_group['options']], + [o() for o in cmdoptions.index_group["options"]], cmd_name=cmd_name, ) @@ -116,49 +112,127 @@ def process_options(self): class PipReqFileOptionsReference(PipOptions): - def determine_opt_prefix(self, opt_name): for command in commands_dict: cmd = create_command(command) if cmd.cmd_opts.has_option(opt_name): return command - raise KeyError(f'Could not identify prefix of opt {opt_name}') + raise KeyError(f"Could not identify prefix of opt {opt_name}") def process_options(self): for option in SUPPORTED_OPTIONS: - if getattr(option, 'deprecated', False): + if getattr(option, "deprecated", False): continue opt = option() opt_name = opt._long_opts[0] if opt._short_opts: - short_opt_name = '{}, '.format(opt._short_opts[0]) + short_opt_name = "{}, ".format(opt._short_opts[0]) else: - short_opt_name = '' + short_opt_name = "" - if option in cmdoptions.general_group['options']: - prefix = '' + if option in cmdoptions.general_group["options"]: + prefix = "" else: - prefix = '{}_'.format(self.determine_opt_prefix(opt_name)) + prefix = "{}_".format(self.determine_opt_prefix(opt_name)) self.view_list.append( - '* :ref:`{short}{long}<{prefix}{opt_name}>`'.format( + "* :ref:`{short}{long}<{prefix}{opt_name}>`".format( short=short_opt_name, long=opt_name, prefix=prefix, - opt_name=opt_name + opt_name=opt_name, ), - "\n" + "\n", ) +class PipCLIDirective(rst.Directive): + """ + - Only works when used in a MyST document. + - Requires sphinx-inline-tabs' tab directive. + """ + + has_content = True + optional_arguments = 1 + + def run(self): + node = nodes.paragraph() + node.document = self.state.document + + os_variants = { + "Linux": { + "highlighter": "console", + "executable": "python", + "prompt": "$", + }, + "MacOS": { + "highlighter": "console", + "executable": "python", + "prompt": "$", + }, + "Windows": { + "highlighter": "doscon", + "executable": "py", + "prompt": "C:>", + }, + } + + if self.arguments: + assert self.arguments == ["in-a-venv"] + in_virtual_environment = True + else: + in_virtual_environment = False + + lines = [] + # Create a tab for each OS + for os, variant in os_variants.items(): + + # Unpack the values + prompt = variant["prompt"] + highlighter = variant["highlighter"] + if in_virtual_environment: + executable = "python" + pip_spelling = "pip" + else: + executable = variant["executable"] + pip_spelling = f"{executable} -m pip" + + # Substitute the various "prompts" into the correct variants + substitution_pipeline = [ + ( + r"(^|(?<=\n))\$ python", + f"{prompt} {executable}", + ), + ( + r"(^|(?<=\n))\$ pip", + f"{prompt} {pip_spelling}", + ), + ] + content = self.block_text + for pattern, substitution in substitution_pipeline: + content = re.sub(pattern, substitution, content) + + # Write the tab + lines.append(f"````{{tab}} {os}") + lines.append(f"```{highlighter}") + lines.append(f"{content}") + lines.append("```") + lines.append("````") + + string_list = StringList(lines) + self.state.nested_parse(string_list, 0, node) + return [node] + + def setup(app): - app.add_directive('pip-command-usage', PipCommandUsage) - app.add_directive('pip-command-description', PipCommandDescription) - app.add_directive('pip-command-options', PipCommandOptions) - app.add_directive('pip-general-options', PipGeneralOptions) - app.add_directive('pip-index-options', PipIndexOptions) + app.add_directive("pip-command-usage", PipCommandUsage) + app.add_directive("pip-command-description", PipCommandDescription) + app.add_directive("pip-command-options", PipCommandOptions) + app.add_directive("pip-general-options", PipGeneralOptions) + app.add_directive("pip-index-options", PipIndexOptions) app.add_directive( - 'pip-requirements-file-options-ref-list', PipReqFileOptionsReference + "pip-requirements-file-options-ref-list", PipReqFileOptionsReference ) + app.add_directive("pip-cli", PipCLIDirective) diff --git a/news/9474.doc.rst b/news/9474.doc.rst new file mode 100644 index 00000000000..c2922424671 --- /dev/null +++ b/news/9474.doc.rst @@ -0,0 +1 @@ +pip's documentation has been rewritten. It now has an improved site structure, uses simpler language, has greater consistency across various sections and should be easier to navigate. diff --git a/noxfile.py b/noxfile.py index 165a430d14b..a530b65ba20 100644 --- a/noxfile.py +++ b/noxfile.py @@ -149,6 +149,22 @@ def get_sphinx_build_command(kind): session.run(*get_sphinx_build_command("man")) +@nox.session(name="docs-live") +def docs_live(session): + # type: (nox.Session) -> None + session.install("-e", ".") + session.install("-r", REQUIREMENTS["docs"], "sphinx-autobuild") + + session.run( + "sphinx-autobuild", + "-d=docs/build/doctrees/livehtml", + "-b=dirhtml", + "docs/html", + "docs/build/livehtml", + *session.posargs, + ) + + @nox.session def lint(session): # type: (nox.Session) -> None diff --git a/tools/requirements/docs.txt b/tools/requirements/docs.txt index a5aae67c106..aed18b5084b 100644 --- a/tools/requirements/docs.txt +++ b/tools/requirements/docs.txt @@ -1,5 +1,7 @@ sphinx == 3.2.1 furo +myst_parser +sphinx-copybutton sphinx-inline-tabs sphinxcontrib-towncrier