From 4119d87445bed562311c38367a7500e6db6b2f04 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 23 Apr 2025 14:29:53 +0100 Subject: [PATCH 1/5] cleanup --- .github/workflows/test.yml | 3 ++ config.ini | 4 ++ pyproject.toml | 2 - scripts/check-config | 86 +++++++++++++++++++++++++++++++++++++ scripts/firedrake-configure | 2 - 5 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 config.ini create mode 100755 scripts/check-config diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 02a258e593..72b1cdf439 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,6 +56,9 @@ jobs: with: path: firedrake-repo + - name: Validate single-source-of-truth + run: ./scripts/check-config + - name: Install system dependencies run: | apt-get update diff --git a/config.ini b/config.ini new file mode 100644 index 0000000000..c52b2047dc --- /dev/null +++ b/config.ini @@ -0,0 +1,4 @@ +[config] +petsc-version = 3.23.0 +petsc-version-spec = >=3.23.0 +min-python-version = 3.10 diff --git a/pyproject.toml b/pyproject.toml index 55189638ed..c0c48c873c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,8 +21,6 @@ dependencies = [ "h5py>3.12.1", "libsupermesh", "loopy>2024.1", - # NOTE: If changing the PETSc/SLEPc version then firedrake-configure also needs - # changing (as well as other references to petsc4py and slepc4py here) "petsc4py==3.23.0", "numpy", "packaging", diff --git a/scripts/check-config b/scripts/check-config new file mode 100755 index 0000000000..1d6c8d4326 --- /dev/null +++ b/scripts/check-config @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +"""Script that makes sure that hardcoded version numbers are consistent. + +It reads in Firedrake's 'config.ini' file and makes sure that everywhere a +version number is hardcoded that it matches the expected value. This allows +for single-source-of-truth of hardcoded values (via CI). + +""" + +import configparser +import pathlib +import re +from collections.abc import Mapping + + +REPO_ROOT = pathlib.Path(__file__).parent.parent + + +class InvalidConfigurationException(Exception): + pass + + +def main(): + config = read_config() + check_min_python_version(config["min-python-version"]) + check_petsc_version(config["petsc-version"]) + check_petsc_version_spec(config["petsc-version-spec"]) + + +def read_config() -> Mapping[str, str]: + parser = configparser.ConfigParser() + parser.read_file(open(REPO_ROOT / "config.ini")) + return parser["config"] + + +def check_min_python_version(min_python_version: str) -> None: + check_file_contains_pattern( + REPO_ROOT / "pyproject.toml", + f"requires-python = \">={min_python_version}\"" + ) + check_file_contains_pattern( + REPO_ROOT / "docs/source/install.rst", + f"Python \\({min_python_version} or greater\\)" + ) + + +def check_petsc_version(petsc_version: str) -> None: + check_file_contains_pattern( + REPO_ROOT / "scripts/firedrake-configure", + f"SUPPORTED_PETSC_VERSION = \"v{petsc_version}\"", + ) + check_file_contains_pattern( + REPO_ROOT / "pyproject.toml", + f"petsc4py=={petsc_version}", + 2, + ) + check_file_contains_pattern( + REPO_ROOT / "pyproject.toml", + f"slepc4py=={petsc_version}", + 3, + ) + + +def check_petsc_version_spec(petsc_version_spec: str) -> None: + # TODO when https://github.com/firedrakeproject/firedrake/pull/4194 is merged + pass + + +def check_file_contains_pattern( + filename: pathlib.Path | str, + pattern: str, + num_expected_matches: int = 1, +) -> None: + with open(filename) as f: + text = f.read() + matches = re.findall(pattern, text) + if len(matches) != num_expected_matches: + raise InvalidConfigurationException( + f"Expected to find {num_expected_matches} matches for '{pattern}' in " + f"{filename} but found {len(matches)}" + ) + + +if __name__ == "__main__": + main() diff --git a/scripts/firedrake-configure b/scripts/firedrake-configure index da5d3f4ea4..e66ee4eb07 100755 --- a/scripts/firedrake-configure +++ b/scripts/firedrake-configure @@ -39,8 +39,6 @@ ARCH_DEFAULT = FiredrakeArch.DEFAULT ARCH_COMPLEX = FiredrakeArch.COMPLEX -# NOTE: When updating this variable corresponding changes must be made inside -# pyproject.toml SUPPORTED_PETSC_VERSION = "v3.23.0" From 10a5648e85ca368a5d331f13a24328e143a9dfa5 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 23 Apr 2025 14:46:46 +0100 Subject: [PATCH 2/5] fixup --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 72b1cdf439..b9d52fe5c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,7 +57,7 @@ jobs: path: firedrake-repo - name: Validate single-source-of-truth - run: ./scripts/check-config + run: ./firedrake-repo/scripts/check-config - name: Install system dependencies run: | From c26084e6be8be61d06b8a1977841e92f671a25da Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Wed, 23 Apr 2025 14:49:13 +0100 Subject: [PATCH 3/5] fixup --- .github/workflows/test.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b9d52fe5c7..255024965c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,15 +56,19 @@ jobs: with: path: firedrake-repo + - name: Install Python + run: | + apt-get update + apt-get -y install python3 + - name: Validate single-source-of-truth run: ./firedrake-repo/scripts/check-config - name: Install system dependencies run: | - apt-get update - apt-get -y install python3 apt-get -y install \ - $(python3 ./firedrake-repo/scripts/firedrake-configure --arch ${{ matrix.arch }} --show-system-packages) python3-venv parallel + python3-venv parallel \ + $(python3 ./firedrake-repo/scripts/firedrake-configure --arch ${{ matrix.arch }} --show-system-packages) - name: Install PETSc run: | From 9789f1c526c2b4eca9d3d3c8cd982052cf053158 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Tue, 29 Apr 2025 15:53:29 +0100 Subject: [PATCH 4/5] Do not rely on an external configuration file --- config.ini | 4 ---- scripts/check-config | 51 +++++++++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 23 deletions(-) delete mode 100644 config.ini diff --git a/config.ini b/config.ini deleted file mode 100644 index c52b2047dc..0000000000 --- a/config.ini +++ /dev/null @@ -1,4 +0,0 @@ -[config] -petsc-version = 3.23.0 -petsc-version-spec = >=3.23.0 -min-python-version = 3.10 diff --git a/scripts/check-config b/scripts/check-config index 1d6c8d4326..c3f89e1bcf 100755 --- a/scripts/check-config +++ b/scripts/check-config @@ -8,7 +8,6 @@ for single-source-of-truth of hardcoded values (via CI). """ -import configparser import pathlib import re from collections.abc import Mapping @@ -22,22 +21,15 @@ class InvalidConfigurationException(Exception): def main(): - config = read_config() - check_min_python_version(config["min-python-version"]) - check_petsc_version(config["petsc-version"]) - check_petsc_version_spec(config["petsc-version-spec"]) + check_min_python_version() + check_petsc_version() + check_petsc_version_spec() -def read_config() -> Mapping[str, str]: - parser = configparser.ConfigParser() - parser.read_file(open(REPO_ROOT / "config.ini")) - return parser["config"] - - -def check_min_python_version(min_python_version: str) -> None: - check_file_contains_pattern( +def check_min_python_version() -> None: + min_python_version = check_file_contains_pattern( REPO_ROOT / "pyproject.toml", - f"requires-python = \">={min_python_version}\"" + f"requires-python = \">=(.*)\"" ) check_file_contains_pattern( REPO_ROOT / "docs/source/install.rst", @@ -45,10 +37,10 @@ def check_min_python_version(min_python_version: str) -> None: ) -def check_petsc_version(petsc_version: str) -> None: - check_file_contains_pattern( +def check_petsc_version() -> None: + petsc_version = check_file_contains_pattern( REPO_ROOT / "scripts/firedrake-configure", - f"SUPPORTED_PETSC_VERSION = \"v{petsc_version}\"", + f"SUPPORTED_PETSC_VERSION = \"v(.*)\"", ) check_file_contains_pattern( REPO_ROOT / "pyproject.toml", @@ -62,7 +54,7 @@ def check_petsc_version(petsc_version: str) -> None: ) -def check_petsc_version_spec(petsc_version_spec: str) -> None: +def check_petsc_version_spec() -> None: # TODO when https://github.com/firedrakeproject/firedrake/pull/4194 is merged pass @@ -71,7 +63,24 @@ def check_file_contains_pattern( filename: pathlib.Path | str, pattern: str, num_expected_matches: int = 1, -) -> None: +) -> str: + """Check that the regex pattern exists in the file. + + Parameters + ---------- + filename : + The filename. + pattern : + The regular expression pattern to look for. + num_expected_matches : + The number of expected matches. + + Returns + ------- + str : + The matched value. This follows the semantics of `re.findall`. + + """ with open(filename) as f: text = f.read() matches = re.findall(pattern, text) @@ -81,6 +90,10 @@ def check_file_contains_pattern( f"{filename} but found {len(matches)}" ) + # all the matches should be the same so just return one of them + match, = set(matches) + return match + if __name__ == "__main__": main() From a28e4cbe38f1b6c601815b3644faca537df79f35 Mon Sep 17 00:00:00 2001 From: Connor Ward Date: Thu, 1 May 2025 21:00:28 +0100 Subject: [PATCH 5/5] Add check for Firedrake version --- scripts/check-config | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/check-config b/scripts/check-config index c3f89e1bcf..4396af94f0 100755 --- a/scripts/check-config +++ b/scripts/check-config @@ -21,11 +21,23 @@ class InvalidConfigurationException(Exception): def main(): + check_firedrake_version() check_min_python_version() check_petsc_version() check_petsc_version_spec() +def check_firedrake_version(): + firedrake_version = check_file_contains_pattern( + REPO_ROOT / "pyproject.toml", + f"version = \"(.*)\"" + ) + check_file_contains_pattern( + REPO_ROOT / "docs/source/install.rst", + f"https://raw.githubusercontent.com/firedrakeproject/firedrake/refs/tags/{firedrake_version}/scripts/firedrake-configure" + ) + + def check_min_python_version() -> None: min_python_version = check_file_contains_pattern( REPO_ROOT / "pyproject.toml",