Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pip fails to log an existing distribution if its location attribute is None #11704

Closed
1 task done
daniil-konovalenko opened this issue Jan 6, 2023 · 5 comments · Fixed by #11710
Closed
1 task done
Labels
state: awaiting PR Feature discussed, PR is needed type: bug A confirmed bug or unintended behavior

Comments

@daniil-konovalenko
Copy link
Contributor

daniil-konovalenko commented Jan 6, 2023

Description

I've encountered an issue with how pip handles custom Distributions that have their location atrribute set to None.
As far as I understand, it's allowed, because the location type is here Optional:

def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]:
"""Find the path to the distribution's metadata directory.
HACK: This relies on importlib.metadata's private ``_path`` attribute. Not
all distributions exist on disk, so importlib.metadata is correct to not
expose the attribute as public. But pip's code base is old and not as clean,
so we do this to avoid having to rewrite too many things. Hopefully we can
eliminate this some day.
"""
return getattr(d, "_path", None)

And

Not all distributions exist on disk

This is exactly my case — I have a custom meta_path finder that loads Distributions on the fly.
When I'm trying to install an already installed package, pip finds an existing distribution and tries to log a message. It fails here when it tries to convert None to an absolute path (see below for the traceback).

s += " in {}".format(display_path(self.satisfied_by.location))

I can fix this internally by overriding the Distribution._path attribute, but I feel that it's better to resolve the underlying issue in pip itself. Perhaps we could fall back to a placeholder like <memory> in case the location is None.

I realise that this is a pretty rare case, and I'll be happy to submit a PR, if the proposed solution is acceptable.

Expected behavior

I think it's better to display a placeholder in case the location is None. Something like

$ pip install example
Requirement already satisfied: example in <memory> (1.0.0)

pip version

22.3.1

Python version

3.11.1

OS

macOS 12.6.2

How to Reproduce

  • create a fresh virtualenv: python -m venv venv
  • create a sitecustomize.py file in the virtualenv's site-packages directory with with the following contents:
import sys
from importlib.metadata import Distribution, DistributionFinder


EXAMPLE_METADATA = '''Metadata-Version: 2.1
Name: example
Version: 1.0.0

'''


class ExampleDistribution(Distribution):
    def locate_file(self, path):
        return path

    def read_text(self, filename):
        if filename == 'METADATA':
            return EXAMPLE_METADATA


class CustomFinder(DistributionFinder):
    def find_distributions(self, context=None):
        return [ExampleDistribution()]


sys.meta_path.append(CustomFinder())
  • run pip install example

Output

