From d354abf058e8450a007bed2c85ef7add6b97cbc2 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 12:50:11 +0100 Subject: [PATCH 1/6] Switch to modern GitHub actions --- .github/actions/test/Dockerfile | 4 ---- .github/main.workflow | 21 --------------------- .github/workflows/publish.yml | 25 +++++++++++++++++++++++++ .github/workflows/test.yml | 24 ++++++++++++++++++++++++ README.md | 2 +- modello.py | 2 +- setup.py | 8 +++++++- 7 files changed, 58 insertions(+), 28 deletions(-) delete mode 100644 .github/actions/test/Dockerfile delete mode 100644 .github/main.workflow create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/actions/test/Dockerfile b/.github/actions/test/Dockerfile deleted file mode 100644 index 9870878..0000000 --- a/.github/actions/test/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM python:3.7-slim -RUN apt-get update \ - && apt-get install --yes --no-install-recommends git \ - && rm -fr /var/lib/apt/lists/* diff --git a/.github/main.workflow b/.github/main.workflow deleted file mode 100644 index 785d579..0000000 --- a/.github/main.workflow +++ /dev/null @@ -1,21 +0,0 @@ -workflow "Test and Publish" { - on = "push" - resolves = ["Release"] -} - -action "Test" { - uses = "./.github/actions/test/" - args = "python setup.py test" -} - -action "Filter release" { - needs = ["Test"] - uses = "actions/bin/filter@95c1a3b" - args = "tag v*" -} - -action "Release" { - uses = "docker://code0x58/action-python-publish:master" - needs = ["Filter release"] - secrets = ["TWINE_PASSWORD", "TWINE_USERNAME"] -} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e6816c9 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,25 @@ +name: Publish + +on: + push: + tags: + - 'v*' + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install build + run: | + python -m pip install --upgrade pip + pip install build + - name: Build distributions + run: python -m build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..e10c98e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,24 @@ +name: Test + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install .[test] + - name: Test with pytest + run: | + pytest -vv --cov=modello diff --git a/README.md b/README.md index 1171e0a..4df145d 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ pipenv install git+https://github.com/Code0x58/modello.git#egg=modello pip install --user git+https://github.com/Code0x58/modello.git#egg=modello ``` -Currently this requires Python 3.6+ but the version requirements can drop a couple of minor versions easily if there is interest. Python 2.7 isn't planned to be supported as the Modello class relies on [PEP-3115](https://www.python.org/dev/peps/pep-3115/). +Currently this requires Python 3.8+ but the version requirements can drop a couple of minor versions easily if there is interest. Python 2.7 isn't planned to be supported as the Modello class relies on [PEP-3115](https://www.python.org/dev/peps/pep-3115/). ## Development diff --git a/modello.py b/modello.py index 86a6b7c..524fe1a 100644 --- a/modello.py +++ b/modello.py @@ -96,7 +96,7 @@ class ModelloMeta(type): @classmethod def __prepare__( metacls, __name: str, __bases: typing.Tuple[type, ...], **kwds: typing.Any - ) -> typing.Mapping[str, typing.Any]: + ) -> typing.MutableMapping[str, typing.Any]: """Return a ModelloMetaNamespace instead of a plain dict to accumlate attributes on.""" return ModelloMetaNamespace(__name, __bases) diff --git a/setup.py b/setup.py index 341ea54..1d73d79 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ tests_require=TEST_REQUIRES, extras_require={"test": TEST_REQUIRES}, py_modules=["modello"], - python_requires=">=3.3", + python_requires=">=3.8", license="MIT", classifiers=dedent( """ @@ -43,6 +43,12 @@ License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 """ ) .strip() From 81be58a5d6ae7f15bb55f7e8c2bc8071346c7fe9 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 17:27:54 +0100 Subject: [PATCH 2/6] Move all config to pyproject --- .github/workflows/test.yml | 2 +- README.md | 6 +-- pyproject.toml | 79 +++++++++++++++++++++++++++++++++++++- setup.cfg | 44 --------------------- 4 files changed, 82 insertions(+), 49 deletions(-) delete mode 100644 setup.cfg diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e10c98e..0681f7c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,4 +21,4 @@ jobs: pip install .[test] - name: Test with pytest run: | - pytest -vv --cov=modello + pytest -vv diff --git a/README.md b/README.md index 4df145d..043f656 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,11 @@ Currently this requires Python 3.8+ but the version requirements can drop a coup ## Development -Run the tests and linting with `python setup.py test`. Pushes have the test suite run against them, and will also publish a release if tagged thanks to GitHub Actions. You can reproduce the Actions locally using [act](https://github.com/nektos/act), e.g. `TWINE_USERNAME= TWINE_PASSWORD= act`. +Run the tests and linting with `pytest`. Pushes have the test suite run against them, and will also publish a release if tagged thanks to GitHub Actions. You can reproduce the Actions locally using [act](https://github.com/nektos/act), e.g. `TWINE_USERNAME= TWINE_PASSWORD= act`. -You can run all the tests with `python setup.py test`. If you want to run a subset of tests or otherwise pass arguments to pytest, use `./pytest …` e.g.: +If you want to run a subset of tests or otherwise pass arguments to pytest, just invoke `pytest` directly, e.g.: ```sh -./pytest examples/jobs.py::jobs.Job +pytest examples/jobs.py::jobs.Job ``` ## TODO: diff --git a/pyproject.toml b/pyproject.toml index 4ba7d43..92a422b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,80 @@ +[build-system] +requires = ["setuptools>=61", "setuptools_scm[toml]>=7"] +build-backend = "setuptools.build_meta" + +[project] +name = "modello" +description = "sympy expressions in models" +readme = "README.md" +requires-python = ">=3.8" +license = {text = "MIT"} +authors = [{name = "Oliver Bristow", email = "github+pypi@oliverbristow.co.uk"}] +dependencies = ["sympy"] +keywords = ["symbolic modeling"] +urls = {homepage = "https://github.com/Code0x58/modello/"} +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dynamic = ["version"] + +[project.optional-dependencies] +test = [ + "flake8-black", + "flake8-docstrings", + "flake8-isort", + "pytest-cov>=2.6.1", + "pytest-ruff", + "pytest-mypy", + "pytest-pudb", + "pytest>=4.1", +] + +[tool.setuptools] +py-modules = ["modello"] + +[tool.setuptools_scm] + +[tool.pytest.ini_options] +addopts = "--doctest-modules --doctest-report=udiff --cov=modello --cov-report=html --cov-report=term --mypy --ruff" +python_files = ["test_modello.py", "examples/*.py"] +cache_dir = "artefacts/reports/.pytest_cache" + +[tool.coverage.run] +data_file = "artefacts/reports/.coverage" +source = ["modello.py"] +branch = true + +[tool.coverage.html] +directory = "artefacts/reports/coverage-html" + +[tool.mypy] +ignore_missing_imports = true +cache_dir = "artefacts/reports/.mypy_cache" + +[tool.mypy-modello] +disallow_untyped_defs = true +disallow_incomplete_defs = true +disallow_untyped_decorators = true + +[tool.isort] +line_length = 120 +force_grid_wrap = 0 +use_parentheses = true +include_trailing_comma = true +combine_as_imports = true +multi_line_output = 5 + [tool.ruff] line-length = 120 -target-version = "py311" \ No newline at end of file +target-version = "py311" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1b09eca..0000000 --- a/setup.cfg +++ /dev/null @@ -1,44 +0,0 @@ -[aliases] -test = pytest - -[tool:pytest] -addopts = - --doctest-modules --doctest-report=udiff - --cov=modello --cov-report=html --cov-report=term - --mypy - --ruff -python_files = - test_modello.py - examples/*.py -cache_dir = artefacts/reports/.pytest_cache - -[coverage:run] -data_file = artefacts/reports/.coverage -source = modello.py -branch = True - -[coverage:html] -directory = artefacts/reports/coverage-html - -[mypy] -ignore_missing_imports = True -cache_dir = artefacts/reports/.mypy_cache - -[mypy-modello] -disallow_untyped_defs = True -disallow_incomplete_defs = True -disallow_untyped_decorators = True - -[isort] -# Import Style -line_length = 120 -force_grid_wrap = false -use_parentheses = true -include_trailing_comma = true -combine_as_imports = true - -# Multiline Import Style: hanging grid grouped -multi_line_output = 5 - -[bdist_wheel] -python-tag=3 From c32f1e0f7bd4b818ec498f94e42f4db104ba6ca3 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 17:36:19 +0100 Subject: [PATCH 3/6] update GitHub actions --- .github/workflows/publish.yml | 29 ++++++++++++++++------------- .github/workflows/test.yml | 25 ++++++++++++++++--------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e6816c9..2b578a4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,25 +1,28 @@ name: Publish on: - push: - tags: - - 'v*' + release: + types: [published] jobs: - publish: + build-and-publish: runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/modello + permissions: + id-token: write steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 with: python-version: '3.x' - - name: Install build + - name: Build package run: | - python -m pip install --upgrade pip - pip install build - - name: Build distributions - run: python -m build + python -m pip install --upgrade pip build + python -m build + # the publishing uses PyPI's trusted publishing, so configured on pypi instead of using secrets - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.PYPI_API_TOKEN }} + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0681f7c..6f65d1a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,24 +1,31 @@ -name: Test +name: CI on: push: + branches: [master] pull_request: jobs: - build: - runs-on: ubuntu-latest + test: + runs-on: ubuntu-22.04 strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.7", "3.13", "3.14-dev"] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install .[test] - - name: Test with pytest + python -m pip install . pytest pytest-cov + - name: Run tests run: | - pytest -vv + pytest + - name: Upload coverage + uses: actions/upload-artifact@v4 + with: + name: coverage-${{ matrix.python-version }} + path: .coverage \ No newline at end of file From 1e9531a33d0a67d540f4685b75e88d6eddc402e2 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 17:36:33 +0100 Subject: [PATCH 4/6] Remove unmaintained pytest-pudb --- modello.py | 1 + pyproject.toml | 1 - setup.py | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modello.py b/modello.py index 524fe1a..8e77728 100644 --- a/modello.py +++ b/modello.py @@ -33,6 +33,7 @@ class ModelloMetaNamespace(dict): def __init__(self, name: str, bases: typing.Tuple[type, ...]) -> None: """Create a namespace for a Modello class to use.""" + super().__init__() self.name = name # map of attributes to sympy Basic (e.g expression, value) objects self.attrs: typing.Dict[str, Basic] = {} diff --git a/pyproject.toml b/pyproject.toml index 92a422b..70d7ef7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,6 @@ test = [ "pytest-cov>=2.6.1", "pytest-ruff", "pytest-mypy", - "pytest-pudb", "pytest>=4.1", ] diff --git a/setup.py b/setup.py index 1d73d79..568f61d 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ "pytest-cov>=2.6.1", "pytest-ruff", "pytest-mypy", - "pytest-pudb", "pytest>=4.1", ] setup( From 66d7c20fa8c8cd5fae49f352cf9af860c4bbc44f Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 17:40:18 +0100 Subject: [PATCH 5/6] Cover python 3.7 --- pyproject.toml | 3 ++- setup.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 70d7ef7..333fa11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" name = "modello" description = "sympy expressions in models" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.7" license = {text = "MIT"} authors = [{name = "Oliver Bristow", email = "github+pypi@oliverbristow.co.uk"}] dependencies = ["sympy"] @@ -20,6 +20,7 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", diff --git a/setup.py b/setup.py index 568f61d..0cdfa65 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ tests_require=TEST_REQUIRES, extras_require={"test": TEST_REQUIRES}, py_modules=["modello"], - python_requires=">=3.8", + python_requires=">=3.7", license="MIT", classifiers=dedent( """ @@ -43,6 +43,7 @@ Operating System :: OS Independent Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 From 2d2de215daa2e8f2a53b4b2faae863629b7f2416 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 18 Jun 2025 17:50:53 +0100 Subject: [PATCH 6/6] Fix test package installation --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f65d1a..3acf1ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install . pytest pytest-cov + python -m pip install --editable .[test] - name: Run tests run: | pytest