Skip to content

Migrate to importlib-metadata #7705

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

Closed
wants to merge 3 commits into from
Closed
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
Empty file.
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ drop = [
"bin/",
# interpreter and OS specific msgpack libs
"msgpack/*.so",
# importlib-metadata carries a bunch of test data we don't need
"importlib_metadata/docs/",
"importlib_metadata/tests/",
# unneeded parts of setuptools
"easy_install.py",
"setuptools",
Expand Down
28 changes: 28 additions & 0 deletions src/pip/_internal/metadata/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
This package wraps the vendored importlib_metadata and pkg_resources to
provide a (mostly) compatible shim.

The pkg_resources implementation is used on Python 2, otherwise we use
importlib_metadata.
"""

import sys

from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if sys.version_info >= (3, 5):
from pip._internal.metadata import _importlib_metadata as impl
else:
from pip._internal.metadata import _pkg_resources as impl

if MYPY_CHECK_RUNNING:
from typing import Union
from pip._internal.metadata import _importlib_metadata as _i
from pip._internal.metadata import _pkg_resources as _p

Distribution = Union[_i.Distribution, _p.Distribution]


get_file_lines = impl.get_file_lines

get_metadata = impl.get_metadata
19 changes: 19 additions & 0 deletions src/pip/_internal/metadata/_importlib_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
from email.message import Message
from typing import Iterator, Optional
from pip._vendor.importlib_metadata import Distribution


def get_metadata(dist):
# type: (Distribution) -> Message
return dist.metadata


def get_file_lines(dist, name):
# type: (Distribution, str) -> Optional[Iterator[str]]
content = dist.read_text("INSTALLER")
if not content:
return None
return content.splitlines()
52 changes: 52 additions & 0 deletions src/pip/_internal/metadata/_pkg_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from __future__ import absolute_import

import logging
from email.parser import FeedParser

from pip._vendor import pkg_resources

from pip._internal.exceptions import NoneMetadataError
from pip._internal.utils.misc import display_path
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
from typing import Iterator, Optional
from email.message import Message
from pip._vendor.pkg_resources import Distribution


logger = logging.getLogger(__name__)


def get_metadata(dist):
# type: (Distribution) -> Message
"""
:raises NoneMetadataError: if the distribution reports `has_metadata()`
True but `get_metadata()` returns None.
"""
metadata_name = 'METADATA'
if (isinstance(dist, pkg_resources.DistInfoDistribution) and
dist.has_metadata(metadata_name)):
metadata = dist.get_metadata(metadata_name)
elif dist.has_metadata('PKG-INFO'):
metadata_name = 'PKG-INFO'
metadata = dist.get_metadata(metadata_name)
else:
logger.warning("No metadata found in %s", display_path(dist.location))
metadata = ''

if metadata is None:
raise NoneMetadataError(dist, metadata_name)

feed_parser = FeedParser()
# The following line errors out if with a "NoneType" TypeError if
# passed metadata=None.
feed_parser.feed(metadata)
return feed_parser.close()


def get_file_lines(dist, name):
# type: (Distribution, str) -> Optional[Iterator[str]]
if not dist.has_metadata(name):
return None
return dist.get_metadata_lines(name)
54 changes: 9 additions & 45 deletions src/pip/_internal/utils/packaging.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
from __future__ import absolute_import

import logging
from email.parser import FeedParser

from pip._vendor import pkg_resources
from pip._vendor.packaging import specifiers, version

from pip._internal.exceptions import NoneMetadataError
from pip._internal.utils.misc import display_path
from pip._internal.metadata import get_file_lines, get_metadata
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
from typing import Optional, Tuple
from email.message import Message
from pip._vendor.pkg_resources import Distribution


logger = logging.getLogger(__name__)
from pip._internal.metadata import Distribution


def check_requires_python(requires_python, version_info):
Expand All @@ -41,35 +30,8 @@ def check_requires_python(requires_python, version_info):
return python_version in requires_python_specifier


def get_metadata(dist):
# type: (Distribution) -> Message
"""
:raises NoneMetadataError: if the distribution reports `has_metadata()`
True but `get_metadata()` returns None.
"""
metadata_name = 'METADATA'
if (isinstance(dist, pkg_resources.DistInfoDistribution) and
dist.has_metadata(metadata_name)):
metadata = dist.get_metadata(metadata_name)
elif dist.has_metadata('PKG-INFO'):
metadata_name = 'PKG-INFO'
metadata = dist.get_metadata(metadata_name)
else:
logger.warning("No metadata found in %s", display_path(dist.location))
metadata = ''

if metadata is None:
raise NoneMetadataError(dist, metadata_name)

feed_parser = FeedParser()
# The following line errors out if with a "NoneType" TypeError if
# passed metadata=None.
feed_parser.feed(metadata)
return feed_parser.close()


def get_requires_python(dist):
# type: (pkg_resources.Distribution) -> Optional[str]
# type: (Distribution) -> Optional[str]
"""
Return the "Requires-Python" metadata for a distribution, or None
if not present.
Expand All @@ -87,8 +49,10 @@ def get_requires_python(dist):

def get_installer(dist):
# type: (Distribution) -> str
if dist.has_metadata('INSTALLER'):
for line in dist.get_metadata_lines('INSTALLER'):
if line.strip():
return line.strip()
lines = get_file_lines(dist, 'INSTALLER')
if lines is None:
return ''
for line in lines:
if line.strip():
return line.strip()
return ''
Loading