From 220bad0edaecc2ee1ff0c2f23ae997fc92ac640d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:03:03 +0200 Subject: [PATCH 1/8] update setup --- pyproject.toml | 29 ++++++++++++++++------------- setup.py | 11 ++++++++++- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7b0aec6..2b76c80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,15 @@ [build-system] requires = [ "setuptools>=64", + "setuptools<72.2; implementation_name == 'pypy'", # https://github.com/pypa/distutils/issues/283 "setuptools_scm>=7", - "numpy>=2.0.0rc1,<2.3; python_version >= '3.9'", - "oldest-supported-numpy; python_version < '3.9'", + "numpy>=2.0.0rc1", "Cython>=3.0.10,<3.1.0", ] build-backend = "setuptools.build_meta" [project] -requires-python = ">=3.8" +requires-python = ">=3.9" name = "pentapy" authors = [{name = "Sebastian Müller", email = "info@geostat-framework.org"}] readme = "README.md" @@ -26,11 +26,11 @@ classifiers = [ "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 3", - "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", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3 :: Only", "Topic :: Scientific/Engineering", "Topic :: Utilities", @@ -45,18 +45,21 @@ all = [ "scikit-umfpack", ] doc = [ - "m2r2>=0.2.8", + "myst_parser", "scipy>=1.1.0", "matplotlib>=3", "perfplot<0.9", "numpydoc>=1.1", "sphinx>=7", "sphinx-gallery>=0.8", - "sphinx-rtd-theme>=2", + "sphinx-rtd-theme>=3", +] +test = [ + "pytest-cov>=3", + "Cython>=3.0.10,<3.1.0", ] -test = ["pytest-cov>=3"] check = [ - "black>=24,<25", + "black>=24", "isort[colors]", "pylint", "cython-lint", @@ -85,11 +88,11 @@ multi_line_output = 3 [tool.black] target-version = [ - "py38", "py39", "py310", "py311", "py312", + "py313", ] [tool.cython-lint] @@ -139,10 +142,10 @@ max-line-length = 120 [tool.cibuildwheel] # Switch to using build build-frontend = "build" -# Disable building PyPy wheels on all platforms, 32bit builds, py3.6, py3.7 -skip = ["cp36-*", "cp37-*", "pp*", "*-win32", "*-manylinux_i686", "*-musllinux_*"] +# explicitly enable pypy +enable = ["pypy"] +# Disable building py3.6/7/8, pp3.8, 32bit linux +skip = ["cp36-*", "cp37-*", "cp38-*", "pp38-*", "*_i686"] # Run the package tests using `pytest` test-extras = "test" test-command = "pytest -v {package}/tests" -# Skip trying to test arm64 builds on Intel Macs -test-skip = "*-macosx_arm64 *-macosx_universal2:arm64" diff --git a/setup.py b/setup.py index 8081e05..32a0777 100644 --- a/setup.py +++ b/setup.py @@ -16,8 +16,17 @@ ) ] +compiler_directives = {} +if int(os.getenv("PENTAPY_CY_DOCS", "0")): + print(f"## pentapy setup: embed signatures for documentation") + compiler_directives["embedsignature"] = True +if int(os.getenv("PENTAPY_CY_COV", "0")): + print(f"## pentapy setup: enable line-trace for coverage") + compiler_directives["linetrace"] = True + +options = {"compiler_directives": compiler_directives} setup( - ext_modules=cythonize(CY_MODULES), + ext_modules=cythonize(CY_MODULES, **options), package_data={"pentapy": ["*.pxd"]}, # include pxd files include_package_data=False, # ignore other files zip_safe=False, From dae9202c58496aae6146c3d2d6a70faf04599c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:03:17 +0200 Subject: [PATCH 2/8] update docs --- .gitignore | 1 + .readthedocs.yml | 2 +- docs/source/changelog.rst | 3 ++- docs/source/conf.py | 21 ++++++++++++--------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index bdd5bb4..129def4 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,4 @@ src/pentapy/_version.py # generated docs docs/source/examples/ docs/source/api/ +docs/source/sg_execution_times.rst diff --git a/.readthedocs.yml b/.readthedocs.yml index 7dd1760..4291bf8 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -8,7 +8,7 @@ build: sphinx: configuration: docs/source/conf.py -formats: all +formats: [pdf] python: install: diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index ab37940..a01bcd9 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1 +1,2 @@ -.. mdinclude:: ../../CHANGELOG.md +.. include:: ../../CHANGELOG.md + :parser: myst_parser.docutils_ diff --git a/docs/source/conf.py b/docs/source/conf.py index f1c3f53..23571ff 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -60,7 +60,7 @@ def setup(app): "sphinx.ext.napoleon", # parameters look better than with numpydoc only "numpydoc", "sphinx_gallery.gen_gallery", - "m2r2", + "myst_parser", ] # autosummaries from source-files @@ -89,7 +89,11 @@ def setup(app): # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: -source_suffix = [".rst", ".md"] +source_suffix = { + ".rst": "restructuredtext", + ".md": "markdown", +} +# source_suffix = [".rst", ".md"] # source_suffix = ".rst" # The master toctree document. @@ -143,7 +147,7 @@ def setup(app): # 'canonical_url': '', # 'analytics_id': '', "logo_only": False, - "display_version": True, + "version_selector": True, "prev_next_buttons_location": "top", # 'style_external_links': False, # 'vcs_pageview_mode': '', @@ -192,11 +196,13 @@ def setup(app): # latex_show_urls = 'footnote' # http://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-latex-output latex_elements = { - "preamble": r""" + "preamble": ( + r""" \setcounter{secnumdepth}{1} \setcounter{tocdepth}{2} \pagestyle{fancy} -""", +""" + ), "pointsize": "10pt", "papersize": "a4paper", "fncychap": "\\usepackage[Glenn]{fncychap}", @@ -252,9 +258,6 @@ def setup(app): "Sphinx": ("http://www.sphinx-doc.org/en/stable/", None), } -# -- Sphinx Gallery Options -from sphinx_gallery.sorting import FileNameSortKey - sphinx_gallery_conf = { # only show "print" output as output "capture_repr": (), @@ -267,7 +270,7 @@ def setup(app): # Remove the "Download all examples" button from the top level gallery "download_all_examples": False, # Sort gallery example by file name instead of number of lines (default) - "within_subsection_order": FileNameSortKey, + "within_subsection_order": "FileNameSortKey", # directory where function granular galleries are stored "backreferences_dir": None, # Modules for which function level galleries are created. In From 3dbf001e544d1c4575ffd18b82c8ac227ff478a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:03:23 +0200 Subject: [PATCH 3/8] update CI --- .github/workflows/main.yml | 124 +++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 38 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53f3026..b2c5420 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,21 +19,27 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: "0" - - name: Set up Python 3.9 + - name: Set up Python 3.11 uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: 3.11 - name: Install dependencies run: | python -m pip install --upgrade pip - pip install --editable .[check] + pip install -v --editable '.[check]' - name: black check run: | python -m black --check --diff --color . + - name: black preview + run: | + python -m black --preview --diff --color . + - name: isort check run: | python -m isort --check --diff --color . @@ -47,84 +53,126 @@ jobs: cython-lint src/pentapy/ build_wheels: - name: wheels for ${{ matrix.cfg.os }} / ${{ matrix.cfg.arch }} - runs-on: ${{ matrix.cfg.os }} + name: wheels for ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - cfg: - - { os: ubuntu-latest, arch: x86_64 } - - { os: windows-latest, arch: AMD64 } - - { os: macos-latest, arch: x86_64 } - - { os: macos-latest, arch: arm64 } - - { os: macos-latest, arch: universal2 } + # macos-13 is an intel runner, macos-latest is apple silicon + os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-13, macos-latest] steps: - uses: actions/checkout@v4 with: - fetch-depth: '0' + fetch-depth: "0" - name: Build wheels - uses: pypa/cibuildwheel@v2.17.0 - env: - CIBW_ARCHS: ${{ matrix.cfg.arch }} + uses: pypa/cibuildwheel@v2.22.0 with: - output-dir: dist + output-dir: dist-wheel-${{ matrix.os }} - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: - path: ./dist/*.whl + name: dist-wheel-${{ matrix.os }} + path: ./dist-wheel-${{ matrix.os }}/*.whl build_sdist: - name: sdist on ${{ matrix.os }} with py ${{ matrix.python-version }} + name: sdist on ${{ matrix.os }} with py ${{ matrix.ver.py }} numpy${{ matrix.ver.np }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ubuntu-latest] - python-version: [3.9] - + os: [ubuntu-latest, windows-latest, macos-13, macos-14] + # https://github.com/scipy/oldest-supported-numpy/blob/main/setup.cfg + ver: + - { py: "3.9", np: "==1.20.0" } + - { py: "3.10", np: "==1.21.6" } + - { py: "3.11", np: "==1.23.2" } + - { py: "3.12", np: "==1.26.2" } + - { py: "3.13", np: "==2.1.0" } + - { py: "3.13", np: ">=2.1.0" } + exclude: + - os: macos-14 + ver: { py: "3.9", np: "==1.20.0" } + - os: macos-14 + ver: { py: "3.10", np: "==1.21.6" } steps: - uses: actions/checkout@v4 with: - fetch-depth: '0' + fetch-depth: "0" - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python ${{ matrix.ver.py }} uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: ${{ matrix.ver.py }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install build coveralls>=3.0.0 - pip install --editable .[test] + pip install build + + - name: Install pentapy + run: | + pip install -v --editable .[test] - name: Run tests - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - python -m pytest --cov pentapy --cov-report term-missing -v tests/ - python -m coveralls --service=github + pip install "numpy${{ matrix.ver.np }}" + python -m pytest -v tests/ - name: Build sdist run: | # PEP 517 package builder from pypa - python -m build --sdist --outdir dist . + python -m build --sdist --outdir dist-sdist . + + - uses: actions/upload-artifact@v4 + if: matrix.os == 'ubuntu-latest' && matrix.ver.py == '3.11' + with: + name: dist-sdist + path: dist-sdist/*.tar.gz + + coverage: + name: coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: '0' - - uses: actions/upload-artifact@v3 - # if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' + - name: Set up Python 3.11 + uses: actions/setup-python@v5 with: - path: dist/*.tar.gz + python-version: 3.11 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install "coveralls>=3.0.0" + + - name: Install pentapy + env: + PENTAPY_CY_COV: 1 + run: | + pip install -v --editable .[test] + + - name: Run tests + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pip install "numpy${{ matrix.ver.np }}" + python -m pytest --cov pentapy --cov-report term-missing -v tests/ + python -m coveralls --service=github upload_to_pypi: needs: [build_wheels, build_sdist] runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact + pattern: dist-* + merge-multiple: true path: dist - name: Publish to Test PyPI @@ -143,4 +191,4 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ - password: ${{ secrets.pypi_password }} + password: ${{ secrets.pypi_password }} \ No newline at end of file From 8871c86ca2bf1b2f829a8c902ce831ed181c8a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:05:14 +0200 Subject: [PATCH 4/8] fix cdivision #23 --- src/pentapy/solver.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pentapy/solver.pyx b/src/pentapy/solver.pyx index 469b074..1659d9d 100644 --- a/src/pentapy/solver.pyx +++ b/src/pentapy/solver.pyx @@ -1,4 +1,4 @@ -# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=True +# cython: language_level=3, boundscheck=False, wraparound=False, cdivision=False """ This is a solver linear equation systems with a penta-diagonal matrix, implemented in cython. From a2b30211b464a03fd2f50616797dfdeae3d0485f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:13:50 +0200 Subject: [PATCH 5/8] solver: catch special case for 3x3 matrices --- src/pentapy/core.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pentapy/core.py b/src/pentapy/core.py index 067189d..94bb087 100644 --- a/src/pentapy/core.py +++ b/src/pentapy/core.py @@ -6,7 +6,7 @@ import numpy as np from pentapy.solver import penta_solver1, penta_solver2 -from pentapy.tools import _check_penta, create_banded, shift_banded +from pentapy.tools import _check_penta, create_banded, create_full, shift_banded def solve(mat, rhs, is_flat=False, index_row_wise=True, solver=1): @@ -77,6 +77,11 @@ def solve(mat, rhs, is_flat=False, index_row_wise=True, solver=1): else: mat_flat = create_banded(mat, col_wise=False, dtype=np.double) rhs = np.asarray(rhs, dtype=np.double) + # Special case: Early exit when the matrix has only 3 rows/columns + # NOTE: this avoids memory leakage in the Cython-solver that will iterate over + # at least 4 rows/columns no matter what + if mat_flat.shape[1] == 3: + return np.linalg.solve(a=create_full(mat_flat, col_wise=False), b=rhs) try: return penta_solver1(mat_flat, rhs) except ZeroDivisionError: @@ -93,6 +98,11 @@ def solve(mat, rhs, is_flat=False, index_row_wise=True, solver=1): else: mat_flat = create_banded(mat, col_wise=False, dtype=np.double) rhs = np.asarray(rhs, dtype=np.double) + # Special case: Early exit when the matrix has only 3 rows/columns + # NOTE: this avoids memory leakage in the Cython-solver that will iterate over + # at least 4 rows/columns no matter what + if mat_flat.shape[1] == 3: + return np.linalg.solve(a=create_full(mat_flat, col_wise=False), b=rhs) try: return penta_solver2(mat_flat, rhs) except ZeroDivisionError: From 10dd116740c37710a1ec167c33534d5683841553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:16:49 +0200 Subject: [PATCH 6/8] please pylint --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2b76c80..3acb6bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,7 +135,7 @@ max-line-length = 120 max-args = 20 max-locals = 50 max-branches = 30 - max-statements = 80 + max-statements = 85 max-attributes = 25 max-public-methods = 75 From 2ed45ef478fbb8e5a01a5199192c5c83d31b18e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:18:52 +0200 Subject: [PATCH 7/8] add cython coverage support --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 3acb6bd..c9bef75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,6 +100,7 @@ max-line-length = 120 [tool.coverage] [tool.coverage.run] + plugins = ["Cython.Coverage"] source = ["pentapy"] omit = [ "*docs*", From 558a7f1e4e3d992af7678cbd84cf291ed6c308db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20M=C3=BCller?= Date: Thu, 1 May 2025 23:44:18 +0200 Subject: [PATCH 8/8] update changelog --- CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1417c4c..4ebef20 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ All notable changes to **pentapy** will be documented in this file. +## [1.4.0] - 2025-05 + +See [#31](https://github.com/GeoStat-Framework/pentapy/pull/31) + +### Enhancements +- added support for python 3.13 +- adding [musllinux](https://musl.libc.org/) wheels +- adding PyPy wheels (pp39 and pp310) + - PyPy needs `setuptools<72.2`: https://github.com/pypa/distutils/issues/283 +- adding 32bit Windows wheels again (still Tier 1 support in Python) +- adding aarch64 Linux wheels + +### Changes +- dropped python 3.8 support + +### Bugfixes +- use numpy solver for 3x3 matrices +- set `cdivision=False` in cython solver + + ## [1.3.0] - 2024-04 See [#21](https://github.com/GeoStat-Framework/pentapy/pull/21) @@ -100,6 +120,7 @@ This is the first release of pentapy, a python toolbox for solving pentadiagonal The solver is implemented in cython, which makes it really fast. +[1.4.0]: https://github.com/GeoStat-Framework/pentapy/compare/v1.3.0...v1.4.0 [1.3.0]: https://github.com/GeoStat-Framework/pentapy/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/GeoStat-Framework/pentapy/compare/v1.1.2...v1.2.0 [1.1.2]: https://github.com/GeoStat-Framework/pentapy/compare/v1.1.1...v1.1.2