Skip to content

Commit 9928c51

Browse files
committed
refactor: Hasher can do sets
1 parent 18d39b5 commit 9928c51

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

coverage/misc.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,12 @@ def update(self, v: Any) -> None:
176176
for e in v:
177177
self.update(e)
178178
case dict():
179-
keys = v.keys()
180-
for k in sorted(keys):
179+
for k, kv in sorted(v.items()):
181180
self.update(k)
182-
self.update(v[k])
181+
self.update(kv)
182+
case set():
183+
for e in sorted(v):
184+
self.update(e)
183185
case _:
184186
for k in dir(v):
185187
if k.startswith("__"):
@@ -191,8 +193,12 @@ def update(self, v: Any) -> None:
191193
self.update(a)
192194
self.hash.update(b".")
193195

196+
def digest(self) -> bytes:
197+
"""Get the full binary digest of the hash."""
198+
return self.hash.digest()
199+
194200
def hexdigest(self) -> str:
195-
"""Retrieve the hex digest of the hash."""
201+
"""Retrieve a 32-char hex digest of the hash."""
196202
return self.hash.hexdigest()[:32]
197203

198204

tests/test_misc.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ class HasherTest(CoverageTest):
2323

2424
run_in_temp_dir = False
2525

26+
def test_none_hashing(self) -> None:
27+
h1 = Hasher()
28+
h1.update([1, None, 2, None])
29+
h2 = Hasher()
30+
h2.update([1, 2])
31+
assert h1.hexdigest() != h2.hexdigest()
32+
assert h1.digest() != h2.digest()
33+
2634
def test_string_hashing(self) -> None:
2735
h1 = Hasher()
2836
h1.update("Hello, world!")
@@ -32,34 +40,52 @@ def test_string_hashing(self) -> None:
3240
h3.update("Hello, world!")
3341
assert h1.hexdigest() != h2.hexdigest()
3442
assert h1.hexdigest() == h3.hexdigest()
43+
assert h1.digest() != h2.digest()
44+
assert h1.digest() == h3.digest()
3545

3646
def test_bytes_hashing(self) -> None:
3747
h1 = Hasher()
3848
h1.update(b"Hello, world!")
3949
h2 = Hasher()
4050
h2.update(b"Goodbye!")
4151
assert h1.hexdigest() != h2.hexdigest()
52+
assert h1.digest() != h2.digest()
4253

4354
def test_unicode_hashing(self) -> None:
4455
h1 = Hasher()
4556
h1.update("Hello, world! \N{SNOWMAN}")
4657
h2 = Hasher()
4758
h2.update("Goodbye!")
4859
assert h1.hexdigest() != h2.hexdigest()
60+
assert h1.digest() != h2.digest()
4961

5062
def test_dict_hashing(self) -> None:
5163
h1 = Hasher()
5264
h1.update({"a": 17, "b": 23})
5365
h2 = Hasher()
5466
h2.update({"b": 23, "a": 17})
5567
assert h1.hexdigest() == h2.hexdigest()
68+
assert h1.digest() == h2.digest()
5669

5770
def test_dict_collision(self) -> None:
5871
h1 = Hasher()
5972
h1.update({"a": 17, "b": {"c": 1, "d": 2}})
6073
h2 = Hasher()
6174
h2.update({"a": 17, "b": {"c": 1}, "d": 2})
6275
assert h1.hexdigest() != h2.hexdigest()
76+
assert h1.digest() != h2.digest()
77+
78+
def test_set_hashing(self) -> None:
79+
h1 = Hasher()
80+
h1.update({(1, 2), (3, 4), (5, 6)})
81+
h2 = Hasher()
82+
h2.update({(5, 6), (1, 2), (3, 4)})
83+
h3 = Hasher()
84+
h3.update({(1, 2)})
85+
assert h1.hexdigest() == h2.hexdigest()
86+
assert h1.hexdigest() != h3.hexdigest()
87+
assert h1.digest() == h2.digest()
88+
assert h1.digest() != h3.digest()
6389

6490

6591
class RemoveFileTest(CoverageTest):

0 commit comments

Comments
 (0)