From 0bde33db4cc391bd4dafaca588f1e5513aae3f7f Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 28 Oct 2025 20:23:39 +0100 Subject: [PATCH 01/10] Make ruff happy. --- src/matplot2tikz/_patch.py | 4 +++- tests/test_barchart_logy.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/matplot2tikz/_patch.py b/src/matplot2tikz/_patch.py index 4532b518..725c2738 100644 --- a/src/matplot2tikz/_patch.py +++ b/src/matplot2tikz/_patch.py @@ -114,7 +114,9 @@ def ensure_list(x: Iterable | float) -> Iterable: hatches = ensure_list(obj.get_hatch()) if obj.get_hatch() is not None else [None] paths = obj.get_paths() - for path, ec, fc, ls, lw, t, off, hatch in zip_modulo(paths, ecs, fcs, lss, lws, ts, offs, hatches): + for path, ec, fc, ls, lw, t, off, hatch in zip_modulo( + paths, ecs, fcs, lss, lws, ts, offs, hatches + ): draw_options = mypath.get_draw_options( data, mypath.LineData(obj=obj, ec=ec, fc=fc, ls=ls, lw=lw, hatch=hatch) ) diff --git a/tests/test_barchart_logy.py b/tests/test_barchart_logy.py index 5e4acf00..6684702b 100644 --- a/tests/test_barchart_logy.py +++ b/tests/test_barchart_logy.py @@ -12,7 +12,7 @@ def plot() -> None: - fig, axes = plt.subplots() + _, axes = plt.subplots() axes.set_yscale("log") axes.set_ylim(0.002, 200) axes.bar([1, 2, 3, 4, 5], [0.01, 0.1, 1, 10, 100]) From c6c9cd981b36f7b36e70665bb558a6e29eb88223 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 28 Oct 2025 20:24:41 +0100 Subject: [PATCH 02/10] Add pandas to dependencies for test environment. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 25e26a7d..22083aeb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ test = [ "pytest-cov>=6.0.0", "coverage[toml]>=7.0.0", "typeguard>=4.4.0", + "pandas", ] dev = [ "tox", From d0f3cdfe4f1b585167454d24609f517bd59afa19 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 28 Oct 2025 20:25:38 +0100 Subject: [PATCH 03/10] Make use of uv (update README.md later). --- requirements-310.txt | 75 ++++++++++++++++++++++++++++++++++++++ requirements-311.txt | 70 ++++++++++++++++++++++++++++++++++++ requirements-312.txt | 68 +++++++++++++++++++++++++++++++++++ requirements-313.txt | 68 +++++++++++++++++++++++++++++++++++ requirements-39.txt | 83 +++++++++++++++++++++++++++++++++++++++++++ requirements-lint.txt | 49 +++++++++++++++++++++++++ tox.ini | 26 +++++++++++--- 7 files changed, 434 insertions(+), 5 deletions(-) create mode 100644 requirements-310.txt create mode 100644 requirements-311.txt create mode 100644 requirements-312.txt create mode 100644 requirements-313.txt create mode 100644 requirements-39.txt create mode 100644 requirements-lint.txt diff --git a/requirements-310.txt b/requirements-310.txt new file mode 100644 index 00000000..dd0468aa --- /dev/null +++ b/requirements-310.txt @@ -0,0 +1,75 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.10 -o requirements-310.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.2 + # via matplotlib +coverage==7.11.0 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +exceptiongroup==1.3.0 + # via pytest +fonttools==4.60.1 + # via matplotlib +iniconfig==2.3.0 + # via pytest +kiwisolver==1.4.9 + # via matplotlib +matplotlib==3.10.7 + # via matplot2tikz (pyproject.toml) +numpy==2.2.6 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==12.0.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +tomli==2.3.0 + # via + # coverage + # pytest +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # exceptiongroup + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) diff --git a/requirements-311.txt b/requirements-311.txt new file mode 100644 index 00000000..eb35d360 --- /dev/null +++ b/requirements-311.txt @@ -0,0 +1,70 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.11 -o requirements-311.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.3 + # via matplotlib +coverage==7.11.0 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +fonttools==4.60.1 + # via matplotlib +iniconfig==2.3.0 + # via pytest +kiwisolver==1.4.9 + # via matplotlib +matplotlib==3.10.7 + # via matplot2tikz (pyproject.toml) +numpy==2.3.4 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==12.0.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +tomli==2.3.0 + # via coverage +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) diff --git a/requirements-312.txt b/requirements-312.txt new file mode 100644 index 00000000..b9e56f36 --- /dev/null +++ b/requirements-312.txt @@ -0,0 +1,68 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.12 -o requirements-312.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.3 + # via matplotlib +coverage==7.11.0 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +fonttools==4.60.1 + # via matplotlib +iniconfig==2.3.0 + # via pytest +kiwisolver==1.4.9 + # via matplotlib +matplotlib==3.10.7 + # via matplot2tikz (pyproject.toml) +numpy==2.3.4 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==12.0.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) diff --git a/requirements-313.txt b/requirements-313.txt new file mode 100644 index 00000000..6f103024 --- /dev/null +++ b/requirements-313.txt @@ -0,0 +1,68 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.13 -o requirements-313.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.3 + # via matplotlib +coverage==7.11.0 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +fonttools==4.60.1 + # via matplotlib +iniconfig==2.3.0 + # via pytest +kiwisolver==1.4.9 + # via matplotlib +matplotlib==3.10.7 + # via matplot2tikz (pyproject.toml) +numpy==2.3.4 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==12.0.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) diff --git a/requirements-39.txt b/requirements-39.txt new file mode 100644 index 00000000..731b56f9 --- /dev/null +++ b/requirements-39.txt @@ -0,0 +1,83 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.9 -o requirements-39.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.0 + # via matplotlib +coverage==7.10.7 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +exceptiongroup==1.3.0 + # via pytest +fonttools==4.60.1 + # via matplotlib +importlib-metadata==8.7.0 + # via typeguard +importlib-resources==6.5.2 + # via matplotlib +iniconfig==2.1.0 + # via pytest +kiwisolver==1.4.7 + # via matplotlib +matplotlib==3.9.4 + # via matplot2tikz (pyproject.toml) +numpy==2.0.2 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==11.3.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +tomli==2.3.0 + # via + # coverage + # pytest +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # exceptiongroup + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) +zipp==3.23.0 + # via + # importlib-metadata + # importlib-resources diff --git a/requirements-lint.txt b/requirements-lint.txt new file mode 100644 index 00000000..1d374e18 --- /dev/null +++ b/requirements-lint.txt @@ -0,0 +1,49 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra lint -o requirements-lint.txt +contourpy==1.3.0 + # via matplotlib +cycler==0.12.1 + # via matplotlib +fonttools==4.60.1 + # via matplotlib +importlib-resources==6.5.2 + # via matplotlib +kiwisolver==1.4.7 + # via matplotlib +matplotlib==3.9.4 + # via matplot2tikz (pyproject.toml) +mypy==1.18.2 + # via matplot2tikz (pyproject.toml) +mypy-extensions==1.1.0 + # via mypy +numpy==2.0.2 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib +packaging==25.0 + # via matplotlib +pathspec==0.12.1 + # via mypy +pillow==11.3.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pyparsing==3.2.5 + # via matplotlib +python-dateutil==2.9.0.post0 + # via matplotlib +ruff==0.14.2 + # via matplot2tikz (pyproject.toml) +six==1.17.0 + # via python-dateutil +tomli==2.3.0 + # via mypy +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # mypy +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) +zipp==3.23.0 + # via importlib-resources diff --git a/tox.ini b/tox.ini index 313b9235..e44729c4 100644 --- a/tox.ini +++ b/tox.ini @@ -8,10 +8,10 @@ isolated_build = True [testenv] description = Run unit tests. -deps = - pandas +install_command = uv pip install {opts} {packages} package = wheel -extras = test +allowlist_externals = + uv setenv = PY_IGNORE_IMPORTMISMATCH=1 # https://github.com/pytest-dev/pytest/issues/2042 COVERAGE_FILE = reports{/}.coverage.{envname} @@ -21,16 +21,31 @@ commands = [testenv:py39] +deps = + -r requirements-39.txt + [testenv:py310] +deps = + -r requirements-310.txt + [testenv:py311] +deps = + -r requirements-311.txt + [testenv:py312] -[testenv:py313] +deps = + -r requirements-312.txt +[testenv:py313] +deps = + -r requirements-313.txt [testenv:lint] description = Run static checkers. basepython = python3.9 -extras = lint +install_command = uv pip install {opts} {packages} +deps = + -r requirements-lint.txt commands = ruff format . --check ruff check . @@ -43,6 +58,7 @@ skip_install = true setenv = COVERAGE_FILE = reports/.coverage depends = py +install_command = uv pip install {opts} {packages} deps = junitparser coverage[toml] From 58ecb5012d67f3efb00eee1fcd0d8bd71592c910 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Wed, 29 Oct 2025 07:40:18 +0100 Subject: [PATCH 04/10] Remove Python 3.9 support. Do linting using Python 3.10. --- pyproject.toml | 3 +- requirements-39.txt | 83 ------------------------------------------- requirements-lint.txt | 6 +--- tests/helpers.py | 5 +++ tox.ini | 9 ++--- 5 files changed, 9 insertions(+), 97 deletions(-) delete mode 100644 requirements-39.txt diff --git a/pyproject.toml b/pyproject.toml index 22083aeb..2657ceed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" license = "MIT" keywords = ["latex", "tikz", "matplotlib", "graphics"] dynamic = ["version"] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ "matplotlib >= 1.4.0", "numpy", @@ -23,7 +23,6 @@ authors = [ ] classifiers=[ "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/requirements-39.txt b/requirements-39.txt deleted file mode 100644 index 731b56f9..00000000 --- a/requirements-39.txt +++ /dev/null @@ -1,83 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile pyproject.toml --extra test --resolution highest --python 3.9 -o requirements-39.txt -colorama==0.4.6 - # via pytest -contourpy==1.3.0 - # via matplotlib -coverage==7.10.7 - # via - # matplot2tikz (pyproject.toml) - # pytest-cov -cycler==0.12.1 - # via matplotlib -exceptiongroup==1.3.0 - # via pytest -fonttools==4.60.1 - # via matplotlib -importlib-metadata==8.7.0 - # via typeguard -importlib-resources==6.5.2 - # via matplotlib -iniconfig==2.1.0 - # via pytest -kiwisolver==1.4.7 - # via matplotlib -matplotlib==3.9.4 - # via matplot2tikz (pyproject.toml) -numpy==2.0.2 - # via - # matplot2tikz (pyproject.toml) - # contourpy - # matplotlib - # pandas -packaging==25.0 - # via - # matplotlib - # pytest -pandas==2.3.3 - # via matplot2tikz (pyproject.toml) -pillow==11.3.0 - # via - # matplot2tikz (pyproject.toml) - # matplotlib -pluggy==1.6.0 - # via - # pytest - # pytest-cov -pygments==2.19.2 - # via pytest -pyparsing==3.2.5 - # via matplotlib -pytest==8.4.2 - # via - # matplot2tikz (pyproject.toml) - # pytest-cov -pytest-cov==7.0.0 - # via matplot2tikz (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # matplotlib - # pandas -pytz==2025.2 - # via pandas -six==1.17.0 - # via python-dateutil -tomli==2.3.0 - # via - # coverage - # pytest -typeguard==4.4.4 - # via matplot2tikz (pyproject.toml) -typing-extensions==4.15.0 - # via - # matplot2tikz (pyproject.toml) - # exceptiongroup - # typeguard -tzdata==2025.2 - # via pandas -webcolors==24.11.1 - # via matplot2tikz (pyproject.toml) -zipp==3.23.0 - # via - # importlib-metadata - # importlib-resources diff --git a/requirements-lint.txt b/requirements-lint.txt index 1d374e18..30529a4d 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -1,13 +1,11 @@ # This file was autogenerated by uv via the following command: -# uv pip compile pyproject.toml --extra lint -o requirements-lint.txt +# uv pip compile pyproject.toml --extra lint --python 3.10 -o requirements-lint.txt contourpy==1.3.0 # via matplotlib cycler==0.12.1 # via matplotlib fonttools==4.60.1 # via matplotlib -importlib-resources==6.5.2 - # via matplotlib kiwisolver==1.4.7 # via matplotlib matplotlib==3.9.4 @@ -45,5 +43,3 @@ typing-extensions==4.15.0 # mypy webcolors==24.11.1 # via matplot2tikz (pyproject.toml) -zipp==3.23.0 - # via importlib-resources diff --git a/tests/helpers.py b/tests/helpers.py index 21125803..ea94d686 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -48,4 +48,9 @@ def assert_equality( # type: ignore[no-untyped-def] this_dir = Path(__file__).resolve().parent with (this_dir / filename).open(encoding="utf-8") as f: reference = f.read() + try: + assert reference == code, filename + "\n" + _unidiff_output(reference, code) + except AssertionError: + with (this_dir / f"{filename[:-4]}_output.tex").open("w") as f: + f.write(code) assert reference == code, filename + "\n" + _unidiff_output(reference, code) diff --git a/tox.ini b/tox.ini index e44729c4..29191540 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = lint - py{39,310,311,312,313} + py{310,311,312,313} combine-test-reports isolated_build = True @@ -19,11 +19,6 @@ commands = # Run tests from .py files pytest --typeguard-packages=matplot2tikz --junitxml=reports/pytest.xml.{envname} {posargs} - -[testenv:py39] -deps = - -r requirements-39.txt - [testenv:py310] deps = -r requirements-310.txt @@ -42,7 +37,7 @@ deps = [testenv:lint] description = Run static checkers. -basepython = python3.9 +basepython = python3.10 install_command = uv pip install {opts} {packages} deps = -r requirements-lint.txt From e37dfa9f90bdbc3c158e809157ee075324b63525 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 4 Nov 2025 15:34:50 +0100 Subject: [PATCH 05/10] Update tox and pyproject.toml to include Python 3.14 support. --- pyproject.toml | 3 +- requirements-314.txt | 68 +++++++ tests/test_contourf_reference.tex | 300 +++++++++++++---------------- tests/test_contourf_reference2.tex | 153 --------------- tox.ini | 18 +- 5 files changed, 211 insertions(+), 331 deletions(-) create mode 100644 requirements-314.txt delete mode 100644 tests/test_contourf_reference2.tex diff --git a/pyproject.toml b/pyproject.toml index 2657ceed..9ab736f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ classifiers=[ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", ] # Enables the usage of setuptools_scm @@ -61,7 +62,7 @@ src = ["src"] extend-exclude = [ "conf.py", ] -target-version = "py39" +target-version = "py310" lint.select = ["ALL"] lint.ignore = [ "COM812", # Conflicts with the formatter diff --git a/requirements-314.txt b/requirements-314.txt new file mode 100644 index 00000000..8bc4d7df --- /dev/null +++ b/requirements-314.txt @@ -0,0 +1,68 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --extra test --resolution highest --python 3.14 -o requirements-314.txt +colorama==0.4.6 + # via pytest +contourpy==1.3.3 + # via matplotlib +coverage==7.11.0 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +cycler==0.12.1 + # via matplotlib +fonttools==4.60.1 + # via matplotlib +iniconfig==2.3.0 + # via pytest +kiwisolver==1.4.9 + # via matplotlib +matplotlib==3.10.7 + # via matplot2tikz (pyproject.toml) +numpy==2.3.4 + # via + # matplot2tikz (pyproject.toml) + # contourpy + # matplotlib + # pandas +packaging==25.0 + # via + # matplotlib + # pytest +pandas==2.3.3 + # via matplot2tikz (pyproject.toml) +pillow==12.0.0 + # via + # matplot2tikz (pyproject.toml) + # matplotlib +pluggy==1.6.0 + # via + # pytest + # pytest-cov +pygments==2.19.2 + # via pytest +pyparsing==3.2.5 + # via matplotlib +pytest==8.4.2 + # via + # matplot2tikz (pyproject.toml) + # pytest-cov +pytest-cov==7.0.0 + # via matplot2tikz (pyproject.toml) +python-dateutil==2.9.0.post0 + # via + # matplotlib + # pandas +pytz==2025.2 + # via pandas +six==1.17.0 + # via python-dateutil +typeguard==4.4.4 + # via matplot2tikz (pyproject.toml) +typing-extensions==4.15.0 + # via + # matplot2tikz (pyproject.toml) + # typeguard +tzdata==2025.2 + # via pandas +webcolors==24.11.1 + # via matplot2tikz (pyproject.toml) diff --git a/tests/test_contourf_reference.tex b/tests/test_contourf_reference.tex index 49a8cb80..cb07b440 100644 --- a/tests/test_contourf_reference.tex +++ b/tests/test_contourf_reference.tex @@ -17,177 +17,137 @@ ymin=0, ymax=2, ytick style={color=black} ] -\addplot [draw=none, fill=darkslateblue7235116] -table{% -x y -0.26666667 0 -0 0 -0 0.26666667 -0.26666667 0 -}; -\addplot [draw=none, fill=darkslateblue7235116] -table{% -x y -0 2 -0.26666667 2 -0 1.7333333 -0 2 -}; -\addplot [draw=none, fill=darkslateblue7235116] -table{% -x y -2 0.26666667 -2 0 -1.7333333 0 -2 0.26666667 -}; -\addplot [draw=none, fill=darkslateblue7235116] -table{% -x y -1.7333333 2 -2 2 -2 1.7333333 -1.7333333 2 -}; -\addplot [draw=none, fill=darkslateblue5294141] -table{% -x y -0 0.5 -0 0.6 -0.033333333 0.5 -0.5 0.033333333 -0.6 0 -0.5 0 -0.26666667 0 -0 0.26666667 -0 0.5 -}; -\addplot [draw=none, fill=darkslateblue5294141] -table{% -x y -0 1.5 -0 1.7333333 -0.26666667 2 -0.5 2 -0.6 2 -0.5 1.9666667 -0.033333333 1.5 -0 1.4 -0 1.5 -}; -\addplot [draw=none, fill=darkslateblue5294141] -table{% -x y -1.5 0.033333333 -1.9666667 0.5 -2 0.6 -2 0.5 -2 0.26666667 -1.7333333 0 -1.5 0 -1.4 0 -1.5 0.033333333 -}; -\addplot [draw=none, fill=darkslateblue5294141] -table{% -x y -1.4 2 -1.5 2 -1.7333333 2 -2 1.7333333 -2 1.5 -2 1.4 -1.9666667 1.5 -1.5 1.9666667 -1.4 2 -}; -\addplot [draw=none, fill=darkcyan32144140] -table{% -x y -0.033333333 0.5 -0 0.6 -0 1 -0 1.4 -0.033333333 1.5 -0.5 1.9666667 -0.6 2 -1 2 -1.4 2 -1.5 1.9666667 -1.9666667 1.5 -2 1.4 -2 1 -2 0.6 -1.9666667 0.5 -1.5 0.033333333 -1.4 0 -1 0 -0.6 0 -0.5 0.033333333 -0.033333333 0.5 +\path [fill=darkslateblue7235116] +(axis cs:0.26666667,0) +--(axis cs:0,0) +--(axis cs:0,0.26666667) +--cycle +(axis cs:0,2) +--(axis cs:0.26666667,2) +--(axis cs:0,1.7333333) +--cycle +(axis cs:2,0.26666667) +--(axis cs:2,0) +--(axis cs:1.7333333,0) +--cycle +(axis cs:1.7333333,2) +--(axis cs:2,2) +--(axis cs:2,1.7333333) +--cycle; +\path [fill=darkslateblue5294141] +(axis cs:0,0.5) +--(axis cs:0,0.6) +--(axis cs:0.033333333,0.5) +--(axis cs:0.5,0.033333333) +--(axis cs:0.6,0) +--(axis cs:0.5,0) +--(axis cs:0.26666667,0) +--(axis cs:0,0.26666667) +--cycle +(axis cs:0,1.5) +--(axis cs:0,1.7333333) +--(axis cs:0.26666667,2) +--(axis cs:0.5,2) +--(axis cs:0.6,2) +--(axis cs:0.5,1.9666667) +--(axis cs:0.033333333,1.5) +--(axis cs:0,1.4) +--cycle +(axis cs:1.5,0.033333333) +--(axis cs:1.9666667,0.5) +--(axis cs:2,0.6) +--(axis cs:2,0.5) +--(axis cs:2,0.26666667) +--(axis cs:1.7333333,0) +--(axis cs:1.5,0) +--(axis cs:1.4,0) +--cycle +(axis cs:1.4,2) +--(axis cs:1.5,2) +--(axis cs:1.7333333,2) +--(axis cs:2,1.7333333) +--(axis cs:2,1.5) +--(axis cs:2,1.4) +--(axis cs:1.9666667,1.5) +--(axis cs:1.5,1.9666667) +--cycle; +\path [fill=darkcyan32144140] +(axis cs:0.033333333,0.5) +--(axis cs:0,0.6) +--(axis cs:0,1) +--(axis cs:0,1.4) +--(axis cs:0.033333333,1.5) +--(axis cs:0.5,1.9666667) +--(axis cs:0.6,2) +--(axis cs:1,2) +--(axis cs:1.4,2) +--(axis cs:1.5,1.9666667) +--(axis cs:1.9666667,1.5) +--(axis cs:2,1.4) +--(axis cs:2,1) +--(axis cs:2,0.6) +--(axis cs:1.9666667,0.5) +--(axis cs:1.5,0.033333333) +--(axis cs:1.4,0) +--(axis cs:1,0) +--(axis cs:0.6,0) +--(axis cs:0.5,0.033333333) +--cycle +(axis cs:0.5,0.3) +--(axis cs:1,0.13333333) +--(axis cs:1.5,0.3) +--(axis cs:1.7,0.5) +--(axis cs:1.8666667,1) +--(axis cs:1.7,1.5) +--(axis cs:1.5,1.7) +--(axis cs:1,1.8666667) +--(axis cs:0.5,1.7) +--(axis cs:0.3,1.5) +--(axis cs:0.13333333,1) +--(axis cs:0.3,0.5) +--cycle; +\path [fill=mediumseagreen68190112] +(axis cs:0.3,0.5) +--(axis cs:0.13333333,1) +--(axis cs:0.3,1.5) +--(axis cs:0.5,1.7) +--(axis cs:1,1.8666667) +--(axis cs:1.5,1.7) +--(axis cs:1.7,1.5) +--(axis cs:1.8666667,1) +--(axis cs:1.7,0.5) +--(axis cs:1.5,0.3) +--(axis cs:1,0.13333333) +--(axis cs:0.5,0.3) +--cycle +(axis cs:0.5,0.7) +--(axis cs:0.7,0.5) +--(axis cs:1,0.4) +--(axis cs:1.3,0.5) +--(axis cs:1.5,0.7) +--(axis cs:1.6,1) +--(axis cs:1.5,1.3) +--(axis cs:1.3,1.5) +--(axis cs:1,1.6) +--(axis cs:0.7,1.5) +--(axis cs:0.5,1.3) +--(axis cs:0.4,1) +--cycle; +\path [fill=greenyellow18922238] +(axis cs:0.4,1) +--(axis cs:0.5,1.3) +--(axis cs:0.7,1.5) +--(axis cs:1,1.6) +--(axis cs:1.3,1.5) +--(axis cs:1.5,1.3) +--(axis cs:1.6,1) +--(axis cs:1.5,0.7) +--(axis cs:1.3,0.5) +--(axis cs:1,0.4) +--(axis cs:0.7,0.5) +--(axis cs:0.5,0.7) +--cycle; -0.5 0.3 -1 0.13333333 -1.5 0.3 -1.7 0.5 -1.8666667 1 -1.7 1.5 -1.5 1.7 -1 1.8666667 -0.5 1.7 -0.3 1.5 -0.13333333 1 -0.3 0.5 -0.5 0.3 -}; -\addplot [draw=none, fill=mediumseagreen68190112] -table{% -x y -0.3 0.5 -0.13333333 1 -0.3 1.5 -0.5 1.7 -1 1.8666667 -1.5 1.7 -1.7 1.5 -1.8666667 1 -1.7 0.5 -1.5 0.3 -1 0.13333333 -0.5 0.3 -0.3 0.5 - -0.5 0.7 -0.7 0.5 -1 0.4 -1.3 0.5 -1.5 0.7 -1.6 1 -1.5 1.3 -1.3 1.5 -1 1.6 -0.7 1.5 -0.5 1.3 -0.4 1 -0.5 0.7 -}; -\addplot [draw=none, fill=greenyellow18922238] -table{% -x y -0.4 1 -0.5 1.3 -0.7 1.5 -1 1.6 -1.3 1.5 -1.5 1.3 -1.6 1 -1.5 0.7 -1.3 0.5 -1 0.4 -0.7 0.5 -0.5 0.7 -0.4 1 -}; \end{axis} \end{tikzpicture} diff --git a/tests/test_contourf_reference2.tex b/tests/test_contourf_reference2.tex deleted file mode 100644 index cb07b440..00000000 --- a/tests/test_contourf_reference2.tex +++ /dev/null @@ -1,153 +0,0 @@ -\begin{tikzpicture} - -\definecolor{darkcyan32144140}{RGB}{32,144,140} -\definecolor{darkgray176}{RGB}{176,176,176} -\definecolor{darkslateblue5294141}{RGB}{52,94,141} -\definecolor{darkslateblue7235116}{RGB}{72,35,116} -\definecolor{greenyellow18922238}{RGB}{189,222,38} -\definecolor{mediumseagreen68190112}{RGB}{68,190,112} - -\begin{axis}[ -tick align=outside, -tick pos=left, -x grid style={darkgray176}, -xmin=0, xmax=2, -xtick style={color=black}, -y grid style={darkgray176}, -ymin=0, ymax=2, -ytick style={color=black} -] -\path [fill=darkslateblue7235116] -(axis cs:0.26666667,0) ---(axis cs:0,0) ---(axis cs:0,0.26666667) ---cycle -(axis cs:0,2) ---(axis cs:0.26666667,2) ---(axis cs:0,1.7333333) ---cycle -(axis cs:2,0.26666667) ---(axis cs:2,0) ---(axis cs:1.7333333,0) ---cycle -(axis cs:1.7333333,2) ---(axis cs:2,2) ---(axis cs:2,1.7333333) ---cycle; -\path [fill=darkslateblue5294141] -(axis cs:0,0.5) ---(axis cs:0,0.6) ---(axis cs:0.033333333,0.5) ---(axis cs:0.5,0.033333333) ---(axis cs:0.6,0) ---(axis cs:0.5,0) ---(axis cs:0.26666667,0) ---(axis cs:0,0.26666667) ---cycle -(axis cs:0,1.5) ---(axis cs:0,1.7333333) ---(axis cs:0.26666667,2) ---(axis cs:0.5,2) ---(axis cs:0.6,2) ---(axis cs:0.5,1.9666667) ---(axis cs:0.033333333,1.5) ---(axis cs:0,1.4) ---cycle -(axis cs:1.5,0.033333333) ---(axis cs:1.9666667,0.5) ---(axis cs:2,0.6) ---(axis cs:2,0.5) ---(axis cs:2,0.26666667) ---(axis cs:1.7333333,0) ---(axis cs:1.5,0) ---(axis cs:1.4,0) ---cycle -(axis cs:1.4,2) ---(axis cs:1.5,2) ---(axis cs:1.7333333,2) ---(axis cs:2,1.7333333) ---(axis cs:2,1.5) ---(axis cs:2,1.4) ---(axis cs:1.9666667,1.5) ---(axis cs:1.5,1.9666667) ---cycle; -\path [fill=darkcyan32144140] -(axis cs:0.033333333,0.5) ---(axis cs:0,0.6) ---(axis cs:0,1) ---(axis cs:0,1.4) ---(axis cs:0.033333333,1.5) ---(axis cs:0.5,1.9666667) ---(axis cs:0.6,2) ---(axis cs:1,2) ---(axis cs:1.4,2) ---(axis cs:1.5,1.9666667) ---(axis cs:1.9666667,1.5) ---(axis cs:2,1.4) ---(axis cs:2,1) ---(axis cs:2,0.6) ---(axis cs:1.9666667,0.5) ---(axis cs:1.5,0.033333333) ---(axis cs:1.4,0) ---(axis cs:1,0) ---(axis cs:0.6,0) ---(axis cs:0.5,0.033333333) ---cycle -(axis cs:0.5,0.3) ---(axis cs:1,0.13333333) ---(axis cs:1.5,0.3) ---(axis cs:1.7,0.5) ---(axis cs:1.8666667,1) ---(axis cs:1.7,1.5) ---(axis cs:1.5,1.7) ---(axis cs:1,1.8666667) ---(axis cs:0.5,1.7) ---(axis cs:0.3,1.5) ---(axis cs:0.13333333,1) ---(axis cs:0.3,0.5) ---cycle; -\path [fill=mediumseagreen68190112] -(axis cs:0.3,0.5) ---(axis cs:0.13333333,1) ---(axis cs:0.3,1.5) ---(axis cs:0.5,1.7) ---(axis cs:1,1.8666667) ---(axis cs:1.5,1.7) ---(axis cs:1.7,1.5) ---(axis cs:1.8666667,1) ---(axis cs:1.7,0.5) ---(axis cs:1.5,0.3) ---(axis cs:1,0.13333333) ---(axis cs:0.5,0.3) ---cycle -(axis cs:0.5,0.7) ---(axis cs:0.7,0.5) ---(axis cs:1,0.4) ---(axis cs:1.3,0.5) ---(axis cs:1.5,0.7) ---(axis cs:1.6,1) ---(axis cs:1.5,1.3) ---(axis cs:1.3,1.5) ---(axis cs:1,1.6) ---(axis cs:0.7,1.5) ---(axis cs:0.5,1.3) ---(axis cs:0.4,1) ---cycle; -\path [fill=greenyellow18922238] -(axis cs:0.4,1) ---(axis cs:0.5,1.3) ---(axis cs:0.7,1.5) ---(axis cs:1,1.6) ---(axis cs:1.3,1.5) ---(axis cs:1.5,1.3) ---(axis cs:1.6,1) ---(axis cs:1.5,0.7) ---(axis cs:1.3,0.5) ---(axis cs:1,0.4) ---(axis cs:0.7,0.5) ---(axis cs:0.5,0.7) ---cycle; - -\end{axis} - -\end{tikzpicture} diff --git a/tox.ini b/tox.ini index 29191540..69d62774 100644 --- a/tox.ini +++ b/tox.ini @@ -1,17 +1,14 @@ [tox] envlist = lint - py{310,311,312,313} + py3{10,11,12,13,14} combine-test-reports isolated_build = True [testenv] description = Run unit tests. -install_command = uv pip install {opts} {packages} package = wheel -allowlist_externals = - uv setenv = PY_IGNORE_IMPORTMISMATCH=1 # https://github.com/pytest-dev/pytest/issues/2042 COVERAGE_FILE = reports{/}.coverage.{envname} @@ -20,25 +17,33 @@ commands = pytest --typeguard-packages=matplot2tikz --junitxml=reports/pytest.xml.{envname} {posargs} [testenv:py310] +basepython = python3.10 deps = -r requirements-310.txt [testenv:py311] +basepython = python3.11 deps = -r requirements-311.txt [testenv:py312] +basepython = python3.12 deps = -r requirements-312.txt [testenv:py313] +basepython = python3.13 deps = -r requirements-313.txt +[testenv:py314] +basepython = python3.14 +deps = + -r requirements-314.txt + [testenv:lint] description = Run static checkers. basepython = python3.10 -install_command = uv pip install {opts} {packages} deps = -r requirements-lint.txt commands = @@ -52,8 +57,7 @@ description = Combine test and coverage data from multiple test runs. skip_install = true setenv = COVERAGE_FILE = reports/.coverage -depends = py -install_command = uv pip install {opts} {packages} +depends = py3 deps = junitparser coverage[toml] From 89c8be7557b6c071768ae2e7c1fc175e80232df0 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 4 Nov 2025 15:35:11 +0100 Subject: [PATCH 06/10] Update development steps - now make use of tox-uv. --- README.md | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 376972f9..e1d75c22 100644 --- a/README.md +++ b/README.md @@ -219,35 +219,31 @@ For contributing, follow these steps: 1. Download the git repository, e.g., using `git clone git@github.com:ErwindeGelder/matplot2tikz.git`. 2. Create a virtual environment, e.g., using `python -m venv venv`. -3. Activate the virtual environment (e.g., on Windows, `venv\Scripts\activate.bat`). -4. Install the necessary libraries using `pip install -e .[dev]`. +3. Activate the virtual environment (e.g., on Windows, `venv\Scripts\activate`). +4. Install `uv` using `pip install uv` and then `tox-uv` using `uv pip install tox-uv`. 5. The main branch is protected, meaning that you cannot directly push changes to this branch. Therefore, if you want to make changes, do so in a seperate branch. For example, you can create a new branch using `git checkout -b feature/my_awesome_new_feature`. 6. Before pushing changes, ensure that the code adheres to the linting rules and that the tests are - successful. To run the linting and testing, tox first needs to know where it can find the - different Python versions that are supported. One way to do so is by making use of pyenv or - pyenv-win. Note that you only need to do this once for a single machine. -7. Run `tox`. This does a linting check and runs all test scripts. To manually perform these steps, - use the following commands (note that to ensure the same output is generated, Python 3.9 is used - in step 2 above): - 1. Run `tox -e lint`. If issues arise, fix them. You can do the linting commands manually - using: - 1. `ruff format . --check` (remove the `--check` flag to let `ruff` do the formatting) - 2. `ruff check .` - 3. `mypy .` - 2. Run `tox -e py39`. - 3. Run `tox -e py310`. - 4. Run `tox -e py311`. - 5. Run `tox -e py312`. - 6. Run `tox -e py313`. + successful. Run `tox`. This does a linting check and runs all test scripts. To manually perform + these steps, use the following commands: + 1. Run `tox -e lint`. You can do the linting commands manually using: + 1. (One time) `uv pip install -r requirements-lint.txt` + 2. `ruff format . --check` (remove the `--check` flag to let `ruff` do the formatting) + 3. `ruff check .` + 4. `mypy .` + 2. Run `tox -e py310`. + 3. Run `tox -e py311`. + 4. Run `tox -e py312`. + 5. Run `tox -e py313`. + 6. Run `tox -e py314`. 7. Run `tox -e combine-test-reports` -8. Check if the tests covered everything using the coverage report in +7. Check if the tests covered everything using the coverage report in `/reports/coverage_html/index.html`. NOTE: Currently, now all code is covered. Ideally, all code is covered, but for now, ensure that all *new* code is covered by the testing. -9. Push changes to GitHub. If everything is OK and you want to merge your changes to the `main` +8. Push changes to GitHub. If everything is OK and you want to merge your changes to the `main` branch, create a pull request. Ideally, there is at least one reviewer who reviews the pull request before the merge. From e2ad1ea39bc768db7891707fe64c1f71dcc871bc Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 4 Nov 2025 15:48:45 +0100 Subject: [PATCH 07/10] Update formatting due to newer version of ruff. --- src/matplot2tikz/_axes.py | 2 +- src/matplot2tikz/_cleanfigure.py | 10 ++++---- src/matplot2tikz/_line2d.py | 21 ++++++++++------- src/matplot2tikz/_patch.py | 4 +++- src/matplot2tikz/_path.py | 39 ++++++++++++++++---------------- src/matplot2tikz/_util.py | 2 +- tests/helpers.py | 2 +- tests/test_cleanfigure.py | 8 +++---- tests/test_contourf.py | 6 +---- tests/test_hatch.py | 2 +- tests/test_line_collection.py | 4 +++- tests/test_patches.py | 4 ++-- 12 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/matplot2tikz/_axes.py b/src/matplot2tikz/_axes.py index 0dd5b95b..68b0bc87 100644 --- a/src/matplot2tikz/_axes.py +++ b/src/matplot2tikz/_axes.py @@ -602,7 +602,7 @@ def _is_label_required(ticks: list | np.ndarray, ticklabels: list) -> bool: If one of the labels is, then all of them must appear in the TikZ plot. """ - for tick, ticklabel in zip(ticks, ticklabels): + for tick, ticklabel in zip(ticks, ticklabels, strict=False): # store the label anyway label = ticklabel.get_text() diff --git a/src/matplot2tikz/_cleanfigure.py b/src/matplot2tikz/_cleanfigure.py index 43b2551c..39533099 100644 --- a/src/matplot2tikz/_cleanfigure.py +++ b/src/matplot2tikz/_cleanfigure.py @@ -2,7 +2,7 @@ import warnings from dataclasses import dataclass, field -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING import matplotlib as mpl import matplotlib.pyplot as plt @@ -38,15 +38,15 @@ class CleanFigureData: target_resolution: int | list[int] | np.ndarray scale_precision: float data: np.ndarray = field(default_factory=initial_data) - visual_data: Optional[np.ndarray] = None + visual_data: np.ndarray | None = None x_lim: np.ndarray = field(default_factory=initial_axis_limits) y_lim: np.ndarray = field(default_factory=initial_axis_limits) - has_lines: Optional[bool] = None - has_markers: Optional[bool] = None + has_lines: bool | None = None + has_markers: bool | None = None def clean_figure( - fig: Optional[FigureBase] = None, + fig: FigureBase | None = None, target_resolution: int | list[int] | np.ndarray = 600, scale_precision: float = 1.0, ) -> None: diff --git a/src/matplot2tikz/_line2d.py b/src/matplot2tikz/_line2d.py index 94cc914b..a3eb21b7 100644 --- a/src/matplot2tikz/_line2d.py +++ b/src/matplot2tikz/_line2d.py @@ -4,7 +4,7 @@ import datetime from collections.abc import Iterable, Sized from dataclasses import dataclass -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING import numpy as np from matplotlib.dates import num2date @@ -26,27 +26,30 @@ class MarkerData: marker: str | None mark_options: list - fc: Optional[ + fc: ( str | tuple[float, float, float] | tuple[float, float, float, float] | tuple[str | tuple[float, float, float], float] | tuple[tuple[float, float, float, float], float] - ] = None # facecolor - ec: Optional[ + | None + ) = None # facecolor + ec: ( str | tuple[float, float, float] | tuple[float, float, float, float] | tuple[str | tuple[float, float, float], float] | tuple[tuple[float, float, float, float], float] - ] = None # edgecolor - lc: Optional[ + | None + ) = None # edgecolor + lc: ( str | tuple[float, float, float] | tuple[float, float, float, float] | tuple[str | tuple[float, float, float], float] | tuple[tuple[float, float, float, float], float] - ] = None # linecolor + | None + ) = None # linecolor def draw_line2d(data: TikzData, obj: Line2D) -> list[str]: @@ -290,7 +293,9 @@ def _table(data: TikzData, obj: Line2D) -> list[str]: data.current_axis_options.add("unbounded coords=jump") ff = data.float_format - plot_table = [f"{x:{xformat}}{col_sep}{y:{ff}}{table_row_sep}" for x, y in zip(xdata, ydata)] + plot_table = [ + f"{x:{xformat}}{col_sep}{y:{ff}}{table_row_sep}" for x, y in zip(xdata, ydata, strict=True) + ] min_extern_length = 3 diff --git a/src/matplot2tikz/_patch.py b/src/matplot2tikz/_patch.py index 725c2738..bafe2609 100644 --- a/src/matplot2tikz/_patch.py +++ b/src/matplot2tikz/_patch.py @@ -153,7 +153,9 @@ def _draw_rectangle(data: TikzData, obj: Rectangle, draw_options: list) -> list[ # "_nolegend_". See . if isinstance(obj.axes, Axes): handles, labels = obj.axes.get_legend_handles_labels() - labels_found = [label for h, label in zip(handles, labels) if obj in h.get_children()] + labels_found = [ + label for h, label in zip(handles, labels, strict=True) if obj in h.get_children() + ] if len(labels_found) == 1: label = labels_found[0] diff --git a/src/matplot2tikz/_path.py b/src/matplot2tikz/_path.py index 80790483..e1da1cd0 100644 --- a/src/matplot2tikz/_path.py +++ b/src/matplot2tikz/_path.py @@ -3,7 +3,7 @@ import contextlib from collections.abc import Iterable, Sequence, Sized from dataclasses import dataclass -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING import numpy as np from matplotlib.dates import DateConverter, num2date @@ -27,15 +27,15 @@ @dataclass class LineData: obj: Collection | Patch - ec: Optional[str | tuple] = None # edgecolor - ec_name: Optional[str] = None - ec_rgba: Optional[np.ndarray] = None - fc: Optional[str | tuple] = None # facecolor - fc_name: Optional[str] = None - fc_rgba: Optional[np.ndarray] = None - ls: Optional[str | tuple[float, Sequence[float] | None]] = None # linestyle - lw: Optional[float] = None # linewidth - hatch: Optional[str] = None + ec: str | tuple | None = None # edgecolor + ec_name: str | None = None + ec_rgba: np.ndarray | None = None + fc: str | tuple | None = None # facecolor + fc_name: str | None = None + fc_rgba: np.ndarray | None = None + ls: str | tuple[float, Sequence[float] | None] | None = None # linestyle + lw: float | None = None # linewidth + hatch: str | None = None @dataclass @@ -46,18 +46,18 @@ class PathCollectionData: labels: list table_options: list is_contour: bool - marker: Optional[str] = None + marker: str | None = None is_filled: bool = False - add_individual_color_code: Optional[bool] = False - legend_text: Optional[str] = None + add_individual_color_code: bool | None = False + legend_text: str | None = None def draw_path( data: TikzData, path: Path, - draw_options: Optional[list[str]] = None, + draw_options: list[str] | None = None, *, - simplify: Optional[bool] = None, + simplify: bool | None = None, ) -> tuple[str, bool]: """Adds code for drawing an ordinary path in PGFPlots (TikZ).""" # For some reasons, matplotlib sometimes adds void paths which consist of @@ -377,7 +377,7 @@ def _draw_pathcollection_draw_contour(path: Path, data: TikzData, pcd: PathColle dd_strings: list[list[str]] = [] if not isinstance(codes, Iterable): return # We cannot draw a path - for row, code in zip(dd, codes): + for row, code in zip(dd, codes, strict=True): if code == 1: # MOVETO # Inserts a newline to trigger "move to" in pgfplots dd_strings.append([]) @@ -534,7 +534,7 @@ def mpl_linewidth2pgfp_linewidth(data: TikzData, line_width: float) -> str | Non def mpl_linestyle2pgfplots_linestyle( data: TikzData, line_style: str | tuple[float, Sequence[float] | None], - line: Optional[Line2D] = None, + line: Line2D | None = None, ) -> str | None: """Translates a line style of matplotlib to the corresponding style in PGFPlots.""" # linestyle is a string or dash tuple. Legal string values are @@ -554,7 +554,7 @@ def mpl_linestyle2pgfplots_linestyle( pgf_line_style += " ".join( [ f"on {ls_on:{ff}}pt off {ls_off:{ff}}pt" - for ls_on, ls_off in zip(line_style[1][::2], line_style[1][1::2]) + for ls_on, ls_off in zip(line_style[1][::2], line_style[1][1::2], strict=True) ] ) return pgf_line_style @@ -574,7 +574,8 @@ def mpl_linestyle2pgfplots_linestyle( lst.append( "dash pattern=" + " ".join( - f"on {a:{ff}}pt off {b:{ff}}pt" for a, b in zip(dash_seq[0::2], dash_seq[1::2]) + f"on {a:{ff}}pt off {b:{ff}}pt" + for a, b in zip(dash_seq[0::2], dash_seq[1::2], strict=True) ) ) diff --git a/src/matplot2tikz/_util.py b/src/matplot2tikz/_util.py index ef740c16..00062692 100644 --- a/src/matplot2tikz/_util.py +++ b/src/matplot2tikz/_util.py @@ -36,7 +36,7 @@ def get_legend_text(obj: Line2D | PathCollection) -> str | None: values = [t.get_text() for t in leg.texts] label = obj.get_label() - d = dict(zip(keys, values)) + d = dict(zip(keys, values, strict=True)) if label in d: return d[label] diff --git a/tests/helpers.py b/tests/helpers.py index ea94d686..a4c29b84 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,8 +1,8 @@ """Helper functions for running the tests.""" import difflib +from collections.abc import Callable from pathlib import Path -from typing import Callable import matplotlib.pyplot as plt from matplotlib.artist import Artist diff --git a/tests/test_cleanfigure.py b/tests/test_cleanfigure.py index 0ed22ac5..7b8e9d3e 100644 --- a/tests/test_cleanfigure.py +++ b/tests/test_cleanfigure.py @@ -222,7 +222,7 @@ def test_surface3d(self) -> None: "Cleaning Line Collections (scatter plot) is not supported yet.", ) assert len(record) == len(warnings) - for record_warning, warning in zip(record, warnings): + for record_warning, warning in zip(record, warnings, strict=True): assert str(record_warning.message) == warning plt.close("all") @@ -284,7 +284,7 @@ def cc(arg: str) -> tuple[float, float, float, float]: for _ in zs: ys = rng.random(size=len(xs)) ys[0], ys[-1] = 0, 0 - verts.append(list(zip(xs, ys))) + verts.append(list(zip(xs, ys, strict=True))) poly = PolyCollection(verts, facecolors=[cc("r"), cc("g"), cc("b"), cc("y")]) poly.set_alpha(0.7) @@ -307,7 +307,7 @@ def test_bar3d(self) -> None: ax: axes3d.Axes3D = fig.add_subplot(111, projection="3d") rng = np.random.default_rng(42) - for c, z in zip(["r", "g", "b", "y"], [30, 20, 10, 0]): + for c, z in zip(["r", "g", "b", "y"], [30, 20, 10, 0], strict=True): xs = np.arange(20) ys = rng.random(size=20) @@ -492,7 +492,7 @@ def test_subplot(self) -> None: with plt.rc_context(rc=RC_PARAMS): fig, axes = plt.subplots(2, 2, figsize=(5, 5)) plotstyles = [("-", "o"), ("-", "None"), ("None", "o"), ("--", "x")] - for ax, style in zip(axes.ravel(), plotstyles): + for ax, style in zip(axes.ravel(), plotstyles, strict=True): ax.plot(x, y, linestyle=style[0], marker=style[1]) ax.set_ylim([20, 80]) ax.set_xlim([20, 80]) diff --git a/tests/test_contourf.py b/tests/test_contourf.py index 71eb3ff2..6a60a618 100644 --- a/tests/test_contourf.py +++ b/tests/test_contourf.py @@ -34,8 +34,4 @@ def plot() -> Figure: def test() -> None: - try: - assert_equality(plot, __file__[:-3] + "_reference.tex") - except AssertionError: - # Try other output, which is the new output since Python 3.9 - assert_equality(plot, __file__[:-3] + "_reference2.tex") + assert_equality(plot, __file__[:-3] + "_reference.tex") diff --git a/tests/test_hatch.py b/tests/test_hatch.py index d82e8c0f..2c556cdb 100644 --- a/tests/test_hatch.py +++ b/tests/test_hatch.py @@ -35,7 +35,7 @@ def plot() -> Figure: ax2.set_xticks([1.5, 2.5, 3.5, 4.5]) patterns = ("-", "+", "x", "\\", "*", "o", "O", ".") - for bar, pattern in zip(bars, patterns): + for bar, pattern in zip(bars, patterns, strict=True): bar.set_hatch(pattern) ax3.fill([1, 3, 3, 1], [1, 1, 2, 2], fill=False, hatch="\\", zorder=1, label="Square") diff --git a/tests/test_line_collection.py b/tests/test_line_collection.py index 16873bf4..dccff782 100644 --- a/tests/test_line_collection.py +++ b/tests/test_line_collection.py @@ -42,7 +42,9 @@ def plot() -> Figure: # Make a sequence of x,y pairs line_segments = LineCollection( - [list(zip(x, y)) for y in ys], linewidths=(0.5, 1, 1.5, 2), linestyles="dashdot" + [list(zip(x, y, strict=True)) for y in ys], + linewidths=(0.5, 1, 1.5, 2), + linestyles="dashdot", ) line_segments.set_array(x) ax.add_collection(line_segments) diff --git a/tests/test_patches.py b/tests/test_patches.py index 479e7514..ecfda2ca 100644 --- a/tests/test_patches.py +++ b/tests/test_patches.py @@ -24,7 +24,7 @@ def plot() -> Figure: y = rng.random(size=n_points) radii = 0.1 * rng.random(size=n_points) patches: list[Patch] = [] - for x1, y1, r in zip(x, y, radii): + for x1, y1, r in zip(x, y, radii, strict=True): circle = Circle((x1, y1), r) patches.append(circle) @@ -36,7 +36,7 @@ def plot() -> Figure: radii = 0.1 * rng.random(size=n_points) theta1 = 360.0 * rng.random(size=n_points) theta2 = 360.0 * rng.random(size=n_points) - for x1, y1, r, t1, t2 in zip(x, y, radii, theta1, theta2): + for x1, y1, r, t1, t2 in zip(x, y, radii, theta1, theta2, strict=True): wedge = Wedge((x1, y1), r, t1, t2) patches.append(wedge) From 6b01b331eaaf5ebcd49c308ad15621f01365c965 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Tue, 4 Nov 2025 16:42:53 +0100 Subject: [PATCH 08/10] Simplify workflow. --- .github/workflows/tests.yaml | 38 ++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 30776bcd..763ee90a 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -5,30 +5,26 @@ on: jobs: test: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] - include: - - python-version: '3.9' - os: ubuntu-latest - tox-env: lint + # Run on a single, standard runner + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.11 + # We just need one modern Python version to run the 'tox' command itself. uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies + python-version: "3.11" + + - name: Install Tox and tox-uv + # Install the required tools into the workflow runner environment run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Test with tox + pip install --upgrade pip + pip install tox tox-uv + + - name: Run All Tox Environments + # The 'tox' command executes the full matrix (py310, py311, etc.) + # defined in tox.ini. tox-uv handles the fast installation. run: tox - env: - # Pass the current matrix Python version to tox-gh-actions - # so it can filter the tox environments - TOX_GH_ACTIONS_MATRIX_PYTHON_VERSION: ${{ matrix.python-version }} - TOX_GH_ACTIONS_TOX_ENV: ${{ matrix.tox-env || '' }} From aad610e01f3b3290d346e8719f94383a8142c3b2 Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Wed, 5 Nov 2025 14:23:53 +0100 Subject: [PATCH 09/10] Use tox-uv to install packages. --- .github/workflows/main_coverage.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main_coverage.yaml b/.github/workflows/main_coverage.yaml index 6e11453d..b7ef2b1d 100644 --- a/.github/workflows/main_coverage.yaml +++ b/.github/workflows/main_coverage.yaml @@ -16,14 +16,14 @@ jobs: fetch-depth: 2 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions pytest-cov + pip install --upgrade pip + pip install tox tox-uv - name: Run tests run: tox run -e py310 -- --cov matplot2tikz --cov-branch --cov-report=xml From 27df0600897a4091c6d7188be1eba74fd9860feb Mon Sep 17 00:00:00 2001 From: Erwin de Gelder Date: Wed, 5 Nov 2025 14:24:21 +0100 Subject: [PATCH 10/10] Bump version. --- src/matplot2tikz/__about__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matplot2tikz/__about__.py b/src/matplot2tikz/__about__.py index d4cebef1..977679d3 100644 --- a/src/matplot2tikz/__about__.py +++ b/src/matplot2tikz/__about__.py @@ -1,3 +1,3 @@ """Version number.""" -__version__ = "0.4.2" +__version__ = "0.5.0"