From fbc6248a2c0aa9c64c5aaaeef91644f926fbfff5 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 16:32:27 -0500 Subject: [PATCH 01/15] update pyproject --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f9b4d843..319732cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ name = "magicgui" description = " build GUIs from python types" keywords = ["gui", "widgets", "type annotations"] readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = { text = "MIT" } authors = [{ email = "talley.lambert@gmail.com", name = "Talley Lambert" }] classifiers = [ @@ -23,11 +23,11 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "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.14", "Topic :: Desktop Environment", "Topic :: Software Development", "Topic :: Software Development :: User Interfaces", @@ -125,10 +125,10 @@ documentation = "https://pyapp-kit.github.io/magicgui/" # https://docs.astral.sh/ruff [tool.ruff] line-length = 88 -target-version = "py39" +target-version = "py310" src = ["src", "tests"] fix = true -# unsafe-fixes = true +unsafe-fixes = true [tool.ruff.lint] pydocstyle = { convention = "numpy" } From 96634dc9b505c4eb6711287a9047a73b008325cc Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 16:57:45 -0500 Subject: [PATCH 02/15] fix magic-siganture --- pyproject.toml | 5 +++-- src/magicgui/signature.py | 17 +++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 319732cc..22d9abe6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ name = "magicgui" description = " build GUIs from python types" keywords = ["gui", "widgets", "type annotations"] readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.9" license = { text = "MIT" } authors = [{ email = "talley.lambert@gmail.com", name = "Talley Lambert" }] classifiers = [ @@ -23,6 +23,7 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -125,7 +126,7 @@ documentation = "https://pyapp-kit.github.io/magicgui/" # https://docs.astral.sh/ruff [tool.ruff] line-length = 88 -target-version = "py310" +target-version = "py39" src = ["src", "tests"] fix = true unsafe-fixes = true diff --git a/src/magicgui/signature.py b/src/magicgui/signature.py index d67ed6ae..3a84cb85 100644 --- a/src/magicgui/signature.py +++ b/src/magicgui/signature.py @@ -182,14 +182,19 @@ def __repr__(self) -> str: rep = rep.replace(": NoneType = ", "=") return rep - def __str__(self) -> str: - """Return string representation of the Parameter in a signature.""" + def _format(self, *, quote_annotation_strings: bool = True) -> str: + """Return formatted string for use in Signature.format() (Python 3.14+).""" hint, _ = get_args(self.annotation) - return str( - inspect.Parameter( - self.name, self.kind, default=self.default, annotation=hint - ) + param = inspect.Parameter( + self.name, self.kind, default=self.default, annotation=hint ) + if hasattr(param, "_format"): # python 3.14+ + return param._format(quote_annotation_strings=quote_annotation_strings) # type: ignore[no-any-return] + return str(param) + + def __str__(self) -> str: + """Return string representation of the Parameter in a signature.""" + return self._format() def to_widget( self, From cf70aa58b08f3130d53d148a34b10b42c1091ab1 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:00:18 -0500 Subject: [PATCH 03/15] add py3.14 test --- .github/workflows/test_and_deploy.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index ef5c9326..4349b73d 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -23,7 +23,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11"] + python-version: ["3.10", "3.13"] os: [ubuntu-latest, macos-latest, windows-latest] add-group: [pyqt6, pyside6] include: @@ -40,7 +40,7 @@ jobs: - python-version: "3.11" os: windows-latest add-group: pyqt5 - - python-version: "3.10" + - python-version: "3.11" os: ubuntu-latest add-group: pyside2 - python-version: "3.12" @@ -49,10 +49,10 @@ jobs: - python-version: "3.12" os: ubuntu-latest add-group: pyside6 - - python-version: "3.13" + - python-version: "3.14" os: ubuntu-latest add-group: pyside6 - - python-version: "3.13" + - python-version: "3.14" os: windows-latest add-group: pyqt6 From 831820cc30a9bd2969c2ba3852432fe4c868fd8e Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:19:32 -0500 Subject: [PATCH 04/15] ignore matplotlib deprecations --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 22d9abe6..60e103d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ dependencies = [ # extras # https://peps.python.org/pep-0621/#dependencies-optional-dependencies [project.optional-dependencies] -pyqt5 = ["PyQt5>=5.15.8", "pyqt5-qt5<=5.15.2; sys_platform == 'win32'"] +pyqt5 = ["PyQt5>=5.15.8", "pyqt5-qt5<=5.15.2; sys_platform == 'win32'", "pyqt5-qt5>5.15.2; sys_platform != 'win32'"] pyqt6 = ["pyqt6>=6.4.0"] pyside2 = ["pyside2>=5.15"] pyside6 = ["pyside6>=6.4.0"] @@ -179,6 +179,7 @@ filterwarnings = [ "ignore:.*read_binary is deprecated:", "ignore:Pickle, copy, and deepcopy support:DeprecationWarning", "ignore:'count' is passed as positional argument::vispy", + "ignore::DeprecationWarning:matplotlib", ] # https://mypy.readthedocs.io/en/stable/config_file.html From 2e1fe87cf555a7defc0b3ffd2e45505db4577d2e Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:23:21 -0500 Subject: [PATCH 05/15] pin numpy <2 for pyside2 --- pyproject.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 60e103d6..c7f33c14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,11 @@ dependencies = [ # extras # https://peps.python.org/pep-0621/#dependencies-optional-dependencies [project.optional-dependencies] -pyqt5 = ["PyQt5>=5.15.8", "pyqt5-qt5<=5.15.2; sys_platform == 'win32'", "pyqt5-qt5>5.15.2; sys_platform != 'win32'"] +pyqt5 = [ + "PyQt5>=5.15.8", + "pyqt5-qt5<=5.15.2; sys_platform == 'win32'", + "pyqt5-qt5>5.15.2; sys_platform != 'win32'", +] pyqt6 = ["pyqt6>=6.4.0"] pyside2 = ["pyside2>=5.15"] pyside6 = ["pyside6>=6.4.0"] @@ -78,7 +82,7 @@ test = [ ] pyqt5 = ["magicgui[pyqt5]", { include-group = "test-qt" }] pyqt6 = ["magicgui[pyqt6]", { include-group = "test-qt" }] -pyside2 = ["magicgui[pyside2]", { include-group = "test-qt" }] +pyside2 = ["magicgui[pyside2]", { include-group = "test-qt" }, "numpy<2"] pyside6 = ["magicgui[pyside6]", { include-group = "test-qt" }] dev = [ { include-group = "test" }, From 20313ceb56d68725343cb828ee8ce862912af845 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:32:40 -0500 Subject: [PATCH 06/15] change numpy pins --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index c7f33c14..5d8fa88f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,6 +67,7 @@ third-party-support = [ "attrs>=25.3.0", "ipykernel>=6.29.5", "matplotlib>=3.9.4", + "numpy >=2.1.0; python_version >= '3.13'", "numpy>=1.26.4", "pandas>=2.2.3; python_version >= '3.11'", "pandas>=2.1", From 33f8a5ad0ccbdc59a969a05d5f719e912ea4d313 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:32:48 -0500 Subject: [PATCH 07/15] change numpy pins --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5d8fa88f..7bbe5c87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ third-party-support = [ "attrs>=25.3.0", "ipykernel>=6.29.5", "matplotlib>=3.9.4", - "numpy >=2.1.0; python_version >= '3.13'", + "numpy>=2.1.0; python_version >= '3.13'", "numpy>=1.26.4", "pandas>=2.2.3; python_version >= '3.11'", "pandas>=2.1", From efaa182fc24917023fa20ef81e27f4c0addb7240 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:35:02 -0500 Subject: [PATCH 08/15] fix pyproject numpy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7bbe5c87..b5830af8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,7 +83,7 @@ test = [ ] pyqt5 = ["magicgui[pyqt5]", { include-group = "test-qt" }] pyqt6 = ["magicgui[pyqt6]", { include-group = "test-qt" }] -pyside2 = ["magicgui[pyside2]", { include-group = "test-qt" }, "numpy<2"] +pyside2 = ["magicgui[pyside2]", { include-group = "test-qt" }, "numpy<2; python_version < '3.13'"] pyside6 = ["magicgui[pyside6]", { include-group = "test-qt" }] dev = [ { include-group = "test" }, From d9a66d6e0638cfda76eccb34496e1b60b17ed8ed Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 17:40:27 -0500 Subject: [PATCH 09/15] don't clean on CI --- tests/conftest.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 82c2f11b..eed700a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import os import pytest from magicgui.application import use_app @@ -14,10 +15,12 @@ def qapp(): @pytest.fixture(autouse=True, scope="function") def always_qapp(qapp): yield qapp - for w in qapp.topLevelWidgets(): - w.close() - w.deleteLater() - qapp.processEvents() + if not os.getenv("CI"): + # I suspect, but can't prove, that this code causes occasional segfaults on CI. + for w in qapp.topLevelWidgets(): + w.close() + w.deleteLater() + qapp.processEvents() @pytest.fixture(autouse=True, scope="function") From ad578c5826b718e767c621a7e035d40cad32df69 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:40:42 +0000 Subject: [PATCH 10/15] style(pre-commit.ci): auto fixes [...] --- tests/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/conftest.py b/tests/conftest.py index eed700a8..31c01bef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import os + import pytest from magicgui.application import use_app From 70f147278c5ed32225b34d373350017fe867e56d Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 29 Dec 2025 18:43:48 -0500 Subject: [PATCH 11/15] try tqdm tmon --- tests/conftest.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 31c01bef..aa252ac2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,17 @@ from magicgui.application import use_app +# Disable tqdm's TMonitor thread to prevent race conditions with Qt threading +# that can cause intermittent segfaults on CI (especially with PySide6 on Linux). +# See: https://github.com/tqdm/tqdm/issues/469 +try: + from tqdm import tqdm as _tqdm_std + + _tqdm_std.monitor_interval = 0 +except ImportError: + pass + + @pytest.fixture(scope="session") def qapp(): yield use_app("qt").native From 38dbbde5915a2e16f58753dc82017c734489cd4e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Dec 2025 23:44:05 +0000 Subject: [PATCH 12/15] style(pre-commit.ci): auto fixes [...] --- tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index aa252ac2..ba60c7b3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,6 @@ from magicgui.application import use_app - # Disable tqdm's TMonitor thread to prevent race conditions with Qt threading # that can cause intermittent segfaults on CI (especially with PySide6 on Linux). # See: https://github.com/tqdm/tqdm/issues/469 From d5fd5dd6f327b30a5b36db991d39cee1be9dd31f Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Tue, 30 Dec 2025 13:20:04 -0500 Subject: [PATCH 13/15] try different os --- .github/workflows/test_and_deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index bf8a3c82..c8f04e64 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -37,11 +37,11 @@ jobs: - python-version: "3.9" os: ubuntu-latest add-group: pyside2 - - python-version: "3.11" + - python-version: "3.12" os: windows-latest add-group: pyqt5 - python-version: "3.11" - os: ubuntu-latest + os: windows-latest add-group: pyside2 - python-version: "3.12" os: ubuntu-latest From ab696adc8533d54c292a623955fc9728937997d2 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Tue, 30 Dec 2025 13:22:32 -0500 Subject: [PATCH 14/15] build docs on 3.13 --- .github/workflows/deploy_docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 2b69fa70..d5a08772 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -17,6 +17,7 @@ jobs: fetch-depth: 0 - uses: astral-sh/setup-uv@v7 with: + python-version: "3.13" enable-cache: true - name: Deploy docs to GitHub Pages From acf0b794399dd5c4a60b59a857f028bd31019666 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Tue, 30 Dec 2025 13:26:40 -0500 Subject: [PATCH 15/15] drop windows version again --- .github/workflows/test_and_deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index c8f04e64..3674baa4 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -40,7 +40,7 @@ jobs: - python-version: "3.12" os: windows-latest add-group: pyqt5 - - python-version: "3.11" + - python-version: "3.10" os: windows-latest add-group: pyside2 - python-version: "3.12"