From db23d6edca6a3d67f247d6105fa01cab22fd150c Mon Sep 17 00:00:00 2001 From: Edoardo Zoni Date: Tue, 9 Sep 2025 13:54:28 -0700 Subject: [PATCH 1/3] Implement same dependency/release update workflow as WarpX --- CMakeLists.txt | 6 +- cmake/dependencies/AMReX.cmake | 10 ++- cmake/dependencies/pybind11.cmake | 10 ++- dependencies.json | 7 ++ docs/source/conf.py | 11 ++- setup.py | 9 +- update_dependencies.py | 141 ++++++++++++++++++++++++++++++ 7 files changed, 186 insertions(+), 8 deletions(-) create mode 100644 dependencies.json create mode 100755 update_dependencies.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 411d75b4..8abc8a73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,11 @@ +# Parse pyAMReX version information +file(READ "${CMAKE_CURRENT_LIST_DIR}/dependencies.json" dependencies_data) +string(JSON pyamrex_version GET "${dependencies_data}" version_pyamrex) + # Preamble #################################################################### # cmake_minimum_required(VERSION 3.24.0) -project(pyAMReX VERSION 25.09) +project(pyAMReX VERSION ${pyamrex_version}) include(${pyAMReX_SOURCE_DIR}/cmake/pyAMReXFunctions.cmake) diff --git a/cmake/dependencies/AMReX.cmake b/cmake/dependencies/AMReX.cmake index 33c6f251..2cedc319 100644 --- a/cmake/dependencies/AMReX.cmake +++ b/cmake/dependencies/AMReX.cmake @@ -67,7 +67,7 @@ macro(find_amrex) message(STATUS "Searching for pre-installed AMReX ...") # https://amrex-codes.github.io/amrex/docs_html/BuildingAMReX.html#importing-amrex-into-your-cmake-project # not strictly required yet to compile pyAMReX: EB - find_package(AMReX 25.09 CONFIG REQUIRED COMPONENTS PARTICLES PIC) + find_package(AMReX ${amrex_version} CONFIG REQUIRED COMPONENTS PARTICLES PIC) message(STATUS "AMReX: Found version '${AMReX_VERSION}'") if(AMReX_GPU_BACKEND STREQUAL CUDA) @@ -86,7 +86,13 @@ option(pyAMReX_amrex_internal "Download & build AMReX" ON) set(pyAMReX_amrex_repo "https://github.com/AMReX-Codes/amrex.git" CACHE STRING "Repository URI to pull and build AMReX from if(pyAMReX_amrex_internal)") -set(pyAMReX_amrex_branch "25.09" + +# Parse AMReX version and commit information +file(READ "${pyAMReX_SOURCE_DIR}/dependencies.json" dependencies_data) +string(JSON amrex_version GET "${dependencies_data}" version_amrex) +string(JSON amrex_commit GET "${dependencies_data}" commit_amrex) + +set(pyAMReX_amrex_branch ${amrex_commit} CACHE STRING "Repository branch for pyAMReX_amrex_repo if(pyAMReX_amrex_internal)") diff --git a/cmake/dependencies/pybind11.cmake b/cmake/dependencies/pybind11.cmake index 45ba7898..b39b88da 100644 --- a/cmake/dependencies/pybind11.cmake +++ b/cmake/dependencies/pybind11.cmake @@ -41,7 +41,7 @@ function(find_pybind11) mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FETCHEDpybind11) endif() elseif(NOT pyAMReX_pybind11_internal) - find_package(pybind11 3.0.0 CONFIG REQUIRED) + find_package(pybind11 ${pybind11_version} CONFIG REQUIRED) message(STATUS "pybind11: Found version '${pybind11_VERSION}'") endif() endfunction() @@ -56,7 +56,13 @@ option(pyAMReX_pybind11_internal "Download & build pybind11" ON) set(pyAMReX_pybind11_repo "https://github.com/pybind/pybind11.git" CACHE STRING "Repository URI to pull and build pybind11 from if(pyAMReX_pybind11_internal)") -set(pyAMReX_pybind11_branch "v3.0.0" + +# Parse AMReX version and commit information +file(READ "${pyAMReX_SOURCE_DIR}/dependencies.json" dependencies_data) +string(JSON pybind11_version GET "${dependencies_data}" version_pybind11) +string(JSON pybind11_commit GET "${dependencies_data}" commit_pybind11) + +set(pyAMReX_pybind11_branch ${pybind11_commit} CACHE STRING "Repository branch for pyAMReX_pybind11_repo if(pyAMReX_pybind11_internal)") diff --git a/dependencies.json b/dependencies.json new file mode 100644 index 00000000..cbeaa1f7 --- /dev/null +++ b/dependencies.json @@ -0,0 +1,7 @@ +{ + "version_pyamrex": "25.09", + "version_amrex": "25.09", + "version_pybind11": "3.0.0", + "commit_amrex": "95822df1a393b39aeca5e590328e228513132159", + "commit_pybind11": "v3.0.0" +} diff --git a/docs/source/conf.py b/docs/source/conf.py index b37aa5d1..1fac635d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,6 +22,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +import json import os import shutil import subprocess @@ -72,14 +73,20 @@ copyright = "2023, The Regents of the University of California, through Lawrence Berkeley National Laboratory, National Renewable Energy Laboratory Alliance for Sustainable Energy, LLC and Lawrence Livermore National Security, LLC (subject to receipt of any required approvals from the U.S. Dept. of Energy)" author = "AMReX collaboration" +# Parse pyAMReX version information +dependencies_file = "../../dependencies.json" +with open(dependencies_file, "r") as file: + dependencies_data = json.load(file) +pyamrex_version = dependencies_data.get("version_pyamrex") + # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = "25.09" +version = pyamrex_version # The full version, including alpha/beta/rc tags. -release = "25.09" +release = pyamrex_version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index bd12b574..70b38816 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,7 @@ # Authors: Axel Huebl # License: BSD-3-Clause-LBNL # +import json import os import platform import re @@ -213,12 +214,18 @@ def build_extension(self, ext): if AMReX_MPI == "ON": install_requires.append("mpi4py>=2.1.0") +# Parse pyAMReX version information +dependencies_file = "dependencies.json" +with open(dependencies_file, "r") as file: + dependencies_data = json.load(file) +pyamrex_version = dependencies_data.get("version_pyamrex") + # keyword reference: # https://packaging.python.org/guides/distributing-packages-using-setuptools setup( name="amrex", # note PEP-440 syntax: x.y.zaN but x.y.z.devN - version="25.09", + version=pyamrex_version, packages=["amrex"], # Python sources: package_dir={"": "src"}, diff --git a/update_dependencies.py b/update_dependencies.py new file mode 100755 index 00000000..e8009edd --- /dev/null +++ b/update_dependencies.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# +# This file is part of pyAMReX. +# +# License: BSD-3-Clause-LBNL + +import argparse +import datetime +import json +import os +import sys +from pathlib import Path + +import requests + + +def update(args): + # list of repositories to update + repo_dict = {} + if args.all or args.amrex: + repo_dict["amrex"] = {} + repo_dict["amrex"]["commit"] = ( + "https://api.github.com/repos/AMReX-Codes/amrex/commits/development" + ) + repo_dict["amrex"]["tags"] = ( + "https://api.github.com/repos/AMReX-Codes/amrex/tags" + ) + if args.all or args.pyamrex: + repo_dict["pyamrex"] = {} + repo_dict["pyamrex"]["commit"] = ( + "https://api.github.com/repos/AMReX-Codes/pyamrex/commits/development" + ) + repo_dict["pyamrex"]["tags"] = ( + "https://api.github.com/repos/AMReX-Codes/pyamrex/tags" + ) + + # list of repositories labels for logging convenience + repo_labels = { + "amrex": "AMReX", + "pyamrex": "pyAMReX", + } + + # read from JSON file with dependencies data + repo_dir = Path(__file__).parent.absolute() + dependencies_file = os.path.join(repo_dir, "dependencies.json") + try: + with open(dependencies_file, "r") as file: + dependencies_data = json.load(file) + except Exception as e: + print(f"An unexpected error occurred: {e}") + sys.exit() + + # loop over repositories and update dependencies data + for repo_name, repo_subdict in repo_dict.items(): + print(f"\nUpdating {repo_labels[repo_name]}...") + # set keys to access dependencies data + commit_key = f"commit_{repo_name}" + version_key = f"version_{repo_name}" + # get new commit information + commit_response = requests.get(repo_subdict["commit"]) + commit_dict = commit_response.json() + # set new commit + repo_commit_sha = commit_dict["sha"] + # get new version tag information + tags_response = requests.get(repo_subdict["tags"]) + tags_list = tags_response.json() + # filter out old-format tags for specific repositories + if repo_name == "amrex": + tags_list_filtered = [ + tag_dict + for tag_dict in tags_list + if (tag_dict["name"] != "boxlib" and tag_dict["name"] != "v2024") + ] + # set new version tag + if repo_name == "pyamrex": + # current date version for the pyAMReX release update + repo_version_tag = datetime.date.today().strftime("%y.%m") + else: + # latest available tag (index 0) for all other dependencies + repo_version_tag = tags_list_filtered[0]["name"] + # use version tag instead of commit sha for a release update + new_commit_sha = repo_version_tag if args.release else repo_commit_sha + # update commit + if repo_name != "pyamrex": + print(f"- old commit: {dependencies_data[commit_key]}") + print(f"- new commit: {new_commit_sha}") + if dependencies_data[commit_key] == new_commit_sha: + print("Skipping commit update...") + else: + print("Updating commit...") + dependencies_data[f"commit_{repo_name}"] = new_commit_sha + # update version + print(f"- old version: {dependencies_data[version_key]}") + print(f"- new version: {repo_version_tag}") + if dependencies_data[version_key] == repo_version_tag: + print("Skipping version update...") + else: + print("Updating version...") + dependencies_data[f"version_{repo_name}"] = repo_version_tag + + # write to JSON file with dependencies data + with open(dependencies_file, "w") as file: + json.dump(dependencies_data, file, indent=4) + + +if __name__ == "__main__": + # define parser + parser = argparse.ArgumentParser() + + # add arguments: AMReX option + parser.add_argument( + "--amrex", + help="Update AMReX only", + action="store_true", + dest="amrex", + ) + + # add arguments: pyAMReX option + parser.add_argument( + "--pyamrex", + help="Update pyAMReX only", + action="store_true", + dest="pyamrex", + ) + + # add arguments: release option + parser.add_argument( + "--release", + help="New release", + action="store_true", + dest="release", + ) + + # parse arguments + args = parser.parse_args() + + # set args.all automatically + args.all = False if (args.amrex or args.pyamrex) else True + + # update + update(args) From ce41e81b263854cbe6159c51924c2664e0ed00ea Mon Sep 17 00:00:00 2001 From: Edoardo Zoni Date: Wed, 10 Sep 2025 15:46:33 -0700 Subject: [PATCH 2/3] Add pybind11 command line argument to the update script --- update_dependencies.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/update_dependencies.py b/update_dependencies.py index e8009edd..3bc00385 100755 --- a/update_dependencies.py +++ b/update_dependencies.py @@ -5,6 +5,7 @@ # License: BSD-3-Clause-LBNL import argparse +import copy import datetime import json import os @@ -25,6 +26,14 @@ def update(args): repo_dict["amrex"]["tags"] = ( "https://api.github.com/repos/AMReX-Codes/amrex/tags" ) + if args.all or args.pybind11: + repo_dict["pybind11"] = {} + repo_dict["pybind11"]["commit"] = ( + "https://api.github.com/repos/pybind/pybind11/commits/master" + ) + repo_dict["pybind11"]["tags"] = ( + "https://api.github.com/repos/pybind/pybind11/tags" + ) if args.all or args.pyamrex: repo_dict["pyamrex"] = {} repo_dict["pyamrex"]["commit"] = ( @@ -37,6 +46,7 @@ def update(args): # list of repositories labels for logging convenience repo_labels = { "amrex": "AMReX", + "pybind11": "pybind11", "pyamrex": "pyAMReX", } @@ -65,6 +75,7 @@ def update(args): tags_response = requests.get(repo_subdict["tags"]) tags_list = tags_response.json() # filter out old-format tags for specific repositories + tags_list_filtered = copy.deepcopy(tags_list) if repo_name == "amrex": tags_list_filtered = [ tag_dict @@ -115,6 +126,14 @@ def update(args): dest="amrex", ) + # add arguments: pybind11 option + parser.add_argument( + "--pybind11", + help="Update pybind11 only", + action="store_true", + dest="pybind11", + ) + # add arguments: pyAMReX option parser.add_argument( "--pyamrex", @@ -135,7 +154,7 @@ def update(args): args = parser.parse_args() # set args.all automatically - args.all = False if (args.amrex or args.pyamrex) else True + args.all = False if (args.amrex or args.pybind11 or args.pyamrex) else True # update update(args) From baafb5564b251c6b66e02828ad8c3c042a438756 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 16 Sep 2025 16:11:40 -0700 Subject: [PATCH 3/3] `MANIFEST.in`: `dependencies.json` --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 9a61a6d7..e09d2652 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,7 @@ include README.md LICENSE include pyproject.toml include requirements.txt requirements_mpi.txt +include dependencies.json global-include CMakeLists.txt *.cmake *.in recursive-include cmake * recursive-include src *