From 4bdf6ca4521fb90d7ddfbf66cf744c882c6e1cda Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 10:57:24 -0500 Subject: [PATCH 01/13] ci: test out wheel build --- .github/workflows/pypi.yml | 61 ++++++++++++++++---------------------- pyproject.toml | 4 +++ 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 8778e94f..ee52736f 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -4,17 +4,18 @@ on: push: branches: [main] tags: [v*] + pull_request: jobs: - test: - uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2 - with: - hatch-build-hooks-enable: true - coverage-upload: none + # test: + # uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2 + # with: + # hatch-build-hooks-enable: true + # coverage-upload: none deploy-sdist: - needs: test - if: success() && startsWith(github.ref, 'refs/tags/v') + # needs: test + # if: success() && startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: id-token: write @@ -34,18 +35,18 @@ jobs: python -m pip install build python -m build - - name: 🚢 Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + # - name: 🚢 Publish to PyPI + # uses: pypa/gh-action-pypi-publish@release/v1 - - uses: softprops/action-gh-release@v2 - with: - generate_release_notes: true - files: "./dist/*" + # - uses: softprops/action-gh-release@v2 + # with: + # generate_release_notes: true + # files: "./dist/*" deploy-wheel: - if: startsWith(github.event.ref, 'refs/tags/v') - needs: deploy-sdist - name: mypyc wheels (${{ matrix.name }}) + # if: startsWith(github.event.ref, 'refs/tags/v') + # needs: deploy-sdist + name: mypyc wheels (${{ matrix.os }}) runs-on: ${{ matrix.os }} permissions: id-token: write @@ -53,17 +54,7 @@ jobs: strategy: fail-fast: false matrix: - include: - - os: ubuntu-latest - name: linux-x86_64 - - os: windows-latest - name: windows-amd64 - - os: macos-13 - name: macos-x86_64 - macos_arch: "x86_64" - - os: macos-14 - name: macos-arm64 - macos_arch: "arm64" + os: [ubuntu-latest, windows-latest, macos-13, macos-latest] steps: - uses: actions/checkout@v4 @@ -74,14 +65,12 @@ jobs: uses: pypa/cibuildwheel@v2.22.0 with: output-dir: dist - env: - CIBW_ARCHS_MACOS: "${{ matrix.macos_arch }}" - - name: Upload wheels as workflow artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.name }}-mypyc-wheels - path: ./dist/*.whl + # - name: Upload wheels as workflow artifacts + # uses: actions/upload-artifact@v4 + # with: + # name: ${{ matrix.name }}-mypyc-wheels + # path: ./dist/*.whl - - name: 🚢 Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + # - name: 🚢 Publish to PyPI + # uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/pyproject.toml b/pyproject.toml index dd7fb69b..e5d990e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -118,6 +118,10 @@ test-extras = ["test"] test-command = "pytest {project}/tests -v" test-skip = ["*-musllinux*", "cp312-win*", "*-macosx_arm64"] +[tool.cibuildwheel.macos] +# https://cibuildwheel.readthedocs.io/en/stable/faq/#apple-silicon +archs = ["x86_64", "arm64"] + [[tool.cibuildwheel.overrides]] select = "*-manylinux_i686*" before-all = "yum install -y python3-devel" From b002527a2a5088ff39f2b23cdc94c0f5f4fb679e Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 10:57:44 -0500 Subject: [PATCH 02/13] upload artifact --- .github/workflows/pypi.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index ee52736f..bc53e6ed 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -66,11 +66,11 @@ jobs: with: output-dir: dist - # - name: Upload wheels as workflow artifacts - # uses: actions/upload-artifact@v4 - # with: - # name: ${{ matrix.name }}-mypyc-wheels - # path: ./dist/*.whl + - name: Upload wheels as workflow artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.name }}-mypyc-wheels + path: ./dist/*.whl # - name: 🚢 Publish to PyPI # uses: pypa/gh-action-pypi-publish@release/v1 From 32e67118d5f062fe734002afb98443e10c6619c5 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 11:24:30 -0500 Subject: [PATCH 03/13] fix name --- .github/workflows/pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index bc53e6ed..eafdb67e 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -69,7 +69,7 @@ jobs: - name: Upload wheels as workflow artifacts uses: actions/upload-artifact@v4 with: - name: ${{ matrix.name }}-mypyc-wheels + name: ${{ runner.os }}-${{ runner.arch }}-mypyc-wheels path: ./dist/*.whl # - name: 🚢 Publish to PyPI From d72105449aff2e3788b1a62cb9b496f6732477bf Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 12:17:04 -0500 Subject: [PATCH 04/13] try skipping --- tests/test_psygnal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_psygnal.py b/tests/test_psygnal.py index 7b5b26d7..5447a6df 100644 --- a/tests/test_psygnal.py +++ b/tests/test_psygnal.py @@ -163,6 +163,9 @@ def boom(v: int) -> None: emitter.one_int.emit_fast(42) +@pytest.mark.skipif( + bool(os.name == "nt" and COMPILED), reason="Windows segfaulting during cibuildwheel" +) def test_emit_fast_recursion_errors(): """Test emit_fast method.""" emitter = Emitter() From a51a7c3b9dea1182a4d8476f7f5d9d9f3b2ca08e Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 14:33:32 -0500 Subject: [PATCH 05/13] hard limit on recursion --- src/psygnal/_signal.py | 22 +++++++++++++++++++++- tests/test_psygnal.py | 3 --- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/psygnal/_signal.py b/src/psygnal/_signal.py index c1b0482e..3ebcb847 100644 --- a/src/psygnal/_signal.py +++ b/src/psygnal/_signal.py @@ -182,7 +182,14 @@ def ensure_at_least_20(val: int): _NULL = object() F = TypeVar("F", bound=Callable) -RECURSION_LIMIT = sys.getrecursionlimit() + +# using 300 instead of sys.getrecursionlimit() +# in a mypyc-compiled program, hitting an actual RecursionError can cause +# a segfault (rather than raise a python exception), so we really MUST +# avoid it. Windows has a lower stack limit than other platforms, so we +# use 300 as a cross-platform "safe" limit, determined via testing. It's +# probably plenty large for most reasonable use-cases. +RECURSION_LIMIT = 300 ReemissionVal = Literal["immediate", "queued", "latest-only"] VALID_REEMISSION = set(ReemissionVal.__args__) # type: ignore @@ -1223,6 +1230,13 @@ def emit_fast(self, *args: Any) -> None: self._args_queue.append(args) return + if self._recursion_depth >= RECURSION_LIMIT: + raise RecursionError( + f"Psygnal recursion limit ({RECURSION_LIMIT}) reached when emitting " + f"signal {self.name!r} with args {args}" + ) + + self._recursion_depth += 1 try: for caller in self._slots: caller.cb(args) @@ -1238,6 +1252,9 @@ def emit_fast(self, *args: Any) -> None: ) # this comment will show up in the traceback raise loop_err from cb_err # emit() call ABOVE || callback error BELOW + finally: + if self._recursion_depth > 0: + self._recursion_depth -= 1 def __call__( self, *args: Any, check_nargs: bool = False, check_types: bool = False @@ -1246,6 +1263,9 @@ def __call__( return self.emit(*args, check_nargs=check_nargs, check_types=check_types) def _run_emit_loop(self, args: tuple[Any, ...]) -> None: + if self._recursion_depth >= RECURSION_LIMIT: + raise RecursionError("Recursion limit reached!") + with self._lock: self._emit_queue.append(args) if len(self._emit_queue) > 1: diff --git a/tests/test_psygnal.py b/tests/test_psygnal.py index 5447a6df..7b5b26d7 100644 --- a/tests/test_psygnal.py +++ b/tests/test_psygnal.py @@ -163,9 +163,6 @@ def boom(v: int) -> None: emitter.one_int.emit_fast(42) -@pytest.mark.skipif( - bool(os.name == "nt" and COMPILED), reason="Windows segfaulting during cibuildwheel" -) def test_emit_fast_recursion_errors(): """Test emit_fast method.""" emitter = Emitter() From 1905149d31e25f93c5e6e516bb7ac9bb9a24fbba Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 27 Jan 2025 14:33:41 -0500 Subject: [PATCH 06/13] move around dev extra --- pyproject.toml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e5d990e1..36c56e47 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,17 +32,6 @@ dependencies = [ # extras # https://peps.python.org/pep-0621/#dependencies-optional-dependencies [project.optional-dependencies] -dev = [ - "ipython", - "mypy", - "mypy_extensions", - "pre-commit", - "PyQt5", - "pytest-mypy-plugins", - "rich", - "ruff", - "typing-extensions", -] docs = [ "griffe==0.25.5", "mkdocs-material==8.5.10", @@ -55,19 +44,32 @@ docs = [ proxy = ["wrapt"] pydantic = ["pydantic"] test = [ - "dask", + "dask[array]>=2024.0.0", "attrs", - "numpy", + "numpy >1.21.6", "pydantic", "pyinstaller>=4.0", "pytest>=6.0", "pytest-cov", "wrapt", - "msgspec; python_version < '3.13'", + "msgspec", "toolz", ] testqt = ["pytest-qt", "qtpy"] +dev = [ + "psygnal[test, testqt]", + "PyQt6", + "ipython", + "mypy", + "mypy_extensions", + "pre-commit", + "pytest-mypy-plugins", + "rich", + "ruff", + "typing-extensions", +] + [project.urls] homepage = "https://github.com/pyapp-kit/psygnal" repository = "https://github.com/pyapp-kit/psygnal" From fc4e1516f0149ae74273ecf60e107b177a970615 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 19:33:56 +0000 Subject: [PATCH 07/13] style(pre-commit.ci): auto fixes [...] --- src/psygnal/_signal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/psygnal/_signal.py b/src/psygnal/_signal.py index 3ebcb847..86573def 100644 --- a/src/psygnal/_signal.py +++ b/src/psygnal/_signal.py @@ -128,7 +128,6 @@ def ensure_at_least_20(val: int): from __future__ import annotations import inspect -import sys import threading import warnings import weakref From 03baf85dee7b849cf64e94b0baefbcc36b94df9b Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 1 Feb 2025 13:34:15 -0500 Subject: [PATCH 08/13] 2-step --- .github/workflows/pypi.yml | 76 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index eafdb67e..0312e97a 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -13,64 +13,66 @@ jobs: # hatch-build-hooks-enable: true # coverage-upload: none - deploy-sdist: - # needs: test - # if: success() && startsWith(github.ref, 'refs/tags/v') + build-sdist: + name: 🐍 sdist runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - - uses: actions/setup-python@v5 + - uses: hynek/build-and-inspect-python-package@v2 with: - python-version: "3.x" - - - name: 👷 Build - run: | - python -m pip install build - python -m build - - # - name: 🚢 Publish to PyPI - # uses: pypa/gh-action-pypi-publish@release/v1 + skip-wheel: true - # - uses: softprops/action-gh-release@v2 - # with: - # generate_release_notes: true - # files: "./dist/*" - - deploy-wheel: - # if: startsWith(github.event.ref, 'refs/tags/v') - # needs: deploy-sdist + build-wheels: name: mypyc wheels (${{ matrix.os }}) runs-on: ${{ matrix.os }} - permissions: - id-token: write - contents: write strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-13, macos-latest] - steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Build wheels via cibuildwheel - uses: pypa/cibuildwheel@v2.22.0 + uses: pypa/cibuildwheel@v2.22 + - name: Upload wheels artifacts + uses: actions/upload-artifact@v4 with: - output-dir: dist + name: cibw-wheels-${{ runner.os }}-${{ runner.arch }} + path: ./wheelhouse/*.whl - - name: Upload wheels as workflow artifacts - uses: actions/upload-artifact@v4 + publish: + name: Publish to PyPI + needs: [test, build-sdist, build-wheels] + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Get sdist + uses: actions/download-artifact@v4 + with: + name: Packages + path: dist + - name: Get wheels + uses: actions/download-artifact@v4 with: - name: ${{ runner.os }}-${{ runner.arch }}-mypyc-wheels - path: ./dist/*.whl + pattern: cibw-wheels-* + path: dist + merge-multiple: true + + - run: | + python -m pip install --upgrade pip + python -m pip install --upgrade twine + ls -l dist # - name: 🚢 Publish to PyPI # uses: pypa/gh-action-pypi-publish@release/v1 + + # - uses: softprops/action-gh-release@v2 + # with: + # generate_release_notes: true + # files: "./dist/*" From b18b67468b02757b4b1cf1340f80f22a5af7be80 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 1 Feb 2025 13:36:18 -0500 Subject: [PATCH 09/13] fix workflow --- .github/workflows/pypi.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 0312e97a..004ae948 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -7,11 +7,11 @@ on: pull_request: jobs: - # test: - # uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2 - # with: - # hatch-build-hooks-enable: true - # coverage-upload: none + test: + uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2 + with: + hatch-build-hooks-enable: true + coverage-upload: none build-sdist: name: 🐍 sdist From 1e52fb724d4fe2e89f76e68db06a96232c539079 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 1 Feb 2025 16:52:35 -0500 Subject: [PATCH 10/13] run last step --- .github/workflows/pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 004ae948..dc59cdbf 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -46,7 +46,7 @@ jobs: publish: name: Publish to PyPI needs: [test, build-sdist, build-wheels] - if: startsWith(github.ref, 'refs/tags/v') + # if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: contents: read From 5789edb0ac4a35d19506e6888ba309d2710a5cdc Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sat, 1 Feb 2025 16:53:20 -0500 Subject: [PATCH 11/13] remove unused --- pyproject.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 36c56e47..af1e28e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,10 +120,6 @@ test-extras = ["test"] test-command = "pytest {project}/tests -v" test-skip = ["*-musllinux*", "cp312-win*", "*-macosx_arm64"] -[tool.cibuildwheel.macos] -# https://cibuildwheel.readthedocs.io/en/stable/faq/#apple-silicon -archs = ["x86_64", "arm64"] - [[tool.cibuildwheel.overrides]] select = "*-manylinux_i686*" before-all = "yum install -y python3-devel" @@ -131,7 +127,6 @@ before-all = "yum install -y python3-devel" [tool.cibuildwheel.environment] HATCH_BUILD_HOOKS_ENABLE = "1" - # https://docs.astral.sh/ruff/ [tool.ruff] line-length = 88 @@ -152,7 +147,7 @@ select = [ "C4", # flake8-comprehensions "B", # flake8-bugbear "A001", # flake8-builtins - "TCH", # flake8-typecheck + "TC", # flake8-typecheck "TID", # flake8-tidy-imports "RUF", # ruff-specific rules ] From e4cc8f2a6639c6646db786e1d1cd6b8c1b233d06 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 2 Feb 2025 16:23:46 -0500 Subject: [PATCH 12/13] remove testing --- .github/workflows/pypi.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index dc59cdbf..e83bf280 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -4,7 +4,6 @@ on: push: branches: [main] tags: [v*] - pull_request: jobs: test: @@ -69,10 +68,10 @@ jobs: python -m pip install --upgrade twine ls -l dist - # - name: 🚢 Publish to PyPI - # uses: pypa/gh-action-pypi-publish@release/v1 + - name: 🚢 Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 - # - uses: softprops/action-gh-release@v2 - # with: - # generate_release_notes: true - # files: "./dist/*" + - uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: "./dist/*" From 9431fba88e9568847bab73ddf84d02b4e8919887 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Mon, 3 Feb 2025 08:49:37 -0500 Subject: [PATCH 13/13] final --- .github/workflows/pypi.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index e83bf280..77ac64ed 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -45,7 +45,7 @@ jobs: publish: name: Publish to PyPI needs: [test, build-sdist, build-wheels] - # if: startsWith(github.ref, 'refs/tags/v') + if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest permissions: contents: read @@ -63,11 +63,6 @@ jobs: path: dist merge-multiple: true - - run: | - python -m pip install --upgrade pip - python -m pip install --upgrade twine - ls -l dist - - name: 🚢 Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1