Skip to content

Commit 457bc1b

Browse files
committed
Merge branch 'main' into feat/hist-bin-params
2 parents 6261f4c + d3ff0f3 commit 457bc1b

15 files changed

+122
-78
lines changed

.github/workflows/docs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
sudo apt install graphviz --yes
3333
3434
- name: Build Docs
35-
uses: aganders3/headless-gui@v1
35+
uses: aganders3/headless-gui@v2
3636
with:
3737
run: make html
3838
working-directory: ./docs

.github/workflows/napari_hub_preview.yml

-21
This file was deleted.

.github/workflows/test_and_deploy.yml

+9-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ on:
1212
workflow_dispatch:
1313
merge_group:
1414

15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
1519
jobs:
1620
test:
1721
name: ${{ matrix.platform }} py${{ matrix.python-version }}
@@ -20,7 +24,7 @@ jobs:
2024
fail-fast: false
2125
matrix:
2226
platform: [ubuntu-latest, macos-latest, windows-latest]
23-
python-version: ['3.9', '3.10', '3.11']
27+
python-version: ['3.10', '3.11', '3.12']
2428

2529
steps:
2630
- uses: actions/checkout@v3
@@ -58,13 +62,15 @@ jobs:
5862
if: ${{ always() }}
5963

6064
- name: Coverage
61-
uses: codecov/codecov-action@v3
65+
uses: codecov/codecov-action@v4
6266
# Don't run coverage on merge queue CI to avoid duplicating reports
6367
# to codecov. See https://github.com/matplotlib/napari-matplotlib/issues/155
6468
if: github.event_name != 'merge_group'
6569
with:
6670
token: ${{ secrets.CODECOV_TOKEN }}
67-
fail_ci_if_error: true
71+
fail_ci_if_error: false
72+
73+
6874

6975
deploy:
7076
# this will run when you have tagged a commit, starting with "v*"

.pre-commit-config.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.5.0
3+
rev: v4.6.0
44
hooks:
55
- id: check-docstring-first
66
- id: end-of-file-fixer
77
- id: trailing-whitespace
88

9-
- repo: https://github.com/psf/black
10-
rev: 24.1.1
9+
- repo: https://github.com/psf/black-pre-commit-mirror
10+
rev: 24.4.2
1111
hooks:
1212
- id: black
1313

@@ -17,14 +17,14 @@ repos:
1717
- id: napari-plugin-checks
1818

1919
- repo: https://github.com/pre-commit/mirrors-mypy
20-
rev: v1.8.0
20+
rev: v1.10.0
2121
hooks:
2222
- id: mypy
2323
additional_dependencies: [numpy, matplotlib]
2424

2525
- repo: https://github.com/astral-sh/ruff-pre-commit
2626
# Ruff version.
27-
rev: 'v0.2.1'
27+
rev: 'v0.4.2'
2828
hooks:
2929
- id: ruff
3030

docs/changelog.rst

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
Changelog
22
=========
3+
2.0.2
4+
-----
5+
Dependencies
6+
~~~~~~~~~~~~
7+
napari-matplotlib now adheres to `SPEC 0 <https://scientific-python.org/specs/spec-0000/>`_, and has:
8+
- Dropped support for Python 3.9
9+
- Added support for Python 3.12
10+
- Added a minimum required numpy verison of 1.23
11+
312
2.0.1
413
-----
514
Bug fixes

docs/conf.py

+49-9
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# import os
1414
# import sys
1515
# sys.path.insert(0, os.path.abspath('.'))
16-
import qtgallery
16+
from sphinx_gallery import scrapers
1717

1818
# -- Project information -----------------------------------------------------
1919

@@ -35,18 +35,58 @@
3535
"sphinx.ext.intersphinx",
3636
]
3737

