Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: drop support for python 3.8, test 3.12 #368

Merged
merged 15 commits into from
Oct 12, 2024
28 changes: 12 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,25 @@ jobs:
fail-fast: false
matrix:
platform: [macos-13, windows-latest]
python-version: ["3.8", "3.11"]
backend: [pyside2, pyqt5]
include:
- platform: macos-13
python-version: "3.10"
backend: pyside6
- platform: macos-13
python-version: "3.11"
backend: pyqt6
python-version: ["3.10", "3.12"]
backend: [pyside6, pyqt6]
exclude:
- platform: windows-latest
python-version: "3.10"
backend: pyside6
- platform: windows-latest
python-version: "3.11"
backend: pyqt6
- platform: windows-latest
include:
- platform: macos-13
python-version: "3.9"
backend: pyside2
- platform: windows-latest
python-version: "3.9"
backend: pyqt5
exclude:
- python-version: "3.11"
backend: pyside2
- platform: windows-latest
python-version: "3.11"
backend: pyqt5
# - platform: windows-latest
# python-version: "3.13"
# backend: pyqt6

steps:
- uses: actions/checkout@v4
Expand All @@ -63,6 +58,7 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true

- name: Install dependencies
run: |
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ name: --pre Test

on:
schedule:
- cron: '0 */12 * * *' # every 12 hours
- cron: "0 */12 * * *" # every 12 hours
workflow_dispatch:

jobs:

test:
name: ${{ matrix.platform }} (${{ matrix.python-version }})
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10']
python-version: ["3.11"]
platform: [macos-13, windows-latest]
backend: [pyside2, pyqt5]

