mirror of
https://github.com/pyapp-kit/superqt.git
synced 2025-12-16 11:10:06 +01:00
build: support uv-based workflows, use on CI (#301)
* ci: [pre-commit.ci] autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.12 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.12...v0.12.2) - [github.com/pre-commit/mirrors-mypy: v1.16.0 → v1.16.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.16.0...v1.16.1) * style: [pre-commit.ci] auto fixes [...] * pin pytestqt * refactor: setup for uv * fix workflow * update deploy too * pin pyside2 to numpy 2 * try uv-managed * bump min qtpy * change authors * change pyside2 * change pyside2 spec * update pyside2 * more pins * update numpy version constraints for pyside2 and test dependencies * pin pytest-qt for napari --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
183
.github/workflows/test_and_deploy.yml
vendored
183
.github/workflows/test_and_deploy.yml
vendored
@@ -15,75 +15,93 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: ${{ matrix.os }} (${{ matrix.python-version }}) ${{ matrix.add-extra || '' }} ${{ matrix.resolution || ''}}
|
||||||
uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2
|
runs-on: ${{ matrix.os }}
|
||||||
with:
|
env:
|
||||||
os: ${{ matrix.platform }}
|
UV_PRERELEASE: ${{ github.event_name == 'schedule' && 'allow' || 'if-necessary-or-explicit' }}
|
||||||
python-version: ${{ matrix.python-version }}
|
UV_NO_SYNC: 1
|
||||||
qt: ${{ matrix.backend }}
|
UV_MANAGED_PYTHON: 1
|
||||||
pip-install-pre-release: ${{ github.event_name == 'schedule' }}
|
|
||||||
coverage-upload: artifact
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [ubuntu-latest, windows-latest, macos-13]
|
python-version: ["3.9", "3.13"]
|
||||||
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
backend: [pyqt5, pyside2, pyqt6]
|
add-extra: [pyqt6, pyside6]
|
||||||
exclude:
|
|
||||||
# Abort (core dumped) on linux pyqt6, unknown reason
|
|
||||||
- platform: ubuntu-latest
|
|
||||||
backend: pyqt6
|
|
||||||
# lack of wheels for pyside2/py3.11
|
|
||||||
- python-version: "3.11"
|
|
||||||
backend: pyside2
|
|
||||||
- python-version: "3.12"
|
|
||||||
backend: pyside2
|
|
||||||
- python-version: "3.12"
|
|
||||||
backend: pyqt5
|
|
||||||
include:
|
include:
|
||||||
- python-version: "3.13"
|
- os: windows-latest
|
||||||
platform: windows-latest
|
python-version: "3.11"
|
||||||
backend: "pyqt6"
|
resolution: "lowest-direct"
|
||||||
- python-version: "3.13"
|
add-extra: pyside6
|
||||||
platform: ubuntu-latest
|
- os: macos-latest
|
||||||
backend: "pyqt6"
|
python-version: "3.12"
|
||||||
|
resolution: "lowest-direct"
|
||||||
- python-version: "3.10"
|
add-extra: pyqt6
|
||||||
platform: macos-latest
|
- python-version: "3.9"
|
||||||
backend: "'pyside6<6.8'"
|
os: ubuntu-latest
|
||||||
|
add-extra: pyqt5
|
||||||
|
- python-version: "3.9"
|
||||||
|
os: ubuntu-latest
|
||||||
|
add-extra: pyside2
|
||||||
- python-version: "3.11"
|
- python-version: "3.11"
|
||||||
platform: macos-latest
|
os: windows-latest
|
||||||
backend: "'pyside6<6.8'"
|
add-extra: pyqt5
|
||||||
- python-version: "3.10"
|
- python-version: "3.10"
|
||||||
platform: windows-latest
|
os: ubuntu-latest
|
||||||
backend: "'pyside6<6.8'"
|
add-extra: pyside2
|
||||||
- python-version: "3.12"
|
- python-version: "3.12"
|
||||||
platform: windows-latest
|
os: ubuntu-latest
|
||||||
backend: "'pyside6<6.8'"
|
add-extra: pyqt6
|
||||||
|
- python-version: "3.12"
|
||||||
|
os: ubuntu-latest
|
||||||
|
add-extra: pyside6
|
||||||
|
|
||||||
# legacy Qt
|
steps:
|
||||||
- python-version: 3.9
|
- uses: actions/checkout@v4
|
||||||
platform: ubuntu-latest
|
with:
|
||||||
backend: "pyqt5==5.12.*"
|
fetch-depth: 0
|
||||||
- python-version: 3.9
|
fetch-tags: true
|
||||||
platform: ubuntu-latest
|
|
||||||
backend: "pyqt5==5.13.*"
|
|
||||||
- python-version: 3.9
|
|
||||||
platform: ubuntu-latest
|
|
||||||
backend: "pyqt5==5.14.*"
|
|
||||||
|
|
||||||
test-qt-minreqs:
|
- name: 🐍 Set up Python ${{ matrix.python-version }}
|
||||||
uses: pyapp-kit/workflows/.github/workflows/test-pyrepo.yml@v2
|
uses: astral-sh/setup-uv@v6
|
||||||
with:
|
with:
|
||||||
python-version: "3.9"
|
python-version: ${{ matrix.python-version }}
|
||||||
qt: pyqt5
|
enable-cache: true
|
||||||
pip-post-installs: "qtpy==1.1.0 typing-extensions==4.5.0" # 4.5.0 is just for pint
|
cache-dependency-glob: "**/pyproject.toml"
|
||||||
pip-install-flags: -e
|
|
||||||
coverage-upload: artifact
|
- uses: pyvista/setup-headless-display-action@v4
|
||||||
|
with:
|
||||||
|
qt: true
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: uv sync --no-dev --group test --extra ${{ matrix.add-extra }} --resolution ${{ matrix.resolution || 'highest'}}
|
||||||
|
|
||||||
|
- name: 🧪 Run Tests
|
||||||
|
run: uv run coverage run -p -m pytest -v
|
||||||
|
|
||||||
|
# If something goes wrong with --pre tests, we can open an issue in the repo
|
||||||
|
- name: 📝 Report --pre Failures
|
||||||
|
if: failure() && github.event_name == 'schedule'
|
||||||
|
uses: JasonEtco/create-an-issue@v2
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PLATFORM: ${{ matrix.os }}
|
||||||
|
PYTHON: ${{ matrix.python-version }}
|
||||||
|
RUN_ID: ${{ github.run_id }}
|
||||||
|
TITLE: "[test-bot] pip install --pre is failing"
|
||||||
|
with:
|
||||||
|
filename: .github/TEST_FAIL_TEMPLATE.md
|
||||||
|
update_existing: true
|
||||||
|
|
||||||
|
- name: Upload coverage
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: covreport-${{ matrix.os }}-py${{ matrix.python-version }}-${{ matrix.add-extra }}-${{ matrix.resolution }}
|
||||||
|
path: ./.coverage*
|
||||||
|
include-hidden-files: true
|
||||||
|
|
||||||
upload_coverage:
|
upload_coverage:
|
||||||
if: always()
|
if: always()
|
||||||
needs: [test, test-qt-minreqs]
|
needs: [test]
|
||||||
uses: pyapp-kit/workflows/.github/workflows/upload-coverage.yml@v2
|
uses: pyapp-kit/workflows/.github/workflows/upload-coverage.yml@v2
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
@@ -91,17 +109,16 @@ jobs:
|
|||||||
uses: pyapp-kit/workflows/.github/workflows/test-dependents.yml@v2
|
uses: pyapp-kit/workflows/.github/workflows/test-dependents.yml@v2
|
||||||
with:
|
with:
|
||||||
dependency-repo: napari/napari
|
dependency-repo: napari/napari
|
||||||
dependency-ref: ${{ matrix.napari-version }}
|
|
||||||
dependency-extras: "testing"
|
dependency-extras: "testing"
|
||||||
qt: ${{ matrix.qt }}
|
qt: ${{ matrix.qt }}
|
||||||
pytest-args: 'src/napari/_qt --import-mode=importlib -k "not async and not qt_dims_2 and not qt_viewer_console_focus and not keybinding_editor and not preferences_dialog_not_dismissed"'
|
pytest-args: 'src/napari/_qt --import-mode=importlib -k "not async and not qt_dims_2 and not qt_viewer_console_focus and not keybinding_editor and not preferences_dialog_not_dismissed"'
|
||||||
python-version: "3.10"
|
python-version: "3.10"
|
||||||
post-install-cmd: "pip install lxml_html_clean"
|
# napari hasn't pinned pytest-qt, but still requires pyside2 tests
|
||||||
|
post-install-cmd: "pip install lxml_html_clean pytest-qt==4.4.0"
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
napari-version: [ "" ]
|
qt: ["pyqt5", "pyside2"]
|
||||||
qt: [ "pyqt5", "pyside2" ]
|
|
||||||
|
|
||||||
check-manifest:
|
check-manifest:
|
||||||
name: Check Manifest
|
name: Check Manifest
|
||||||
@@ -110,35 +127,33 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: pipx run check-manifest
|
- run: pipx run check-manifest
|
||||||
|
|
||||||
deploy:
|
build-and-inspect-package:
|
||||||
# this will run when you have tagged a commit, starting with "v*"
|
name: Build & inspect package.
|
||||||
# and requires that you have put your twine API key in your
|
needs: test
|
||||||
# github secrets (see readme for details)
|
|
||||||
needs: [test, check-manifest]
|
|
||||||
if: ${{ github.repository == 'pyapp-kit/superqt' && contains(github.ref, 'tags') }}
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up Python
|
- uses: hynek/build-and-inspect-python-package@v2
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.x"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install build twine
|
|
||||||
- name: Build and publish
|
|
||||||
env:
|
|
||||||
TWINE_USERNAME: __token__
|
|
||||||
TWINE_PASSWORD: ${{ secrets.TWINE_API_KEY }}
|
|
||||||
run: |
|
|
||||||
git tag
|
|
||||||
python -m build
|
|
||||||
twine check dist/*
|
|
||||||
twine upload dist/*
|
|
||||||
|
|
||||||
|
upload-to-pypi:
|
||||||
|
if: success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' && github.repository == 'pyapp-kit/superqt'
|
||||||
|
name: Upload package to PyPI
|
||||||
|
needs: build-and-inspect-package
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Download built artifact to dist/
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Packages
|
||||||
|
path: dist
|
||||||
|
- name: 🚢 Publish to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
- uses: softprops/action-gh-release@v2
|
- uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
|
files: "./dist/*"
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -82,3 +82,4 @@ screenshots
|
|||||||
|
|
||||||
.mypy_cache
|
.mypy_cache
|
||||||
docs/_auto_images/
|
docs/_auto_images/
|
||||||
|
uv.lock
|
||||||
|
|||||||
136
pyproject.toml
136
pyproject.toml
@@ -3,6 +3,12 @@
|
|||||||
requires = ["hatchling", "hatch-vcs"]
|
requires = ["hatchling", "hatch-vcs"]
|
||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
source = "vcs"
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.sdist]
|
||||||
|
include = ["src", "tests", "CHANGELOG.md"]
|
||||||
|
|
||||||
# https://peps.python.org/pep-0621/
|
# https://peps.python.org/pep-0621/
|
||||||
[project]
|
[project]
|
||||||
name = "superqt"
|
name = "superqt"
|
||||||
@@ -10,7 +16,7 @@ description = "Missing widgets and components for PyQt/PySide"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
license = { text = "BSD 3-Clause License" }
|
license = { text = "BSD 3-Clause License" }
|
||||||
authors = [{ email = "talley.lambert@gmail.com", name = "Talley Lambert" }]
|
authors = [{ name = "superqt community" }]
|
||||||
keywords = [
|
keywords = [
|
||||||
"qt",
|
"qt",
|
||||||
"pyqt",
|
"pyqt",
|
||||||
@@ -40,32 +46,64 @@ classifiers = [
|
|||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pygments>=2.4.0",
|
"pygments>=2.4.0",
|
||||||
"qtpy>=1.1.0",
|
"qtpy>=2.4.0",
|
||||||
"typing-extensions >=3.7.4.3,!=3.10.0.0", # however, pint requires >4.5.0
|
"typing-extensions >=4.5.0",
|
||||||
|
"typing-extensions >=4.12.0; python_version >= '3.13'",
|
||||||
]
|
]
|
||||||
|
|
||||||
# extras
|
|
||||||
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
cmap = ["cmap >=0.2"]
|
||||||
|
font-fa5 = ["fonticon-fontawesome5>=5.15.4"]
|
||||||
|
font-fa6 = ["fonticon-fontawesome6>=6.4.0"]
|
||||||
|
font-mi6 = ["fonticon-materialdesignicons6>=6.9.96"]
|
||||||
|
font-mi7 = ["fonticon-materialdesignicons7>=7.2.96"]
|
||||||
|
iconify = ["pyconify >=0.1.4"]
|
||||||
|
pyqt5 = [
|
||||||
|
"PyQt5>=5.15.10",
|
||||||
|
"pyqt5-qt5>=5.15.16; sys_platform != 'win32'",
|
||||||
|
"pyqt5-qt5==5.15.2; sys_platform == 'win32'",
|
||||||
|
]
|
||||||
|
pyqt6 = [ # 6.6 has segfaults with QElidingLabel
|
||||||
|
"pyqt6>=6.4.0,!=6.6",
|
||||||
|
"pyqt6>=6.7.0,!=6.6; python_version >= '3.12'",
|
||||||
|
]
|
||||||
|
pyside2 = [
|
||||||
|
"pyside2>=5.15",
|
||||||
|
"numpy>=1.19,<2; python_version < '3.11'",
|
||||||
|
"numpy>=1.26,<2; python_version >= '3.11' and python_version < '3.13'",
|
||||||
|
]
|
||||||
|
# see issues surrounding usage of Generics in pyside6.5.x
|
||||||
|
# https://github.com/pyapp-kit/superqt/pull/177
|
||||||
|
# https://github.com/pyapp-kit/superqt/pull/164
|
||||||
|
# https://bugreports.qt.io/browse/PYSIDE-2627
|
||||||
|
pyside6 = [
|
||||||
|
"pyside6>=6.4.0,!=6.5.0,!=6.5.1,!=6.6.2",
|
||||||
|
"pyside6>=6.7.0; python_version >= '3.12'",
|
||||||
|
]
|
||||||
|
quantity = ["pint>=0.21"]
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
test = [
|
test = [
|
||||||
"pint",
|
"cmap>=0.6.2",
|
||||||
"pytest",
|
"numpy>=1.19; python_version < '3.11'",
|
||||||
"pytest-cov",
|
"numpy>=1.26; python_version >= '3.11' and python_version < '3.13'",
|
||||||
"pytest-qt==4.4.0",
|
"numpy>=2.1; python_version >= '3.13'",
|
||||||
"numpy",
|
"pint>=0.24.4",
|
||||||
"cmap",
|
"pyconify>=0.2.1",
|
||||||
"pyconify",
|
"pytest>=8.4.1",
|
||||||
|
"pytest-cov>=6.2.1",
|
||||||
|
"pytest-qt==4.4.0", # for pyside2 support
|
||||||
]
|
]
|
||||||
dev = [
|
dev = [
|
||||||
"ipython",
|
{ include-group = "test" },
|
||||||
"ruff",
|
"ipython>=8.18.1",
|
||||||
"mypy",
|
"mypy>=1.17.0",
|
||||||
"pdbpp",
|
"pre-commit-uv>=4.1.4",
|
||||||
"pre-commit",
|
"pdbpp>=0.11.6; sys_platform != 'win32'",
|
||||||
"pydocstyle",
|
"pydocstyle>=6.3.0",
|
||||||
"rich",
|
"rich>=14.0.0",
|
||||||
"types-Pygments",
|
"ruff>=0.12.3",
|
||||||
"superqt[test,pyqt6]",
|
"types-pygments>=2.19.0.20250715",
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
"mkdocs-macros-plugin ==1.3.7",
|
"mkdocs-macros-plugin ==1.3.7",
|
||||||
@@ -74,21 +112,7 @@ docs = [
|
|||||||
"mkdocstrings-python ==1.13.0",
|
"mkdocstrings-python ==1.13.0",
|
||||||
"superqt[font-fa5, cmap, quantity]",
|
"superqt[font-fa5, cmap, quantity]",
|
||||||
]
|
]
|
||||||
quantity = ["pint"]
|
|
||||||
cmap = ["cmap >=0.1.1"]
|
|
||||||
pyside2 = ["pyside2"]
|
|
||||||
# see issues surrounding usage of Generics in pyside6.5.x
|
|
||||||
# https://github.com/pyapp-kit/superqt/pull/177
|
|
||||||
# https://github.com/pyapp-kit/superqt/pull/164
|
|
||||||
# https://bugreports.qt.io/browse/PYSIDE-2627
|
|
||||||
pyside6 = ["pyside6 !=6.5.0,!=6.5.1,!=6.6.2,<6.8"]
|
|
||||||
pyqt5 = ["pyqt5"]
|
|
||||||
pyqt6 = ["pyqt6<6.7"]
|
|
||||||
font-fa5 = ["fonticon-fontawesome5"]
|
|
||||||
font-fa6 = ["fonticon-fontawesome6"]
|
|
||||||
font-mi6 = ["fonticon-materialdesignicons6"]
|
|
||||||
font-mi7 = ["fonticon-materialdesignicons7"]
|
|
||||||
iconify = ["pyconify >=0.1.4"]
|
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Documentation = "https://pyapp-kit.github.io/superqt/"
|
Documentation = "https://pyapp-kit.github.io/superqt/"
|
||||||
@@ -96,45 +120,9 @@ Source = "https://github.com/pyapp-kit/superqt"
|
|||||||
Tracker = "https://github.com/pyapp-kit/superqt/issues"
|
Tracker = "https://github.com/pyapp-kit/superqt/issues"
|
||||||
Changelog = "https://github.com/pyapp-kit/superqt/blob/main/CHANGELOG.md"
|
Changelog = "https://github.com/pyapp-kit/superqt/blob/main/CHANGELOG.md"
|
||||||
|
|
||||||
[tool.hatch.version]
|
[tool.uv.sources]
|
||||||
source = "vcs"
|
superqt = { workspace = true }
|
||||||
|
|
||||||
[tool.hatch.build.targets.sdist]
|
|
||||||
include = ["src", "tests", "CHANGELOG.md"]
|
|
||||||
|
|
||||||
# these let you run tests across all backends easily with:
|
|
||||||
# hatch run test:test
|
|
||||||
[tool.hatch.envs.test]
|
|
||||||
|
|
||||||
[tool.hatch.envs.test.scripts]
|
|
||||||
test = "pytest"
|
|
||||||
|
|
||||||
[[tool.hatch.envs.test.matrix]]
|
|
||||||
qt = ["pyside6", "pyqt6"]
|
|
||||||
python = ["3.11"]
|
|
||||||
|
|
||||||
[[tool.hatch.envs.test.matrix]]
|
|
||||||
qt = ["pyside2", "pyqt5", "pyqt5.12"]
|
|
||||||
python = ["3.9"]
|
|
||||||
|
|
||||||
[tool.hatch.envs.test.overrides]
|
|
||||||
matrix.qt.extra-dependencies = [
|
|
||||||
{ value = "pyside2", if = [
|
|
||||||
"pyside2",
|
|
||||||
] },
|
|
||||||
{ value = "pyside6", if = [
|
|
||||||
"pyside6",
|
|
||||||
] },
|
|
||||||
{ value = "pyqt5", if = [
|
|
||||||
"pyqt5",
|
|
||||||
] },
|
|
||||||
{ value = "pyqt6", if = [
|
|
||||||
"pyqt6",
|
|
||||||
] },
|
|
||||||
{ value = "pyqt5==5.12", if = [
|
|
||||||
"pyqt5.12",
|
|
||||||
] },
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
|
|||||||
Reference in New Issue
Block a user