Skip to content

Commit 5119d46

Browse files
committed
Improve conversion of direct_url.hash to hashes
1 parent cdd9c95 commit 5119d46

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

src/pip/_internal/models/direct_url.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,22 +105,30 @@ def __init__(
105105
hash: Optional[str] = None,
106106
hashes: Optional[Dict[str, str]] = None,
107107
) -> None:
108-
if hash is not None:
108+
self.hashes = hashes
109+
self.hash = hash
110+
111+
@property
112+
def hash(self) -> Optional[str]:
113+
return self._hash
114+
115+
@hash.setter
116+
def hash(self, value: Optional[str]) -> None:
117+
if value is not None:
109118
# Auto-populate the hashes key to upgrade to the new format automatically.
110-
# We don't back-populate the legacy hash key.
119+
# We don't back-populate the legacy hash key from hashes.
111120
try:
112-
hash_name, hash_value = hash.split("=", 1)
121+
hash_name, hash_value = value.split("=", 1)
113122
except ValueError:
114123
raise DirectUrlValidationError(
115-
f"invalid archive_info.hash format: {hash!r}"
124+
f"invalid archive_info.hash format: {value!r}"
116125
)
117-
if hashes is None:
118-
hashes = {hash_name: hash_value}
119-
elif hash_name not in hash:
120-
hashes = hashes.copy()
121-
hashes[hash_name] = hash_value
122-
self.hash = hash
123-
self.hashes = hashes
126+
if self.hashes is None:
127+
self.hashes = {hash_name: hash_value}
128+
elif hash_name not in self.hashes:
129+
self.hashes = self.hashes.copy()
130+
self.hashes[hash_name] = hash_value
131+
self._hash = value
124132

125133
@classmethod
126134
def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]:

tests/unit/test_direct_url.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,33 @@ def _redact_archive(url: str) -> str:
140140
== "https://${PIP_TOKEN}@g.c/u/p.git"
141141
)
142142
assert _redact_git("ssh://[email protected]/u/p.git") == "ssh://[email protected]/u/p.git"
143+
144+
145+
def test_hash_to_hashes() -> None:
146+
direct_url = DirectUrl(url="https://e.c/archive.tar.gz", info=ArchiveInfo())
147+
assert isinstance(direct_url.info, ArchiveInfo)
148+
direct_url.info.hash = "sha256=abcdef"
149+
assert direct_url.info.hashes == {"sha256": "abcdef"}
150+
151+
152+
def test_hash_to_hashes_constructor() -> None:
153+
direct_url = DirectUrl(
154+
url="https://e.c/archive.tar.gz", info=ArchiveInfo(hash="sha256=abcdef")
155+
)
156+
assert isinstance(direct_url.info, ArchiveInfo)
157+
assert direct_url.info.hashes == {"sha256": "abcdef"}
158+
direct_url = DirectUrl(
159+
url="https://e.c/archive.tar.gz",
160+
info=ArchiveInfo(hash="sha256=abcdef", hashes={"sha512": "123456"}),
161+
)
162+
assert isinstance(direct_url.info, ArchiveInfo)
163+
assert direct_url.info.hashes == {"sha256": "abcdef", "sha512": "123456"}
164+
# In case of conflict between hash and hashes, hashes wins.
165+
direct_url = DirectUrl(
166+
url="https://e.c/archive.tar.gz",
167+
info=ArchiveInfo(
168+
hash="sha256=abcdef", hashes={"sha256": "012345", "sha512": "123456"}
169+
),
170+
)
171+
assert isinstance(direct_url.info, ArchiveInfo)
172+
assert direct_url.info.hashes == {"sha256": "012345", "sha512": "123456"}

0 commit comments

Comments
 (0)