1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Use email.message to parse metadata

This commit is contained in:
Tzu-ping Chung 2021-07-09 23:10:32 +08:00
parent 28fff1e483
commit aee4b50021
2 changed files with 31 additions and 28 deletions

View file

@ -1,3 +1,4 @@
import email.message
import logging
import re
from typing import (
@ -52,11 +53,6 @@ class BaseDistribution(Protocol):
"""
raise NotImplementedError()
@property
def metadata_version(self) -> Optional[str]:
"""Value of "Metadata-Version:" in the distribution, if available."""
raise NotImplementedError()
@property
def canonical_name(self) -> str:
raise NotImplementedError()
@ -89,12 +85,27 @@ class BaseDistribution(Protocol):
"""Read a file in the .dist-info (or .egg-info) directory."""
raise NotImplementedError()
def iter_dependencies(self, extras: Collection[str]) -> Iterable[Requirement]:
raise NotImplementedError()
def iter_entry_points(self) -> Iterable[BaseEntryPoint]:
raise NotImplementedError()
@property
def metadata(self) -> email.message.Message:
"""Metadata of distribution parsed from e.g. METADATA or PKG-INFO."""
raise NotImplementedError()
@property
def metadata_version(self) -> Optional[str]:
"""Value of "Metadata-Version:" in the distribution, if available."""
return self.metadata.get("Metadata-Version")
def iter_dependencies(self, extras: Collection[str]) -> Iterable[Requirement]:
for value in self.metadata.get_all("Requires-Dist"):
requirement = Requirement(value)
marker = requirement.marker
if marker and any(marker.evaluate({"extra": extra}) for extra in extras):
continue
yield requirement
class BaseEnvironment:
"""An environment containing distributions to introspect."""

View file

@ -1,4 +1,5 @@
import logging
import email.message
import zipfile
from typing import Collection, Iterable, Iterator, List, NamedTuple, Optional
@ -10,7 +11,7 @@ from pip._vendor.packaging.version import parse as parse_version
from pip._internal.models.direct_url import DirectUrl
from pip._internal.utils import misc # TODO: Move definition here.
from pip._internal.utils.direct_url_helpers import dist_get_direct_url
from pip._internal.utils.packaging import get_installer
from pip._internal.utils.packaging import get_installer, get_metadata
from pip._internal.utils.wheel import pkg_resources_distribution_for_wheel
from .base import BaseDistribution, BaseEntryPoint, BaseEnvironment, DistributionVersion
@ -38,13 +39,6 @@ class Distribution(BaseDistribution):
def location(self) -> Optional[str]:
return self._dist.location
@property
def metadata_version(self) -> Optional[str]:
for line in self._dist.get_metadata_lines(self._dist.PKG_INFO):
if line.lower().startswith("metadata-version:"):
return line.split(":", 1)[-1].strip()
return None
@property
def canonical_name(self) -> str:
return canonicalize_name(self._dist.project_name)
@ -73,18 +67,6 @@ class Distribution(BaseDistribution):
def in_usersite(self) -> bool:
return misc.dist_in_usersite(self._dist)
def iter_dependencies(self, extras: Collection[str]) -> Iterable[Requirement]:
# pkg_resources raises on invalid extras, so we sanitize.
requested_extras = set(extras)
valid_extras = requested_extras & set(self._dist.extras)
for invalid_extra in requested_extras ^ valid_extras:
logger.warning(
"Invalid extra %r for package %r discarded",
invalid_extra,
self.canonical_name,
)
return self._dist.requires(extras)
def read_text(self, name: str) -> str:
return self._dist.get_metadata(name)
@ -94,6 +76,16 @@ class Distribution(BaseDistribution):
name, _, value = str(entry_point).partition("=")
yield EntryPoint(name=name.strip(), value=value.strip(), group=group)
@property
def metadata(self) -> email.message.Message:
return get_metadata(self._dist)
def iter_dependencies(self, extras: Collection[str]) -> Iterable[Requirement]:
"""pkg_resources caches this for performance so we take advantage of it."""
if extras: # pkg_resources raises on invalid extras, so we sanitize.
extras = set(extras).intersection(self._dist.extras)
return self._dist.requires(extras)
class Environment(BaseEnvironment):
def __init__(self, ws: pkg_resources.WorkingSet) -> None: