From f29d42007f7177c510667f06dbe7828cae1c82fb Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Fri, 26 Jun 2026 14:28:16 +0200 Subject: [PATCH] Make gridtools-cpp installable from a git ref via scikit-build-core Switch the gridtools-cpp Python distribution to the scikit-build-core PEP 517 backend driven by a new root-level pyproject.toml. The backend runs the root CMakeLists.txt on every build, installing the headers and CMake config into the package data and reading the version from version.txt -- so the package is fully self-contained and installs cleanly straight from a git ref with no subdirectory and no out-of-band nox prepare step: pip install "git+https://github.com/GridTools/gridtools.git@" The wheel stays header-only and platform independent (py3-none-any). - add root pyproject.toml (scikit-build-core); allowlist it in .gitignore - move the gridtools_cpp package to src/gridtools_cpp/ - drop the now-obsolete .python_package/pyproject.toml and setup.cfg.in - slim noxfile.py to build the root project (same session names + dist path, so the CI workflow is unchanged) and refresh DEVELOPMENT.md --- .gitignore | 1 + .python_package/.gitignore | 3 - .python_package/DEVELOPMENT.md | 48 ++++------ .python_package/noxfile.py | 90 ++----------------- .python_package/pyproject.toml | 3 - .python_package/setup.cfg.in | 45 ---------- pyproject.toml | 42 +++++++++ .../src => src}/gridtools_cpp/__init__.py | 0 .../src => src}/gridtools_cpp/py.typed | 0 9 files changed, 71 insertions(+), 161 deletions(-) delete mode 100644 .python_package/pyproject.toml delete mode 100644 .python_package/setup.cfg.in create mode 100644 pyproject.toml rename {.python_package/src => src}/gridtools_cpp/__init__.py (100%) rename {.python_package/src => src}/gridtools_cpp/py.typed (100%) diff --git a/.gitignore b/.gitignore index 50d1f64c6e..cf8cc94f65 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ __pycache__ !LICENSE !mainpage.dox !modules +!pyproject.toml !README.md !Vagrant_bootstrap.sh !Vagrantfile diff --git a/.python_package/.gitignore b/.python_package/.gitignore index 287461ae68..a680f1a1f6 100644 --- a/.python_package/.gitignore +++ b/.python_package/.gitignore @@ -1,7 +1,4 @@ .nox/ -LICENSE dist/ -setup.cfg *.egg-info/ -src/gridtools_cpp/data build/ diff --git a/.python_package/DEVELOPMENT.md b/.python_package/DEVELOPMENT.md index f08ac4e070..860428a5d0 100644 --- a/.python_package/DEVELOPMENT.md +++ b/.python_package/DEVELOPMENT.md @@ -1,60 +1,50 @@ # Development -In order to be able to work on this package, it is necessary to run a preparation step. -This will generate the `setup.cfg` file from `setup.cfg.in` and install the gridtools header distribution into the package data. -It will read the version number from the top-level `version.txt` and copy the `LICENSE` file to where packaging tools can find it. +The `gridtools-cpp` distribution is built from the repository root with +[scikit-build-core](https://scikit-build-core.readthedocs.io/) (see the top-level +`pyproject.toml`). The build runs the root `CMakeLists.txt` to install the headers and +CMake config into the package data, and reads the version from `version.txt` — there is +no separate preparation step. -All of this requires `nox`, the preparation step runs in an isolated environment and installs additional requirements `cmake` and `ninja` at runtime. +## Installing + +As always it is recommended to carry out the following steps in a virtual environment. +From the repository root: ```bash -pip install nox -nox -s prepare +pip install . ``` -To delete all generated files run +Directly from a git ref (no subdirectory needed): ```bash -nox -s clean clean_cache +pip install "git+https://github.com/GridTools/gridtools.git@" ``` -where `clean_cache` deletes chached files from Nox sessions like CMake builds and testing wheels (found in `.nox/.cache`), and `clean` deletes visible artifacts like `dist/`, `build/`, `.egg-info/`. -`setup.cfg` will not be deleted for convenience, to make sure tools keep functioning as expected. - -## Installing - -As always it is recommended to carry out the following steps in a virtual environment: +## Building for distribution ```bash -nox -s build -- --wheel . -pip install dist/gridtools_cpp-2.2.0-py3-none-any.whl +python -m build --wheel ``` +The header-only wheel is platform independent (`gridtools_cpp--py3-none-any.whl`). + ## Testing -Using nox, the tests will be carried out in isolated python environments for you: +Using nox (from this directory), the tests run in isolated environments: ```bash nox -s test_src ``` -To test the wheel distribution specifically: +To build and test the wheel distribution specifically: ```bash nox -s build_wheel test_wheel_with_python-3.10 # replace 3.10 with the Python version you are running ``` -## Advanced testing (all supported versions) - -The following requires you to have Python interpreters for Python 3.8, 3.9, 3.10 and 3.11 in your system path. +To run against all supported versions (requires Python 3.8, 3.9, 3.10 and 3.11 in your path): ```bash nox ``` - -## Building for distribution - -Uses (`build`)[https://pypa-build.readthedocs.io/en/latest/], follow the link for available options. - -```bash -nox -s build -- -``` diff --git a/.python_package/noxfile.py b/.python_package/noxfile.py index 6e061bbdce..5182d7a8e7 100644 --- a/.python_package/noxfile.py +++ b/.python_package/noxfile.py @@ -6,80 +6,30 @@ # Please, refer to the LICENSE file in the root directory. # SPDX-License-Identifier: BSD-3-Clause -import configparser -import pathlib import shutil import nox -_RELATIVE_DATA_DIR = pathlib.Path("src/gridtools_cpp/data") +_ROOT = ".." nox.options.sessions = ["test_src", "test_wheel"] @nox.session -def prepare(session: nox.Session): - session.install("cmake>=3.18.1") - session.install("ninja") - build_path = session.cache_dir.joinpath("build").absolute() - build_path.mkdir(exist_ok=True) - install_path = pathlib.Path(".").absolute() / _RELATIVE_DATA_DIR - source_path = pathlib.Path("..").absolute() - with session.chdir(build_path): - session.run( - "cmake", - "-DBUILD_TESTING=OFF", - "-DGT_INSTALL_EXAMPLES:BOOL=OFF", - f"-DCMAKE_INSTALL_PREFIX={install_path}", - "-GNinja", - str(source_path), - ) - session.run("cmake", "--install", ".") - session.log("installed gridttols sources") - version_path = source_path / "version.txt" - config = configparser.ConfigParser() - config.read("setup.cfg.in") - config["metadata"]["version"] = version_path.read_text().strip() - with open("setup.cfg", mode="w") as setup_fp: - config.write(setup_fp) - session.log("updated version metadata") - shutil.copy(source_path / "LICENSE", ".") - session.log("copied license file") - - -def get_wheel(session: nox.Session) -> pathlib.Path: - return list(session.cache_dir.joinpath("dist").glob("gridtools_cpp-*.whl"))[0] +def test_src(session: nox.Session): + session.install(_ROOT) + session.install("pytest") + session.run("pytest", "tests", *session.posargs) @nox.session def build_wheel(session: nox.Session): - prepare(session) dist_path = session.cache_dir.joinpath("dist").absolute() - nox_workdir = pathlib.Path(".").absolute() - session.install("build[virtualenv]", "wheel") - with session.chdir(session.cache_dir): - session.run( - "python", - "-m", - "build", - "--no-isolation", - "--wheel", - "-o", - str(dist_path), - str(nox_workdir), - ) + session.install("build") + session.run("python", "-m", "build", "--wheel", "-o", str(dist_path), _ROOT) session.log(f"built wheel in {dist_path}") - session.log("\n".join(str(path) for path in dist_path.iterdir())) - - -@nox.session -def test_src(session: nox.Session): - prepare(session) - session.install(".") - session.install("pytest") - session.run("pytest", "tests", *session.posargs) @nox.session @@ -93,34 +43,12 @@ def test_wheel(session: nox.Session): @nox.session(python=["3.8", "3.9", "3.10", "3.11"]) def test_wheel_with_python(session: nox.Session): - wheel_path = get_wheel(session) + wheel_path = next(session.cache_dir.joinpath("dist").glob("gridtools_cpp-*.whl")) session.install("pytest") session.install(str(wheel_path)) session.run("pytest", "tests", *session.posargs) -@nox.session -def clean_cache(session: nox.Session): - for subtree in session.cache_dir.iterdir(): - shutil.rmtree(subtree, True) - - -@nox.session -def build(session: nox.Session): - prepare(session) - session.install("build[virtualenv]") - session.run("python", "-m", "build", "--no-isolation", *session.posargs) - - @nox.session def clean(session: nox.Session): - data_dir = _RELATIVE_DATA_DIR - session.log(f"rm -r {data_dir}") - shutil.rmtree(data_dir, True) - session.log("rm -r src/*.egg-info") - for egg_tree in pathlib.Path("src").glob("*.egg-info"): - shutil.rmtree(egg_tree, True) - session.log("rm -r dist") - shutil.rmtree("dist", True) - session.log("rm -r build") - shutil.rmtree("build", True) + shutil.rmtree(session.cache_dir.joinpath("dist"), True) diff --git a/.python_package/pyproject.toml b/.python_package/pyproject.toml deleted file mode 100644 index 7b959378a4..0000000000 --- a/.python_package/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools>=64", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/.python_package/setup.cfg.in b/.python_package/setup.cfg.in deleted file mode 100644 index 2b08478a84..0000000000 --- a/.python_package/setup.cfg.in +++ /dev/null @@ -1,45 +0,0 @@ -[metadata] -name = gridtools-cpp -author = ETH Zurich -author_email = gridtools@cscs.ch -license_files = LICENSE # this file is automatically copied from the top level -long_description = file: README.md -long_description_content_type = text/markdown; charset=UTF-8 -url = https://gridtools.github.io -project_urls = - Source Code = https://github.com/GridTools/gridtools -platforms = any -version = # leave empty, automatically generated -classifiers = - Development Status :: 5 - Production/Stable - Intended Audience :: Science/Research - License :: OSI Approved :: BSD License - Operating System :: OS Independent - Programming Language :: Python :: 3 :: Only - Topic :: Scientific/Engineering :: Atmospheric Science - Topic :: Scientific/Engineering :: Mathematics - Topic :: Scientific/Engineering :: Physics - -[options] -packages = find_namespace: -package_dir = - = src -python_requires = >=3.8 - -[options.package_data] -* = - *.hpp - *.h - *.cmake - py.typed - -[options.packages.find] -where = src -exclude = tests - -[tools:isort] -line_length = 100 - -[flake8] -max-line-length = 100 - diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..93473c690d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,42 @@ +[build-system] +requires = ["scikit-build-core>=0.11"] +build-backend = "scikit_build_core.build" + +[project] +name = "gridtools-cpp" +dynamic = ["version"] +description = "Python package for GridTools headers and CMake files" +readme = ".python_package/README.md" +license = "BSD-3-Clause" +license-files = ["LICENSE"] +authors = [{ name = "ETH Zurich", email = "gridtools@cscs.ch" }] +requires-python = ">=3.8" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Scientific/Engineering :: Atmospheric Science", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Scientific/Engineering :: Physics", +] + +[project.urls] +Homepage = "https://gridtools.github.io" +"Source Code" = "https://github.com/GridTools/gridtools" + +[tool.scikit-build] +cmake.version = ">=3.21" +wheel.py-api = "py3" +wheel.platlib = false +wheel.packages = ["src/gridtools_cpp"] +wheel.install-dir = "gridtools_cpp/data" + +[tool.scikit-build.cmake.define] +BUILD_TESTING = "OFF" +GT_INSTALL_EXAMPLES = "OFF" + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "version.txt" +regex = "(?P.+)" diff --git a/.python_package/src/gridtools_cpp/__init__.py b/src/gridtools_cpp/__init__.py similarity index 100% rename from .python_package/src/gridtools_cpp/__init__.py rename to src/gridtools_cpp/__init__.py diff --git a/.python_package/src/gridtools_cpp/py.typed b/src/gridtools_cpp/py.typed similarity index 100% rename from .python_package/src/gridtools_cpp/py.typed rename to src/gridtools_cpp/py.typed