From f207204617ebe6686f704f7e482934b931e3f067 Mon Sep 17 00:00:00 2001 From: Delun Gong Date: Wed, 12 Aug 2026 18:27:25 +0800 Subject: [PATCH 1/2] Fix CI lint and make release publishing idempotent --- .github/workflows/release.yml | 22 ++++++++++++++-------- pyproject.toml | 6 ++++++ src/diffractscout/cli.py | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 64e9a56..95ac548 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,15 +71,21 @@ jobs: SHA256SUMS.txt if-no-files-found: error - - name: Create GitHub release + - name: Create or update GitHub release env: GH_TOKEN: ${{ github.token }} shell: bash run: | - gh release create "${GITHUB_REF_NAME}" \ - dist/* \ - diffractscout-${GITHUB_REF_NAME}-*.zip \ - SHA256SUMS.txt \ - --verify-tag \ - --generate-notes \ - --title "DiffractScout ${GITHUB_REF_NAME}" + assets=( + dist/* + diffractscout-${GITHUB_REF_NAME}-*.zip + SHA256SUMS.txt + ) + if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then + gh release upload "${GITHUB_REF_NAME}" "${assets[@]}" --clobber + else + gh release create "${GITHUB_REF_NAME}" "${assets[@]}" \ + --verify-tag \ + --generate-notes \ + --title "DiffractScout ${GITHUB_REF_NAME}" + fi diff --git a/pyproject.toml b/pyproject.toml index e4da3ce..870d6ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,6 +91,12 @@ target-version = "py310" select = ["E4", "E7", "E9", "F"] ignore = ["E501"] +# The crystallographic h, k, l convention is part of the public result schema +# and of the directional-elasticity equations in these domain modules. +[tool.ruff.lint.per-file-ignores] +"src/diffractscout/elasticity.py" = ["E741"] +"src/diffractscout/models.py" = ["E741"] + [tool.coverage.run] omit = [ "src/diffractscout/gui.py", diff --git a/src/diffractscout/cli.py b/src/diffractscout/cli.py index 9c1e612..0ff8f63 100644 --- a/src/diffractscout/cli.py +++ b/src/diffractscout/cli.py @@ -186,7 +186,7 @@ def build_parser() -> argparse.ArgumentParser: benchmark.add_argument("--overwrite", action="store_true") benchmark.add_argument("--json", action="store_true") - gui = subparsers.add_parser("gui", help="Launch the optional Tk desktop interface.") + subparsers.add_parser("gui", help="Launch the optional Tk desktop interface.") return parser From 960da5a2933ea31de8146406ac50ce94d87d4f93 Mon Sep 17 00:00:00 2001 From: Delun Gong Date: Wed, 12 Aug 2026 18:31:54 +0800 Subject: [PATCH 2/2] Fix Python 3.10 metadata checks and Windows archive test --- pyproject.toml | 1 + scripts/check_docs.py | 6 +++++- tests/test_archive_tree.py | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 870d6ba..6cb771b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ test = [ "pytest-cov>=5.0", "ruff>=0.5", "PyYAML>=6.0", + "tomli>=2.0; python_version < '3.11'", ] paper = [ "matplotlib>=3.7", diff --git a/scripts/check_docs.py b/scripts/check_docs.py index 6fb8545..db3396a 100755 --- a/scripts/check_docs.py +++ b/scripts/check_docs.py @@ -7,9 +7,13 @@ from pathlib import Path import re import sys -import tomllib from urllib.parse import unquote +try: + import tomllib +except ModuleNotFoundError: # Python 3.10 + import tomli as tomllib + try: import yaml except ImportError as exc: # pragma: no cover - release dependency supplies it diff --git a/tests/test_archive_tree.py b/tests/test_archive_tree.py index 3af7d70..bc4bb67 100644 --- a/tests/test_archive_tree.py +++ b/tests/test_archive_tree.py @@ -22,8 +22,10 @@ def _sha256(path: Path) -> str: def test_reproducible_archive_is_byte_identical(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: source = tmp_path / "evidence" (source / "nested").mkdir(parents=True) - (source / "z.txt").write_text("zeta\n", encoding="utf-8") - (source / "nested" / "a.json").write_text('{"a": 1}\n', encoding="utf-8") + # Write exact fixture bytes so the archive contract is tested independently + # of platform-specific text newline translation. + (source / "z.txt").write_bytes(b"zeta\n") + (source / "nested" / "a.json").write_bytes(b'{"a": 1}\n') monkeypatch.setenv("SOURCE_DATE_EPOCH", "1786492800") first = MODULE.create_reproducible_zip(source, tmp_path / "first.zip", root_name="bundle")