Source code for datalad_next.utils.multihash

"""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 {}


[docs] 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))
[docs] def update(self, data: ByteString) -> None: """Updates all configured digests""" for h in self._hasher.values(): h.update(data)
[docs] 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()}