From 6f35990a5a9d97cdfd71aa20612ad0ad8539ec4e Mon Sep 17 00:00:00 2001 From: Janosh Riebesell Date: Mon, 11 Mar 2024 16:23:36 +0100 Subject: [PATCH] Add Python 3.12 to officially supported versions and test it in CI (#139) * add python 3.12 to officially supported versions and test it in CI * explicit setuptools install in test.yml * split release.yml workflow out from test.yml * fix release wf name * remove PR and push triggers from release.yml * refactor CrystalGraphConverter._create_graph_fast --- .github/workflows/release.yml | 85 +++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 90 ++++------------------------------- .pre-commit-config.yaml | 4 +- chgnet/graph/converter.py | 20 +++----- chgnet/model/dynamics.py | 2 +- pyproject.toml | 1 + 6 files changed, 105 insertions(+), 97 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e9269322 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,85 @@ +name: Release + +on: + release: + types: [published] + workflow_dispatch: + inputs: + task: + type: choice + options: [release, test-release] + default: test-release + description: Release to PyPI or TestPyPI. + +jobs: + tests: + # run test.yml first to ensure that the test suite is passing + uses: ./.github/workflows/test.yml + + build_source_dist: + name: Build source distribution + needs: tests + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + name: Install Python + with: + python-version: "3.10" + + - name: Build source distribution + run: | + pip install build + python -m build --sdist + + - uses: actions/upload-artifact@v3 + with: + path: dist/*.tar.gz + + build_wheels: + name: Build wheels for Python ${{ matrix.python-version }} on ${{ matrix.os }} + needs: tests + strategy: + matrix: + os: [ubuntu-latest, macos-14, windows-latest] + python-version: ["39", "310", "311", "312"] + runs-on: ${{ matrix.os }} + steps: + - name: Check out repo + uses: actions/checkout@v4 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.16.5 + env: + CIBW_BUILD: cp${{ matrix.python-version }}-* + CIBW_ARCHS_MACOS: universal2 + + - name: Save artifact + uses: actions/upload-artifact@v3 + with: + path: wheelhouse + + release: + name: Release wheels and source distribution to PyPI + needs: [build_wheels, build_source_dist] + runs-on: ubuntu-latest + permissions: + # For pypi trusted publishing + id-token: write + steps: + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: artifact + path: dist + + - name: Publish to PyPi or TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + skip-existing: true + verbose: true + # set the repository URL to the test PyPI repository if the task is 'test-release' + # else empty string defaults to production PyPI + repository-url: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'test-release' && 'https://test.pypi.org/legacy/' || '' }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c42dcac..479b7f9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,15 +4,8 @@ on: push: branches: [main] pull_request: - release: - types: [published] workflow_dispatch: - inputs: - task: - type: choice - options: [tests, release, test-release] - default: tests - description: Run tests, release to PyPI, or release to TestPyPI. + workflow_call: jobs: tests: @@ -20,6 +13,7 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, macos-14, windows-latest] + python-version: ["3.10", "3.12"] runs-on: ${{ matrix.os }} steps: @@ -29,7 +23,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: ${{ matrix.python-version }} cache: pip cache-dependency-path: pyproject.toml @@ -38,15 +32,17 @@ jobs: - name: Install dependencies run: | - uv pip install cython --system - # install ase from main branch until FrechetCellFilter is released - # TODO remove uv pip install git+https://gitlab.com/ase/ase + uv pip install cython setuptools --system + python setup.py build_ext --inplace + uv pip install -e .[test] --system + + # TODO remove next line installing ase from main branch when FrechetCellFilter is released uv pip install --upgrade 'ase@git+https://gitlab.com/ase/ase' --system - name: Run Tests - run: pytest --capture=no --cov --cov-report=xml . + run: pytest --capture=no --cov --cov-report=xml env: CHGNET_DEVICE: cpu @@ -56,71 +52,3 @@ jobs: with: project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} coverage-reports: coverage.xml - - build_source_dist: - name: Build source distribution - needs: tests - runs-on: ubuntu-latest - if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.task == 'release') - steps: - - name: Check out repo - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - name: Install Python - with: - python-version: "3.10" - - - name: Build source distribution - run: | - pip install build - python -m build --sdist - - - uses: actions/upload-artifact@v3 - with: - path: dist/*.tar.gz - - build_wheels: - name: Build wheels for Python ${{ matrix.python-version }} on ${{ matrix.os }} - needs: tests - if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.task == 'release') - strategy: - matrix: - os: [ubuntu-latest, macos-14, windows-latest] - python-version: ["39", "310", "311"] - runs-on: ${{ matrix.os }} - steps: - - name: Check out repo - uses: actions/checkout@v4 - - - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 - env: - CIBW_BUILD: cp${{ matrix.python-version }}-* - CIBW_ARCHS_MACOS: universal2 - - - name: Save artifact - uses: actions/upload-artifact@v3 - with: - path: wheelhouse - - release: - name: Release wheels and source distribution to PyPI - needs: [build_wheels, build_source_dist] - runs-on: ubuntu-latest - permissions: - # For pypi trusted publishing - id-token: write - steps: - - name: Download build artifacts - uses: actions/download-artifact@v3 - with: - name: artifact - path: dist - - - name: Publish to PyPi or TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - skip-existing: true - verbose: true - repository-url: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.task == 'test-release' && 'https://test.pypi.org/legacy/' || '' }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 60fa5e18..72275eec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ default_install_hook_types: [pre-commit, commit-msg] repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.0 + rev: v0.3.2 hooks: - id: ruff args: [--fix] @@ -46,7 +46,7 @@ repos: - svelte - repo: https://github.com/pre-commit/mirrors-eslint - rev: v9.0.0-beta.1 + rev: v9.0.0-beta.2 hooks: - id: eslint types: [file] diff --git a/chgnet/graph/converter.py b/chgnet/graph/converter.py index 9a29a856..376dcb5b 100644 --- a/chgnet/graph/converter.py +++ b/chgnet/graph/converter.py @@ -250,25 +250,19 @@ def _create_graph_fast( distance = np.ascontiguousarray(distance) gc_saved = gc.get_threshold() gc.set_threshold(0) - ( - nodes, - directed_edges_list, - undirected_edges_list, - undirected_edges, - ) = make_graph( + nodes, dir_edges_list, undir_edges_list, undirected_edges = make_graph( center_index, len(center_index), neighbor_index, image, distance, n_atoms ) graph = Graph(nodes=nodes) - graph.directed_edges_list = directed_edges_list - graph.undirected_edges_list = undirected_edges_list + graph.directed_edges_list = dir_edges_list + graph.undirected_edges_list = undir_edges_list graph.undirected_edges = undirected_edges gc.set_threshold(gc_saved[0]) return graph def set_isolated_atom_response( - self, - on_isolated_atoms: Literal["ignore", "warn", "error"], + self, on_isolated_atoms: Literal["ignore", "warn", "error"] ) -> None: """Set the graph converter's response to isolated atom graph Args: @@ -282,7 +276,7 @@ def set_isolated_atom_response( self.on_isolated_atoms = on_isolated_atoms return - def as_dict(self) -> dict[str, float]: + def as_dict(self) -> dict[str, str | float]: """Save the args of the graph converter.""" return { "atom_graph_cutoff": self.atom_graph_cutoff, @@ -291,6 +285,6 @@ def as_dict(self) -> dict[str, float]: } @classmethod - def from_dict(cls, dict) -> CrystalGraphConverter: + def from_dict(cls, dct: dict) -> CrystalGraphConverter: """Create converter from dictionary.""" - return CrystalGraphConverter(**dict) + return CrystalGraphConverter(**dct) diff --git a/chgnet/model/dynamics.py b/chgnet/model/dynamics.py index 2eaf65d7..d964a7a7 100644 --- a/chgnet/model/dynamics.py +++ b/chgnet/model/dynamics.py @@ -52,7 +52,7 @@ class CHGNetCalculator(Calculator): """CHGNet Calculator for ASE applications.""" - implemented_properties = ("energy", "forces", "stress", "magmoms") # type: ignore + implemented_properties = ("energy", "forces", "stress", "magmoms") def __init__( self, diff --git a/pyproject.toml b/pyproject.toml index 47955ddb..5d34cbe8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Scientific/Engineering :: Chemistry",