$ pip install example
ERROR: Exception:
Traceback (most recent call last):
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 158, in _make_candidate_from_dist
    base = self._installed_candidate_cache[dist.canonical_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
KeyError: 'example'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/cli/base_command.py", line 160, in exc_logging_wrapper
    status = run_func(*args)
             ^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/cli/req_command.py", line 247, in wrapper
    return func(self, options, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/commands/install.py", line 400, in run
    requirement_set = resolver.resolve(
                      ^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 92, in resolve
    result = self._result = resolver.resolve(
                            ^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_vendor/resolvelib/resolvers.py", line 481, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_vendor/resolvelib/resolvers.py", line 348, in resolve
    self._add_to_criteria(self.state.criteria, r, parent=None)
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_vendor/resolvelib/resolvers.py", line 147, in _add_to_criteria
    matches = self._p.find_matches(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/provider.py", line 224, in find_matches
    return self._factory.find_candidates(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 424, in find_candidates
    return self._iter_found_candidates(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 320, in _iter_found_candidates
    _get_installed_candidate(),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 268, in _get_installed_candidate
    candidate = self._make_candidate_from_dist(
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 160, in _make_candidate_from_dist
    base = AlreadyInstalledCandidate(dist, template, factory=self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 354, in __init__
    factory.preparer.prepare_installed_requirement(self._ireq, skip_reason)
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/operations/prepare.py", line 656, in prepare_installed_requirement
    logger.info(
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 1489, in info
    self._log(INFO, msg, args, **kwargs)
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 1634, in _log
    self.handle(record)
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 1644, in handle
    self.callHandlers(record)
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 1706, in callHandlers
    hdlr.handle(record)
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 978, in handle
    self.emit(record)
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/utils/logging.py", line 168, in emit
    message = self.format(record)
              ^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 953, in format
    return fmt.format(record)
           ^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/utils/logging.py", line 112, in format
    formatted = super().format(record)
                ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 687, in format
    record.message = record.getMessage()
                     ^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/.pyenv/versions/3.11.1/lib/python3.11/logging/__init__.py", line 377, in getMessage
    msg = msg % self.args
          ~~~~^~~~~~~~~~~
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/req/req_install.py", line 198, in __str__
    s += " in {}".format(display_path(self.satisfied_by.location))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/danielkono/personal/python/pip-none-path-example/venv/lib/python3.11/site-packages/pip/_internal/utils/misc.py", line 154, in display_path
    path = os.path.normcase(os.path.abspath(path))
                            ^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 399, in abspath
TypeError: expected str, bytes or os.PathLike object, not NoneType

Code of Conduct

@daniil-konovalenko daniil-konovalenko added S: needs triage Issues/PRs that need to be triaged type: bug A confirmed bug or unintended behavior labels Jan 6, 2023
@daniil-konovalenko daniil-konovalenko changed the title pip fails to log an existing distribution if it's location attribute is None pip fails to log an existing distribution if its location attribute is None Jan 6, 2023
@uranusjr
Copy link
Member

uranusjr commented Jan 6, 2023

Definitely a bug. Pull request would be most welcomed. I am curious why Mypy does not already catch this.

@uranusjr uranusjr removed the S: needs triage Issues/PRs that need to be triaged label Jan 6, 2023
@daniil-konovalenko
Copy link
Contributor Author

I am curious why Mypy does not already catch this.

That's a good question, I'll try to look into it while working on the PR

@daniil-konovalenko
Copy link
Contributor Author

mypy seems to think it's an str🤔

        if self.satisfied_by is not None:
            reveal_type(self.satisfied_by.location)
            ...

Mypy output:

src/pip/_internal/req/req_install.py:198: note: Revealed type is "builtins.str"

@daniil-konovalenko
Copy link
Contributor Author

Okay, found why mypy didn't catch it:

# mypy: strict-optional=False

@daniil-konovalenko
Copy link
Contributor Author

Okay, found why mypy didn't catch it:

# mypy: strict-optional=False

A relevant PR that enables this check: #11379

inmantaci pushed a commit to inmanta/inmanta-core that referenced this issue Jan 31, 2023
Bumps [pip](https://github.com/pypa/pip) from 22.3.1 to 23.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/pypa/pip/blob/main/NEWS.rst">pip's changelog</a>.</em></p>
<blockquote>
<h1>23.0 (2023-01-30)</h1>
<h2>Features</h2>
<ul>
<li>Change the hashes in the installation report to be a mapping. Emit the
<code>archive_info.hashes</code> dictionary in <code>direct_url.json</code>. (<code>[#11312](pypa/pip#11312) &lt;https://github.com/pypa/pip/issues/11312&gt;</code>_)</li>
<li>Implement logic to read the <code>EXTERNALLY-MANAGED</code> file as specified in PEP 668.
This allows a downstream Python distributor to prevent users from using pip to
modify the externally managed environment. (<code>[#11381](pypa/pip#11381) &lt;https://github.com/pypa/pip/issues/11381&gt;</code>_)</li>
<li>Enable the use of <code>keyring</code> found on <code>PATH</code>. This allows <code>keyring</code>
installed using <code>pipx</code> to be used by <code>pip</code>. (<code>[#11589](pypa/pip#11589) &lt;https://github.com/pypa/pip/issues/11589&gt;</code>_)</li>
<li>The inspect and installation report formats are now declared stabled, and their version
has been bumped from <code>0</code> to <code>1</code>. (<code>[#11757](pypa/pip#11757) &lt;https://github.com/pypa/pip/issues/11757&gt;</code>_)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li>Wheel cache behavior is restored to match previous versions, allowing the
cache to find existing entries. (<code>[#11527](pypa/pip#11527) &lt;https://github.com/pypa/pip/issues/11527&gt;</code>_)</li>
<li>Use the &quot;venv&quot; scheme if available to obtain prefixed lib paths. (<code>[#11598](pypa/pip#11598) &lt;https://github.com/pypa/pip/issues/11598&gt;</code>_)</li>
<li>Deprecated a historical ambiguity in how <code>egg</code> fragments in URL-style
requirements are formatted and handled. <code>egg</code> fragments that do not look
like PEP 508 names now produce a deprecation warning. (<code>[#11617](pypa/pip#11617) &lt;https://github.com/pypa/pip/issues/11617&gt;</code>_)</li>
<li>Fix scripts path in isolated build environment on Debian. (<code>[#11623](pypa/pip#11623) &lt;https://github.com/pypa/pip/issues/11623&gt;</code>_)</li>
<li>Make <code>pip show</code> show the editable location if package is editable (<code>[#11638](pypa/pip#11638) &lt;https://github.com/pypa/pip/issues/11638&gt;</code>_)</li>
<li>Stop checking that <code>wheel</code> is present when <code>build-system.requires</code>
is provided without <code>build-system.build-backend</code> as <code>setuptools</code>
(which we still check for) will inject it anyway. (<code>[#11673](pypa/pip#11673) &lt;https://github.com/pypa/pip/issues/11673&gt;</code>_)</li>
<li>Fix an issue when an already existing in-memory distribution would cause
exceptions in <code>pip install</code> (<code>[#11704](pypa/pip#11704) &lt;https://github.com/pypa/pip/issues/11704&gt;</code>_)</li>
</ul>
<h2>Vendored Libraries</h2>
<ul>
<li>Upgrade certifi to 2022.12.7</li>
<li>Upgrade chardet to 5.1.0</li>
<li>Upgrade colorama to 0.4.6</li>
<li>Upgrade distro to 1.8.0</li>
<li>Remove pep517 from vendored packages</li>
<li>Upgrade platformdirs to 2.6.2</li>
<li>Add pyproject-hooks 1.0.0</li>
<li>Upgrade requests to 2.28.2</li>
<li>Upgrade rich to 12.6.0</li>
<li>Upgrade urllib3 to 1.26.14</li>
</ul>
<h2>Improved Documentation</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/pypa/pip/commit/368c7b4c557e673b05b0f8cffc967d3e333eee19"><code>368c7b4</code></a> Bump for release</li>
<li><a href="https://github.com/pypa/pip/commit/aa94ccadb45d6ee44defea8a82bd5b647ccba799"><code>aa94cca</code></a> Update AUTHORS.txt</li>
<li><a href="https://github.com/pypa/pip/commit/60ce5c0943c303e48f0aed8bce650f725dcd222d"><code>60ce5c0</code></a> Fix the kind of news fragment</li>
<li><a href="https://github.com/pypa/pip/commit/e3e7bc34eb486622ebbb6412afc98ee57fcbff4a"><code>e3e7bc3</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11766">#11766</a> from uranusjr/upgrade-pre-commit-isort</li>
<li><a href="https://github.com/pypa/pip/commit/b653b129c56b29ad565886c1f423de89639d20f3"><code>b653b12</code></a> Bump pre-commit isort to 5.12.0</li>
<li><a href="https://github.com/pypa/pip/commit/a2a4feb588edc7233ae262d76b2c7291d6857a31"><code>a2a4feb</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11761">#11761</a> from sbidoul/direct-url-hashes-part-3-sbi</li>
<li><a href="https://github.com/pypa/pip/commit/ec7eb6f179866151f148c7695fc773e66b8c3adc"><code>ec7eb6f</code></a> Add version history to inspect and install report docs</li>
<li><a href="https://github.com/pypa/pip/commit/169511e68eb64efff5705305f72b0c53d7bff580"><code>169511e</code></a> Update direct URL hashes examples</li>
<li><a href="https://github.com/pypa/pip/commit/efedf09c4967dcbe3105e3746aaca7bfb55d605f"><code>efedf09</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11759">#11759</a> from pradyunsg/fix-keyring-auth</li>
<li><a href="https://github.com/pypa/pip/commit/60a45984404460192067f3990e0258deeeafa636"><code>60a4598</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11758">#11758</a> from pradyunsg/vendoring-update</li>
<li>Additional commits viewable in <a href="https://github.com/pypa/pip/compare/22.3.1...23.0">compare view</a></li>
</ul>
</details>
<br />

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

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

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

---

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

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

</details>
mergify bot pushed a commit to aws/jsii that referenced this issue Feb 8, 2023
…s/@jsii/python-runtime (#3950)

Updates the requirements on [pip](https://github.com/pypa/pip) to permit the latest version.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/pypa/pip/blob/main/NEWS.rst">pip's changelog</a>.</em></p>
<blockquote>
<h1>23.0 (2023-01-30)</h1>
<h2>Features</h2>
<ul>
<li>Change the hashes in the installation report to be a mapping. Emit the
<code>archive_info.hashes</code> dictionary in <code>direct_url.json</code>. (<code>[#11312](pypa/pip#11312) &lt;https://github.com/pypa/pip/issues/11312&gt;</code>_)</li>
<li>Implement logic to read the <code>EXTERNALLY-MANAGED</code> file as specified in PEP 668.
This allows a downstream Python distributor to prevent users from using pip to
modify the externally managed environment. (<code>[#11381](pypa/pip#11381) &lt;https://github.com/pypa/pip/issues/11381&gt;</code>_)</li>
<li>Enable the use of <code>keyring</code> found on <code>PATH</code>. This allows <code>keyring</code>
installed using <code>pipx</code> to be used by <code>pip</code>. (<code>[#11589](pypa/pip#11589) &lt;https://github.com/pypa/pip/issues/11589&gt;</code>_)</li>
<li>The inspect and installation report formats are now declared stabled, and their version
has been bumped from <code>0</code> to <code>1</code>. (<code>[#11757](pypa/pip#11757) &lt;https://github.com/pypa/pip/issues/11757&gt;</code>_)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li>Wheel cache behavior is restored to match previous versions, allowing the
cache to find existing entries. (<code>[#11527](pypa/pip#11527) &lt;https://github.com/pypa/pip/issues/11527&gt;</code>_)</li>
<li>Use the &quot;venv&quot; scheme if available to obtain prefixed lib paths. (<code>[#11598](pypa/pip#11598) &lt;https://github.com/pypa/pip/issues/11598&gt;</code>_)</li>
<li>Deprecated a historical ambiguity in how <code>egg</code> fragments in URL-style
requirements are formatted and handled. <code>egg</code> fragments that do not look
like PEP 508 names now produce a deprecation warning. (<code>[#11617](pypa/pip#11617) &lt;https://github.com/pypa/pip/issues/11617&gt;</code>_)</li>
<li>Fix scripts path in isolated build environment on Debian. (<code>[#11623](pypa/pip#11623) &lt;https://github.com/pypa/pip/issues/11623&gt;</code>_)</li>
<li>Make <code>pip show</code> show the editable location if package is editable (<code>[#11638](pypa/pip#11638) &lt;https://github.com/pypa/pip/issues/11638&gt;</code>_)</li>
<li>Stop checking that <code>wheel</code> is present when <code>build-system.requires</code>
is provided without <code>build-system.build-backend</code> as <code>setuptools</code>
(which we still check for) will inject it anyway. (<code>[#11673](pypa/pip#11673) &lt;https://github.com/pypa/pip/issues/11673&gt;</code>_)</li>
<li>Fix an issue when an already existing in-memory distribution would cause
exceptions in <code>pip install</code> (<code>[#11704](pypa/pip#11704) &lt;https://github.com/pypa/pip/issues/11704&gt;</code>_)</li>
</ul>
<h2>Vendored Libraries</h2>
<ul>
<li>Upgrade certifi to 2022.12.7</li>
<li>Upgrade chardet to 5.1.0</li>
<li>Upgrade colorama to 0.4.6</li>
<li>Upgrade distro to 1.8.0</li>
<li>Remove pep517 from vendored packages</li>
<li>Upgrade platformdirs to 2.6.2</li>
<li>Add pyproject-hooks 1.0.0</li>
<li>Upgrade requests to 2.28.2</li>
<li>Upgrade rich to 12.6.0</li>
<li>Upgrade urllib3 to 1.26.14</li>
</ul>
<h2>Improved Documentation</h2>

</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/pypa/pip/commit/368c7b4c557e673b05b0f8cffc967d3e333eee19"><code>368c7b4</code></a> Bump for release</li>
<li><a href="https://github.com/pypa/pip/commit/aa94ccadb45d6ee44defea8a82bd5b647ccba799"><code>aa94cca</code></a> Update AUTHORS.txt</li>
<li><a href="https://github.com/pypa/pip/commit/60ce5c0943c303e48f0aed8bce650f725dcd222d"><code>60ce5c0</code></a> Fix the kind of news fragment</li>
<li><a href="https://github.com/pypa/pip/commit/e3e7bc34eb486622ebbb6412afc98ee57fcbff4a"><code>e3e7bc3</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11766">#11766</a> from uranusjr/upgrade-pre-commit-isort</li>
<li><a href="https://github.com/pypa/pip/commit/b653b129c56b29ad565886c1f423de89639d20f3"><code>b653b12</code></a> Bump pre-commit isort to 5.12.0</li>
<li><a href="https://github.com/pypa/pip/commit/a2a4feb588edc7233ae262d76b2c7291d6857a31"><code>a2a4feb</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11761">#11761</a> from sbidoul/direct-url-hashes-part-3-sbi</li>
<li><a href="https://github.com/pypa/pip/commit/ec7eb6f179866151f148c7695fc773e66b8c3adc"><code>ec7eb6f</code></a> Add version history to inspect and install report docs</li>
<li><a href="https://github.com/pypa/pip/commit/169511e68eb64efff5705305f72b0c53d7bff580"><code>169511e</code></a> Update direct URL hashes examples</li>
<li><a href="https://github.com/pypa/pip/commit/efedf09c4967dcbe3105e3746aaca7bfb55d605f"><code>efedf09</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11759">#11759</a> from pradyunsg/fix-keyring-auth</li>
<li><a href="https://github.com/pypa/pip/commit/60a45984404460192067f3990e0258deeeafa636"><code>60a4598</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/pypa/pip/issues/11758">#11758</a> from pradyunsg/vendoring-update</li>
<li>Additional commits viewable in <a href="https://github.com/pypa/pip/compare/22.3...23.0">compare view</a></li>
</ul>
</details>
<br />


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

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

---

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

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


</details>
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 17, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
state: awaiting PR Feature discussed, PR is needed type: bug A confirmed bug or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants