diff --git a/src/packaging/tags.py b/src/packaging/tags.py index f5903402..4fa51276 100644 --- a/src/packaging/tags.py +++ b/src/packaging/tags.py @@ -13,6 +13,7 @@ import sysconfig from importlib.machinery import EXTENSION_SUFFIXES from typing import ( + Any, Iterable, Iterator, Sequence, @@ -92,6 +93,13 @@ def __str__(self) -> str: def __repr__(self) -> str: return f"<{self} @ {id(self)}>" + def __setstate__(self, state: tuple[dict[str, Any], dict[str, Any]]) -> None: + # cached _hash is wrong when unpickling + _, slots = state + for slot in slots: + setattr(self, slot, slots[slot]) + self._hash = hash((self._interpreter, self._abi, self._platform)) + def parse_tag(tag: str) -> frozenset[Tag]: """ diff --git a/tests/test_tags.py b/tests/test_tags.py index 5ec89b24..391cda01 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -13,6 +13,7 @@ import importlib import os import pathlib +import pickle import platform import struct import sys @@ -1490,3 +1491,9 @@ def _calcsize(fmt): monkeypatch.setattr(struct, "calcsize", _calcsize) importlib.reload(tags) assert tags._32_BIT_INTERPRETER == expected + + +def test_pickle(): + # Make sure equality works between a pickle/unpickle round trip. + tag = tags.Tag("py3", "none", "any") + assert pickle.loads(pickle.dumps(tag)) == tag