Skip to content

Commit

Permalink
importlib: Read distribution name/version from metadata directory nam…
Browse files Browse the repository at this point in the history
…e, if possible

importlib does not cache metadata in-memory, so querying even simple
attributes like distribution names and versions can quickly become
expensive (as each access requires reading METADATA). Fortunately,
`Distribution.canonical_name` is optimized to parse the metadata
directory name to query the name if possible. This commit extends this
optimization to the finder implementation and version attribute.
  • Loading branch information
ichard26 committed Apr 28, 2024
1 parent e884c00 commit d380180
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 14 deletions.
Empty file.
8 changes: 8 additions & 0 deletions src/pip/_internal/metadata/importlib/_compat.py
@@ -1,4 +1,5 @@
import importlib.metadata
import os
from typing import Any, Optional, Protocol, cast


Expand Down Expand Up @@ -49,6 +50,13 @@ 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.
"""
# Try to get the name from the metadata directory name.
# This is much faster than reading metadata.
if info_location := get_info_location(dist):
stem, suffix = os.path.splitext(info_location.name)
if suffix in (".dist-info", ".egg-info"):
return stem.split("-", 1)[0]

name = cast(Any, dist).name
if not isinstance(name, str):
raise BadMetadata(dist, reason="invalid metadata entry 'name'")
Expand Down
23 changes: 9 additions & 14 deletions src/pip/_internal/metadata/importlib/_dists.py
Expand Up @@ -153,25 +153,20 @@ def installed_location(self) -> Optional[str]:
return None
return normalize_path(str(self._installed_location))

def _get_dist_name_from_location(self) -> Optional[str]:
"""Try to get the name from the metadata directory name.
This is much faster than reading metadata.
"""
if self._info_location is None:
return None
stem, suffix = os.path.splitext(self._info_location.name)
if suffix not in (".dist-info", ".egg-info"):
return None
return stem.split("-", 1)[0]

@property
def canonical_name(self) -> NormalizedName:
name = self._get_dist_name_from_location() or get_dist_name(self._dist)
return canonicalize_name(name)
return canonicalize_name(get_dist_name(self._dist))

@property
def version(self) -> DistributionVersion:
# Try to get the version from the metadata directory name.
# This is much faster than reading metadata.
if self._info_location is not None:
stem, suffix = os.path.splitext(self._info_location.name)
if suffix in (".dist-info", ".egg-info"):
version = stem.split("-", 1)[1]
return parse_version(version)

return parse_version(self._dist.version)

def is_file(self, path: InfoPath) -> bool:
Expand Down

0 comments on commit d380180

Please sign in to comment.