38+
39+
def reset_napari(gallery_conf, fname): # type: ignore[no-untyped-def]
40+
from napari.settings import get_settings
41+
from qtpy.QtWidgets import QApplication
42+
43+
settings = get_settings()
44+
settings.appearance.theme = "dark"
45+
46+
# Disabling `QApplication.exec_` means example scripts can call `exec_`
47+
# (scripts work when run normally) without blocking example execution by
48+
# sphinx-gallery. (from qtgallery)
49+
QApplication.exec_ = lambda _: None
50+
51+
52+
def napari_scraper(block, block_vars, gallery_conf): # type: ignore[no-untyped-def]
53+
"""Basic napari window scraper.
54+
55+
Looks for any QtMainWindow instances and takes a screenshot of them.
56+
57+
`app.processEvents()` allows Qt events to propagateo and prevents hanging.
58+
"""
59+
import napari
60+
61+
imgpath_iter = block_vars["image_path_iterator"]
62+
63+
if app := napari.qt.get_app():
64+
app.processEvents()
65+
else:
66+
return ""
67+
68+
img_paths = []
69+
for win, img_path in zip(
70+
reversed(napari._qt.qt_main_window._QtMainWindow._instances),
71+
imgpath_iter,
72+
strict=False,
73+
):
74+
img_paths.append(img_path)
75+
win._window.screenshot(img_path, canvas_only=False)
76+
77+
napari.Viewer.close_all()
78+
app.processEvents()
79+
80+
return scrapers.figure_rst(img_paths, gallery_conf["src_dir"])
81+
82+
3883
sphinx_gallery_conf = {
3984
"filename_pattern": ".",
40-
"image_scrapers": (qtgallery.qtscraper,),
41-
"reset_modules": (qtgallery.reset_qapp,),
85+
"image_scrapers": (napari_scraper,),
86+
"reset_modules": (reset_napari,),
4287
}
88+
suppress_warnings = ["config.cache"]
4389

44-
qtgallery_conf = {
45-
"xvfb_size": (640, 480),
46-
"xvfb_color_depth": 24,
47-
"xfvb_use_xauth": False,
48-
"xfvb_extra_args": [],
49-
}
5090

5191
numpydoc_show_class_members = False
5292
automodapi_inheritance_diagram = True

pyproject.toml

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
2-
requires = ["setuptools", "wheel", "setuptools_scm"]
2+
requires = ["setuptools", "setuptools_scm"]
33
build-backend = "setuptools.build_meta"
44

55
[tool.setuptools_scm]
@@ -12,9 +12,15 @@ filterwarnings = [
1212
# Coming from vispy
1313
"ignore:distutils Version classes are deprecated:DeprecationWarning",
1414
"ignore:`np.bool8` is a deprecated alias for `np.bool_`:DeprecationWarning",
15+
# Coming from pydantic via napari
16+
"ignore:Pickle, copy, and deepcopy support will be removed from itertools in Python 3.14.:DeprecationWarning"
1517
]
1618
qt_api = "pyqt6"
17-
addopts = "--mpl --mpl-baseline-relative"
19+
addopts = ["--mpl", "--mpl-baseline-relative", "--strict-config", "--strict-markers", "-ra"]
20+
minversion = "7"
21+
testpaths = ["src/napari_matplotlib/tests"]
22+
log_cli_level = "INFO"
23+
xfail_strict = true
1824

1925
[tool.black]
2026
line-length = 79
@@ -24,8 +30,11 @@ profile = "black"
2430
line_length = 79
2531

