hh-python is the Python implementation of Humanized Hash (hh). The C++17 repository hh-cpp is
the reference: it owns docs/SPEC.md, docs/SECURITY.md and the canonical golden vectors. This
repository carries a byte-identical copy of the vectors in testdata/ and records the hh-cpp
release and the file hashes in testdata/SOURCE. The port follows SPEC.md, not the C++ source.
Bug reports and patches are welcome: open an issue or a pull request. Security problems are
reported privately, as docs/SECURITY.md of hh-cpp describes.
Output is byte-identical with hh-cpp. A mismatch against the vectors is a bug here, never a reason to change the vectors. The algorithm has no version and never changes; what the specification leaves open (API shape, error texts, performance) may evolve under SemVer.
hh is a standalone library. Nothing here names a particular host application.
dependencies = []. The package imports the standard library only, and of it only what every build has:hashlib,hmac,binascii,struct,math.isqrtand the like. It does not importzlib, which is optional in CPython builds: deflate, Adler-32, PNG, BMP, the JPEG encoder and the rasteriser are written here. SHA-256, HMAC, PBKDF2 and CRC-32 are the standard library's.- No third-party packages anywhere, including the tests and the tools. Tests use
unittestonly; they may cross-check againstzliband may use floating point to measure error. - The build backend is setuptools;
buildis the only package needed to make a release. No linter, formatter or type checker is required to work on the code, and none is configured. - License: MIT (
LICENSE); contributions are accepted under it.
- Everything is English: code, comments, docstrings, documentation, commit messages. No emoji.
- PEP 8 with 100 columns, double quotes, type hints on every function, a docstring on every
public object. Public names live in
humanized_hash/__init__.pyand__all__; every other module starts with an underscore. - Python 3.9 is the oldest supported version:
from __future__ import annotationsin every module,typing.Optionalandtyping.Unionwhere an annotation is evaluated at run time, nomatch, noint.bit_count, nozip(strict=...). - Comments explain the code and cite the section of the specification or the standard (RFC 1951, ITU-T T.81).
- Integer arithmetic only: no
float, no/, noround, nothing frommathbutisqrt. Python integers are unbounded; mask where the specification works modulo 2^32. - Invalid values raise
HhError(aValueError) with theErrorCodeof the specification, in the order of checks the specification gives; arguments of the wrong type raiseTypeError. - Buffers that held key material are overwritten before release, as far as Python allows; the documentation says where it does not.
- A faster path must equal the per-sample definition exactly.
tests/reference.pyis that definition;tests/test_raster.pycompares the two. tests/test_package.pyenforces the rules that a program can check.
python -m unittest discover -s tests -t .runs every test against the source tree; it must pass withpython -W error -X devon every supported version.HH_TEST_INSTALLED=1tests the installed package instead,HH_TESTDATA_DIRpoints at the vectors.tools/crosscheck.sh <hh_cli>runs the differential test against hh-cpp: generated cases and the hand-made cases oftools/edge-cases.txt, a file of bytes that every implementation carries in the same copy;python tools/bench.pytimes every step. The tools may use floating point, the library never.tools/update-vectors.sh <hh-cpp checkout>refreshestestdata/andtestdata/SOURCE; never edit those files by hand.python -m buildmakes the source distribution and the wheel. The version lives insrc/humanized_hash/_version.pyand nowhere else.
Atomic, imperative, lower case, for example "add the baseline jpeg encoder". Every commit passes the tests.