diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_docs.yml index 8745acd..8f2ee01 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_docs.yml @@ -46,11 +46,14 @@ jobs: # This action sets the current path to the root of your github repo - uses: actions/checkout@v7 - - name: Update pip - run: python3 -m pip install --upgrade pip setuptools + - name: Update pip and extra deps + run: | + python3 -m pip install --upgrade pip setuptools + python3 -m pip install --no-binary=h5py h5py + python3 -m pip install . --group docs - name: Install dependencies - run: python3 -m pip install --no-binary=h5py -e ".[docs]" + run: python3 -m pip install -e . --no-build-isolation - name: Build docs run: jupyter book build . diff --git a/.github/workflows/check_formatting.yml b/.github/workflows/check_formatting.yml index afe2700..96183fc 100644 --- a/.github/workflows/check_formatting.yml +++ b/.github/workflows/check_formatting.yml @@ -43,11 +43,13 @@ jobs: steps: - uses: actions/checkout@v7 - - name: Update pip - run: python3 -m pip install --upgrade pip setuptools + - name: Update pip and install build deps + run: | + python3 -m pip install --upgrade pip setuptools + python3 -m pip install . --group dev --no-build-isolation - name: Install code - run: python3 -m pip install .[dev] + run: python3 -m pip install . --no-build-isolation - name: Check code formatting with ruff run: | diff --git a/.github/workflows/test_dolfinx_versions.yml b/.github/workflows/test_dolfinx_versions.yml index 56441dd..c9233ab 100644 --- a/.github/workflows/test_dolfinx_versions.yml +++ b/.github/workflows/test_dolfinx_versions.yml @@ -31,4 +31,4 @@ jobs: # Call the reusable workflow uses: ./.github/workflows/test_workflow.yml with: - dolfinx_tag: ${{ matrix.tag }} + tag: ${{ matrix.tag }} diff --git a/.github/workflows/test_package_openmpi.yml b/.github/workflows/test_package_openmpi.yml deleted file mode 100644 index 7c98a9a..0000000 --- a/.github/workflows/test_package_openmpi.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: Test package with different mpi compilers - -on: - push: - branches: - - main - pull_request: - branches: - - main - - workflow_call: - workflow_dispatch: - schedule: - - cron: "0 8 * * *" - -jobs: - create-datasets: - uses: ./.github/workflows/create_legacy_data.yml - with: - artifact_name: "legacy_ompi" - - create-legacy-datasets: - uses: ./.github/workflows/create_legacy_checkpoint.yml - with: - artifact_name: "legacy_checkpoint_ompi" - - test-code: - runs-on: ubuntu-latest - needs: [create-datasets, create-legacy-datasets] - container: ${{ matrix.container }} - env: - DEB_PYTHON_INSTALL_LAYOUT: deb_system - PETSC_ARCH: "linux-gnu-real64-32" - OMPI_ALLOW_RUN_AS_ROOT: 1 - OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: 1 - PRTE_MCA_rmaps_default_mapping_policy: :oversubscribe - working-directory: ./src - PIP_NO_BINARY: h5py - - strategy: - matrix: - adios2: ["v2.11.0", "v2.12.1", "default"] - container: - - ghcr.io/fenics/test-env:current-openmpi - - ghcr.io/fenics/test-env:current-mpich - steps: - - uses: actions/checkout@v7 - - - name: Update pip - run: python3 -m pip install --upgrade pip - - - name: Install build requirements - run: python3 -m pip install -r build-requirements.txt - - - name: Install DOLFINx - uses: jorgensd/actions/install-dolfinx@v0.4 - with: - adios2: ${{ matrix.adios2 }} - petsc_arch: ${{ env.PETSC_ARCH }} - dolfinx: main - basix: main - ufl: main - ffcx: main - working-directory: ${{ env.working-directory}} - - - name: Download legacy data - uses: actions/download-artifact@v8 - with: - name: legacy_ompi - path: ./legacy - - - name: Download legacy data - uses: actions/download-artifact@v8 - with: - name: legacy_checkpoint_ompi - path: ./legacy_checkpoint - - - name: Install package - run: | - HDF5_MPI=ON HDF5_PKGCONFIG_NAME="hdf5" python3 -m pip install h5py --no-build-isolation --no-binary=h5py - python3 -m pip install .[test] - - name: Run tests - run: | - coverage run --rcfile=.coveragerc -m mpi4py -m pytest -xvs ./tests/ - - - name: Run tests in parallel - run: | - mpirun -n 2 coverage run --rcfile=.coveragerc -m mpi4py -m pytest -xvs ./tests/ diff --git a/.github/workflows/test_redhat.yml b/.github/workflows/test_redhat.yml deleted file mode 100644 index e0a8b65..0000000 --- a/.github/workflows/test_redhat.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Test package with redhat - -on: - # push: - # branches: - # - main - # pull_request: - # branches: - # - main - - workflow_call: - workflow_dispatch: - # schedule: - # - cron: "0 8 * * *" - -jobs: - create-datasets: - uses: ./.github/workflows/create_legacy_data.yml - with: - artifact_name: "legacy_ompi" - - create-legacy-datasets: - uses: ./.github/workflows/create_legacy_checkpoint.yml - with: - artifact_name: "legacy_checkpoint_ompi" - - test-code: - runs-on: "ubuntu-latest" - needs: [create-datasets, create-legacy-datasets] - container: docker.io/fenicsproject/test-env:current-redhat - env: - DEB_PYTHON_INSTALL_LAYOUT: deb_system - PETSC_ARCH: "" - PETSC_DIR: "/usr/local/" - PYTHONPATH: "/usr/local/lib/:${PYTHONPATH}" - working-directory: ./src - - strategy: - matrix: - adios2: ["master"] - steps: - - uses: actions/checkout@v7 - - - name: Get pip flags based on version - id: python-version - shell: bash -el {0} - run: | - MODERN_PIP=$(python3 -c "import sys; t = sys.version_info >= (3, 11, 0); sys.stdout.write(str(t))") - if [ ${MODERN_PIP} == "True" ]; then - FLAGS="--break-system-packages" - else - FLAGS="" - python3 -m pip install --upgrade pip - fi - echo "PYTHON_FLAGS=${FLAGS}" >> "$GITHUB_OUTPUT" - - - name: Update pip - run: python3 -m pip install ${{ steps.python-version.outputs.PYTHON_FLAGS}} --upgrade pip setuptools - - - name: Install DOLFINx - uses: jorgensd/actions/install-dolfinx@v0.4 - with: - adios2: ${{ matrix.adios2 }} - petsc_arch: ${{ env.PETSC_ARCH }} - petsc_dir: ${{ env.PETSC_DIR }} - dolfinx: main - basix: main - ufl: main - ffcx: main - working-directory: ${{ env.working-directory}} - - - name: Download legacy data - uses: actions/download-artifact@v8 - with: - name: legacy_ompi - path: ./legacy - - - name: Download legacy data - uses: actions/download-artifact@v8 - with: - name: legacy_checkpoint_ompi - path: ./legacy_checkpoint - - - name: Install package - run: python3 -m pip install ${{ steps.python-version.outputs.PYTHON_FLAGS}} --check-build-dependencies .[test] - - - name: Run tests - run: | - coverage run --rcfile=.coveragerc -m mpi4py -m pytest -xvs ./tests - - - name: Run tests in parallel - run: | - mpirun -n 4 coverage run --rcfile=.coveragerc -m mpi4py -m pytest -xvs ./tests diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 7849337..6d829aa 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -1,17 +1,49 @@ -name: Test +name: Test package on: workflow_call: inputs: - dolfinx_tag: + tag: + description: "Tag of DOLFINx docker image" + default: "nightly" required: true type: string + workflow_dispatch: + inputs: + tag: + description: "Tag of DOLFINx docker image" + default: "nightly" + required: true + type: string +env: + DEB_PYTHON_INSTALL_LAYOUT: deb_system + DEFAULT_TAG: nightly + HDF5_MPI: "ON" + HDF5_INCLUDEDIR: "/usr/include/hdf5/openmpi" + H5PY_SETUP_REQUIRES: 0 + OMPI_ALLOW_RUN_AS_ROOT: 1 + OMPI_ALLOW_RUN_AS_ROOT_CONFIRM: 1 + PRTE_MCA_rmaps_default_mapping_policy: :oversubscribe + CC: mpicc + CXX: mpicxx jobs: + get_image_tag: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.docker_tag.outputs.image }} + steps: + - id: docker_tag + run: echo "image=${{ inputs.tag || env.DEFAULT_TAG }}" >> $GITHUB_OUTPUT + test-code: runs-on: ubuntu-24.04 # The container tag is now dynamic based on the input passed by the caller - container: ghcr.io/fenics/dolfinx/dolfinx:${{ inputs.dolfinx_tag }} + container: ghcr.io/fenics/test-env:current + needs: + [get_image_tag] + env: + working-directory: ./src steps: - uses: actions/checkout@v7 @@ -20,7 +52,8 @@ jobs: run: python3 -m pip install --upgrade pip - name: Install build requirements - run: python3 -m pip install -r build-requirements.txt + run: python3 -m pip install --group build --no-build-isolation + # Note: We assume the caller workflow has already uploaded these artifacts - name: Download legacy mpich data @@ -35,10 +68,38 @@ jobs: name: legacy_checkpoint_mpich path: ./legacy_checkpoint + - name: Install DOLFINx (stable) + if: needs.get_image_tag.outputs.image == 'stable' + uses: jorgensd/actions/install-dolfinx@v0.4 + with: + adios2: v2.12.1 + petsc_arch: linux-gnu-real64-32 + dolfinx: release + basix: release + ufl: release + ffcx: release + working-directory: ${{ env.working-directory}} + + - name: Install DOLFINx (nightly) + if: needs.get_image_tag.outputs.image == 'nightly' + uses: jorgensd/actions/install-dolfinx@v0.4 + with: + adios2: v2.12.1 + petsc_arch: linux-gnu-real64-32 + working-directory: ${{ env.working-directory}} + + - name: Configure HDF5 MPI Environment + run: | + # Evaluate architecture dynamically and write to GITHUB_ENV + ARCH_TRIPLET=$(gcc -print-multiarch) + echo "HDF5_LIBDIR=/usr/lib/${ARCH_TRIPLET}/hdf5/openmpi" >> $GITHUB_ENV + - name: Install package run: | - HDF5_MPI=ON HDF5_PKGCONFIG_NAME="hdf5" python3 -m pip install h5py --no-build-isolation --no-binary=h5py - python3 -m pip install .[test] + python3 -m pip install "Cython>=3.0.11" "pkgconfig>=1.5.5" + python3 -m pip install h5py --no-binary=h5py --no-build-isolation + python3 -m pip install --group dev --group test + python3 -m pip install . --no-build-isolation - name: Show adios2 version run: python3 -c "import adios2; print(adios2.__version__)" @@ -65,6 +126,6 @@ jobs: - name: Upload coverage report uses: actions/upload-artifact@v7 with: - name: code-coverage-report-${{ inputs.dolfinx_tag }} + name: code-coverage-report-${{ inputs.tag }} path: htmlcov if-no-files-found: error diff --git a/build-requirements.txt b/build-requirements.txt deleted file mode 100644 index a58cd3b..0000000 --- a/build-requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -scikit-build-core[pyproject]>=0.11.0 -nanobind>=1.3.2 -setuptools>=77.0.3 -packaging>=24.2 -pkgconfig diff --git a/docs/testing.md b/docs/testing.md index 7751c05..e7cbe20 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -21,7 +21,8 @@ Install the library with the optional `test` dependencies to ensure you have packages like `pytest`, `coverage`, and `ipyparallel` ```bash -python3 -m pip install ".[test]" +python3 -m pip install . --group test --no-build-isolation +python3 -m pip install -e . --no-build-isolation ``` ### Running Tests diff --git a/pyproject.toml b/pyproject.toml index ccb8852..9bba01a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,13 @@ -[build-system] # Require setuptool version due to https://github.com/pypa/setuptools/issues/2938 -requires = ["setuptools>=61.0.0", "wheel"] +[build-system] +requires = [ + "setuptools>=77.0.3", + "wheel", + "scikit-build-core[pyproject]>=0.11.0", + "nanobind>=1.3.2,<2.15", # Temporary cap on nanobind for stable dolfinx + "packaging>=24.2", + "pkgconfig" +] +build-backend = "setuptools.build_meta" [project] name = "io4dolfinx" @@ -14,6 +22,20 @@ readme = "README.md" dependencies = ["fenics-dolfinx>=0.10.0", "packaging"] [project.optional-dependencies] +h5py = ["h5py"] +pyvista = ["pyvista"] +xdmf = ["h5py"] +exodus = ["netcdf4"] + +[dependency-groups] +build = [ + "scikit-build-core[pyproject]>=0.11.0", + "nanobind>=1.3.2,<3.0", + "setuptools>=77.0.3", + "packaging>=24.2", + "pkgconfig" +] + test = [ "pytest", "coverage", @@ -22,23 +44,28 @@ test = [ "io4dolfinx[pyvista]", "io4dolfinx[xdmf]" ] -dev = ["pdbpp", "ipython", "mypy", "ruff"] -h5py = ["h5py"] -pyvista = ["pyvista"] -xdmf = ["h5py"] -exodus = ["netcdf4"] +dev = [ + "pdbpp", + "ipython", + "mypy", + "ruff" +] docs = [ "jupyter-book<2.0.0", "ipyparallel", "ipywidgets", "jupytext", - "ipykernel<7.0.0", # Note: Remove once https://github.com/ipython/ipykernel/issues/1450 is in a release + "ipykernel", "sphinx-codeautolink", "io4dolfinx[h5py]", "io4dolfinx[pyvista]", "sphinx_external_toc<1.1.0", ] -all = ["io4dolfinx[test,dev,docs]"] +all = [ + { include-group = "test" }, + { include-group = "dev" }, + { include-group = "docs" } +] [tool.pytest.ini_options] addopts = ["--import-mode=importlib"] @@ -67,7 +94,6 @@ select = [ "I001", ] - [tool.ruff.lint.isort] known-first-party = ["io4dolfinx"] known-third-party = [ @@ -91,7 +117,6 @@ section-order = [ [tool.ruff.lint.isort.sections] "mpi" = ["mpi4py", "petsc4py"] - [tool.bumpversion] allow_dirty = false commit = true @@ -102,7 +127,6 @@ tag_name = "v{new_version}" tag_message = "Bump version: {current_version} → {new_version}" current_version = "1.3.0" - [[tool.bumpversion.files]] filename = "pyproject.toml" search = 'version = "{current_version}"'