2632
[tool.ruff]
27-
target-version = "py39"
28-
select = ["I", "UP", "F", "E", "W", "D"]
33+
target-version = "py310"
34+
fix = true
35+
36+
[tool.ruff.lint]
37+
select = ["B", "I", "UP", "F", "E", "W", "D"]
2938
ignore = [
3039
"D100", # Missing docstring in public module
3140
"D104", # Missing docstring in public package
@@ -35,24 +44,25 @@ ignore = [
3544
"D401", # First line of docstring should be in imperative mood
3645

3746
]
38-
fix = true
3947

40-
[tool.ruff.per-file-ignores]
48+
[tool.ruff.lint.per-file-ignores]
4149
"docs/*" = ["D"]
4250
"examples/*" = ["D"]
4351
"src/napari_matplotlib/tests/*" = ["D"]
4452

45-
[tool.ruff.pydocstyle]
53+
[tool.ruff.lint.pydocstyle]
4654
convention = "numpy"
4755

4856
[tool.mypy]
49-
python_version = "3.9"
57+
python_version = "3.10"
5058
# Block below are checks that form part of mypy 'strict' mode
5159
strict = true
5260
disallow_subclassing_any = false # TODO: fix
5361
warn_return_any = false # TODO: fix
5462
ignore_missing_imports = true
5563

64+
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
65+
5666
[[tool.mypy.overrides]]
5767
module = [
5868
"napari_matplotlib/tests/*",

setup.cfg

+3-4
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ packages = find:
2929
install_requires =
3030
matplotlib
3131
napari
32-
numpy
32+
numpy>=1.23
3333
tinycss2
34-
python_requires = >=3.9
34+
python_requires = >=3.10
3535
include_package_data = True
3636
package_dir =
3737
=src
@@ -47,11 +47,10 @@ napari.manifest =
4747

4848
[options.extras_require]
4949
docs =
50-
napari[all]==0.4.19rc3
50+
napari[all]
5151
numpydoc
5252
pydantic<2
5353
pydata-sphinx-theme
54-
qtgallery
5554
sphinx
5655
sphinx-automodapi
5756
sphinx-gallery

src/napari_matplotlib/base.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
from pathlib import Path
3-
from typing import Optional
43

54
import matplotlib.style as mplstyle
65
import napari
@@ -38,7 +37,7 @@ class BaseNapariMPLWidget(QWidget):
3837
def __init__(
3938
self,
4039
napari_viewer: napari.Viewer,
41-
parent: Optional[QWidget] = None,
40+
parent: QWidget | None = None,
4241
):
4342
super().__init__(parent=parent)
4443
self.viewer = napari_viewer
@@ -173,7 +172,7 @@ class NapariMPLWidget(BaseNapariMPLWidget):
173172
def __init__(
174173
self,
175174
napari_viewer: napari.viewer.Viewer,
176-
parent: Optional[QWidget] = None,
175+
parent: QWidget | None = None,
177176
):
178177
super().__init__(napari_viewer=napari_viewer, parent=parent)
179178
self._setup_callbacks()
@@ -282,7 +281,7 @@ class SingleAxesWidget(NapariMPLWidget):
282281
def __init__(
283282
self,
284283
napari_viewer: napari.viewer.Viewer,
285-
parent: Optional[QWidget] = None,
284+
parent: QWidget | None = None,
286285
):
287286
super().__init__(napari_viewer=napari_viewer, parent=parent)
288287
self.add_single_axes()

src/napari_matplotlib/histogram.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class HistogramWidget(SingleAxesWidget):
7878
def __init__(
7979
self,
8080
napari_viewer: napari.viewer.Viewer,
81-
parent: Optional[QWidget] = None,
81+
parent: QWidget | None = None,
8282
):
8383
super().__init__(napari_viewer, parent=parent)
8484

@@ -168,7 +168,7 @@ def on_update_layers(self) -> None:
168168

169169
def _update_contrast_lims(self) -> None:
170170
for lim, line in zip(
171-
self.layers[0].contrast_limits, self._contrast_lines
171+
self.layers[0].contrast_limits, self._contrast_lines, strict=False
172172
):
173173
line.set_xdata(lim)
174174

@@ -285,7 +285,7 @@ class FeaturesHistogramWidget(SingleAxesWidget):
285285
def __init__(
286286
self,
287287
napari_viewer: napari.viewer.Viewer,
288-
parent: Optional[QWidget] = None,
288+
parent: QWidget | None = None,
289289
):
290290
super().__init__(napari_viewer, parent=parent)
291291

@@ -301,12 +301,12 @@ def __init__(
301301
self._update_layers(None)
302302

303303
@property
304-
def x_axis_key(self) -> Optional[str]:
304+
def x_axis_key(self) -> str | None:
305305
"""Key to access x axis data from the FeaturesTable"""
306306
return self._x_axis_key
307307

308308
@x_axis_key.setter
309-
def x_axis_key(self, key: Optional[str]) -> None:
309+
def x_axis_key(self, key: str | None) -> None:
310310
self._x_axis_key = key
311311
self._draw()
312312

@@ -330,7 +330,7 @@ def _get_valid_axis_keys(self) -> list[str]:
330330
else:
331331
return self.layers[0].features.keys()
332332

333-
def _get_data(self) -> tuple[Optional[npt.NDArray[Any]], str]:
333+
def _get_data(self) -> tuple[npt.NDArray[Any] | None, str]:
334334
"""Get the plot data.
335335
336336
Returns

0 commit comments

Comments
 (0)