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

Skip dist if metadata does not have a valid name #11353

Merged
merged 1 commit into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions news/11352.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Ignore distributions with invalid ``Name`` in metadata instead of crashing, when
using the ``importlib.metadata`` backend.
14 changes: 13 additions & 1 deletion src/pip/_internal/metadata/importlib/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
from typing import Any, Optional, Protocol, cast


class BadMetadata(ValueError):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also derive from PipError?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the convention is. This is supposed to be somewhat internal to the metadata subpackage and shouldn’t be uncaught.

def __init__(self, dist: importlib.metadata.Distribution, *, reason: str) -> None:
self.dist = dist
self.reason = reason

def __str__(self) -> str:
return f"Bad metadata in {self.dist} ({self.reason})"


class BasePath(Protocol):
"""A protocol that various path objects conform.

Expand Down Expand Up @@ -40,4 +49,7 @@ def get_dist_name(dist: importlib.metadata.Distribution) -> str:
The ``name`` attribute is only available in Python 3.10 or later. We are
targeting exactly that, but Mypy does not know this.
"""
return cast(Any, dist).name
name = cast(Any, dist).name
if not isinstance(name, str):
raise BadMetadata(dist, reason="invalid metadata entry 'name'")
return name
14 changes: 11 additions & 3 deletions src/pip/_internal/metadata/importlib/_envs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import functools
import importlib.metadata
import logging
import os
import pathlib
import sys
Expand All @@ -14,9 +15,11 @@
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.filetypes import WHEEL_EXTENSION

from ._compat import BasePath, get_dist_name, get_info_location
from ._compat import BadMetadata, BasePath, get_dist_name, get_info_location
from ._dists import Distribution

logger = logging.getLogger(__name__)


def _looks_like_wheel(location: str) -> bool:
if not location.endswith(WHEEL_EXTENSION):
Expand Down Expand Up @@ -56,11 +59,16 @@ def _find_impl(self, location: str) -> Iterator[FoundResult]:
# To know exactly where we find a distribution, we have to feed in the
# paths one by one, instead of dumping the list to importlib.metadata.
for dist in importlib.metadata.distributions(path=[location]):
normalized_name = canonicalize_name(get_dist_name(dist))
info_location = get_info_location(dist)
try:
raw_name = get_dist_name(dist)
except BadMetadata as e:
logger.warning("Skipping %s due to %s", info_location, e.reason)
continue
normalized_name = canonicalize_name(raw_name)
if normalized_name in self._found_names:
continue
self._found_names.add(normalized_name)
info_location = get_info_location(dist)
yield dist, info_location

def find(self, location: str) -> Iterator[BaseDistribution]:
Expand Down