Skip to content

Commit

Permalink
Change metadata tests to not rely on __hash__/__eq__
Browse files Browse the repository at this point in the history
  • Loading branch information
abravalheri committed Jan 21, 2022
1 parent dda204b commit f1625d3
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
7 changes: 6 additions & 1 deletion packaging/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ def _normalize_field_name_for_dynamic(field: str) -> NormalizedDynamicFields:
_setattr = object.__setattr__


@dataclasses.dataclass(frozen=True)
# In the following we use `frozen` to prevent inconsistencies, specially with `dynamic`.
# Comparison is disabled because currently `Requirement` objects are
# unhashable/not-comparable.


@dataclasses.dataclass(frozen=True, eq=False)
class CoreMetadata:
"""
Core metadata for Python packages, represented as an immutable
Expand Down
22 changes: 18 additions & 4 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_replace(self):
}
metadata1 = dataclasses.replace(metadata, **attrs)
req = next(iter(metadata1.requires_dist))
assert req == Requirement("appdirs>1.4")
assert str(req) == "appdirs>1.4"

with pytest.raises(InvalidCoreMetadataField):
dataclasses.replace(metadata, dynamic=["myfield"])
Expand Down Expand Up @@ -216,7 +216,7 @@ def test_parsing(self, spec: str) -> None:
pkg_info = CoreMetadata.from_pkg_info(text)
if example["is_final_metadata"]:
metadata = CoreMetadata.from_dist_info_metadata(text)
assert metadata == pkg_info
assert_equal_metadata(metadata, pkg_info)
if example["has_dynamic_fields"]:
with pytest.raises(DynamicNotAllowed):
CoreMetadata.from_dist_info_metadata(text)
Expand Down Expand Up @@ -309,7 +309,7 @@ def test_parse(self, pkg: str, version: str) -> None:
recons_data = from_(recons_file)
description = metadata.description.replace("\r\n", "\n")
metadata = dataclasses.replace(metadata, description=description)
assert metadata == recons_data
assert_equal_metadata(metadata, recons_data)
# - Make sure the reconstructed file can be parsed with compat32
attrs = dataclasses.asdict(_Compat32Metadata.from_pkg_info(recons_file))
assert CoreMetadata(**attrs)
Expand All @@ -321,13 +321,27 @@ def test_parse(self, pkg: str, version: str) -> None:
result_contents = to_(data)
assert file_contents == result_contents
result_data = from_(result_contents)
assert data == result_data
assert_equal_metadata(data, result_data)
file_contents, data = result_contents, result_data


# --- Helper Functions/Classes ---


def assert_equal_metadata(metadata1: CoreMetadata, metadata2: CoreMetadata):
fields = (f.name for f in dataclasses.fields(CoreMetadata))
for field in fields:
value1, value2 = getattr(metadata1, field), getattr(metadata2, field)
if field.endswith("dist"):
# Currently `Requirement` objects are not directly comparable,
# therefore sets containing those objects are also not comparable.
# The best approach is to convert requirements to strings first.
req1, req2 = set(map(str, value1)), set(map(str, value2))
assert req1 == req2
else:
assert value1 == value2


class _Compat32Metadata(CoreMetadata):
"""The Core Metadata spec requires the file to be parse-able with compat32.
The implementation uses a different approach to ensure UTF-8 can be used.
Expand Down

0 comments on commit f1625d3

Please sign in to comment.