mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Add DictMetadata for adapting zip data to Distribution
pkg_resources.Distribution classes delegate to the IMetadataProvider implementation provided at construction. This is the one we'll use for adapting a ZipFile to pkg_resources.DistInfoDistribution.
This commit is contained in:
parent
c3ab0a0b13
commit
20706eb93f
2 changed files with 101 additions and 0 deletions
44
src/pip/_internal/utils/pkg_resources.py
Normal file
44
src/pip/_internal/utils/pkg_resources.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from pip._vendor.pkg_resources import yield_lines
|
||||||
|
from pip._vendor.six import ensure_str
|
||||||
|
|
||||||
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||||
|
|
||||||
|
if MYPY_CHECK_RUNNING:
|
||||||
|
from typing import Dict, Iterable, List
|
||||||
|
|
||||||
|
|
||||||
|
class DictMetadata(object):
|
||||||
|
"""IMetadataProvider that reads metadata files from a dictionary.
|
||||||
|
"""
|
||||||
|
def __init__(self, metadata):
|
||||||
|
# type: (Dict[str, bytes]) -> None
|
||||||
|
self._metadata = metadata
|
||||||
|
|
||||||
|
def has_metadata(self, name):
|
||||||
|
# type: (str) -> bool
|
||||||
|
return name in self._metadata
|
||||||
|
|
||||||
|
def get_metadata(self, name):
|
||||||
|
# type: (str) -> str
|
||||||
|
try:
|
||||||
|
return ensure_str(self._metadata[name])
|
||||||
|
except UnicodeDecodeError as e:
|
||||||
|
# Mirrors handling done in pkg_resources.NullProvider.
|
||||||
|
e.reason += " in {} file".format(name)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def get_metadata_lines(self, name):
|
||||||
|
# type: (str) -> Iterable[str]
|
||||||
|
return yield_lines(self.get_metadata(name))
|
||||||
|
|
||||||
|
def metadata_isdir(self, name):
|
||||||
|
# type: (str) -> bool
|
||||||
|
return False
|
||||||
|
|
||||||
|
def metadata_listdir(self, name):
|
||||||
|
# type: (str) -> List[str]
|
||||||
|
return []
|
||||||
|
|
||||||
|
def run_script(self, script_name, namespace):
|
||||||
|
# type: (str, str) -> None
|
||||||
|
pass
|
57
tests/unit/test_utils_pkg_resources.py
Normal file
57
tests/unit/test_utils_pkg_resources.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
from email.message import Message
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from pip._vendor.pkg_resources import DistInfoDistribution, Requirement
|
||||||
|
from pip._vendor.six import ensure_binary
|
||||||
|
|
||||||
|
from pip._internal.utils.packaging import get_metadata, get_requires_python
|
||||||
|
from pip._internal.utils.pkg_resources import DictMetadata
|
||||||
|
from tests.lib import skip_if_python2
|
||||||
|
|
||||||
|
|
||||||
|
def test_dict_metadata_works():
|
||||||
|
name = "simple"
|
||||||
|
version = "0.1.0"
|
||||||
|
require_a = "a==1.0"
|
||||||
|
require_b = "b==1.1; extra == 'also_b'"
|
||||||
|
requires = [require_a, require_b, "c==1.2; extra == 'also_c'"]
|
||||||
|
extras = ["also_b", "also_c"]
|
||||||
|
requires_python = ">=3"
|
||||||
|
|
||||||
|
metadata = Message()
|
||||||
|
metadata["Name"] = name
|
||||||
|
metadata["Version"] = version
|
||||||
|
for require in requires:
|
||||||
|
metadata["Requires-Dist"] = require
|
||||||
|
for extra in extras:
|
||||||
|
metadata["Provides-Extra"] = extra
|
||||||
|
metadata["Requires-Python"] = requires_python
|
||||||
|
|
||||||
|
inner_metadata = DictMetadata({
|
||||||
|
"METADATA": ensure_binary(metadata.as_string())
|
||||||
|
})
|
||||||
|
dist = DistInfoDistribution(
|
||||||
|
location="<in-memory>", metadata=inner_metadata, project_name=name
|
||||||
|
)
|
||||||
|
|
||||||
|
assert name == dist.project_name
|
||||||
|
assert version == dist.version
|
||||||
|
assert set(extras) == set(dist.extras)
|
||||||
|
assert [Requirement.parse(require_a)] == dist.requires([])
|
||||||
|
assert [
|
||||||
|
Requirement.parse(require_a), Requirement.parse(require_b)
|
||||||
|
] == dist.requires(["also_b"])
|
||||||
|
assert metadata.as_string() == get_metadata(dist).as_string()
|
||||||
|
assert requires_python == get_requires_python(dist)
|
||||||
|
|
||||||
|
|
||||||
|
# Metadata is not decoded on Python 2, so no chance for error.
|
||||||
|
@skip_if_python2
|
||||||
|
def test_dict_metadata_throws_on_bad_unicode():
|
||||||
|
metadata = DictMetadata({
|
||||||
|
"METADATA": b"\xff"
|
||||||
|
})
|
||||||
|
|
||||||
|
with pytest.raises(UnicodeDecodeError) as e:
|
||||||
|
metadata.get_metadata("METADATA")
|
||||||
|
assert "METADATA" in str(e.value)
|
Loading…
Reference in a new issue