Expand Down Expand Up @@ -55,7 +54,7 @@ jobs:
PLATFORM: ${{ matrix.platform }}
PYTHON: ${{ matrix.python }}
RUN_ID: ${{ github.run_id }}
TITLE: '[test-bot] pip install --pre is failing'
TITLE: "[test-bot] pip install --pre is failing"
with:
filename: .github/TEST_FAIL_TEMPLATE.md
update_existing: true
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ It forms the basis of [`napari-micromanager`](https://github.com/pymmcore-plus/n

See complete list of available widgets in the [documentation](https://pymmcore-plus.github.io/pymmcore-widgets/#widgets)


## Installation

```sh
Expand All @@ -28,5 +27,5 @@ pip install pymmcore-widgets
# you must install one yourself, for example:
pip install PyQt5

# package is tested against PyQt5, PyQt6, PySide2, and PySide6
# package is tested against PyQt5, PyQt6, PySide2, and PySide6(==6.7)
```
20 changes: 15 additions & 5 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@ pip install pymmcore-widgets

### Installing PyQt or PySide

Since [pymmcore-widgets](./index.md) relies on either the [PyQt](https://riverbankcomputing.com/software/pyqt/) or [PySide](https://www.qt.io/qt-for-python) libraries, you also **need** to install one of these packages. You can use any of the available versions of these libraries: [PyQt5](https://pypi.org/project/PyQt5/), [PyQt6](https://pypi.org/project/PyQt6/), [PySide2](https://pypi.org/project/PySide2/) or [PySide6](https://pypi.org/project/PySide6/). For example, to install [PyQt6](https://riverbankcomputing.com/software/pyqt/download), you can use:
Since [pymmcore-widgets](./index.md) relies on either the
[PyQt](https://riverbankcomputing.com/software/pyqt/) or
[PySide](https://www.qt.io/qt-for-python) libraries, you also **need** to
install one of these packages. You can use any of the available versions of
these libraries: [PyQt5](https://pypi.org/project/PyQt5/),
[PyQt6](https://pypi.org/project/PyQt6/),
[PySide2](https://pypi.org/project/PySide2/) or
[PySide6](https://pypi.org/project/PySide6/). We strongly recommend using PyQt6
if possible. If you must use a specific backend version and run into problems,
please open an issue

For example, to install [PyQt6](https://riverbankcomputing.com/software/pyqt/download), you can use:

```sh
pip install PyQt6
Expand All @@ -21,10 +32,9 @@ pip install PyQt6
!!! Note
Widgets are tested on:

* `macOS & Windows`
* `Python 3.8, 3.9 3.10 & 3.11`
* `PyQt5 & PyQt6`
* `PySide2 & PySide6`
* macOS & Windows
* Python 3.9 and above
* PyQt5, PyQt6, PySide2 & PySide6(==6.7)

### Installing Micro-Manager

Expand Down
23 changes: 16 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ sources = ["src"]
name = "pymmcore-widgets"
description = "A set of Qt-based widgets onto the pymmcore-plus model"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = { text = "BSD 3-Clause License" }
authors = [
{ email = "[email protected]", name = "Federico Gasparoli" },
Expand All @@ -34,10 +34,11 @@ classifiers = [
"Intended Audience :: Science/Research",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python",
"Topic :: Software Development :: Widget Sets",
"Topic :: System :: Hardware :: Hardware Drivers",
Expand All @@ -60,11 +61,19 @@ allow-direct-references = true
# extras
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
[project.optional-dependencies]
test = ["pytest>=6.0", "pytest-cov", "pytest-qt", "PyYAML", "vispy", "cmap", "zarr"]
test = [
"pytest>=6.0",
"pytest-cov",
"pytest-qt",
"PyYAML",
"vispy",
"cmap",
"zarr",
]
pyqt5 = ["PyQt5"]
pyside2 = ["PySide2"]
pyqt6 = ["PyQt6"]
pyside6 = ["PySide6<6.5"]
pyside6 = ["PySide6==6.7.3"] # pretty hard to find a good match here...
image = ["vispy"]

dev = [
Expand Down Expand Up @@ -97,8 +106,9 @@ Documentation = "https://pymmcore-plus.github.io/pymmcore-widgets"
# https://beta.ruff.rs/docs/rules/
[tool.ruff]
line-length = 88
target-version = "py38"
target-version = "py39"
src = ["src", "tests"]

[tool.ruff.lint]
pydocstyle = { convention = "numpy" }
select = [
Expand All @@ -115,7 +125,6 @@ select = [
"RUF", # ruff-specific rules
"TID", # tidy
"TCH", # typecheck
# "SLF", # private-access
]
ignore = [
"D100", # Missing docstring in public module
Expand All @@ -135,6 +144,7 @@ testpaths = ["tests"]
filterwarnings = [
"error",
"ignore:distutils Version classes are deprecated",
"ignore:Failed to disconnect:RuntimeWarning:",
# warning, but not error, that will show up on useq<0.3.3
]

Expand Down Expand Up @@ -178,4 +188,3 @@ ignore = [

[tool.typos.default]
extend-ignore-identifiers-re = ["(?i)nd2?.*", "(?i)ome", "FO(Vs?)?"]

8 changes: 6 additions & 2 deletions src/pymmcore_widgets/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re
from pathlib import Path
from typing import Any, ContextManager, Sequence
from typing import TYPE_CHECKING, Any

import useq
from psygnal import SignalInstance
Expand All @@ -21,6 +21,10 @@
)
from superqt.utils import signals_blocked

if TYPE_CHECKING:
from collections.abc import Sequence
from contextlib import AbstractContextManager


class ComboMessageBox(QDialog):
"""Dialog that presents a combo box of `items`."""
Expand Down Expand Up @@ -91,7 +95,7 @@ def guess_objective_or_prompt(
return None


def block_core(obj: Any) -> ContextManager:
def block_core(obj: Any) -> AbstractContextManager:
"""Block core signals."""
if isinstance(obj, QObject):
return signals_blocked(obj) # type: ignore [no-any-return]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import annotations

from typing import Any, Sequence, cast
from typing import TYPE_CHECKING, Any, cast

from qtpy.QtCore import Qt
from qtpy.QtWidgets import QTableWidget, QTableWidgetItem

from pymmcore_widgets.device_properties._property_widget import PropertyWidget

if TYPE_CHECKING:
from collections.abc import Sequence

DEV_PROP_ROLE = Qt.ItemDataRole.UserRole + 1


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import itertools
import warnings
from collections import Counter
from typing import Any, Sequence, cast
from typing import TYPE_CHECKING, Any, cast

from pymmcore_plus import CMMCorePlus, DeviceProperty
from pymmcore_plus.model import PixelSizeGroup, PixelSizePreset, Setting
Expand Down Expand Up @@ -35,6 +35,9 @@
from pymmcore_widgets.useq_widgets import DataTable, DataTableWidget
from pymmcore_widgets.useq_widgets._column_info import FloatColumn, TextColumn

if TYPE_CHECKING:
from collections.abc import Sequence

FIXED = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
PX = "px"
ID = "id"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from logging import getLogger
from typing import Iterable, cast
from typing import TYPE_CHECKING, cast

from pymmcore_plus import CMMCorePlus, DeviceProperty, DeviceType
from qtpy.QtCore import Qt
Expand All @@ -13,6 +13,9 @@

from ._property_widget import PropertyWidget

if TYPE_CHECKING:
from collections.abc import Iterable

logger = getLogger(__name__)


Expand Down
3 changes: 2 additions & 1 deletion src/pymmcore_widgets/device_properties/_properties_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Iterable, cast
from typing import TYPE_CHECKING, cast

from pymmcore_plus import CMMCorePlus
from qtpy.QtWidgets import QGridLayout, QLabel, QWidget
Expand All @@ -14,6 +14,7 @@

if TYPE_CHECKING:
import re
from collections.abc import Iterable


class PropertiesWidget(QWidget):
Expand Down
5 changes: 4 additions & 1 deletion src/pymmcore_widgets/hcs/_plate_calibration_widget.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from contextlib import suppress
from typing import Mapping
from typing import TYPE_CHECKING

import numpy as np
import useq
Expand All @@ -28,6 +28,9 @@
)
from pymmcore_widgets.useq_widgets._well_plate_widget import WellPlateView

if TYPE_CHECKING:
from collections.abc import Mapping


class PlateCalibrationWidget(QWidget):
"""Widget to calibrate a well plate.
Expand Down
5 changes: 4 additions & 1 deletion src/pymmcore_widgets/hcs/_util.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from __future__ import annotations

from typing import Iterable
from typing import TYPE_CHECKING

import numpy as np

if TYPE_CHECKING:
from collections.abc import Iterable


def find_circle_center(
coords: Iterable[tuple[float, float]],
Expand Down
5 changes: 4 additions & 1 deletion src/pymmcore_widgets/hcs/_well_calibration_widget.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from pathlib import Path
from typing import Iterator, NamedTuple, cast
from typing import TYPE_CHECKING, NamedTuple, cast

from fonticon_mdi6 import MDI6
from pymmcore_plus import CMMCorePlus
Expand All @@ -23,6 +23,9 @@

from ._util import find_circle_center, find_rectangle_center

if TYPE_CHECKING:
from collections.abc import Iterator

COMBO_ROLE = Qt.ItemDataRole.UserRole + 1
ICON_PATH = Path(__file__).parent / "icons"
ONE_CIRCLE = QIcon(str(ICON_PATH / "circle-center.svg"))
Expand Down
4 changes: 3 additions & 1 deletion src/pymmcore_widgets/hcwizard/_dev_setup_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

import logging
from contextlib import suppress
from typing import TYPE_CHECKING, Sequence
from typing import TYPE_CHECKING

from pymmcore_plus import CMMCorePlus, Keyword
from qtpy.QtCore import Qt
Expand All @@ -104,6 +104,8 @@
from ._simple_prop_table import PropTable

if TYPE_CHECKING:
from collections.abc import Sequence

from qtpy.QtGui import QFocusEvent

logger = logging.getLogger(__name__)
Expand Down
4 changes: 3 additions & 1 deletion src/pymmcore_widgets/hcwizard/_peripheral_setup_dialog.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Iterable, cast
from typing import TYPE_CHECKING, cast

from pymmcore_plus.model import Device, Microscope
from qtpy.QtCore import QSize, Qt
Expand All @@ -20,6 +20,8 @@
from ._dev_setup_dialog import DeviceSetupDialog

if TYPE_CHECKING:
from collections.abc import Iterable

from pymmcore_plus import CMMCorePlus

FLAGS = Qt.WindowType.MSWindowsFixedSizeDialogHint | Qt.WindowType.Sheet
Expand Down
Loading