diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 504efd32..7ae1bdf1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,34 +12,30 @@ jobs: python-version: ['3.9','3.10','3.11','3.12'] steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install poetry - run: pipx install poetry - - - name: Install python dependencies - run: | - poetry env use ${{ matrix.python-version }} - poetry install --with dev --extras all - - - name: Run test suite - env: - # show timings of tests - PYTEST_ADDOPTS: "--durations=0" - run: poetry run pytest --run-extra-mlips --cov janus_core --cov-append . - - - name: Report coverage to Coveralls - uses: coverallsapp/github-action@v2 - with: - parallel: true - flag-name: run-${{ matrix.python-version }} - file: coverage.xml - base-path: janus_core + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "0.5.7" + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: uv sync --all-extras + + - name: Run test suite + env: + # show timings of tests + PYTEST_ADDOPTS: "--durations=0" + run: uv run pytest --run-extra-mlips --cov janus_core --cov-append . + + - name: Report coverage to Coveralls + uses: coverallsapp/github-action@v2 + with: + parallel: true + flag-name: run-${{ matrix.python-version }} + file: coverage.xml + base-path: janus_core coverage: needs: tests @@ -54,50 +50,42 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 - - - name: Check all sources documented - run: | - diff -y --suppress-common-lines \ - <(git ls-files janus_core/** | sed '/.py$/!d; s/\/__init__.py//; s#/#.#g; s/.py$//' | sort) \ - <(sed -nr '/automodule/{s/.*::\s*//;p}' docs/source/apidoc/* | sort) + - uses: actions/checkout@v4 - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: '3.11' + - name: Check all sources documented + run: | + diff -y --suppress-common-lines \ + <(git ls-files janus_core/** | sed '/.py$/!d; s/\/__init__.py//; s#/#.#g; s/.py$//' | sort) \ + <(sed -nr '/automodule/{s/.*::\s*//;p}' docs/source/apidoc/* | sort) - - name: Install poetry - run: pipx install poetry + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "0.5.7" + python-version: "3.12" - - name: Install python dependencies - run: | - poetry env use 3.11 - poetry install --with docs + - name: Install dependencies + run: uv sync - - name: Build docs - run: cd docs && poetry run make + - name: Build docs + run: cd docs && uv run make html pre-commit: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install poetry - run: pipx install poetry + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "0.5.7" + python-version: "3.12" - - name: Install python dependencies - run: | - poetry env use 3.11 - poetry install --with pre-commit,docs,dev --extras "chgnet m3gnet" + - name: Install dependencies + run: uv sync - - name: Run pre-commit - run: | - poetry run pre-commit install - poetry run pre-commit run --all-files || ( git status --short ; git diff ; exit 1 ) + - name: Run pre-commit + run: | + uv run pre-commit install + uv run pre-commit run --all-files || ( git status --short ; git diff ; exit 1 ) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7039eda9..e81ae360 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,35 +22,28 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - container: sphinxdoc/sphinx steps: - - uses: actions/checkout@v4 - - - name: Install poetry - run: | - apt update - apt upgrade -y - apt install -y pipx - pipx install poetry - - - name: add deps - run: | - apt install -y python3-dev build-essential - - - name: sphinx - run: | - export PATH="$HOME/.local/bin:$PATH" - poetry install --with docs - cd docs - poetry run make html - - - name: upload - uses: actions/upload-pages-artifact@v3 - with: - # Upload entire repository - path: './docs/build/html/.' - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "0.5.7" + python-version: "3.12" + + - name: Install dependencies + run: uv sync + + - name: Build docs + run: cd docs && uv run make html + + - name: upload + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: './docs/build/html/.' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish-on-pypi.yml b/.github/workflows/publish-on-pypi.yml index d0f8e9cd..8b5b2ef5 100644 --- a/.github/workflows/publish-on-pypi.yml +++ b/.github/workflows/publish-on-pypi.yml @@ -10,50 +10,42 @@ jobs: publish: runs-on: ubuntu-latest if: github.repository == 'stfc/janus-core' && startsWith(github.ref, 'refs/tags/v') + environment: + name: release steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install poetry - run: pipx install poetry - - - name: Build project for distribution - run: | - poetry env use 3.11 - poetry build - - - name: Check prerelease - id: check-prerelease - run: | - [[ "$(poetry version --short)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || echo prerelease=true >> $GITHUB_OUTPUT - - - name: Get version from pyproject.toml - run: | - export PYTHONPATH=$(pwd) - echo "VERSION=$(poetry version --short)" >> $GITHUB_ENV - - - name: Check version matches tag - if: ${{ ! contains(github.ref, env.VERSION) }} - run: | - echo "Git tag does not match version in pyproject.toml" - exit 1 - - - name: Create Release - uses: ncipollo/release-action@v1 - with: - artifacts: "dist/*" - token: ${{ secrets.GITHUB_TOKEN }} - draft: false - prerelease: steps.check-prerelease.outputs.prerelease == 'true' - skipIfReleaseExists: true - - - name: Publish to PyPI - env: - POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }} - run: poetry publish + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "0.5.7" + python-version: "3.12" + + - name: Install dependencies + run: uv sync + + - name: Build + run: uv build + + - name: Get version from pyproject.toml + run: echo "VERSION=$(uvx --from=toml-cli toml get --toml-path=pyproject.toml project.version)" >> $GITHUB_ENV + + - name: Check version matches tag + if: ${{ ! contains(github.ref, env.VERSION) }} + run: | + echo "Git tag does not match version in pyproject.toml" + exit 1 + + - name: Create Release + uses: ncipollo/release-action@v1 + with: + artifacts: "dist/*" + token: ${{ secrets.GITHUB_TOKEN }} + draft: false + prerelease: steps.check-prerelease.outputs.prerelease == 'true' + skipIfReleaseExists: true + + - name: Publish to PyPI + run: uv publish diff --git a/README.md b/README.md index 8fe9ddcc..1cca1073 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ or to install all supported MLIPs: python3 -m pip install janus-core[all] ``` -Individual `extras` are listed in [Getting Started](https://stfc.github.io/janus-core/getting_started/getting_started.html#installation), as well as in [pyproject.toml](pyproject.toml) under `[tool.poetry.extras]`. +Individual `extras` are listed in [Getting Started](https://stfc.github.io/janus-core/getting_started/getting_started.html#installation), as well as in [pyproject.toml](pyproject.toml) under `[project.optional-dependencies]`. ### Further help @@ -282,19 +282,18 @@ This is also the case the calculations performed using the CLI, with the same in ## Development -We recommend installing poetry for dependency management when developing for `janus-core`: +We recommend installing uv for dependency management when developing for `janus-core`: -1. Install [poetry](https://python-poetry.org/docs/#installation) -2. (Optional) Create a virtual environment -3. Install `janus-core` with dependencies: +1. Install [uv](https://docs.astral.sh/uv/getting-started/installation) +2. Install `janus-core` with dependencies in a virtual environment: ```shell git clone https://github.com/stfc/janus-core cd janus-core -python3 -m pip install --upgrade pip -poetry install --with pre-commit,dev,docs # install with useful dev dependencies -pre-commit install # install pre-commit hooks -pytest -v # discover and run all tests +uv sync --all-extras # Create a virtual environment and install all dependencies +source .venv/bin/activate +pre-commit install # Install pre-commit hooks +pytest -v # Discover and run all tests ``` diff --git a/docs/source/developer_guide/get_started.rst b/docs/source/developer_guide/get_started.rst index 725d161e..e97607a1 100644 --- a/docs/source/developer_guide/get_started.rst +++ b/docs/source/developer_guide/get_started.rst @@ -2,27 +2,36 @@ Getting started =============== -We recommend `installing poetry `_ for dependency management when developing for ``janus-core``. +We recommend `installing uv `_ for dependency management when developing for ``janus-core``. This provides a number of useful features, including: -- Dependency management (``poetry [add,update,remove]`` etc.) and organization (groups) -- Storing the versions of all installations in a ``poetry.lock`` file, for reproducible builds -- Improved dependency resolution -- Virtual environment management (optional) -- Building and publishing tools +- `Dependency management `_ (``uv [add,remove]`` etc.) and organization (`groups `_) + +- Storing the versions of all installations in a `uv.lock `_ file, for reproducible builds + +- Improved `dependency resolution `_ + +- Virtual environment management + +- `Building and publishing `_ tools + + * Currently, an external build backend, such as `pdm `_, is required + Dependencies useful for development can then be installed by running:: - poetry install --with pre-commit,dev,docs + uv sync + source .venv/bin/activate + Extras, such as optional MLIPs, can also be installed by running:: - poetry install --with pre-commit,dev,docs --extras "alignn sevennet" + uv sync --extra alignn --extra sevennet or to install all supported MLIPs:: - poetry install --with pre-commit,dev,docs --extras all + uv sync --all-extras Running unit tests diff --git a/docs/source/developer_guide/tutorial.rst b/docs/source/developer_guide/tutorial.rst index 60001157..51968560 100644 --- a/docs/source/developer_guide/tutorial.rst +++ b/docs/source/developer_guide/tutorial.rst @@ -12,20 +12,34 @@ The following steps can then be taken, using `ALIGNN-FF `_. - -New MLIPs should be added as optional dependencies under ``[tool.poetry.dependencies]``, and added as an ``extra`` under ``[tool.poetry.extras]``:: - - [tool.poetry.dependencies] - alignn = { version = "2024.5.27", optional = true } - sevenn = { version = "0.10.0", optional = true } - torch_geometric = { version = "^2.5.3", optional = true } - - [tool.poetry.extras] - alignn = ["alignn"] - sevennet = ["sevenn", "torch_geometric"] - -Poetry will automatically resolve dependencies of the MLIP, if present, to ensure consistency with existing dependencies. +Dependencies for ``janus-core`` are specified through a ``pyproject.toml`` file, +with syntax consistent with `PEP 621 `_. + +New MLIPs should be added as optional dependencies under ``[project.optional-dependencies]``, +both with its own label, and to ``all`` if it is compatible with existing MLIPs:: + + [project.optional-dependencies] + alignn = [ + "alignn == 2024.5.27", + ] + chgnet = [ + "chgnet == 0.3.8", + ] + m3gnet = [ + "matgl == 1.1.3", + "dgl == 2.1.0", + sevennet = [ + "sevenn == 0.10.0", + "torch-geometric == 2.6.1", + ] + all = [ + "janus-core[alignn]", + "janus-core[chgnet]", + "janus-core[m3gnet]", + "janus-core[sevennet]", + ] + +uv will automatically resolve dependencies of the MLIP, if present, to ensure consistency with existing dependencies. .. note:: In the case of ``sevennet``, it was necessary to add ``torch_geometric`` as an additional dependency, but in most cases this should not be required @@ -34,14 +48,13 @@ Extra dependencies can then be installed by running: .. code-block:: bash - poetry lock - poetry install --extras "alignn sevennet" + uv sync --extra alignn --extra sevennet or, for all extras: .. code-block:: bash - poetry install --extras all + uv sync --extra all 2. Register MLIP architecture diff --git a/docs/source/getting_started/getting_started.rst b/docs/source/getting_started/getting_started.rst index 6b6b38e4..564e29e5 100644 --- a/docs/source/getting_started/getting_started.rst +++ b/docs/source/getting_started/getting_started.rst @@ -57,4 +57,4 @@ Currently supported extras are: - ``m3gnet``: `M3GNet `_ - ``sevenn``: `SevenNet `_ -``extras`` are also listed in `pyproject.toml `_ under ``[tool.poetry.extras]``. +``extras`` are also listed in `pyproject.toml `_ under ``[project.optional-dependencies]``. diff --git a/pyproject.toml b/pyproject.toml index bb3a729b..a481a7d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,18 +1,17 @@ -[tool.poetry] +[project] name = "janus-core" version = "0.6.6" description = "Tools for machine learnt interatomic potentials" authors = [ - "Elliott Kasoar", - "Federica Zanca", - "Harvey Devereux", - "Patrick Austin", - "David Mason", - "Jacob Wilkins", - "Alin M. Elena", + { name = "Elliott Kasoar" }, + { name = "Federica Zanca" }, + { name = "Harvey Devereux "}, + { name = "Patrick Austin" }, + { name = "David Mason" }, + { name = "Jacob Wilkins" }, + { name = "Alin M. Elena" }, ] -readme = "README.md" -packages = [{include = "janus_core"}] +requires-python = "<3.13,>=3.9" classifiers = [ "Programming Language :: Python", "Intended Audience :: Science/Research", @@ -20,71 +19,80 @@ classifiers = [ "Natural Language :: English", "Development Status :: 3 - Alpha", ] +readme = "README.md" + +dependencies = [ + "ase<4.0,>=3.23", + "codecarbon<3.0.0,>=2.5.0", + "mace-torch==0.3.8", + "numpy<2.0.0,>=1.26.4", + "phonopy<3.0.0,>=2.23.1", + "pyyaml<7.0.0,>=6.0.1", + "rich<14.0.0,>=13.9.1", + "seekpath<2.0.0,>=1.9.7", + "spglib<3.0.0,>=2.3.0", + "torch<=2.2,>=2.1", + "torch-dftd==0.4.0", + "typer<1.0.0,>=0.12.5", + "typer-config<2.0.0,>=1.4.0", +] + +[project.optional-dependencies] +alignn = [ + "alignn == 2024.5.27", +] +chgnet = [ + "chgnet == 0.3.8", +] +m3gnet = [ + "matgl == 1.1.3", + "dgl == 2.1.0", +] +sevennet = [ + "sevenn == 0.10.0", +] +all = [ + "janus-core[alignn]", + "janus-core[chgnet]", + "janus-core[m3gnet]", + "janus-core[sevennet]", +] + +[project.scripts] +janus = "janus_core.cli.janus:app" + +[project.urls] repository = "https://github.com/stfc/janus-core/" documentation = "https://stfc.github.io/janus-core/" -[tool.poetry.scripts] -janus = "janus_core.cli.janus:app" +[dependency-groups] +dev = [ + "coverage[toml]<8.0.0,>=7.4.1", + "pgtest<2.0.0,>=1.3.2", + "pytest<9.0,>=8.0", + "pytest-cov<5.0.0,>=4.1.0", + "tox-uv<2.0,>=1.16.1", + "wheel<1.0,>=0.42", +] -[tool.poetry.dependencies] -ase = "^3.23" -codecarbon = "^2.5.0" -mace-torch = "0.3.8" -numpy = "^1.26.4" -phonopy = "^2.23.1" -python = "^3.9" -pyyaml = "^6.0.1" -rich = "^13.9.1" -seekpath = "^1.9.7" -spglib = "^2.3.0" -torch = ">= 2.1, <= 2.2" # Range required for dgl -torch-dftd = "0.4.0" -typer = "^0.12.5" -typer-config = "^1.4.0" - -alignn = { version = "2024.5.27", optional = true } -chgnet = {version = "0.3.8", optional = true} -dgl = { version = "2.1.0", optional = true } # Pin due to matgl installation issues -matgl = { version = "1.1.3", optional = true} -sevenn = { version = "0.10.0", optional = true } -torchdata = {version = "0.7.1", optional = true} # Pin due to dgl issue -torch_geometric = { version = "^2.5.3", optional = true } - -[tool.poetry.extras] -all = ["alignn", "chgnet", "matgl", "dgl", "torchdata", "sevenn", "torch_geometric"] -alignn = ["alignn"] -chgnet = ["chgnet"] -m3gnet = ["matgl", "dgl", "torchdata"] -sevennet = ["sevenn", "torch_geometric"] - -[tool.poetry.group.dev.dependencies] -coverage = {extras = ["toml"], version = "^7.4.1"} -pgtest = "^1.3.2" -pytest = "^8.0" -pytest-cov = "^4.1.0" -tox = "^4.12.1" -wheel = "^0.42" - -[tool.poetry.group.pre-commit] -optional = true -[tool.poetry.group.pre-commit.dependencies] -pre-commit = "^3.6.0" -ruff = "^0.7.4" - -[tool.poetry.group.docs] -optional = true -[tool.poetry.group.docs.dependencies] -furo = "^2024.1.29" -markupsafe = "<2.1" -numpydoc = "^1.6.0" -sphinx = "^7.2.6" -sphinxcontrib-contentui = "^0.2.5" -sphinxcontrib-details-directive = "^0.1" -sphinx-copybutton = "^0.5.2" +docs = [ + "furo<2025.0.0,>=2024.1.29", + "markupsafe<2.1", + "numpydoc<2.0.0,>=1.6.0", + "sphinx<8.0.0,>=7.2.6", + "sphinxcontrib-contentui<1.0.0,>=0.2.5", + "sphinxcontrib-details-directive<1.0,>=0.1", + "sphinx-copybutton<1.0.0,>=0.5.2", +] + +pre-commit = [ + "pre-commit<4.0.0,>=3.6.0", + "ruff<1.0.0,>=0.7.4", +] [build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" +requires = ["pdm-backend"] +build-backend = "pdm.backend" [tool.pytest.ini_options] # Configuration for [pytest](https://docs.pytest.org) @@ -149,3 +157,10 @@ exclude = [ ".__weakref__$", ".__repr__$", ] + +[tool.uv] +default-groups = [ + "dev", + "docs", + "pre-commit", +] diff --git a/tox.ini b/tox.ini index 944d8dc0..4057dbf3 100644 --- a/tox.ini +++ b/tox.ini @@ -3,21 +3,24 @@ envlist = py311 [testenv] usedevelop=True +uv_sync_flags=--python={env_python} [testenv:py{39,310,311,312}] +runner = uv-venv-lock-runner +extras = all +with_dev = True description = Run the test suite against Python versions -allowlist_externals = poetry -commands_pre = poetry install --no-root --sync --extras all -commands = poetry run pytest {posargs} --run-extra-mlips --cov janus_core --import-mode importlib +commands = pytest {posargs} --run-extra-mlips --cov janus_core --import-mode importlib [testenv:pre-commit] +runner = uv-venv-lock-runner +extras = all +with_dev = True description = Run the pre-commit checks -allowlist_externals = poetry -commands_pre = poetry install --no-root --sync -commands = poetry run pre-commit run {posargs} --all-files +commands = pre-commit run {posargs} --all-files [testenv:docs] +runner = uv-venv-lock-runner +with_dev = True description = Build the documentation -allowlist_externals = poetry, echo -commands_pre = poetry install --no-root --sync -commands = poetry run sphinx-build -nW --keep-going -b html {posargs} docs/source docs/build/html +commands = sphinx-build -nW --keep-going -b html {posargs} docs/source docs/build/html