Skip to content

Commit

Permalink
Allow for algorithm list
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoesters committed Jul 3, 2024
1 parent 12ed816 commit 82712f5
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 21 deletions.
2 changes: 1 addition & 1 deletion CONSTRUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ Additional artifacts to be produced after building the installer.
It expects either a list of strings or single-key dictionaries:
Allowed keys are:
- `hash`: The hash of the installer files.
- `algorithm`: The hash algorithm. Must be among `hashlib`'s available algorithms:
- `algorithm` (str or list): The hash algorithm. Must be among `hashlib`'s available algorithms:
https://docs.python.org/3/library/hashlib.html#hashlib.algorithms_available
- `info.json`: The internal `info` object, serialized to JSON. Takes no options.
- `pkgs_list`: The list of packages contained in a given environment. Options:
Expand Down
22 changes: 14 additions & 8 deletions constructor/build_outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,29 @@ def process_build_outputs(info):
logger.info("build_outputs: '%s' created '%s'.", name, outpath)


def dump_hash(info, algorithm=""):
if algorithm not in hashlib.algorithms_available:
raise ValueError(f"Invalid algorithm: {', '.join(algorithm)}")
def dump_hash(info, algorithm=[]):
if isinstance(algorithm, str):
algorithm = [algorithm]
algorithms = set(algorithm)
if any(algo not in hashlib.algorithms_available for algo in algorithms):
invalid = algorithms.difference(set(hashlib.algorithms_available))
raise ValueError(f"Invalid algorithm: {', '.join(invalid)}")
BUFFER_SIZE = 65536
if isinstance(info["_outpath"], str):
installers = [Path(info["_outpath"])]
else:
installers = [Path(outpath) for outpath in info["_outpath"]]
outpaths = []
for installer in installers:
filehash = hashlib.new(algorithm)
filehashes = {algo: hashlib.new(algo) for algo in algorithms}
with open(installer, "rb") as f:
while buffer := f.read(BUFFER_SIZE):
filehash.update(buffer)
outpath = Path(f"{installer}.{algorithm}")
outpath.write_text(f"{filehash.hexdigest()} {installer.name}\n")
outpaths.append(str(outpath.absolute()))
for algo in algorithms:
filehashes[algo].update(buffer)
for algo, filehash in filehashes.items():
outpath = Path(f"{installer}.{algo}")
outpath.write_text(f"{filehash.hexdigest()} {installer.name}\n")
outpaths.append(str(outpath.absolute()))
return ", ".join(outpaths)


Expand Down
2 changes: 1 addition & 1 deletion constructor/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@
It expects either a list of strings or single-key dictionaries:
Allowed keys are:
- `hash`: The hash of the installer files.
- `algorithm`: The hash algorithm. Must be among `hashlib`'s available algorithms:
- `algorithm` (str or list): The hash algorithm. Must be among `hashlib`'s available algorithms:
https://docs.python.org/3/library/hashlib.html#hashlib.algorithms_available
- `info.json`: The internal `info` object, serialized to JSON. Takes no options.
- `pkgs_list`: The list of packages contained in a given environment. Options:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/construct-yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ Additional artifacts to be produced after building the installer.
It expects either a list of strings or single-key dictionaries:
Allowed keys are:
- `hash`: The hash of the installer files.
- `algorithm`: The hash algorithm. Must be among `hashlib`'s available algorithms:
- `algorithm` (str or list): The hash algorithm. Must be among `hashlib`'s available algorithms:
https://docs.python.org/3/library/hashlib.html#hashlib.algorithms_available
- `info.json`: The internal `info` object, serialized to JSON. Takes no options.
- `pkgs_list`: The list of packages contained in a given environment. Options:
Expand Down
31 changes: 21 additions & 10 deletions tests/test_outputs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from pathlib import Path

import pytest

from constructor.build_outputs import dump_hash


Expand All @@ -8,20 +10,29 @@ def test_hash_dump(tmp_path):
testfile.write_text("test string")
testfile = tmp_path / "test2.txt"
testfile.write_text("another test")
expected = (
"d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b",
"64320dd12e5c2caeac673b91454dac750c08ba333639d129671c2f58cb5d0ad1",
)
expected = {
"sha256": (
"d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b",
"64320dd12e5c2caeac673b91454dac750c08ba333639d129671c2f58cb5d0ad1",
),
"md5": (
"6f8db599de986fab7a21625b7916589c",
"5e8862cd73694287ff341e75c95e3c6a",
),
}
info = {
"_outpath": [
str(tmp_path / "test.txt"),
str(tmp_path / "test2.txt"),
]
}
dump_hash(info, algorithm="sha256")
with pytest.raises(ValueError):
dump_hash(info, algorithm="bad_algorithm")
dump_hash(info, algorithm=["sha256", "md5"])
for f, file in enumerate(info["_outpath"]):
hashfile = Path(f"{file}.sha256")
assert hashfile.exists()
filehash, filename = hashfile.read_text().strip().split()
assert filehash == expected[f]
assert filename == Path(file).name
for algorithm in expected:
hashfile = Path(f"{file}.{algorithm}")
assert hashfile.exists()
filehash, filename = hashfile.read_text().strip().split()
assert filehash == expected[algorithm][f]
assert filename == Path(file).name

0 comments on commit 82712f5

Please sign in to comment.