forked from datalad/datalad-next
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request datalad#345 from mih/multihash
New `MultiHash` class
- Loading branch information
Showing
8 changed files
with
107 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
### 💫 Enhancements and new features | ||
|
||
- New `MultiHash` helper to compute multiple hashes in one go. | ||
Fixes https://github.com/datalad/datalad-next/issues/345 (by @mih) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""Compute more than one hash for the same data in one go""" | ||
|
||
from __future__ import annotations | ||
|
||
import hashlib | ||
from typing import ( | ||
ByteString, | ||
Dict, | ||
) | ||
|
||
|
||
class NoOpHash: | ||
"""Companion of :class:`MultiHash` that computes no hash at all | ||
This can be used wherever ``MultiHash`` would be used, because | ||
it implements its API. However, no hash is computed and no | ||
hexdigest is reported. | ||
""" | ||
def __init__(self, algorithms: None = None): | ||
pass | ||
|
||
def update(self, data): | ||
pass | ||
|
||
def get_hexdigest(self): | ||
return {} | ||
|
||
|
||
class MultiHash: | ||
"""Compute any number of hashes as if computing just one | ||
Supports any hash algorithm supported by the ``hashlib`` module | ||
of the standard library. | ||
""" | ||
def __init__(self, algorithms: list[str]): | ||
""" | ||
Parameters | ||
---------- | ||
algorithms: list | ||
Hash names, must match the name of the algorithms in the | ||
``hashlib`` module (case insensitive). | ||
""" | ||
# yes, this will crash, if an invalid hash algorithm name | ||
# is given | ||
_hasher = [] | ||
for h in algorithms: | ||
hr = getattr(hashlib, h.lower(), None) | ||
if hr is None: | ||
raise ValueError(f'unsupported hash algorithm {h}') | ||
_hasher.append(hr()) | ||
self._hasher = dict(zip(algorithms, _hasher)) | ||
|
||
def update(self, data: ByteString) -> None: | ||
"""Updates all configured digests""" | ||
for h in self._hasher.values(): | ||
h.update(data) | ||
|
||
def get_hexdigest(self) -> Dict[str, str]: | ||
"""Returns a mapping of algorithm name to hexdigest for all algorithms | ||
""" | ||
return {a: h.hexdigest() for a, h in self._hasher.items()} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import pytest | ||
|
||
from ..multihash import ( | ||
MultiHash, | ||
NoOpHash, | ||
) | ||
|
||
|
||
def test_multihash(): | ||
mh = MultiHash(['sha1', 'MD5']) | ||
mh.update(b'') | ||
hd = mh.get_hexdigest() | ||
assert len(hd) == 2 | ||
# algorithm label preserves original casing | ||
assert hd['MD5'] == 'd41d8cd98f00b204e9800998ecf8427e' | ||
assert hd['sha1'] == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' | ||
|
||
with pytest.raises(ValueError): | ||
MultiHash(['bogus']) | ||
|
||
|
||
|
||
def test_noophash(): | ||
mh = NoOpHash() | ||
mh.update(b'') | ||
assert mh.get_hexdigest() == {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,5 +18,6 @@ Python utilities | |
url_operations.ssh | ||
utils | ||
utils.http_helpers | ||
utils.multihash | ||
utils.requests_auth | ||
tests.fixtures |