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/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 * 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..3bc00385 --- /dev/null +++ b/update_dependencies.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 +# +# This file is part of pyAMReX. +# +# License: BSD-3-Clause-LBNL + +import argparse +import copy +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.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"] = ( + "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", + "pybind11": "pybind11", + "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 + tags_list_filtered = copy.deepcopy(tags_list) + 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: pybind11 option + parser.add_argument( + "--pybind11", + help="Update pybind11 only", + action="store_true", + dest="pybind11", + ) + + # 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.pybind11 or args.pyamrex) else True + + # update + update(args)