diff --git a/.github/project_dict.pws b/.github/project_dict.pws index 555564baa..45feb8dcf 100644 --- a/.github/project_dict.pws +++ b/.github/project_dict.pws @@ -1,4 +1,4 @@ -personal_ws-1.1 en 31 +personal_ws-1.1 en 32 napari autoupdate aspell @@ -30,3 +30,4 @@ ImageJ QtViewer ubuntu numpy +pydantic diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index 7d3eda730..8bbd3038d 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -38,10 +38,6 @@ on: required: false type: number default: 60 - pydantic: - required: false - type: string - default: "" artifact_suffix: required: false type: string @@ -50,7 +46,7 @@ on: jobs: test: - name: ${{ inputs.os }} py ${{ inputs.python_version }} ${{ inputs.napari }} ${{ inputs.qt_backend }} ${{ inputs.pydantic }} + name: ${{ inputs.os }} py ${{ inputs.python_version }} ${{ inputs.napari }} ${{ inputs.qt_backend }} runs-on: ${{ inputs.os }} env: NAPARI: ${{ inputs.napari }} @@ -92,8 +88,8 @@ jobs: # shellcheck disable=SC2086 python -m tox $TOX_ARGS -- package/tests/test_PartSegImage $PYTEST_ARGS env: - PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} - UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} + PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version) || 'requirements/version_denylist.txt' }} + UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version) || 'requirements/version_denylist.txt' }} - name: Test with tox PartSegCore if: ${{ inputs.napari == 'latest' }} @@ -102,8 +98,8 @@ jobs: # shellcheck disable=SC2086 python -m tox $TOX_ARGS -- package/tests/test_PartSegCore $PYTEST_ARGS env: - PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} - UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} + PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version) || 'requirements/version_denylist.txt' }} + UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version ) || 'requirements/version_denylist.txt' }} - name: Test with tox PartSeg if: ${{ inputs.napari == 'latest' }} @@ -113,8 +109,8 @@ jobs: # shellcheck disable=SC2086 python -m tox $TOX_ARGS -- package/tests/test_PartSeg $PYTEST_ARGS env: - PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} - UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} + PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version ) || 'requirements/version_denylist.txt' }} + UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version ) || 'requirements/version_denylist.txt' }} - name: Test with tox all if: ${{ inputs.napari != 'latest' }} @@ -124,8 +120,8 @@ jobs: # shellcheck disable=SC2086 python -m tox $TOX_ARGS ${PYTEST_ARGS:+-- $PYTEST_ARGS} env: - PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} - UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}{1}.txt', inputs.python_version, inputs.pydantic ) || 'requirements/version_denylist.txt' }} + PIP_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version ) || 'requirements/version_denylist.txt' }} + UV_CONSTRAINT: ${{ inputs.napari == 'latest' && format('requirements/constraints_py{0}.txt', inputs.python_version ) || 'requirements/version_denylist.txt' }} - uses: actions/upload-artifact@v7 diff --git a/.github/workflows/test_napari_widgets.yml b/.github/workflows/test_napari_widgets.yml index 4c9a9f1f6..047e52fbf 100644 --- a/.github/workflows/test_napari_widgets.yml +++ b/.github/workflows/test_napari_widgets.yml @@ -31,17 +31,13 @@ jobs: qt_backend: ${{ matrix.qt_backend }} timeout: 10 - test-pyqt5: + test-qt5: name: PyQt5 ${{ matrix.napari }} strategy: fail-fast: false matrix: - napari: ["napari419", "napari54"] - qt_backend: ["PyQt5"] - include: - - napari: "napari54" - qt_backend: "PySide2" - if: github.event_name == 'push' + napari: ["napari62"] + qt_backend: ["PyQt5", "PySide2"] uses: ./.github/workflows/base_test_workflow.yml with: python_version: "3.10" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6b258048d..ba9c24481 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -77,17 +77,12 @@ jobs: - python_version: "3.12" os: "ubuntu-22.04" qt_backend: "PyQt6" - - python_version: "3.10" - os: "ubuntu-22.04" - qt_backend: "PyQt5" - pydantic: "_pydantic_1" with: test_data: True python_version: ${{ matrix.python_version }} os: ${{ matrix.os }} qt_backend: ${{ matrix.qt_backend }} tox_args: ${{ matrix.tox_args }} - pydantic: ${{ matrix.pydantic }} base-test-main: name: Base py${{ matrix.python_version }} @@ -110,10 +105,6 @@ jobs: - python_version: "3.11" os: "ubuntu-22.04" qt_backend: "PyQt6" - - python_version: "3.11" - os: "ubuntu-22.04" - qt_backend: "PyQt5" - pydantic: "_pydantic_1" exclude: - python_version: "3.11" qt_backend: "PySide2" @@ -126,7 +117,6 @@ jobs: python_version: ${{ matrix.python_version }} os: ${{ matrix.os }} qt_backend: ${{ matrix.qt_backend }} - pydantic: ${{ matrix.pydantic }} artifact_suffix: "-main" pytest_args: "-v" diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index f2ab73d6b..60bee1c42 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -37,7 +37,6 @@ jobs: for pyv in 3.10 3.11 3.12 3.13 3.14; do uv pip compile --python-version ${pyv} --upgrade --output-file requirements/constraints_py${pyv}.txt pyproject.toml requirements/version_denylist.txt "${flags[@]}" - uv pip compile --python-version ${pyv} --upgrade --output-file requirements/constraints_py${pyv}_pydantic_1.txt pyproject.toml requirements/version_denylist.txt "${flags[@]}" --constraint requirements/pydantic_1.txt done uv pip compile --python-version 3.12 --upgrade --output-file requirements/constraints_py3.12_docs.txt pyproject.toml --extra docs --extra pyqt6 # END PYTHON DEPENDENCIES diff --git a/package/PartSeg/common_backend/load_backup.py b/package/PartSeg/common_backend/load_backup.py index 665b2a549..0573b91d2 100644 --- a/package/PartSeg/common_backend/load_backup.py +++ b/package/PartSeg/common_backend/load_backup.py @@ -27,7 +27,7 @@ def import_config(): if os.path.exists(state_store.save_folder): return version = packaging.version.parse(parsed_version.base_version) - base_folder = os.path.dirname(state_store.save_folder) + base_folder: str = os.path.dirname(state_store.save_folder) possible_folders = glob(os.path.join(base_folder, "*")) versions = sorted( ( @@ -46,15 +46,11 @@ def import_config(): "Import from old version", "There is no configuration folder for this version of PartSeg\n" "Would you like to import it from " + before_name + " version of PartSeg", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.Yes, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.Yes, ) - if resp == QMessageBox.Yes: + if resp == QMessageBox.StandardButton.Yes: shutil.copytree(os.path.join(base_folder, before_name), state_store.save_folder) if os.path.exists(os.path.join(state_store.save_folder, IGNORE_FILE)): os.remove(os.path.join(state_store.save_folder, IGNORE_FILE)) - napari_settings = napari_get_settings(state_store.save_folder) - if hasattr(napari_settings, "load") and napari_settings.load is not None: - napari_settings.load() - elif getattr(napari_settings, "_load", None) is not None: - napari_settings._load() # pylint: disable=protected-access + napari_get_settings(state_store.save_folder) diff --git a/package/PartSeg/common_gui/algorithms_description.py b/package/PartSeg/common_gui/algorithms_description.py index c50009c0a..eedcf718b 100644 --- a/package/PartSeg/common_gui/algorithms_description.py +++ b/package/PartSeg/common_gui/algorithms_description.py @@ -383,6 +383,7 @@ def _any(): class FormWidget(QWidget): value_changed = Signal() + _model_class: type[BaseModel] | None = None def __init__( self, diff --git a/package/PartSeg/common_gui/error_report.py b/package/PartSeg/common_gui/error_report.py index dde7af2ac..09548c3d3 100644 --- a/package/PartSeg/common_gui/error_report.py +++ b/package/PartSeg/common_gui/error_report.py @@ -18,7 +18,6 @@ import sentry_sdk from napari.settings import get_settings from napari.utils.theme import get_theme -from packaging.version import parse as parse_version from qtpy.QtGui import QIcon from qtpy.QtWidgets import ( QApplication, @@ -54,7 +53,6 @@ _FEEDBACK_URL = "https://sentry.io/api/0/projects/{organization_slug}/{project_slug}/user-feedback/".format( organization_slug="cent", project_slug="partseg" ) -_napari_ge_5 = parse_version(version("napari")) >= parse_version("0.5.0a1") def _print_traceback(exception, file_): @@ -84,10 +82,7 @@ def __init__(self, exception: Exception, description: str, additional_notes: str self.create_issue_btn = QPushButton("Create issue") self.cancel_btn = QPushButton("Cancel") self.error_description = QTextEdit() - if _napari_ge_5: - theme = get_theme(get_settings().appearance.theme) - else: - theme = get_theme(get_settings().appearance.theme, as_dict=False) + theme = get_theme(get_settings().appearance.theme) self._highlight = Pylighter(self.error_description.document(), "python", theme.syntax_style) self.traceback_summary = additional_info if additional_info is None: diff --git a/package/PartSeg/common_gui/napari_image_view.py b/package/PartSeg/common_gui/napari_image_view.py index 4d1fbdcbc..bdbce0202 100644 --- a/package/PartSeg/common_gui/napari_image_view.py +++ b/package/PartSeg/common_gui/napari_image_view.py @@ -212,11 +212,7 @@ def setup_ui(self): layout.addWidget(self.viewer_widget) self.setLayout(layout) - - if hasattr(self.viewer_widget.canvas, "background_color_override"): - self.viewer_widget.canvas.background_color_override = "black" - self.viewer.scale_bar.color = "white" - self.viewer.scale_bar.colored = True + self.viewer_widget.canvas.background_color_override = "black" def _connect_to_settings(self): self.settings.mask_changed.connect(self.set_mask) @@ -327,21 +323,13 @@ def update_spacing_info(self, image: Image | None = None) -> None: image_info.mask.scale = image.normalized_scaling() def _active_layer(self): - if hasattr(self.viewer.layers, "selection"): - return self.viewer.layers.selection.active - return self.viewer.active_layer + return self.viewer.layers.selection.active - def _coordinates(self): + def _coordinates(self) -> list[int] | None: active_layer = self._active_layer() if active_layer is None: return None - if ( - hasattr(self.viewer, "cursor") - and hasattr(self.viewer.cursor, "position") - and hasattr(active_layer, "world_to_data") - ): - return [int(x) for x in active_layer.world_to_data(self.viewer.cursor.position)] - return [int(x) for x in active_layer.coordinates] + return [int(x) for x in active_layer.world_to_data(self.viewer.cursor.position)] def print_info(self, event=None): cords = self._coordinates() diff --git a/package/PartSeg/plugins/napari_io/loader.py b/package/PartSeg/plugins/napari_io/loader.py index c72f3bad5..afe36fb83 100644 --- a/package/PartSeg/plugins/napari_io/loader.py +++ b/package/PartSeg/plugins/napari_io/loader.py @@ -1,9 +1,7 @@ import os import typing -from importlib.metadata import version import numpy as np -from packaging.version import parse as parse_version from PartSeg.plugins.napari_widgets._settings import get_settings from PartSegCore import UNIT_SCALE @@ -40,19 +38,10 @@ def adjust_color(color: str | list[int]) -> str | tuple[float]: return color -if parse_version(version("napari")) >= parse_version("0.4.19a1"): - - def add_color(image: Image, idx: int) -> dict: - return { - "colormap": adjust_color(image.get_colors()[idx]), - } - -else: - - def add_color(image: Image, idx: int) -> dict: # noqa: ARG001 - # Do nothing, as napari is not able to pass hex color to image - # the image and idx are present to keep the same signature - return {} +def add_color(image: Image, idx: int) -> dict: + return { + "colormap": adjust_color(image.get_colors()[idx]), + } def _image_to_layers(project_info, scale, translate): diff --git a/package/PartSeg/plugins/napari_widgets/_settings.py b/package/PartSeg/plugins/napari_widgets/_settings.py index 2781916d1..e4e775fc3 100644 --- a/package/PartSeg/plugins/napari_widgets/_settings.py +++ b/package/PartSeg/plugins/napari_widgets/_settings.py @@ -2,6 +2,7 @@ from magicgui.widgets import Container, create_widget from napari.layers import Layer +from platformdirs import user_config_dir from PartSeg._roi_analysis.partseg_settings import PartSettings from PartSeg.common_backend import napari_get_settings @@ -43,10 +44,10 @@ def get_settings() -> PartSegNapariSettings: global _SETTINGS # noqa: PLW0603 # pylint: disable=global-statement if _SETTINGS is None: napari_settings = napari_get_settings() - if hasattr(napari_settings, "path"): - save_path = napari_settings.path - else: + if napari_settings.config_path is not None: save_path = os.path.dirname(napari_settings.config_path) + else: + save_path = user_config_dir("napari", False) # pragma: no cover _SETTINGS = PartSegNapariSettings(os.path.join(save_path, "PartSeg_napari_plugins")) _SETTINGS.load() return _SETTINGS diff --git a/package/PartSeg/plugins/napari_widgets/lables_control.py b/package/PartSeg/plugins/napari_widgets/lables_control.py index 489258aa9..8380e7df8 100644 --- a/package/PartSeg/plugins/napari_widgets/lables_control.py +++ b/package/PartSeg/plugins/napari_widgets/lables_control.py @@ -1,18 +1,14 @@ from collections.abc import Sequence -from importlib.metadata import version from napari import Viewer from napari.layers import Labels from napari.utils.colormaps import DirectLabelColormap -from packaging.version import parse as parse_version from qtpy.QtWidgets import QHBoxLayout, QPushButton, QTabWidget from PartSeg.common_backend.base_settings import BaseSettings from PartSeg.common_gui.label_create import LabelChoose, LabelEditor, LabelShow from PartSeg.plugins.napari_widgets._settings import get_settings -NAPARI_GE_5_0 = parse_version(version("napari")) >= parse_version("0.5.0a1") - class NapariLabelShow(LabelShow): def __init__(self, viewer: Viewer, name: str, label: list[Sequence[float]], removable, parent=None): diff --git a/package/PartSegCore/analysis/measurement_base.py b/package/PartSegCore/analysis/measurement_base.py index fe4f81ceb..db5098171 100644 --- a/package/PartSegCore/analysis/measurement_base.py +++ b/package/PartSegCore/analysis/measurement_base.py @@ -247,7 +247,7 @@ def replace(self, **kwargs) -> Leaf: if getattr(self, key) is not None and (key != "parameters" or dict(self.parameters)): del kwargs[key] - return self.copy(update=kwargs) + return self.model_copy(update=kwargs) Leaf.replace_ = replace diff --git a/package/PartSegCore/mask_create.py b/package/PartSegCore/mask_create.py index 7484c85f4..7f072fa1e 100644 --- a/package/PartSegCore/mask_create.py +++ b/package/PartSegCore/mask_create.py @@ -200,7 +200,7 @@ def _fill_holes(mask_description: MaskProperty, mask: np.ndarray) -> np.ndarray: if mask_description.save_components: border = 1 res_slice = tuple(slice(border, -border) for _ in range(mask.ndim)) - mask_description_copy = mask_description.copy(update={"save_components": False}) + mask_description_copy = mask_description.model_copy(update={"save_components": False}) mask_prohibited = mask > 0 for component, slice_arr, cmp_num in _cut_components(mask, mask, border): mask_prohibited_component = mask_prohibited[slice_arr] diff --git a/package/PartSegCore/utils.py b/package/PartSegCore/utils.py index fc8b88fc1..171978a50 100644 --- a/package/PartSegCore/utils.py +++ b/package/PartSegCore/utils.py @@ -444,12 +444,18 @@ class Config: extra = "forbid" def __getitem__(self, item): - if item in self.__fields__: + if item in self.__class__.model_fields: warnings.warn("Access to attribute by [] is deprecated. Use . instead", FutureWarning, stacklevel=2) return getattr(self, item) raise KeyError(f"{item} not found in {self.__class__.__name__}") - def copy(self: PydanticBaseModel, *, validate: bool = True, **kwargs: typing.Any) -> PydanticBaseModel: + def model_copy(self: typing.Self, *, validate: bool = True, **kwargs: typing.Any) -> typing.Self: + copy_res = super().model_copy(**kwargs) + if validate: + return self.__class__(**{name: getattr(copy_res, name) for name in copy_res.model_fields_set}) + return copy_res + + def copy(self: typing.Self, *, validate: bool = True, **kwargs: typing.Any) -> typing.Self: copy_res = super().copy(**kwargs) if validate: return self.validate( diff --git a/package/PartSegImage/channel_class.py b/package/PartSegImage/channel_class.py index 85b2e3805..8874b58cb 100644 --- a/package/PartSegImage/channel_class.py +++ b/package/PartSegImage/channel_class.py @@ -1,15 +1,6 @@ -from importlib.metadata import PackageNotFoundError, version -from typing import TYPE_CHECKING, Union +from typing import Union -try: - PYDANTIC_2 = version("pydantic") >= "2.0.0" -except PackageNotFoundError: # pragma: no cover - PYDANTIC_2 = False - - -if TYPE_CHECKING: - from pydantic import GetJsonSchemaHandler - from pydantic_core.core_schema import CoreSchema +from pydantic_core import core_schema def check_type(value): # type: ignore [misc] @@ -17,22 +8,13 @@ def check_type(value): # type: ignore [misc] return value if value.__class__.__module__.startswith("napari"): value = value.name - if not isinstance(value, (str, int)): - raise TypeError(f"Channel need to be int or str, provided {type(value)}") + if not isinstance(value, (str, int)): # pragma: no cover + raise ValueError(f"Channel need to be int or str, provided {type(value)}") + if isinstance(value, str) and not value: + raise ValueError("Channel name can not be empty string") return Channel(value) -if PYDANTIC_2: - - def check_type_(value, _validation_info=None, **_): - return check_type(value) - -else: - - def check_type_(value): # type: ignore [misc] - return check_type(value) - - class Channel: """ This class is introduced to distinguish numerical algorithm parameter from choose channel. @@ -67,19 +49,39 @@ def as_dict(self): return {"value": self._value} @classmethod - def __get_validators__(cls): - yield check_type_ + def validate(cls, value: "int | str | Channel") -> "Channel": + return cls(check_type(value)) @classmethod - def __modify_schema__(cls, field_schema): - """Pydantic 1 dataclass schema modification method. It is used to modify schema for this class""" - # TODO check if still required - field_schema["title"] = "Channel" - field_schema["type"] = "object" - field_schema["properties"] = {"value": {"title": "value", "anyOf": [{"type": "string"}, {"type": "integer"}]}} + def __get_pydantic_core_schema__(cls, source_type, handler): + value_schema = core_schema.union_schema( + [ + core_schema.int_schema(), + core_schema.str_schema(min_length=1), + ] + ) + + return core_schema.no_info_plain_validator_function( + cls.validate, + serialization=core_schema.plain_serializer_function_ser_schema( + lambda value: value.value, + return_schema=value_schema, + ), + ) @classmethod - def __get_pydantic_json_schema__(cls, core_schema: "CoreSchema", handler: "GetJsonSchemaHandler"): - json_schema: dict[str, str | dict] = {} - cls.__modify_schema__(json_schema) + def __get_pydantic_json_schema__(cls, schema, handler): + json_schema = handler( + core_schema.union_schema( + [ + core_schema.int_schema(), + core_schema.str_schema(min_length=1), + ] + ) + ) + json_schema.update( + title="Channel", + description="Image channel index or channel name. Accepts an integer or any non-empty string.", + examples=[0, "nucleus"], + ) return json_schema diff --git a/package/tests/test_PartSeg/test_common_backend.py b/package/tests/test_PartSeg/test_common_backend.py index fdbdef3fc..bd4385774 100644 --- a/package/tests/test_PartSeg/test_common_backend.py +++ b/package/tests/test_PartSeg/test_common_backend.py @@ -625,8 +625,8 @@ def test_base_settings_history(self, tmp_path, qtbot, monkeypatch): mask_property=MaskProperty.simple_mask(), arrays=BytesIO(), ) - hist_elem2 = hist_elem.copy(update={"roi_extraction_parameters": {"a": 2}, "arrays": BytesIO()}) - hist_elem3 = hist_elem.copy(update={"roi_extraction_parameters": {"a": 3}, "arrays": BytesIO()}) + hist_elem2 = hist_elem.model_copy(update={"roi_extraction_parameters": {"a": 2}, "arrays": BytesIO()}) + hist_elem3 = hist_elem.model_copy(update={"roi_extraction_parameters": {"a": 3}, "arrays": BytesIO()}) settings.add_history_element(hist_elem) assert settings.history_size() == 1 assert settings.history_redo_size() == 0 diff --git a/package/tests/test_PartSeg/test_napari_image_view.py b/package/tests/test_PartSeg/test_napari_image_view.py index f9eb881ce..20f4eed5a 100644 --- a/package/tests/test_PartSeg/test_napari_image_view.py +++ b/package/tests/test_PartSeg/test_napari_image_view.py @@ -1,14 +1,12 @@ # pylint: disable=no-self-use import gc from functools import partial -from importlib.metadata import version from unittest.mock import MagicMock import numpy as np import pytest from napari.layers import Image as NapariImage from napari.qt import QtViewer -from packaging.version import parse as parse_version from qtpy.QtCore import QPoint from vispy.geometry import Rect @@ -28,24 +26,11 @@ from PartSegCore.roi_info import ROIInfo from PartSegImage import Image -NAPARI_GE_5_0 = parse_version(version("napari")) >= parse_version("0.5.0a1") -NAPARI_GE_4_19 = parse_version(version("napari")) >= parse_version("0.4.19a1") +EXPECTED_RANGE = (0, 0, 1) -if NAPARI_GE_5_0: - EXPECTED_RANGE = (0, 0, 1) -else: - EXPECTED_RANGE = (0, 1, 1) - -if NAPARI_GE_4_19: - - def get_color_dict(layer): - return layer.colormap.color_dict - -else: - - def get_color_dict(layer): - return layer.color +def get_color_dict(layer): + return layer.colormap.color_dict def test_image_info(): @@ -79,8 +64,7 @@ def image_view(base_settings, image2, qtbot, request): view.deleteLater() qtbot.wait(50) gc.collect() - if hasattr(QtViewer, "_instances"): - QtViewer._instances.clear() + QtViewer._instances.clear() class TestImageView: diff --git a/package/tests/test_PartSeg/test_napari_io.py b/package/tests/test_PartSeg/test_napari_io.py index 2ba1f8ff1..4126e7876 100644 --- a/package/tests/test_PartSeg/test_napari_io.py +++ b/package/tests/test_PartSeg/test_napari_io.py @@ -1,12 +1,10 @@ # pylint: disable=no-self-use import os -from importlib.metadata import version import numpy as np import pytest from napari.layers import Image, Labels, Layer -from packaging.version import parse as parse_version from PartSeg.plugins.napari_io.load_image import napari_get_reader as napari_get_reader_image from PartSeg.plugins.napari_io.load_mask_project import napari_get_reader as napari_get_reader_mask @@ -45,9 +43,6 @@ def test_project_to_layers_analysis(analysis_segmentation): assert not l4.visible -@pytest.mark.skipif( - parse_version(version("napari")) < parse_version("0.4.19a16"), reason="not supported by old napari versions" -) def test_passing_colormap(analysis_segmentation): res = project_to_layers(analysis_segmentation) l1 = Layer.create(*res[0]) diff --git a/package/tests/test_PartSeg/test_napari_widgets.py b/package/tests/test_PartSeg/test_napari_widgets.py index 3de4bd3c8..21352d23f 100644 --- a/package/tests/test_PartSeg/test_napari_widgets.py +++ b/package/tests/test_PartSeg/test_napari_widgets.py @@ -1,7 +1,6 @@ import contextlib import gc import json -from importlib.metadata import version from unittest.mock import Mock, patch import numpy as np @@ -11,7 +10,6 @@ from napari.layers import Image as NapariImage from napari.layers import Labels from napari.utils import Colormap -from packaging.version import parse as parse_version from qtpy.QtCore import QObject, QTimer, Signal from PartSeg._roi_analysis.profile_export import ExportDialog, ImportDialog @@ -60,28 +58,17 @@ from PartSegCore.segmentation.watershed import WatershedSelection from PartSegCore.universal_const import LayerNamingFormat -NAPARI_GE_5_0 = parse_version(version("napari")) >= parse_version("0.5.0a1") -NAPARI_GE_4_19 = parse_version(version("napari")) >= parse_version("0.4.19a1") -if NAPARI_GE_4_19: +def check_auto_mode(layer): + from napari.utils.colormaps import CyclicLabelColormap # noqa: PLC0415 - def check_auto_mode(layer): - from napari.utils.colormaps import CyclicLabelColormap # noqa: PLC0415 + assert isinstance(layer.colormap, CyclicLabelColormap) - assert isinstance(layer.colormap, CyclicLabelColormap) - def check_direct_mode(layer): - from napari.utils.colormaps import DirectLabelColormap # noqa: PLC0415 +def check_direct_mode(layer): + from napari.utils.colormaps import DirectLabelColormap # noqa: PLC0415 - assert isinstance(layer.colormap, DirectLabelColormap) - -else: - - def check_auto_mode(layer): - assert layer.color_mode == "auto" - - def check_direct_mode(layer): - assert layer.color_mode == "direct" + assert isinstance(layer.colormap, DirectLabelColormap) @pytest.fixture(autouse=True) diff --git a/package/tests/test_PartSeg/test_roi_analysis_batch.py b/package/tests/test_PartSeg/test_roi_analysis_batch.py index 539168401..9bb9c36b7 100644 --- a/package/tests/test_PartSeg/test_roi_analysis_batch.py +++ b/package/tests/test_PartSeg/test_roi_analysis_batch.py @@ -663,7 +663,7 @@ def test_add_roi_extraction(self, qtbot, part_settings, roi_extraction_profile): assert len(widget.calculation_plan.execution_tree.children) == 1 assert len(widget.calculation_plan.execution_tree.children[0].children) == 0 assert widget.calculation_plan.execution_tree.children[0].operation == roi_extraction_profile - roi_extraction_profile2 = roi_extraction_profile.copy(update={"name": "roi_extraction_profile2"}) + roi_extraction_profile2 = roi_extraction_profile.model_copy(update={"name": "roi_extraction_profile2"}) widget.update_element_chk.setChecked(True) widget.add_roi_extraction(roi_extraction_profile2) assert len(widget.calculation_plan.execution_tree.children) == 1 @@ -680,7 +680,7 @@ def test_add_save_operation(self, qtbot, part_settings): assert len(widget.calculation_plan.execution_tree.children) == 1 assert len(widget.calculation_plan.execution_tree.children[0].children) == 0 assert widget.calculation_plan.execution_tree.children[0].operation == save_step_profile - save_step_profile2 = save_step_profile.copy(update={"suffix": "_save"}) + save_step_profile2 = save_step_profile.model_copy(update={"suffix": "_save"}) widget.update_element_chk.setChecked(True) widget.add_save_operation(save_step_profile2) assert len(widget.calculation_plan.execution_tree.children) == 1 diff --git a/package/tests/test_PartSeg/test_viewer.py b/package/tests/test_PartSeg/test_viewer.py index 97461edee..47f37640d 100644 --- a/package/tests/test_PartSeg/test_viewer.py +++ b/package/tests/test_PartSeg/test_viewer.py @@ -1,11 +1,9 @@ import platform -from importlib.metadata import version import numpy as np import pytest import qtpy from napari.layers import Labels, Points -from packaging.version import parse as parse_version from qtpy.QtCore import QCoreApplication from PartSeg._roi_analysis.image_view import ResultImageView @@ -19,7 +17,7 @@ pytestmark = pytest.mark.filterwarnings("ignore:Public access to Window.qt_viewer") -MOCK_APP_FIXTURE_NAME = "mock_app_model" if parse_version(version("napari")) >= parse_version("0.5.4") else "mock_app" +MOCK_APP_FIXTURE_NAME = "mock_app_model" class TestResultImageView: diff --git a/package/tests/test_PartSegCore/test_analysis_batch.py b/package/tests/test_PartSegCore/test_analysis_batch.py index 329106995..cb246c6f6 100644 --- a/package/tests/test_PartSegCore/test_analysis_batch.py +++ b/package/tests/test_PartSegCore/test_analysis_batch.py @@ -95,7 +95,7 @@ def get_name(cls) -> str: class DummySpacingCheck(DummyExtraction): def calculation_run(self, report_fun: Callable[[str, int], None]) -> ROIExtractionResult: - assert self.image.spacing == (3, 2, 1) + assert self.image.spacing == (3, 2, 1), f"Wrong spacing {self.image.spacing}" return ROIExtractionResult(np.ones(self.image.shape, dtype=np.uint8), self.get_segmentation_profile()) @@ -243,9 +243,9 @@ def calculation_plan_long(ltww_segmentation, measurement_list): mask_suffix = MaskSuffix(name="", suffix="_mask") children = [] for i in range(20): - measurement = measurement_list.copy() + measurement = measurement_list.model_copy() measurement.name_prefix = f"{i}_" - measurement.measurement_profile = measurement.measurement_profile.copy() + measurement.measurement_profile = measurement.measurement_profile.model_copy() measurement.measurement_profile.name_prefix = f"{i}_" children.append( CalculationTree(mask_suffix, [CalculationTree(ltww_segmentation, [CalculationTree(measurement, [])])]) diff --git a/package/tests/test_PartSegCore/test_mask_create.py b/package/tests/test_PartSegCore/test_mask_create.py index 9c956775a..32880e252 100644 --- a/package/tests/test_PartSegCore/test_mask_create.py +++ b/package/tests/test_PartSegCore/test_mask_create.py @@ -291,7 +291,7 @@ def test_save_component_fill_holes(self): save_components=True, clip_to_mask=True, ) - mp2 = mp.copy(update={"fill_holes": RadiusType.R3D}) + mp2 = mp.model_copy(update={"fill_holes": RadiusType.R3D}) mask1 = calculate_mask(mp, mask2, None, (1, 1, 1)) assert np.all(mask == mask1) mask1 = calculate_mask(mp2, mask2, None, (1, 1, 1)) @@ -376,7 +376,10 @@ def test_clip(self): mask2[:] = 0 mask2[4:6, 4:6, 4:6] = 1 mask3 = calculate_mask( - mp.copy(update={"dilate": RadiusType.NO, "dilate_radius": 0, "reversed_mask": True}), mask2, mask, (1, 1, 1) + mp.model_copy(update={"dilate": RadiusType.NO, "dilate_radius": 0, "reversed_mask": True}), + mask2, + mask, + (1, 1, 1), ) mask[mask2 == 1] = 0 assert np.all(mask3 == mask) diff --git a/package/tests/test_PartSegImage/test_channel_class.py b/package/tests/test_PartSegImage/test_channel_class.py index 99000959e..4e0122a26 100644 --- a/package/tests/test_PartSegImage/test_channel_class.py +++ b/package/tests/test_PartSegImage/test_channel_class.py @@ -1,5 +1,3 @@ -import json - import pytest from pydantic import BaseModel @@ -32,16 +30,17 @@ class Model(BaseModel): MODEL_SCHEMA = { - "title": "Model", - "type": "object", "properties": { "channel": { + "anyOf": [{"type": "integer"}, {"type": "string", "minLength": 1}], + "description": "Image channel index or channel name. Accepts an integer or any non-empty string.", + "examples": [0, "nucleus"], "title": "Channel", - "type": "object", - "properties": {"value": {"title": "value", "anyOf": [{"type": "string"}, {"type": "integer"}]}}, } }, "required": ["channel"], + "title": "Model", + "type": "object", } @@ -53,4 +52,4 @@ def test_as_pydantic_field(value): def test_json_schema(): - assert json.loads(Model.schema_json()) == MODEL_SCHEMA + assert Model.model_json_schema() == MODEL_SCHEMA diff --git a/pyproject.toml b/pyproject.toml index a1cf5a6ce..e5dec569f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ "PartSegCore-compiled-backend>=0.13.11,<0.16.0", "PartSegData==0.10.0", "QtAwesome!=1.2.0,>=1.0.3", - "QtPy>=1.10.0", + "QtPy>=2.3.1", "SimpleITK>=2.2.0", "platformdirs>=4.3.0", "czifile>=2019.5.22", @@ -53,28 +53,29 @@ dependencies = [ "imagecodecs>=2023.9.18", "imageio>=2.20.0", "ipykernel>=5.2.0", - "local-migrator>=0.1.7", + "local-migrator>=0.1.10", "magicgui>=0.7.0", "mahotas>=1.4.13", - "napari>=0.5.0", - "numpy>=1.23.0", + "napari>=0.6.2 ; python_version < '3.14'", + "napari >= 0.7.0 ; python_version >= '3.14'", + "numpy>=1.24.2", "oiffile>=2020.1.18", "openpyxl>=3.0.7", "packaging>=22.0", "pandas>=1.4.0", - "psygnal>=0.5.0", - "pydantic>=1.9.1,<3", + "psygnal>=0.10.0", + "pydantic>=2.2.0", "pygments>=2.12.0", "qtconsole>=4.7.7", "requests>=2.25.0", - "scipy>=1.10.0", + "scipy>=1.10.1", "sentry-sdk>=2.4.0", "six>=1.11.0", - "superqt>=0.6.7", + "superqt>=0.7.3", "sympy>=1.10", - "tifffile>=2022.4.8", + "tifffile>=2023.9.26", "traceback-with-variables>=2.0.4", - "vispy>=0.14.1 ", + "vispy>=0.15.2", "xlrd>=1.1.0", "xlsxwriter>=2.0.0", ] diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt deleted file mode 100644 index a86c3c466..000000000 --- a/requirements/constraints_py3.10_pydantic_1.txt +++ /dev/null @@ -1,515 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --python-version 3.10 --output-file requirements/constraints_py3.10_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller_base --constraint requirements/pydantic_1.txt -alabaster==1.0.0 - # via sphinx -altgraph==0.17.5 - # via pyinstaller -annotated-doc==0.0.4 - # via typer -app-model==0.3.2 - # via napari -appdirs==1.4.4 - # via napari -asttokens==3.0.1 - # via stack-data -attrs==26.1.0 - # via - # jsonschema - # referencing -babel==2.18.0 - # via sphinx -build==1.5.0 - # via npe2 -cachey==0.2.1 - # via napari -certifi==2026.5.20 - # via - # napari - # requests - # sentry-sdk -charset-normalizer==3.4.7 - # via requests -click==8.4.1 - # via dask -cloudpickle==3.1.2 - # via dask -comm==0.2.3 - # via ipykernel -coverage==7.14.1 - # via partseg (pyproject.toml) -czifile==2019.7.2.2 - # via partseg (pyproject.toml) -dask==2026.3.0 - # via napari -debugpy==1.8.20 - # via ipykernel -decorator==5.3.1 - # via ipython -defusedxml==0.7.1 - # via partseg (pyproject.toml) -docstring-parser==0.18.0 - # via magicgui -docutils==0.21.2 - # via sphinx -et-xmlfile==2.0.0 - # via openpyxl -exceptiongroup==1.3.1 - # via - # ipython - # pytest -executing==2.2.1 - # via stack-data -flexcache==0.3 - # via pint -flexparser==0.4 - # via pint -fonticon-fontawesome6==6.4.0 - # via partseg (pyproject.toml) -freetype-py==2.5.1 - # via vispy -fsspec==2026.4.0 - # via dask -h5py==3.16.0 - # via partseg (pyproject.toml) -heapdict==1.0.1 - # via cachey -hsluv==5.0.4 - # via vispy -idna==3.17 - # via requests -imagecodecs==2025.3.30 - # via partseg (pyproject.toml) -imageio==2.37.3 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) - # napari - # napari-svg - # scikit-image -imagesize==2.0.0 - # via sphinx -importlib-metadata==9.0.0 - # via - # build - # dask -in-n-out==0.2.1 - # via app-model -iniconfig==2.3.0 - # via pytest -ipykernel==7.2.0 - # via - # partseg (pyproject.toml) - # napari-console - # qtconsole -ipython==8.39.0 - # via - # partseg (pyproject.toml) - # ipykernel - # napari-console -ipython-pygments-lexers==1.1.1 - # via qtconsole -jedi==0.20.0 - # via ipython -jinja2==3.1.6 - # via sphinx -jsonschema==4.26.0 - # via napari -jsonschema-specifications==2025.9.1 - # via jsonschema -jupyter-client==8.8.0 - # via - # ipykernel - # qtconsole -jupyter-core==5.9.1 - # via - # ipykernel - # jupyter-client - # qtconsole -kiwisolver==1.5.0 - # via vispy -lazy-loader==0.5 - # via - # napari - # scikit-image -local-migrator==0.1.10 - # via - # partseg (pyproject.toml) - # nme -locket==1.0.0 - # via partd -lxml==6.1.1 - # via - # partseg (pyproject.toml) - # lxml-html-clean -lxml-html-clean==0.4.5 - # via lxml -magicgui==0.10.2 - # via - # partseg (pyproject.toml) - # napari -mahotas==1.4.18 - # via partseg (pyproject.toml) -markdown-it-py==4.2.0 - # via rich -markupsafe==3.0.3 - # via jinja2 -matplotlib-inline==0.2.2 - # via - # ipykernel - # ipython -mdurl==0.1.2 - # via markdown-it-py -mpmath==1.3.0 - # via sympy -napari==0.5.6 - # via partseg (pyproject.toml) -napari-console==0.1.3 - # via napari -napari-plugin-engine==0.2.1 - # via napari -napari-svg==0.2.1 - # via napari -nest-asyncio==1.6.0 - # via ipykernel -networkx==3.4.2 - # via scikit-image -nme==0.1.8 - # via partseg (pyproject.toml) -npe2==0.7.9 - # via - # -r requirements/version_denylist.txt - # napari -numpy==2.2.6 - # via - # partseg (pyproject.toml) - # czifile - # dask - # h5py - # imagecodecs - # imageio - # mahotas - # napari - # napari-svg - # oiffile - # pandas - # partsegcore-compiled-backend - # scikit-image - # scipy - # tifffile - # vispy -numpydoc==1.10.0 - # via napari -oiffile==2025.5.10 - # via partseg (pyproject.toml) -openpyxl==3.1.5 - # via partseg (pyproject.toml) -packaging==26.2 - # via - # partseg (pyproject.toml) - # build - # dask - # ipykernel - # lazy-loader - # local-migrator - # pooch - # pyinstaller - # pyinstaller-hooks-contrib - # pytest - # qtconsole - # qtpy - # scikit-image - # sphinx - # vispy -pandas==2.3.3 - # via - # partseg (pyproject.toml) - # napari -parso==0.8.7 - # via jedi -partd==1.4.2 - # via dask -partsegcore-compiled-backend==0.15.14 - # via partseg (pyproject.toml) -partsegdata==0.10.0 - # via partseg (pyproject.toml) -pexpect==4.9.0 - # via ipython -pillow==12.2.0 - # via - # imageio - # napari - # scikit-image -pint==0.24.4 - # via napari -platformdirs==4.10.0 - # via - # partseg (pyproject.toml) - # jupyter-core - # npe2 - # pint - # pooch -pluggy==1.6.0 - # via - # pytest - # pytest-qt -pooch==1.9.0 - # via scikit-image -prompt-toolkit==3.0.52 - # via ipython -psutil==7.2.2 - # via - # ipykernel - # napari -psygnal==0.15.1 - # via - # partseg (pyproject.toml) - # app-model - # magicgui - # napari - # npe2 -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyconify==0.2.1 - # via superqt -pydantic==1.10.26 - # via - # -c requirements/pydantic_1.txt - # partseg (pyproject.toml) - # app-model - # napari - # npe2 - # pydantic-compat -pydantic-compat==0.1.2 - # via app-model -pygments==2.20.0 - # via - # partseg (pyproject.toml) - # ipython - # ipython-pygments-lexers - # napari - # pytest - # qtconsole - # rich - # sphinx - # superqt -pyinstaller==6.20.0 - # via partseg (pyproject.toml) -pyinstaller-hooks-contrib==2026.5 - # via pyinstaller -pyopengl==3.1.10 - # via napari -pyproject-hooks==1.2.0 - # via build -pyqt6==6.11.0 - # via - # partseg (pyproject.toml) - # napari -pyqt6-qt6==6.11.1 - # via pyqt6 -pyqt6-sip==13.11.1 - # via pyqt6 -pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) - # napari -pyside6==6.11.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6-addons==6.11.1 - # via pyside6 -pyside6-essentials==6.11.1 - # via - # pyside6 - # pyside6-addons -pytest==9.0.3 - # via - # partseg (pyproject.toml) - # pytest-qt - # pytest-timeout -pytest-qt==4.4.0 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pytest-timeout==2.4.0 - # via partseg (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # jupyter-client - # pandas -pytz==2026.2 - # via pandas -pyyaml==6.0.3 - # via - # dask - # napari - # npe2 -pyzmq==27.1.0 - # via - # ipykernel - # jupyter-client -qtawesome==1.4.2 - # via partseg (pyproject.toml) -qtconsole==5.7.2 - # via - # partseg (pyproject.toml) - # napari-console -qtpy==2.4.3 - # via - # partseg (pyproject.toml) - # magicgui - # napari - # napari-console - # qtawesome - # qtconsole - # superqt -referencing==0.37.0 - # via - # jsonschema - # jsonschema-specifications -requests==2.34.2 - # via - # partseg (pyproject.toml) - # pooch - # pyconify - # sphinx -rich==15.0.0 - # via - # npe2 - # typer -rpds-py==0.30.0 - # via - # jsonschema - # referencing -scikit-image==0.25.2 - # via - # partseg (pyproject.toml) - # napari -scipy==1.15.3 - # via - # partseg (pyproject.toml) - # napari - # scikit-image -sentry-sdk==2.61.1 - # via partseg (pyproject.toml) -setuptools==82.0.1 - # via - # pyinstaller - # pyinstaller-hooks-contrib -shellingham==1.5.4 - # via typer -shiboken2==5.15.2.1 - # via pyside2 -shiboken6==6.11.1 - # via - # pyside6 - # pyside6-addons - # pyside6-essentials -simpleitk==2.5.5 - # via partseg (pyproject.toml) -six==1.17.0 - # via - # partseg (pyproject.toml) - # python-dateutil -snowballstemmer==3.1.0 - # via sphinx -sphinx==8.1.3 - # via numpydoc -sphinxcontrib-applehelp==2.0.0 - # via sphinx -sphinxcontrib-devhelp==2.0.0 - # via sphinx -sphinxcontrib-htmlhelp==2.1.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==2.0.0 - # via sphinx -sphinxcontrib-serializinghtml==2.0.0 - # via sphinx -stack-data==0.6.3 - # via ipython -superqt==0.7.8 - # via - # partseg (pyproject.toml) - # magicgui - # napari -sympy==1.14.0 - # via partseg (pyproject.toml) -tifffile==2025.5.10 - # via - # partseg (pyproject.toml) - # czifile - # napari - # oiffile - # scikit-image -tomli==2.4.1 - # via - # build - # npe2 - # numpydoc - # pyside6 - # pytest - # sphinx -tomli-w==1.2.0 - # via npe2 -toolz==1.1.0 - # via - # dask - # napari - # partd -tornado==6.5.6 - # via - # ipykernel - # jupyter-client -tqdm==4.67.3 - # via napari -traceback-with-variables==2.2.1 - # via partseg (pyproject.toml) -traitlets==5.15.0 - # via - # ipykernel - # ipython - # jupyter-client - # jupyter-core - # matplotlib-inline - # qtconsole -typer==0.26.4 - # via npe2 -typing-extensions==4.15.0 - # via - # app-model - # exceptiongroup - # flexcache - # flexparser - # ipython - # magicgui - # napari - # pint - # pydantic - # referencing - # superqt -tzdata==2026.2 - # via pandas -urllib3==2.7.0 - # via - # requests - # sentry-sdk -vispy==0.14.3 - # via - # partseg (pyproject.toml) - # napari - # napari-svg -wcwidth==0.7.0 - # via prompt-toolkit -wrapt==2.2.1 - # via napari -xlrd==2.0.2 - # via partseg (pyproject.toml) -xlsxwriter==3.2.9 - # via partseg (pyproject.toml) -zipp==4.1.0 - # via importlib-metadata diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt deleted file mode 100644 index d32da1d36..000000000 --- a/requirements/constraints_py3.11_pydantic_1.txt +++ /dev/null @@ -1,500 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --python-version 3.11 --output-file requirements/constraints_py3.11_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller_base --constraint requirements/pydantic_1.txt -alabaster==1.0.0 - # via sphinx -altgraph==0.17.5 - # via pyinstaller -annotated-doc==0.0.4 - # via typer -app-model==0.3.2 - # via napari -appdirs==1.4.4 - # via napari -asttokens==3.0.1 - # via stack-data -attrs==26.1.0 - # via - # jsonschema - # referencing -babel==2.18.0 - # via sphinx -build==1.5.0 - # via npe2 -cachey==0.2.1 - # via napari -certifi==2026.5.20 - # via - # napari - # requests - # sentry-sdk -charset-normalizer==3.4.7 - # via requests -click==8.4.1 - # via dask -cloudpickle==3.1.2 - # via dask -comm==0.2.3 - # via ipykernel -coverage==7.14.1 - # via partseg (pyproject.toml) -czifile==2019.7.2.3 - # via partseg (pyproject.toml) -dask==2026.3.0 - # via napari -debugpy==1.8.20 - # via ipykernel -decorator==5.3.1 - # via ipython -defusedxml==0.7.1 - # via partseg (pyproject.toml) -docstring-parser==0.18.0 - # via magicgui -docutils==0.22.4 - # via sphinx -et-xmlfile==2.0.0 - # via openpyxl -executing==2.2.1 - # via stack-data -flexcache==0.3 - # via pint -flexparser==0.4 - # via pint -fonticon-fontawesome6==6.4.0 - # via partseg (pyproject.toml) -freetype-py==2.5.1 - # via vispy -fsspec==2026.4.0 - # via dask -h5py==3.16.0 - # via partseg (pyproject.toml) -heapdict==1.0.1 - # via cachey -hsluv==5.0.4 - # via vispy -idna==3.17 - # via requests -imagecodecs==2026.3.6 - # via partseg (pyproject.toml) -imageio==2.37.3 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) - # napari - # napari-svg - # scikit-image -imagesize==2.0.0 - # via sphinx -importlib-metadata==9.0.0 - # via dask -in-n-out==0.2.1 - # via app-model -iniconfig==2.3.0 - # via pytest -ipykernel==7.2.0 - # via - # partseg (pyproject.toml) - # napari-console - # qtconsole -ipython==9.14.0 - # via - # partseg (pyproject.toml) - # ipykernel - # napari-console -ipython-pygments-lexers==1.1.1 - # via - # ipython - # qtconsole -jedi==0.20.0 - # via ipython -jinja2==3.1.6 - # via sphinx -jsonschema==4.26.0 - # via napari -jsonschema-specifications==2025.9.1 - # via jsonschema -jupyter-client==8.8.0 - # via - # ipykernel - # qtconsole -jupyter-core==5.9.1 - # via - # ipykernel - # jupyter-client - # qtconsole -kiwisolver==1.5.0 - # via vispy -lazy-loader==0.5 - # via - # napari - # scikit-image -local-migrator==0.1.10 - # via - # partseg (pyproject.toml) - # nme -locket==1.0.0 - # via partd -lxml==6.1.1 - # via - # partseg (pyproject.toml) - # lxml-html-clean -lxml-html-clean==0.4.5 - # via lxml -magicgui==0.10.2 - # via - # partseg (pyproject.toml) - # napari -mahotas==1.4.18 - # via partseg (pyproject.toml) -markdown-it-py==4.2.0 - # via rich -markupsafe==3.0.3 - # via jinja2 -matplotlib-inline==0.2.2 - # via - # ipykernel - # ipython -mdurl==0.1.2 - # via markdown-it-py -mpmath==1.3.0 - # via sympy -napari==0.5.6 - # via partseg (pyproject.toml) -napari-console==0.1.3 - # via napari -napari-plugin-engine==0.2.1 - # via napari -napari-svg==0.2.1 - # via napari -nest-asyncio==1.6.0 - # via ipykernel -networkx==3.6.1 - # via scikit-image -nme==0.1.8 - # via partseg (pyproject.toml) -npe2==0.7.9 - # via - # -r requirements/version_denylist.txt - # napari -numpy==2.4.6 - # via - # partseg (pyproject.toml) - # czifile - # dask - # h5py - # imagecodecs - # imageio - # mahotas - # napari - # napari-svg - # oiffile - # pandas - # partsegcore-compiled-backend - # scikit-image - # scipy - # tifffile - # vispy -numpydoc==1.10.0 - # via napari -oiffile==2026.2.8 - # via partseg (pyproject.toml) -openpyxl==3.1.5 - # via partseg (pyproject.toml) -packaging==26.2 - # via - # partseg (pyproject.toml) - # build - # dask - # ipykernel - # lazy-loader - # local-migrator - # pooch - # pyinstaller - # pyinstaller-hooks-contrib - # pytest - # qtconsole - # qtpy - # scikit-image - # sphinx - # vispy -pandas==3.0.3 - # via - # partseg (pyproject.toml) - # napari -parso==0.8.7 - # via jedi -partd==1.4.2 - # via dask -partsegcore-compiled-backend==0.15.14 - # via partseg (pyproject.toml) -partsegdata==0.10.0 - # via partseg (pyproject.toml) -pexpect==4.9.0 - # via ipython -pillow==12.2.0 - # via - # imageio - # napari - # scikit-image -pint==0.25.3 - # via napari -platformdirs==4.10.0 - # via - # partseg (pyproject.toml) - # jupyter-core - # npe2 - # pint - # pooch -pluggy==1.6.0 - # via - # pytest - # pytest-qt -pooch==1.9.0 - # via scikit-image -prompt-toolkit==3.0.52 - # via ipython -psutil==7.2.2 - # via - # ipykernel - # ipython - # napari -psygnal==0.15.1 - # via - # partseg (pyproject.toml) - # app-model - # magicgui - # napari - # npe2 -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyconify==0.2.1 - # via superqt -pydantic==1.10.26 - # via - # -c requirements/pydantic_1.txt - # partseg (pyproject.toml) - # app-model - # napari - # npe2 - # pydantic-compat -pydantic-compat==0.1.2 - # via app-model -pygments==2.20.0 - # via - # partseg (pyproject.toml) - # ipython - # ipython-pygments-lexers - # napari - # pytest - # qtconsole - # rich - # sphinx - # superqt -pyinstaller==6.20.0 - # via partseg (pyproject.toml) -pyinstaller-hooks-contrib==2026.5 - # via pyinstaller -pyopengl==3.1.10 - # via napari -pyproject-hooks==1.2.0 - # via build -pyqt6==6.11.0 - # via - # partseg (pyproject.toml) - # napari -pyqt6-qt6==6.11.1 - # via pyqt6 -pyqt6-sip==13.11.1 - # via pyqt6 -pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6==6.11.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6-addons==6.11.1 - # via pyside6 -pyside6-essentials==6.11.1 - # via - # pyside6 - # pyside6-addons -pytest==9.0.3 - # via - # partseg (pyproject.toml) - # pytest-qt - # pytest-timeout -pytest-qt==4.4.0 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pytest-timeout==2.4.0 - # via partseg (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # jupyter-client - # pandas -pyyaml==6.0.3 - # via - # dask - # napari - # npe2 -pyzmq==27.1.0 - # via - # ipykernel - # jupyter-client -qtawesome==1.4.2 - # via partseg (pyproject.toml) -qtconsole==5.7.2 - # via - # partseg (pyproject.toml) - # napari-console -qtpy==2.4.3 - # via - # partseg (pyproject.toml) - # magicgui - # napari - # napari-console - # qtawesome - # qtconsole - # superqt -referencing==0.37.0 - # via - # jsonschema - # jsonschema-specifications -requests==2.34.2 - # via - # partseg (pyproject.toml) - # pooch - # pyconify - # sphinx -rich==15.0.0 - # via - # npe2 - # typer -roman-numerals==4.1.0 - # via sphinx -rpds-py==2026.5.1 - # via - # jsonschema - # referencing -scikit-image==0.26.0 - # via - # partseg (pyproject.toml) - # napari -scipy==1.17.1 - # via - # partseg (pyproject.toml) - # napari - # scikit-image -sentry-sdk==2.61.1 - # via partseg (pyproject.toml) -setuptools==82.0.1 - # via - # pyinstaller - # pyinstaller-hooks-contrib -shellingham==1.5.4 - # via typer -shiboken2==5.15.2.1 - # via pyside2 -shiboken6==6.11.1 - # via - # pyside6 - # pyside6-addons - # pyside6-essentials -simpleitk==2.5.5 - # via partseg (pyproject.toml) -six==1.17.0 - # via - # partseg (pyproject.toml) - # python-dateutil -snowballstemmer==3.1.0 - # via sphinx -sphinx==9.0.4 - # via numpydoc -sphinxcontrib-applehelp==2.0.0 - # via sphinx -sphinxcontrib-devhelp==2.0.0 - # via sphinx -sphinxcontrib-htmlhelp==2.1.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==2.0.0 - # via sphinx -sphinxcontrib-serializinghtml==2.0.0 - # via sphinx -stack-data==0.6.3 - # via ipython -superqt==0.7.8 - # via - # partseg (pyproject.toml) - # magicgui - # napari -sympy==1.14.0 - # via partseg (pyproject.toml) -tifffile==2026.3.3 - # via - # partseg (pyproject.toml) - # czifile - # napari - # oiffile - # scikit-image -tomli-w==1.2.0 - # via npe2 -toolz==1.1.0 - # via - # dask - # napari - # partd -tornado==6.5.6 - # via - # ipykernel - # jupyter-client -tqdm==4.67.3 - # via napari -traceback-with-variables==2.2.1 - # via partseg (pyproject.toml) -traitlets==5.15.0 - # via - # ipykernel - # ipython - # jupyter-client - # jupyter-core - # matplotlib-inline - # qtconsole -typer==0.26.4 - # via npe2 -typing-extensions==4.15.0 - # via - # app-model - # flexcache - # flexparser - # ipython - # magicgui - # napari - # pint - # pydantic - # referencing - # superqt -urllib3==2.7.0 - # via - # requests - # sentry-sdk -vispy==0.14.3 - # via - # partseg (pyproject.toml) - # napari - # napari-svg -wcwidth==0.7.0 - # via prompt-toolkit -wrapt==2.2.1 - # via napari -xlrd==2.0.2 - # via partseg (pyproject.toml) -xlsxwriter==3.2.9 - # via partseg (pyproject.toml) -zipp==4.1.0 - # via importlib-metadata diff --git a/requirements/constraints_py3.12_pydantic_1.txt b/requirements/constraints_py3.12_pydantic_1.txt deleted file mode 100644 index 0240eceac..000000000 --- a/requirements/constraints_py3.12_pydantic_1.txt +++ /dev/null @@ -1,496 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --python-version 3.12 --output-file requirements/constraints_py3.12_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller_base --constraint requirements/pydantic_1.txt -alabaster==1.0.0 - # via sphinx -altgraph==0.17.5 - # via pyinstaller -annotated-doc==0.0.4 - # via typer -app-model==0.3.2 - # via napari -appdirs==1.4.4 - # via napari -asttokens==3.0.1 - # via stack-data -attrs==26.1.0 - # via - # jsonschema - # referencing -babel==2.18.0 - # via sphinx -build==1.5.0 - # via npe2 -cachey==0.2.1 - # via napari -certifi==2026.5.20 - # via - # napari - # requests - # sentry-sdk -charset-normalizer==3.4.7 - # via requests -click==8.4.1 - # via dask -cloudpickle==3.1.2 - # via dask -comm==0.2.3 - # via ipykernel -coverage==7.14.1 - # via partseg (pyproject.toml) -czifile==2026.4.30 - # via partseg (pyproject.toml) -dask==2026.3.0 - # via napari -debugpy==1.8.20 - # via ipykernel -decorator==5.3.1 - # via ipython -defusedxml==0.7.1 - # via partseg (pyproject.toml) -docstring-parser==0.18.0 - # via magicgui -docutils==0.22.4 - # via sphinx -et-xmlfile==2.0.0 - # via openpyxl -executing==2.2.1 - # via stack-data -flexcache==0.3 - # via pint -flexparser==0.4 - # via pint -fonticon-fontawesome6==6.4.0 - # via partseg (pyproject.toml) -freetype-py==2.5.1 - # via vispy -fsspec==2026.4.0 - # via dask -h5py==3.16.0 - # via partseg (pyproject.toml) -heapdict==1.0.1 - # via cachey -hsluv==5.0.4 - # via vispy -idna==3.17 - # via requests -imagecodecs==2026.5.10 - # via - # partseg (pyproject.toml) - # czifile -imageio==2.37.3 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) - # napari - # napari-svg - # scikit-image -imagesize==2.0.0 - # via sphinx -in-n-out==0.2.1 - # via app-model -iniconfig==2.3.0 - # via pytest -ipykernel==7.2.0 - # via - # partseg (pyproject.toml) - # napari-console - # qtconsole -ipython==9.14.0 - # via - # partseg (pyproject.toml) - # ipykernel - # napari-console -ipython-pygments-lexers==1.1.1 - # via - # ipython - # qtconsole -jedi==0.20.0 - # via ipython -jinja2==3.1.6 - # via sphinx -jsonschema==4.26.0 - # via napari -jsonschema-specifications==2025.9.1 - # via jsonschema -jupyter-client==8.8.0 - # via - # ipykernel - # qtconsole -jupyter-core==5.9.1 - # via - # ipykernel - # jupyter-client - # qtconsole -kiwisolver==1.5.0 - # via vispy -lazy-loader==0.5 - # via - # napari - # scikit-image -local-migrator==0.1.10 - # via - # partseg (pyproject.toml) - # nme -locket==1.0.0 - # via partd -lxml==6.1.1 - # via - # partseg (pyproject.toml) - # lxml-html-clean -lxml-html-clean==0.4.5 - # via lxml -magicgui==0.10.2 - # via - # partseg (pyproject.toml) - # napari -mahotas==1.4.18 - # via partseg (pyproject.toml) -markdown-it-py==4.2.0 - # via rich -markupsafe==3.0.3 - # via jinja2 -matplotlib-inline==0.2.2 - # via - # ipykernel - # ipython -mdurl==0.1.2 - # via markdown-it-py -mpmath==1.3.0 - # via sympy -napari==0.5.6 - # via partseg (pyproject.toml) -napari-console==0.1.3 - # via napari -napari-plugin-engine==0.2.1 - # via napari -napari-svg==0.2.1 - # via napari -nest-asyncio==1.6.0 - # via ipykernel -networkx==3.6.1 - # via scikit-image -nme==0.1.8 - # via partseg (pyproject.toml) -npe2==0.7.9 - # via - # -r requirements/version_denylist.txt - # napari -numpy==2.4.6 - # via - # partseg (pyproject.toml) - # czifile - # dask - # h5py - # imagecodecs - # imageio - # mahotas - # napari - # napari-svg - # oiffile - # pandas - # partsegcore-compiled-backend - # scikit-image - # scipy - # tifffile - # vispy -numpydoc==1.10.0 - # via napari -oiffile==2026.2.8 - # via partseg (pyproject.toml) -openpyxl==3.1.5 - # via partseg (pyproject.toml) -packaging==26.2 - # via - # partseg (pyproject.toml) - # build - # dask - # ipykernel - # lazy-loader - # local-migrator - # pooch - # pyinstaller - # pyinstaller-hooks-contrib - # pytest - # qtconsole - # qtpy - # scikit-image - # sphinx - # vispy -pandas==3.0.3 - # via - # partseg (pyproject.toml) - # napari -parso==0.8.7 - # via jedi -partd==1.4.2 - # via dask -partsegcore-compiled-backend==0.15.14 - # via partseg (pyproject.toml) -partsegdata==0.10.0 - # via partseg (pyproject.toml) -pexpect==4.9.0 - # via ipython -pillow==12.2.0 - # via - # imageio - # napari - # scikit-image -pint==0.25.3 - # via napari -platformdirs==4.10.0 - # via - # partseg (pyproject.toml) - # jupyter-core - # npe2 - # pint - # pooch -pluggy==1.6.0 - # via - # pytest - # pytest-qt -pooch==1.9.0 - # via scikit-image -prompt-toolkit==3.0.52 - # via ipython -psutil==7.2.2 - # via - # ipykernel - # ipython - # napari -psygnal==0.15.1 - # via - # partseg (pyproject.toml) - # app-model - # magicgui - # napari - # npe2 -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyconify==0.2.1 - # via superqt -pydantic==1.10.26 - # via - # -c requirements/pydantic_1.txt - # partseg (pyproject.toml) - # app-model - # napari - # npe2 - # pydantic-compat -pydantic-compat==0.1.2 - # via app-model -pygments==2.20.0 - # via - # partseg (pyproject.toml) - # ipython - # ipython-pygments-lexers - # napari - # pytest - # qtconsole - # rich - # sphinx - # superqt -pyinstaller==6.20.0 - # via partseg (pyproject.toml) -pyinstaller-hooks-contrib==2026.5 - # via pyinstaller -pyopengl==3.1.10 - # via napari -pyproject-hooks==1.2.0 - # via build -pyqt6==6.11.0 - # via - # partseg (pyproject.toml) - # napari -pyqt6-qt6==6.11.1 - # via pyqt6 -pyqt6-sip==13.11.1 - # via pyqt6 -pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6==6.11.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6-addons==6.11.1 - # via pyside6 -pyside6-essentials==6.11.1 - # via - # pyside6 - # pyside6-addons -pytest==9.0.3 - # via - # partseg (pyproject.toml) - # pytest-qt - # pytest-timeout -pytest-qt==4.4.0 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pytest-timeout==2.4.0 - # via partseg (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # jupyter-client - # pandas -pyyaml==6.0.3 - # via - # dask - # napari - # npe2 -pyzmq==27.1.0 - # via - # ipykernel - # jupyter-client -qtawesome==1.4.2 - # via partseg (pyproject.toml) -qtconsole==5.7.2 - # via - # partseg (pyproject.toml) - # napari-console -qtpy==2.4.3 - # via - # partseg (pyproject.toml) - # magicgui - # napari - # napari-console - # qtawesome - # qtconsole - # superqt -referencing==0.37.0 - # via - # jsonschema - # jsonschema-specifications -requests==2.34.2 - # via - # partseg (pyproject.toml) - # pooch - # pyconify - # sphinx -rich==15.0.0 - # via - # npe2 - # typer -roman-numerals==4.1.0 - # via sphinx -rpds-py==2026.5.1 - # via - # jsonschema - # referencing -scikit-image==0.26.0 - # via - # partseg (pyproject.toml) - # napari -scipy==1.17.1 - # via - # partseg (pyproject.toml) - # napari - # scikit-image -sentry-sdk==2.61.1 - # via partseg (pyproject.toml) -setuptools==82.0.1 - # via - # pyinstaller - # pyinstaller-hooks-contrib -shellingham==1.5.4 - # via typer -shiboken2==5.15.2.1 - # via pyside2 -shiboken6==6.11.1 - # via - # pyside6 - # pyside6-addons - # pyside6-essentials -simpleitk==2.5.5 - # via partseg (pyproject.toml) -six==1.17.0 - # via - # partseg (pyproject.toml) - # python-dateutil -snowballstemmer==3.1.0 - # via sphinx -sphinx==9.1.0 - # via numpydoc -sphinxcontrib-applehelp==2.0.0 - # via sphinx -sphinxcontrib-devhelp==2.0.0 - # via sphinx -sphinxcontrib-htmlhelp==2.1.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==2.0.0 - # via sphinx -sphinxcontrib-serializinghtml==2.0.0 - # via sphinx -stack-data==0.6.3 - # via ipython -superqt==0.7.8 - # via - # partseg (pyproject.toml) - # magicgui - # napari -sympy==1.14.0 - # via partseg (pyproject.toml) -tifffile==2026.6.1 - # via - # partseg (pyproject.toml) - # napari - # oiffile - # scikit-image -tomli-w==1.2.0 - # via npe2 -toolz==1.1.0 - # via - # dask - # napari - # partd -tornado==6.5.6 - # via - # ipykernel - # jupyter-client -tqdm==4.67.3 - # via napari -traceback-with-variables==2.2.1 - # via partseg (pyproject.toml) -traitlets==5.15.0 - # via - # ipykernel - # ipython - # jupyter-client - # jupyter-core - # matplotlib-inline - # qtconsole -typer==0.26.4 - # via npe2 -typing-extensions==4.15.0 - # via - # app-model - # flexcache - # flexparser - # magicgui - # napari - # pint - # pydantic - # referencing - # superqt -urllib3==2.7.0 - # via - # requests - # sentry-sdk -vispy==0.14.3 - # via - # partseg (pyproject.toml) - # napari - # napari-svg -wcwidth==0.7.0 - # via prompt-toolkit -wrapt==2.2.1 - # via napari -xlrd==2.0.2 - # via partseg (pyproject.toml) -xlsxwriter==3.2.9 - # via partseg (pyproject.toml) diff --git a/requirements/constraints_py3.13_pydantic_1.txt b/requirements/constraints_py3.13_pydantic_1.txt deleted file mode 100644 index ef04e17a6..000000000 --- a/requirements/constraints_py3.13_pydantic_1.txt +++ /dev/null @@ -1,495 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv pip compile --python-version 3.13 --output-file requirements/constraints_py3.13_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller_base --constraint requirements/pydantic_1.txt -alabaster==1.0.0 - # via sphinx -altgraph==0.17.5 - # via pyinstaller -annotated-doc==0.0.4 - # via typer -app-model==0.3.2 - # via napari -appdirs==1.4.4 - # via napari -asttokens==3.0.1 - # via stack-data -attrs==26.1.0 - # via - # jsonschema - # referencing -babel==2.18.0 - # via sphinx -build==1.5.0 - # via npe2 -cachey==0.2.1 - # via napari -certifi==2026.5.20 - # via - # napari - # requests - # sentry-sdk -charset-normalizer==3.4.7 - # via requests -click==8.4.1 - # via dask -cloudpickle==3.1.2 - # via dask -comm==0.2.3 - # via ipykernel -coverage==7.14.1 - # via partseg (pyproject.toml) -czifile==2026.4.30 - # via partseg (pyproject.toml) -dask==2026.3.0 - # via napari -debugpy==1.8.20 - # via ipykernel -decorator==5.3.1 - # via ipython -defusedxml==0.7.1 - # via partseg (pyproject.toml) -docstring-parser==0.18.0 - # via magicgui -docutils==0.22.4 - # via sphinx -et-xmlfile==2.0.0 - # via openpyxl -executing==2.2.1 - # via stack-data -flexcache==0.3 - # via pint -flexparser==0.4 - # via pint -fonticon-fontawesome6==6.4.0 - # via partseg (pyproject.toml) -freetype-py==2.5.1 - # via vispy -fsspec==2026.4.0 - # via dask -h5py==3.16.0 - # via partseg (pyproject.toml) -heapdict==1.0.1 - # via cachey -hsluv==5.0.4 - # via vispy -idna==3.17 - # via requests -imagecodecs==2026.5.10 - # via - # partseg (pyproject.toml) - # czifile -imageio==2.37.3 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) - # napari - # napari-svg - # scikit-image -imagesize==2.0.0 - # via sphinx -in-n-out==0.2.1 - # via app-model -iniconfig==2.3.0 - # via pytest -ipykernel==7.2.0 - # via - # partseg (pyproject.toml) - # napari-console - # qtconsole -ipython==9.14.0 - # via - # partseg (pyproject.toml) - # ipykernel - # napari-console -ipython-pygments-lexers==1.1.1 - # via - # ipython - # qtconsole -jedi==0.20.0 - # via ipython -jinja2==3.1.6 - # via sphinx -jsonschema==4.26.0 - # via napari -jsonschema-specifications==2025.9.1 - # via jsonschema -jupyter-client==8.8.0 - # via - # ipykernel - # qtconsole -jupyter-core==5.9.1 - # via - # ipykernel - # jupyter-client - # qtconsole -kiwisolver==1.5.0 - # via vispy -lazy-loader==0.5 - # via - # napari - # scikit-image -local-migrator==0.1.10 - # via - # partseg (pyproject.toml) - # nme -locket==1.0.0 - # via partd -lxml==6.1.1 - # via - # partseg (pyproject.toml) - # lxml-html-clean -lxml-html-clean==0.4.5 - # via lxml -magicgui==0.10.2 - # via - # partseg (pyproject.toml) - # napari -mahotas==1.4.18 - # via partseg (pyproject.toml) -markdown-it-py==4.2.0 - # via rich -markupsafe==3.0.3 - # via jinja2 -matplotlib-inline==0.2.2 - # via - # ipykernel - # ipython -mdurl==0.1.2 - # via markdown-it-py -mpmath==1.3.0 - # via sympy -napari==0.5.6 - # via partseg (pyproject.toml) -napari-console==0.1.3 - # via napari -napari-plugin-engine==0.2.1 - # via napari -napari-svg==0.2.1 - # via napari -nest-asyncio==1.6.0 - # via ipykernel -networkx==3.6.1 - # via scikit-image -nme==0.1.8 - # via partseg (pyproject.toml) -npe2==0.7.9 - # via - # -r requirements/version_denylist.txt - # napari -numpy==2.4.6 - # via - # partseg (pyproject.toml) - # czifile - # dask - # h5py - # imagecodecs - # imageio - # mahotas - # napari - # napari-svg - # oiffile - # pandas - # partsegcore-compiled-backend - # scikit-image - # scipy - # tifffile - # vispy -numpydoc==1.10.0 - # via napari -oiffile==2026.2.8 - # via partseg (pyproject.toml) -openpyxl==3.1.5 - # via partseg (pyproject.toml) -packaging==26.2 - # via - # partseg (pyproject.toml) - # build - # dask - # ipykernel - # lazy-loader - # local-migrator - # pooch - # pyinstaller - # pyinstaller-hooks-contrib - # pytest - # qtconsole - # qtpy - # scikit-image - # sphinx - # vispy -pandas==3.0.3 - # via - # partseg (pyproject.toml) - # napari -parso==0.8.7 - # via jedi -partd==1.4.2 - # via dask -partsegcore-compiled-backend==0.15.14 - # via partseg (pyproject.toml) -partsegdata==0.10.0 - # via partseg (pyproject.toml) -pexpect==4.9.0 - # via ipython -pillow==12.2.0 - # via - # imageio - # napari - # scikit-image -pint==0.25.3 - # via napari -platformdirs==4.10.0 - # via - # partseg (pyproject.toml) - # jupyter-core - # npe2 - # pint - # pooch -pluggy==1.6.0 - # via - # pytest - # pytest-qt -pooch==1.9.0 - # via scikit-image -prompt-toolkit==3.0.52 - # via ipython -psutil==7.2.2 - # via - # ipykernel - # ipython - # napari -psygnal==0.15.1 - # via - # partseg (pyproject.toml) - # app-model - # magicgui - # napari - # npe2 -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.3 - # via stack-data -pyconify==0.2.1 - # via superqt -pydantic==1.10.26 - # via - # -c requirements/pydantic_1.txt - # partseg (pyproject.toml) - # app-model - # napari - # npe2 - # pydantic-compat -pydantic-compat==0.1.2 - # via app-model -pygments==2.20.0 - # via - # partseg (pyproject.toml) - # ipython - # ipython-pygments-lexers - # napari - # pytest - # qtconsole - # rich - # sphinx - # superqt -pyinstaller==6.20.0 - # via partseg (pyproject.toml) -pyinstaller-hooks-contrib==2026.5 - # via pyinstaller -pyopengl==3.1.10 - # via napari -pyproject-hooks==1.2.0 - # via build -pyqt6==6.11.0 - # via - # partseg (pyproject.toml) - # napari -pyqt6-qt6==6.11.1 - # via pyqt6 -pyqt6-sip==13.11.1 - # via pyqt6 -pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6==6.11.1 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pyside6-addons==6.11.1 - # via pyside6 -pyside6-essentials==6.11.1 - # via - # pyside6 - # pyside6-addons -pytest==9.0.3 - # via - # partseg (pyproject.toml) - # pytest-qt - # pytest-timeout -pytest-qt==4.4.0 - # via - # -r requirements/version_denylist.txt - # partseg (pyproject.toml) -pytest-timeout==2.4.0 - # via partseg (pyproject.toml) -python-dateutil==2.9.0.post0 - # via - # jupyter-client - # pandas -pyyaml==6.0.3 - # via - # dask - # napari - # npe2 -pyzmq==27.1.0 - # via - # ipykernel - # jupyter-client -qtawesome==1.4.2 - # via partseg (pyproject.toml) -qtconsole==5.7.2 - # via - # partseg (pyproject.toml) - # napari-console -qtpy==2.4.3 - # via - # partseg (pyproject.toml) - # magicgui - # napari - # napari-console - # qtawesome - # qtconsole - # superqt -referencing==0.37.0 - # via - # jsonschema - # jsonschema-specifications -requests==2.34.2 - # via - # partseg (pyproject.toml) - # pooch - # pyconify - # sphinx -rich==15.0.0 - # via - # npe2 - # typer -roman-numerals==4.1.0 - # via sphinx -rpds-py==2026.5.1 - # via - # jsonschema - # referencing -scikit-image==0.26.0 - # via - # partseg (pyproject.toml) - # napari -scipy==1.17.1 - # via - # partseg (pyproject.toml) - # napari - # scikit-image -sentry-sdk==2.61.1 - # via partseg (pyproject.toml) -setuptools==82.0.1 - # via - # pyinstaller - # pyinstaller-hooks-contrib -shellingham==1.5.4 - # via typer -shiboken2==5.15.2.1 - # via pyside2 -shiboken6==6.11.1 - # via - # pyside6 - # pyside6-addons - # pyside6-essentials -simpleitk==2.5.5 - # via partseg (pyproject.toml) -six==1.17.0 - # via - # partseg (pyproject.toml) - # python-dateutil -snowballstemmer==3.1.0 - # via sphinx -sphinx==9.1.0 - # via numpydoc -sphinxcontrib-applehelp==2.0.0 - # via sphinx -sphinxcontrib-devhelp==2.0.0 - # via sphinx -sphinxcontrib-htmlhelp==2.1.0 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==2.0.0 - # via sphinx -sphinxcontrib-serializinghtml==2.0.0 - # via sphinx -stack-data==0.6.3 - # via ipython -superqt==0.7.8 - # via - # partseg (pyproject.toml) - # magicgui - # napari -sympy==1.14.0 - # via partseg (pyproject.toml) -tifffile==2026.6.1 - # via - # partseg (pyproject.toml) - # napari - # oiffile - # scikit-image -tomli-w==1.2.0 - # via npe2 -toolz==1.1.0 - # via - # dask - # napari - # partd -tornado==6.5.6 - # via - # ipykernel - # jupyter-client -tqdm==4.67.3 - # via napari -traceback-with-variables==2.2.1 - # via partseg (pyproject.toml) -traitlets==5.15.0 - # via - # ipykernel - # ipython - # jupyter-client - # jupyter-core - # matplotlib-inline - # qtconsole -typer==0.26.4 - # via npe2 -typing-extensions==4.15.0 - # via - # app-model - # flexcache - # flexparser - # magicgui - # napari - # pint - # pydantic - # superqt -urllib3==2.7.0 - # via - # requests - # sentry-sdk -vispy==0.14.3 - # via - # partseg (pyproject.toml) - # napari - # napari-svg -wcwidth==0.7.0 - # via prompt-toolkit -wrapt==2.2.1 - # via napari -xlrd==2.0.2 - # via partseg (pyproject.toml) -xlsxwriter==3.2.9 - # via partseg (pyproject.toml) diff --git a/requirements/constraints_py3.14_pydantic_1.txt b/requirements/constraints_py3.14_pydantic_1.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tox.ini b/tox.ini index 385ec09a7..0d3708348 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py{310,311,312,313,314}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{310,311,312,313,314}-{PyQt5,PyQt6}-napari_repo,py{310,311,312,313,314}-{PyQt5,PyQt6,PySide2}-napari_{419,54,70}, py{312,313,314}-PySide6-napari_{419,54,70,repo} +envlist = py{310,311,312,313,314}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{310,311,312,313,314}-{PyQt5,PyQt6}-napari_repo,py{310,311,312,313,314}-{PyQt5,PyQt6,PySide2}-napari_{62,70}, py{312,313,314}-PySide6-napari_{62,70,repo} toxworkdir=/tmp/tox [gh-actions] @@ -21,8 +21,7 @@ fail_on_no_env = True [gh-actions:env] NAPARI = latest: all - napari419: napari_419 - napari54: napari_54 + napari62: napari_62 napari70: napari_70 repo: napari_repo BACKEND = @@ -76,11 +75,10 @@ deps= lxml_html_clean -[testenv:py{310,311,312,313,314,315}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{419,54,70}] +[testenv:py{310,311,312,313,314,315}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{62,70}] deps = {[testenv]deps} - napari_419: napari==0.4.19.post1 - napari_54: napari==0.5.4 + napari_62: napari==0.6.2 napari_70: napari==0.7.0 commands = python -m pytest -v --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json {posargs:package/tests/test_PartSeg/test_napari_widgets.py}