Skip to content

Commit 1bd8c37

Browse files
committed
Include hash in parbaked recipe filename to avoid collisions
Fixes #1784
1 parent ba8f35b commit 1bd8c37

2 files changed

Lines changed: 17 additions & 5 deletions

File tree

src/CSET/recipes/__init__.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
"""Operations on recipes."""
1616

17+
import hashlib
1718
import importlib.resources
1819
import logging
1920
from collections.abc import Iterator
21+
from io import StringIO
2022
from pathlib import Path
2123
from typing import Any
2224

@@ -214,10 +216,18 @@ def parbake(self, ROSE_DATAC: Path, SHARE_DIR: Path) -> None:
214216

215217
# Parbake this recipe, saving into recipe_dir.
216218
recipe = parse_recipe(Path(self.recipe), self.variables)
217-
output = recipe_dir / f"{slugify(recipe['title'])}.yaml"
218-
with open(output, "wt") as fp:
219-
with YAML(pure=True, output=fp) as yaml:
219+
220+
# Serialise into memory, as we use the serialised value twice.
221+
with StringIO() as s:
222+
with YAML(pure=True, output=s) as yaml:
220223
yaml.dump(recipe)
224+
serialised_recipe = s.getvalue().encode()
225+
# Include shortened hash in filename to avoid collisions between recipes
226+
# with the same title.
227+
digest = hashlib.sha256(serialised_recipe).hexdigest()
228+
output_filename = recipe_dir / f"{slugify(recipe['title'])}_{digest[:12]}.yaml"
229+
with open(output_filename, "wb") as fp:
230+
fp.write(serialised_recipe)
221231

222232

223233
class Config:

tests/test_recipes.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,6 @@ def test_RawRecipe_parbake(tmp_working_dir):
209209
)
210210
)
211211
# Expected.
212-
parbaked_recipe_file = rose_datac / "recipes/recipe_value.yaml"
213212
expected = dedent(
214213
f"""\
215214
title: Recipe value
@@ -222,6 +221,7 @@ def test_RawRecipe_parbake(tmp_working_dir):
222221
# Act.
223222
r.parbake(rose_datac, tmp_working_dir)
224223
# Assert.
224+
parbaked_recipe_file = next((rose_datac / "recipes").glob("recipe_value_*.yaml"))
225225
assert parbaked_recipe_file.exists()
226226
assert parbaked_recipe_file.read_text() == expected
227227

@@ -248,7 +248,6 @@ def test_RawRecipe_parbake_aggregation(tmp_working_dir):
248248
)
249249
)
250250
# Expected.
251-
parbaked_recipe_file = rose_datac / "aggregation_recipes/recipe_value.yaml"
252251
expected = dedent(
253252
f"""\
254253
title: Recipe value
@@ -263,6 +262,9 @@ def test_RawRecipe_parbake_aggregation(tmp_working_dir):
263262
# Act.
264263
r.parbake(rose_datac, tmp_working_dir)
265264
# Assert.
265+
parbaked_recipe_file = next(
266+
(rose_datac / "aggregation_recipes").glob("recipe_value_*.yaml")
267+
)
266268
assert parbaked_recipe_file.exists()
267269
assert parbaked_recipe_file.read_text() == expected
268270

0 commit comments

Comments
 (0)