From 107c615d62ef5068859575d63ded5e59a795da01 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 8 Dec 2023 16:05:27 +0100 Subject: [PATCH 01/51] refactor: Fix Qt flags (#1041) Instead of using global `Qt` or Widget namespaces for enum selection point, enum directly. ## Summary by CodeRabbit - **New Features** - Enhanced the About dialog to support parent window association for better modal behavior. - Advanced tabs, mask control, and advanced window classes now accept a parent argument for improved widget hierarchy management. - Profile selection and color map creation processes have been refined with updated initialization parameters. - Custom load and save dialog conditions and method calls have been updated for consistency with the latest dialog standards. - **Bug Fixes** - Corrected the context menu policy settings for various GUI components to align with updated Qt enumerations. - Adjusted file dialog acceptance checks to use the revised dialog code enumeration. - Resolved issues with incorrect enum usage in searchable combo boxes and list widgets, ensuring proper item filtering and selection behavior. - **Documentation** - Updated comments and docstrings across multiple modules for better clarity and understanding of the codebase. - **Refactor** - Standardized the use of enum values across the application, replacing direct value usage with fully qualified enum names for better code maintainability and readability. - **Style** - Minor stylistic changes in comments and method calls to adhere to the updated coding standards and conventions. Please note that these changes are aimed at improving the user experience and ensuring compatibility with the latest standards and practices in application development. --- package/PartSeg/common_gui/about_dialog.py | 8 +++---- package/PartSeg/common_gui/advanced_tabs.py | 24 +++++++++---------- .../common_gui/algorithms_description.py | 8 +++---- .../PartSeg/common_gui/collapse_checkbox.py | 6 ++--- .../PartSeg/common_gui/colormap_creator.py | 6 ++--- .../PartSeg/common_gui/custom_load_dialog.py | 2 +- .../PartSeg/common_gui/custom_save_dialog.py | 10 ++++---- package/PartSeg/common_gui/error_report.py | 6 ++--- package/PartSeg/common_gui/flow_layout.py | 4 ++-- .../PartSeg/common_gui/image_adjustment.py | 2 +- .../common_gui/multiple_file_widget.py | 16 ++++++------- .../PartSeg/common_gui/napari_image_view.py | 2 +- package/PartSeg/common_gui/numpy_qimage.py | 2 +- package/PartSeg/common_gui/qt_modal.py | 10 ++++---- .../common_gui/searchable_combo_box.py | 8 +++---- .../common_gui/searchable_list_widget.py | 2 +- .../common_gui/select_multiple_files.py | 8 +++---- .../common_gui/show_directory_dialog.py | 2 +- .../PartSeg/common_gui/universal_gui_part.py | 13 +++++----- .../test_PartSeg/test_colormap_create.py | 5 +++- 20 files changed, 74 insertions(+), 70 deletions(-) diff --git a/package/PartSeg/common_gui/about_dialog.py b/package/PartSeg/common_gui/about_dialog.py index 25d503847..8c996b1c6 100644 --- a/package/PartSeg/common_gui/about_dialog.py +++ b/package/PartSeg/common_gui/about_dialog.py @@ -10,8 +10,8 @@ class AboutDialog(QDialog): - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent=parent) self.setWindowTitle("About PartSeg") text = ( f"PartSeg ({PartSeg.__version__})
" @@ -46,8 +46,8 @@ def __init__(self): self.cite_as.setMarkdown(cite_as_text) ok_but = QPushButton("Ok") ok_but.clicked.connect(self.accept) - text_label.setTextInteractionFlags(Qt.TextSelectableByMouse) - layout = QGridLayout() + text_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) + layout = QGridLayout(self) layout.addWidget(text_label, 0, 0, 1, 3) layout.addWidget(self.change_log, 1, 0, 1, 3) layout.addWidget(QLabel("Cite as:"), 2, 0, 1, 3) diff --git a/package/PartSeg/common_gui/advanced_tabs.py b/package/PartSeg/common_gui/advanced_tabs.py index f7716d082..d7c0f6709 100644 --- a/package/PartSeg/common_gui/advanced_tabs.py +++ b/package/PartSeg/common_gui/advanced_tabs.py @@ -1,6 +1,6 @@ """ -This module contains base for advanced window for PartSeg. -In this moment controlling colormaps tabs and developer PartSegCore +This module contains base for the advanced window for PartSeg. +At this moment controlling colormaps tabs and developer PartSegCore """ import importlib import sys @@ -41,22 +41,22 @@ class DevelopTab(QWidget): """ Widget for developer utilities. Currently only contains button for reload algorithms and - To enable it run program with `--develop` flag. + To enable it run program with a `--develop` flag. - If you would like to use it for developing your own algorithm and modify same of ParsSeg class - please protect this part of code with something like: + If you would like to use it for developing your own algorithm and modify some of the PartSeg class. + Please protect this part of code with something like: >>> if tifffile.tifffile.TiffPage.__module__ != "PartSegImage.image_reader": This is taken from :py:mod:`PartSegImage.image_reader` """ - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent=parent) # noinspection PyArgumentList self.reload_btn = QPushButton("Reload algorithms", clicked=self.reload_algorithm_action) - layout = QGridLayout() + layout = QGridLayout(self) layout.addWidget(self.reload_btn, 0, 0) layout.setColumnStretch(1, 1) layout.setRowStretch(1, 1) @@ -83,15 +83,15 @@ def reload_algorithm_action(self): class MaskControl(QWidget): - def __init__(self, settings: ViewSettings): - super().__init__() + def __init__(self, settings: ViewSettings, parent=None): + super().__init__(parent=parent) self.settings = settings self.color_picker = QColorDialog() self.color_picker.setWindowFlag(Qt.WindowType.Widget) self.color_picker.setOptions( QColorDialog.ColorDialogOption.DontUseNativeDialog | QColorDialog.ColorDialogOption.NoButtons ) - self.opacity_spin = QDoubleSpinBox() + self.opacity_spin = QDoubleSpinBox(self) self.opacity_spin.setRange(0, 1) self.opacity_spin.setSingleStep(0.1) self.opacity_spin.setDecimals(2) @@ -233,7 +233,7 @@ class AdvancedWindow(QTabWidget): :param image_view_names: passed as second argument to :py:class:`~.PColormapList` """ - def __init__(self, settings: ViewSettings, image_view_names: List[str], reload_list=None, parent=None): + def __init__(self, settings: BaseSettings, image_view_names: List[str], reload_list=None, parent=None): super().__init__(parent) self.color_control = ColorControl(settings, image_view_names) self.settings = settings diff --git a/package/PartSeg/common_gui/algorithms_description.py b/package/PartSeg/common_gui/algorithms_description.py index ca9b5139f..6494678f7 100644 --- a/package/PartSeg/common_gui/algorithms_description.py +++ b/package/PartSeg/common_gui/algorithms_description.py @@ -72,8 +72,8 @@ def _pretty_print(data, indent=2) -> str: class ProfileSelect(QComboBox): - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent=parent) self._settings = None def _update_choices(self): @@ -189,7 +189,7 @@ def _get_numeric_field(ap: AlgorithmProperty): @classmethod def _get_field_from_value_type(cls, ap: AlgorithmProperty): if issubclass(ap.value_type, Channel): - res = ChannelComboBox() + res = ChannelComboBox(parent=None) res.change_channels_num(10) elif issubclass(ap.value_type, AlgorithmDescribeBase): res = SubAlgorithmWidget(ap) @@ -205,7 +205,7 @@ def _get_field_from_value_type(cls, ap: AlgorithmProperty): elif issubclass(ap.value_type, ROIExtractionProfile): res = ProfileSelect() elif issubclass(ap.value_type, list): - res = QComboBox() + res = QComboBox(parent=None) res.addItems(list(map(str, ap.possible_values))) elif issubclass(ap.value_type, BaseModel): res = FieldsList([cls.from_algorithm_property(x) for x in base_model_to_algorithm_property(ap.value_type)]) diff --git a/package/PartSeg/common_gui/collapse_checkbox.py b/package/PartSeg/common_gui/collapse_checkbox.py index a04597fb7..70c6d9a0c 100644 --- a/package/PartSeg/common_gui/collapse_checkbox.py +++ b/package/PartSeg/common_gui/collapse_checkbox.py @@ -13,8 +13,8 @@ class CollapseCheckbox(QCheckBox): Check box for hide widgets. It is painted as: ▶, {info_text}, line - If triangle is ▶ then widgets are hidden - If triangle is ▼ then widgets are shown + If triangle is ▶ then widgets are hidden. + If triangle is ▼ then widgets are shown. :param info_text: optional text to be show """ @@ -25,7 +25,7 @@ def __init__(self, info_text: str = "", parent: typing.Optional[QWidget] = None) self.stateChanged.connect(self.hide_element) metrics = QFontMetrics(QFont()) - self.text_size = metrics.size(Qt.TextSingleLine, info_text) + self.text_size = metrics.size(Qt.TextFlag.TextSingleLine, info_text) self.info_text = info_text def add_hide_element(self, val: QWidget): diff --git a/package/PartSeg/common_gui/colormap_creator.py b/package/PartSeg/common_gui/colormap_creator.py index 2362a8686..3c8b406fd 100644 --- a/package/PartSeg/common_gui/colormap_creator.py +++ b/package/PartSeg/common_gui/colormap_creator.py @@ -88,9 +88,9 @@ def paintEvent(self, a0: QPaintEvent) -> None: for pos_factor in self.position_list: pos = width * pos_factor point = QPointF(pos + margin, self.height() / 2) - painter.setBrush(QBrush(Qt.black)) + painter.setBrush(QBrush(Qt.GlobalColor.black)) painter.drawEllipse(point, 5, 5) - painter.setBrush(QBrush(Qt.white)) + painter.setBrush(QBrush(Qt.GlobalColor.white)) painter.drawEllipse(point, 3, 3) painter.restore() @@ -495,7 +495,7 @@ def __init__( self.colormap_map = colormap_map self._widget_dict: Dict[str, ChannelPreview] = {} self.scroll_area = QScrollArea() - self.central_widget = QWidget() + self.central_widget = QWidget(self) layout2 = QVBoxLayout() self.grid_layout = QGridLayout() layout2.addLayout(self.grid_layout) diff --git a/package/PartSeg/common_gui/custom_load_dialog.py b/package/PartSeg/common_gui/custom_load_dialog.py index 534592f41..c20dbd1f7 100644 --- a/package/PartSeg/common_gui/custom_load_dialog.py +++ b/package/PartSeg/common_gui/custom_load_dialog.py @@ -149,7 +149,7 @@ def __init__( def accept(self): super().accept() - if self.result() != QFileDialog.Accepted: + if self.result() != QFileDialog.DialogCode.Accepted: return directory = dirname(self.selectedFiles()[0]) self.settings.add_path_history(directory) diff --git a/package/PartSeg/common_gui/custom_save_dialog.py b/package/PartSeg/common_gui/custom_save_dialog.py index 01552ed0b..7164a54af 100644 --- a/package/PartSeg/common_gui/custom_save_dialog.py +++ b/package/PartSeg/common_gui/custom_save_dialog.py @@ -59,12 +59,12 @@ def __init__( parent=None, caption="Save file", history: typing.Optional[typing.List[str]] = None, - file_mode=QFileDialog.AnyFile, + file_mode=QFileDialog.FileMode.AnyFile, ): super().__init__(save_register, caption, parent) self.setFileMode(file_mode) - self.setOption(QFileDialog.DontUseNativeDialog, not system_widget) - self.setAcceptMode(QFileDialog.AcceptSave) + self.setOption(QFileDialog.Option.DontUseNativeDialog, not system_widget) + self.setAcceptMode(QFileDialog.AcceptMode.AcceptSave) self.filterSelected.connect(self.change_filter) self.accepted_native = False self.values = {} @@ -161,7 +161,7 @@ def __init__( base_values: typing.Optional[dict] = None, parent=None, caption="Save file", - file_mode=QFileDialog.AnyFile, + file_mode=QFileDialog.FileMode.AnyFile, ): if default_directory is None: default_directory = str(Path.home()) @@ -183,7 +183,7 @@ def __init__( def accept(self): super().accept() - if self.result() != QDialog.Accepted: + if self.result() != QDialog.DialogCode.Accepted: return directory = os.path.dirname(self.selectedFiles()[0]) self.settings.add_path_history(directory) diff --git a/package/PartSeg/common_gui/error_report.py b/package/PartSeg/common_gui/error_report.py index 345210d93..d56c7420e 100644 --- a/package/PartSeg/common_gui/error_report.py +++ b/package/PartSeg/common_gui/error_report.py @@ -259,9 +259,9 @@ def __init__( else: exception, traceback_summary = exception if isinstance(exception, SegmentationLimitException): - super().__init__(f"{exception}", parent, QListWidgetItem.UserType) + super().__init__(f"{exception}", parent, QListWidgetItem.ItemType.UserType) elif isinstance(exception, Exception): - super().__init__(f"{type(exception)}: {exception}", parent, QListWidgetItem.UserType) + super().__init__(f"{type(exception)}: {exception}", parent, QListWidgetItem.ItemType.UserType) self.setToolTip("Double click for report") self.exception = exception self.additional_info = traceback_summary @@ -357,7 +357,7 @@ class QMessageFromException(QMessageBox): """ - def __init__(self, icon, title, text, exception, standard_buttons=QMessageBox.Ok, parent=None): + def __init__(self, icon, title, text, exception, standard_buttons=QMessageBox.StandardButton.Ok, parent=None): super().__init__(icon, title, text, standard_buttons, parent) self.exception = exception stream = io.StringIO() diff --git a/package/PartSeg/common_gui/flow_layout.py b/package/PartSeg/common_gui/flow_layout.py index c01bf756f..41c2d3aae 100644 --- a/package/PartSeg/common_gui/flow_layout.py +++ b/package/PartSeg/common_gui/flow_layout.py @@ -131,10 +131,10 @@ def doLayout(self, rect, testOnly): wid = item.widget() if wid is not None: space_x = self.spacing() + wid.style().layoutSpacing( - QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal + QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Horizontal ) space_y = self.spacing() + wid.style().layoutSpacing( - QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical + QSizePolicy.ControlType.PushButton, QSizePolicy.ControlType.PushButton, Qt.Orientation.Vertical ) else: space_x = self.spacing() # + wid.layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, diff --git a/package/PartSeg/common_gui/image_adjustment.py b/package/PartSeg/common_gui/image_adjustment.py index 442da9423..d543fab27 100644 --- a/package/PartSeg/common_gui/image_adjustment.py +++ b/package/PartSeg/common_gui/image_adjustment.py @@ -22,7 +22,7 @@ def __init__(self, image: Image, transform_dict: Optional[Dict[str, TransformBas for key, val in transform_dict.items(): self.choose.addItem(key) initial_values = val.calculate_initial(image) - form_widget = FormWidget(val.get_fields_per_dimension(image.get_dimension_letters()), initial_values) + form_widget = FormWidget(val.get_fields_per_dimension(list(image.get_dimension_letters())), initial_values) self.stacked.addWidget(form_widget) self.choose.currentIndexChanged.connect(self.stacked.setCurrentIndex) diff --git a/package/PartSeg/common_gui/multiple_file_widget.py b/package/PartSeg/common_gui/multiple_file_widget.py index 658bce3d6..ec956cc09 100644 --- a/package/PartSeg/common_gui/multiple_file_widget.py +++ b/package/PartSeg/common_gui/multiple_file_widget.py @@ -42,7 +42,7 @@ class MultipleFilesTreeWidget(QTreeWidget): def __init__(self, compare, parent=None): super().__init__(parent) self.compare = compare - self.setContextMenuPolicy(Qt.CustomContextMenu) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.showContextMenu) def showContextMenu(self, point): @@ -67,7 +67,7 @@ def set_show_compare(self, compare: bool): self.compare = compare def mouseMoveEvent(self, event): # pylint: disable=no-self-use - QApplication.setOverrideCursor(Qt.ArrowCursor) + QApplication.setOverrideCursor(Qt.CursorShape.ArrowCursor) super().mouseMoveEvent(event) @@ -76,14 +76,14 @@ def __init__(self, settings: BaseSettings, parent=None): super().__init__(parent) self.settings = settings self.file_list = QListWidget() - self.file_list.setSelectionMode(QAbstractItemView.ExtendedSelection) + self.file_list.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.cancel_btn = QPushButton("Cancel", clicked=self.reject) self.load_btn = QPushButton("Load", clicked=self.accept) for name_list, method in settings.get_last_files_multiple(): entry = f"{name_list[0]} {method}" item = QListWidgetItem(entry, self.file_list) - item.setData(Qt.UserRole, (name_list, method)) + item.setData(Qt.ItemDataRole.UserRole, (name_list, method)) last_set = {(tuple(x), y) for x, y in settings.get_last_files_multiple()} for name_list, method in settings.get_last_files(): @@ -91,7 +91,7 @@ def __init__(self, settings: BaseSettings, parent=None): continue entry = f"{name_list[0]} {method}" item = QListWidgetItem(entry, self.file_list) - item.setData(Qt.UserRole, (name_list, method)) + item.setData(Qt.ItemDataRole.UserRole, (name_list, method)) layout = QGridLayout() layout.addWidget(QLabel("Select files")) @@ -105,7 +105,7 @@ def __init__(self, settings: BaseSettings, parent=None): ) def get_files(self) -> List[Tuple[List[str], str]]: - return [item.data(Qt.UserRole) for item in self.file_list.selectedItems()] + return [item.data(Qt.ItemDataRole.UserRole) for item in self.file_list.selectedItems()] def accept(self) -> None: self.settings.set_in_profile("multiple_files_dialog_size", (self.size().width(), self.size().height())) @@ -281,7 +281,7 @@ def save_state_action(self, state: ProjectInfoBase, custom_name): except ValueError: metric = QFontMetrics(self.file_view.font()) width = self.file_view.width() - 45 - clipped_text = metric.elidedText(normed_file_path, Qt.ElideLeft, width) + clipped_text = metric.elidedText(normed_file_path, Qt.TextElideMode.ElideLeft, width) item = QTreeWidgetItem(self.file_view, [clipped_text]) item.setToolTip(0, normed_file_path) self.file_list.append(normed_file_path) @@ -382,7 +382,7 @@ class MultipleLoadDialog(CustomLoadDialog): def __init__(self, load_register, history=None): load_register = {key: val for key, val in load_register.items() if not val.partial()} super().__init__(load_register=load_register, history=history) - self.setFileMode(QFileDialog.ExistingFiles) + self.setFileMode(QFileDialog.FileMode.ExistingFiles) def accept(self): self.files_list.extend(self.selectedFiles()) diff --git a/package/PartSeg/common_gui/napari_image_view.py b/package/PartSeg/common_gui/napari_image_view.py index 68b854745..cb02eb08a 100644 --- a/package/PartSeg/common_gui/napari_image_view.py +++ b/package/PartSeg/common_gui/napari_image_view.py @@ -171,7 +171,7 @@ def __init__( self.search_roi_btn.clicked.connect(self._search_component) self.search_roi_btn.setDisabled(True) self.roll_dim_button = QtViewerPushButton(self.viewer, "roll", "Roll dimension", self._rotate_dim) - self.roll_dim_button.setContextMenuPolicy(Qt.CustomContextMenu) + self.roll_dim_button.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.roll_dim_button.customContextMenuRequested.connect(self._dim_order_menu) self.mask_chk = QCheckBox() self.mask_chk.setVisible(False) diff --git a/package/PartSeg/common_gui/numpy_qimage.py b/package/PartSeg/common_gui/numpy_qimage.py index 0b3a476bd..dedfe21e8 100644 --- a/package/PartSeg/common_gui/numpy_qimage.py +++ b/package/PartSeg/common_gui/numpy_qimage.py @@ -19,7 +19,7 @@ def __init__(self, image: np.ndarray): image.shape[1], image.shape[0], image.dtype.itemsize * image.shape[1] * image.shape[2], - QImage.Format_RGBA8888, + QImage.Format.Format_RGBA8888, ) self.image = image diff --git a/package/PartSeg/common_gui/qt_modal.py b/package/PartSeg/common_gui/qt_modal.py index e259ad1e2..0ab34b1a0 100644 --- a/package/PartSeg/common_gui/qt_modal.py +++ b/package/PartSeg/common_gui/qt_modal.py @@ -1,6 +1,6 @@ """from napari._qt.dialog.modal """ from qtpy.QtCore import QPoint, QRect, Qt -from qtpy.QtGui import QCursor, QGuiApplication +from qtpy.QtGui import QCursor, QGuiApplication, QKeyEvent from qtpy.QtWidgets import QDialog, QFrame, QVBoxLayout @@ -37,7 +37,7 @@ def __init__(self, parent): super().__init__(parent) self.setObjectName("QtModalPopup") self.setModal(False) # if False, then clicking anywhere else closes it - self.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint) + self.setWindowFlags(Qt.WindowType.Popup | Qt.WindowType.FramelessWindowHint) self.setLayout(QVBoxLayout()) self.frame = QFrame() @@ -121,15 +121,15 @@ def move_to(self, position="top", *, win_ratio=0.9, min_length=0): top = max(min(screen_geometry.bottom() - height, top), screen_geometry.top()) self.setGeometry(left, top, width, height) - def keyPressEvent(self, event): + def keyPressEvent(self, event: QKeyEvent): """Close window on return, else pass event through to super class. Parameters ---------- - event : qtpy.QtCore.QEvent + event : qtpy.QtGui.QKeyEvent Event from the Qt context. """ - if event.key() in (Qt.Key_Return, Qt.Key_Enter): + if event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter): self.close() return super().keyPressEvent(event) diff --git a/package/PartSeg/common_gui/searchable_combo_box.py b/package/PartSeg/common_gui/searchable_combo_box.py index 517a13a46..68f32d4d6 100644 --- a/package/PartSeg/common_gui/searchable_combo_box.py +++ b/package/PartSeg/common_gui/searchable_combo_box.py @@ -16,11 +16,11 @@ def __init__(self, parent=None): super().__init__(parent) self.setEditable(True) self.completer_object = QCompleter() - self.completer_object.setCaseSensitivity(Qt.CaseInsensitive) - self.completer_object.setCompletionMode(QCompleter.PopupCompletion) - self.completer_object.setFilterMode(Qt.MatchContains) + self.completer_object.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) + self.completer_object.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) + self.completer_object.setFilterMode(Qt.MatchFlag.MatchContains) self.setCompleter(self.completer_object) - self.setInsertPolicy(QComboBox.NoInsert) + self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert) if parse(QT_VERSION) < parse("5.14.0"): # pragma: no cover self.currentIndexChanged.connect(self._text_activated) diff --git a/package/PartSeg/common_gui/searchable_list_widget.py b/package/PartSeg/common_gui/searchable_list_widget.py index 8fa7785c9..3b1f0dd11 100644 --- a/package/PartSeg/common_gui/searchable_list_widget.py +++ b/package/PartSeg/common_gui/searchable_list_widget.py @@ -22,7 +22,7 @@ def __getattr__(self, item): return super().__getattr__(item) def update_visible(self, text): - items_text = [x.text() for x in self.list_widget.findItems(text, Qt.MatchContains)] + items_text = [x.text() for x in self.list_widget.findItems(text, Qt.MatchFlag.MatchContains)] for index in range(self.list_widget.count()): item = self.item(index) item.setHidden(item.text() not in items_text) diff --git a/package/PartSeg/common_gui/select_multiple_files.py b/package/PartSeg/common_gui/select_multiple_files.py index 37dc118ff..751a00417 100644 --- a/package/PartSeg/common_gui/select_multiple_files.py +++ b/package/PartSeg/common_gui/select_multiple_files.py @@ -38,7 +38,7 @@ def __init__(self, files): discard = QPushButton("Discard", self) discard.clicked.connect(self.close) self.files = QListWidget(self) - self.files.setSelectionMode(QAbstractItemView.ExtendedSelection) + self.files.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) for file_name in files: self.files.addItem(file_name) for i in range(self.files.count()): @@ -78,7 +78,7 @@ def __init__(self, file_path): class FileListWidget(QListWidget): def __init__(self, parent=None): super().__init__(parent) - self.setContextMenuPolicy(Qt.CustomContextMenu) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) class AddFiles(QWidget): @@ -195,7 +195,7 @@ def find_all(self): self.update_files_list(paths) else: - QMessageBox.warning(self, "No new files", "No new files found", QMessageBox.Ok) + QMessageBox.warning(self, "No new files", "No new files found", QMessageBox.StandardButton.Ok) def update_files_list(self, paths): dialog = AcceptFiles(paths) @@ -209,7 +209,7 @@ def update_files_list(self, paths): def select_files(self): dial = QFileDialog(self, "Select files") dial.setDirectory(self.settings.get(IO_BATCH_DIRECTORY, self.settings.get(OPEN_DIRECTORY, str(Path.home())))) - dial.setFileMode(QFileDialog.ExistingFiles) + dial.setFileMode(QFileDialog.FileMode.ExistingFiles) if dial.exec_(): self.settings.set(IO_BATCH_DIRECTORY, os.path.dirname(str(dial.selectedFiles()[0]))) new_paths = sorted(set(map(str, dial.selectedFiles())) - self.files_to_proceed) diff --git a/package/PartSeg/common_gui/show_directory_dialog.py b/package/PartSeg/common_gui/show_directory_dialog.py index eab940373..3f4dab43d 100644 --- a/package/PartSeg/common_gui/show_directory_dialog.py +++ b/package/PartSeg/common_gui/show_directory_dialog.py @@ -13,7 +13,7 @@ def __init__(self, path_to_directory, additional_text=""): self.path_to_directory = path_to_directory text_label = QLabel(path_to_directory) text_label.setWordWrap(True) - text_label.setTextInteractionFlags(Qt.TextSelectableByMouse) + text_label.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse) open_btn = QPushButton("Open directory") open_btn.clicked.connect(self.open_folder) close_btn = QPushButton("Close") diff --git a/package/PartSeg/common_gui/universal_gui_part.py b/package/PartSeg/common_gui/universal_gui_part.py index 974f9d6a6..3c012db23 100644 --- a/package/PartSeg/common_gui/universal_gui_part.py +++ b/package/PartSeg/common_gui/universal_gui_part.py @@ -141,12 +141,13 @@ def __init__( lab = QLabel(f"{name}:") layout.addWidget(lab) val = QDoubleSpinBox() - val.setButtonSymbols(QAbstractSpinBox.NoButtons) + val.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons) val.setRange(*data_range) val.setValue(value * UNIT_SCALE[unit.value]) - val.setAlignment(Qt.AlignRight) + val.setAlignment(Qt.AlignmentFlag.AlignRight) font = val.font() fm = QFontMetrics(font) + # TODO check width attribute val_len = max(fm.width(str(data_range[0])), fm.width(str(data_range[1]))) + fm.width(" " * 8) val.setFixedWidth(val_len) layout.addWidget(val) @@ -171,7 +172,7 @@ def get_unit_str(self): def right_label(text): label = QLabel(text) - label.setAlignment(Qt.AlignVCenter | Qt.AlignRight) + label.setAlignment(Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignRight) return label @@ -189,7 +190,7 @@ class CustomSpinBox(QSpinBox): def __init__(self, *args, bounds=None, **kwargs): super().__init__(*args, **kwargs) - self.setStepType(QAbstractSpinBox.AdaptiveDecimalStepType) + self.setStepType(QAbstractSpinBox.StepType.AdaptiveDecimalStepType) if bounds is not None: warnings.warn("bounds parameter is deprecated", FutureWarning, stacklevel=2) # pragma: no cover @@ -208,7 +209,7 @@ class CustomDoubleSpinBox(QDoubleSpinBox): def __init__(self, *args, bounds=None, **kwargs): super().__init__(*args, **kwargs) - self.setStepType(QAbstractSpinBox.AdaptiveDecimalStepType) + self.setStepType(QAbstractSpinBox.StepType.AdaptiveDecimalStepType) if bounds is not None: warnings.warn("bounds parameter is deprecated", FutureWarning, stacklevel=2) # pragma: no cover @@ -351,7 +352,7 @@ def __init__(self, lines=5, text="", parent=None): self.lines = lines self.setReadOnly(True) p: QPalette = self.palette() - p.setColor(QPalette.Base, p.color(self.backgroundRole())) + p.setColor(QPalette.ColorRole.Base, p.color(self.backgroundRole())) self.setPalette(p) def height(self): diff --git a/package/tests/test_PartSeg/test_colormap_create.py b/package/tests/test_PartSeg/test_colormap_create.py index 5221ed223..0f373444c 100644 --- a/package/tests/test_PartSeg/test_colormap_create.py +++ b/package/tests/test_PartSeg/test_colormap_create.py @@ -33,8 +33,9 @@ def test_color_conversion(): class TestColormapEdit: - def test_click(self, qtbot: QtBot): + def test_click(self, qtbot: QtBot, qapp): widget = ColormapEdit() + widget.show() qtbot.addWidget(widget) width = widget.width() - 20 with qtbot.waitSignal(widget.double_clicked): @@ -47,6 +48,8 @@ def test_click(self, qtbot: QtBot): with qtbot.assertNotEmitted(widget.double_clicked): qtbot.mouseDClick(widget, Qt.LeftButton, pos=QPoint(30, widget.height() // 2)) assert len(widget.colormap.colors) == 3 + qapp.processEvents() + widget.hide() def test_distribute_evenly(self, qtbot: QtBot): widget = ColormapEdit() From 79b1564a5957540cf3f6800ee1e28d0945253100 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 8 Dec 2023 21:37:36 +0100 Subject: [PATCH 02/51] refactor: Fix qt flags in roi mask code (#1042) ## Summary by CodeRabbit - **Refactor** - Updated event and modifier constants to align with the latest standards in the user interface library. - **Bug Fixes** - Ensured consistent behavior of keyboard and window event handling across the application. --- package/PartSeg/_roi_mask/main_window.py | 40 +++++++++++-------- .../_roi_mask/segmentation_info_dialog.py | 2 +- .../PartSeg/_roi_mask/simple_measurements.py | 6 +-- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/package/PartSeg/_roi_mask/main_window.py b/package/PartSeg/_roi_mask/main_window.py index 13977d4dd..870c30de1 100644 --- a/package/PartSeg/_roi_mask/main_window.py +++ b/package/PartSeg/_roi_mask/main_window.py @@ -211,11 +211,11 @@ def set_image(self, image: Image) -> bool: self, "Not supported", "Time data are currently not supported. Maybe You would like to treat time as z-stack", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No, ) - if res == QMessageBox.Yes: + if res == QMessageBox.StandardButton.Yes: image = image.swap_time_and_stack() else: return False @@ -314,7 +314,9 @@ def save_segmentation(self): save_location, _selected_filter, save_class, values = dial.get_result() def exception_hook(exception): - QMessageBox.critical(self, "Save error", f"Error on disc operation. Text: {exception}", QMessageBox.Ok) + QMessageBox.critical( + self, "Save error", f"Error on disc operation. Text: {exception}", QMessageBox.StandardButton.Ok + ) raise exception dial = ExecuteFunctionDialog( @@ -326,8 +328,12 @@ def exception_hook(exception): dial.exec_() def save_result(self): - if self.settings.image_path is not None and QMessageBox.Yes == QMessageBox.question( - self, "Copy", "Copy name to clipboard?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes + if self.settings.image_path is not None and QMessageBox.StandardButton.Yes == QMessageBox.question( + self, + "Copy", + "Copy name to clipboard?", + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.Yes, ): clipboard = QGuiApplication.clipboard() clipboard.setText(os.path.splitext(os.path.basename(self.settings.image_path))[0]) @@ -354,17 +360,19 @@ def save_result(self): if conflict: # TODO modify because of long lists conflict_str = "\n".join(conflict) - if QMessageBox.No == QMessageBox.warning( + if QMessageBox.StandardButton.No == QMessageBox.warning( self, "Overwrite", f"Overwrite files:\n {conflict_str}", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No, + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No, ): self.save_result() def exception_hook(exception): - QMessageBox.critical(self, "Save error", f"Error on disc operation. Text: {exception}", QMessageBox.Ok) + QMessageBox.critical( + self, "Save error", f"Error on disc operation. Text: {exception}", QMessageBox.StandardButton.Ok + ) dial = ExecuteFunctionDialog( res.save_class.save, @@ -392,7 +400,7 @@ def leaveEvent(self, _event): class ChosenComponents(QWidget): """ - :type check_box: dict[int, QCheckBox] + :type check_box: dict[int, ComponentCheckBox] """ check_change_signal = Signal() @@ -769,7 +777,7 @@ def __init__(self, settings: StackSettings, parent=None): super().__init__(parent) self._settings = settings self.path = QTextEdit("Path: example image") - self.path.setWordWrapMode(QTextOption.WrapAnywhere) + self.path.setWordWrapMode(QTextOption.WrapMode.WrapAnywhere) self.path.setReadOnly(True) self.setMinimumHeight(20) self.spacing = [QDoubleSpinBox() for _ in range(3)] @@ -785,8 +793,8 @@ def __init__(self, settings: StackSettings, parent=None): self.sync_dirs.stateChanged.connect(self.set_sync_dirs) units_value = self._settings.get("units_value", Units.nm) for el in self.spacing: - el.setAlignment(Qt.AlignRight) - el.setButtonSymbols(QAbstractSpinBox.NoButtons) + el.setAlignment(Qt.AlignmentFlag.AlignRight) + el.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons) el.setRange(0, 100000) # noinspection PyUnresolvedReferences el.valueChanged.connect(self.image_spacing_change) @@ -898,7 +906,7 @@ def __init__( # noqa: PLR0915 self.image_view = StackImageView(self.settings, self.channel_control, name="channelcontrol") self.image_view.setMinimumWidth(450) self.info_text = QLabel() - self.info_text.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) + self.info_text.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Preferred) self.image_view.text_info_change.connect(self.info_text.setText) self.options_panel = Options(self.settings, self.image_view) self.main_menu = MainMenu(self.settings, self) @@ -930,7 +938,7 @@ def __init__( # noqa: PLR0915 view_menu.addAction("Toggle scale bar").triggered.connect(self._toggle_scale_bar) action = view_menu.addAction("Screenshot") action.triggered.connect(self.screenshot(self.image_view)) - action.setShortcut(QKeySequence.Print) + action.setShortcut(QKeySequence.StandardKey.Print) image_menu = menu_bar.addMenu("Image operations") image_menu.addAction("Image adjustment").triggered.connect(self.image_adjust_exec) help_menu = menu_bar.addMenu("Help") diff --git a/package/PartSeg/_roi_mask/segmentation_info_dialog.py b/package/PartSeg/_roi_mask/segmentation_info_dialog.py index abac19ac2..fb708953a 100644 --- a/package/PartSeg/_roi_mask/segmentation_info_dialog.py +++ b/package/PartSeg/_roi_mask/segmentation_info_dialog.py @@ -74,7 +74,7 @@ def set_parameter_action(self): self.set_parameters(parameters.algorithm, parameters.values) def event(self, event: QEvent): - if event.type() == QEvent.WindowActivate: + if event.type() == QEvent.Type.WindowActivate: index = self.components.currentRow() self.components.clear() self.components.addItems(list(map(str, self.get_parameters.keys()))) diff --git a/package/PartSeg/_roi_mask/simple_measurements.py b/package/PartSeg/_roi_mask/simple_measurements.py index 4094e345f..00517c822 100644 --- a/package/PartSeg/_roi_mask/simple_measurements.py +++ b/package/PartSeg/_roi_mask/simple_measurements.py @@ -141,11 +141,11 @@ def refresh_measurements(self): self.measurement_layout.addWidget(chk) def keyPressEvent(self, e: QKeyEvent): - if not e.modifiers() & Qt.ControlModifier: + if not e.modifiers() & Qt.KeyboardModifier.ControlModifier: return selected = self.result_view.selectedRanges() - if e.key() == Qt.Key_C: # copy + if e.key() == Qt.Key.Key_C: # copy s = "" for r in range(selected[0].topRow(), selected[0].bottomRow() + 1): @@ -158,7 +158,7 @@ def keyPressEvent(self, e: QKeyEvent): QApplication.clipboard().setText(s) def event(self, event: QEvent) -> bool: - if event.type() == QEvent.WindowActivate: + if event.type() == QEvent.Type.WindowActivate: if self.settings.image is not None: self.channel_select.change_channels_num(self.settings.image.channels) self.refresh_measurements() From 20eff8929a9dea676e2368feec477606a36795fa Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 8 Dec 2023 23:30:12 +0100 Subject: [PATCH 03/51] refactor: fix qt flags in roi analysis (#1043) ## Summary by CodeRabbit - **Refactor** - Updated Qt library API usage across various components for alignment with the latest Qt framework conventions. - **Bug Fixes** - Ensured optional handling of pipeline results to prevent potential crashes when no result is present. - **Documentation** - No visible changes to end-user documentation in this release. --- .../PartSeg/_roi_analysis/advanced_window.py | 4 +-- .../calculation_pipeline_thread.py | 2 +- package/PartSeg/_roi_analysis/main_window.py | 17 ++++++----- .../_roi_analysis/measurement_widget.py | 4 +-- .../_roi_analysis/prepare_plan_widget.py | 10 +++---- .../PartSeg/_roi_analysis/profile_export.py | 28 +++++++++---------- 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/package/PartSeg/_roi_analysis/advanced_window.py b/package/PartSeg/_roi_analysis/advanced_window.py index 7fec48bf9..600289d0a 100644 --- a/package/PartSeg/_roi_analysis/advanced_window.py +++ b/package/PartSeg/_roi_analysis/advanced_window.py @@ -100,7 +100,7 @@ def __init__(self, settings: PartSettings): units_value = self._settings.get("units_value", Units.nm) for el in self.spacing: - el.setAlignment(Qt.AlignRight) + el.setAlignment(Qt.AlignmentFlag.AlignRight) el.setButtonSymbols(QAbstractSpinBox.NoButtons) el.setRange(0, 1000000) # noinspection PyUnresolvedReferences @@ -225,7 +225,7 @@ def showEvent(self, _event): self.update_spacing() def event(self, event: QEvent): - if event.type() == QEvent.WindowActivate and self.isVisible(): + if event.type() == QEvent.Type.WindowActivate and self.isVisible(): self.update_spacing() return super().event(event) diff --git a/package/PartSeg/_roi_analysis/calculation_pipeline_thread.py b/package/PartSeg/_roi_analysis/calculation_pipeline_thread.py index 76f6d8f73..2047caae9 100644 --- a/package/PartSeg/_roi_analysis/calculation_pipeline_thread.py +++ b/package/PartSeg/_roi_analysis/calculation_pipeline_thread.py @@ -9,7 +9,7 @@ class CalculatePipelineThread(ProgressTread): - result: PipelineResult + result: typing.Optional[PipelineResult] def __init__(self, image: Image, mask: typing.Union[np.ndarray, None], pipeline: SegmentationPipeline, parent=None): super().__init__(parent=parent) diff --git a/package/PartSeg/_roi_analysis/main_window.py b/package/PartSeg/_roi_analysis/main_window.py index 27dee0093..f44a476f0 100644 --- a/package/PartSeg/_roi_analysis/main_window.py +++ b/package/PartSeg/_roi_analysis/main_window.py @@ -229,19 +229,19 @@ def choose_pipeline(self, text): def update_tooltips(self): for i in range(1, self.choose_profile.count()): - if self.choose_profile.itemData(i, Qt.ToolTipRole) is not None: + if self.choose_profile.itemData(i, Qt.ItemDataRole.ToolTipRole) is not None: continue text = self.choose_profile.itemText(i) profile: ROIExtractionProfile = self._settings.roi_profiles[text] tool_tip_text = str(profile) - self.choose_profile.setItemData(i, tool_tip_text, Qt.ToolTipRole) + self.choose_profile.setItemData(i, tool_tip_text, Qt.ItemDataRole.ToolTipRole) for i in range(1, self.choose_pipe.count()): - if self.choose_pipe.itemData(i, Qt.ToolTipRole) is not None: + if self.choose_pipe.itemData(i, Qt.ItemDataRole.ToolTipRole) is not None: continue text = self.choose_pipe.itemText(i) profile: SegmentationPipeline = self._settings.roi_pipelines[text] tool_tip_text = str(profile) - self.choose_pipe.setItemData(i, tool_tip_text, Qt.ToolTipRole) + self.choose_pipe.setItemData(i, tool_tip_text, Qt.ItemDataRole.ToolTipRole) @staticmethod def update_combo_box(combo_box: QComboBox, dkt: dict): @@ -260,7 +260,10 @@ def update_combo_box(combo_box: QComboBox, dkt: dict): combo_box.addItems(sorted(new_names)) def keyPressEvent(self, event: QKeyEvent): - if event.key() in [Qt.Key_Enter, Qt.Key_Return] and event.modifiers() == Qt.ControlModifier: + if ( + event.key() in [Qt.Key.Key_Enter, Qt.Key.Key_Return] + and event.modifiers() == Qt.KeyboardModifier.ControlModifier + ): self.execute_btn.click() def save_profile(self): @@ -383,7 +386,7 @@ def __init__(self, settings: PartSettings, main_window): self.advanced_btn.clicked.connect(self.advanced_window_show) self.mask_manager_btn.clicked.connect(self.mask_manager) self.batch_processing_btn.clicked.connect(self.batch_window) - self.setFocusPolicy(Qt.StrongFocus) + self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) def resizeEvent(self, event: QResizeEvent): if event.size().width() < 800: @@ -608,7 +611,7 @@ def __init__( # noqa: PLR0915 info_layout = QHBoxLayout() info_layout.addWidget(self.left_stack.selector) info_layout.addWidget(self.options_panel.compare_btn) - info_layout.addWidget(self.info_text, 1, Qt.AlignHCenter) + info_layout.addWidget(self.info_text, 1, Qt.AlignmentFlag.AlignHCenter) image_layout = EqualColumnLayout() image_layout.addWidget(self.left_stack) diff --git a/package/PartSeg/_roi_analysis/measurement_widget.py b/package/PartSeg/_roi_analysis/measurement_widget.py index f6342c1d2..8d515df63 100644 --- a/package/PartSeg/_roi_analysis/measurement_widget.py +++ b/package/PartSeg/_roi_analysis/measurement_widget.py @@ -284,11 +284,11 @@ def append_measurement_result(self): # pragma: no cover raise NotImplementedError def keyPressEvent(self, e: QKeyEvent): - if not e.modifiers() & Qt.ControlModifier: + if not e.modifiers() & Qt.KeyboardModifier.ControlModifier: return selected = self.info_field.selectedRanges() - if e.key() == Qt.Key_C: # copy + if e.key() == Qt.Key.Key_C: # copy s = "" for r in range(selected[0].topRow(), selected[0].bottomRow() + 1): diff --git a/package/PartSeg/_roi_analysis/prepare_plan_widget.py b/package/PartSeg/_roi_analysis/prepare_plan_widget.py index 6cad8fe59..5829520f0 100644 --- a/package/PartSeg/_roi_analysis/prepare_plan_widget.py +++ b/package/PartSeg/_roi_analysis/prepare_plan_widget.py @@ -80,7 +80,7 @@ def __init__(self, mask_names): super().__init__() self.mask_names = mask_names completer = QCompleter(list(mask_names)) - completer.setCaseSensitivity(Qt.CaseInsensitive) + completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self.setWindowTitle("Masks name choose") self.mask1_name = QLineEdit() self.cancel_btn = QPushButton("Cancel") @@ -119,7 +119,7 @@ def __init__(self, mask_names: typing.Iterable[str]): super().__init__() self.mask_names = mask_names completer = QCompleter(list(mask_names)) - completer.setCaseSensitivity(Qt.CaseInsensitive) + completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) self.setWindowTitle("Masks name choose") self.mask1_name = QLineEdit() self.mask2_name = QLineEdit() @@ -943,7 +943,7 @@ def __init__(self, parent=None, calculation_plan=None): self.calculation_plan = None self.header().close() self.itemSelectionChanged.connect(self.set_path) - self.setContextMenuPolicy(Qt.CustomContextMenu) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) if calculation_plan is not None: self.set_plan(calculation_plan) @@ -1001,7 +1001,7 @@ def explore_tree(self, up_widget, node_plan, deep=True): widget.setText(0, CalculationPlan.get_el_name(node_plan.operation)) self.setCurrentItem(widget) if isinstance(node_plan.operation, (MeasurementCalculate, ROIExtractionProfile)): - widget.setData(0, Qt.UserRole, node_plan.operation) + widget.setData(0, Qt.ItemDataRole.UserRole, node_plan.operation) if isinstance(node_plan.operation, (MeasurementCalculate, ROIExtractionProfile, MaskCreate)): desc = QTreeWidgetItem(widget) desc.setText(0, "Description") @@ -1120,7 +1120,7 @@ def __init__(self, settings: PartSettings): def _context_menu(self, point): item = self.plan_view.itemAt(point) - data = item.data(0, Qt.UserRole) + data = item.data(0, Qt.ItemDataRole.UserRole) if data is None: return diff --git a/package/PartSeg/_roi_analysis/profile_export.py b/package/PartSeg/_roi_analysis/profile_export.py index 7f569e3a7..b8feea93f 100644 --- a/package/PartSeg/_roi_analysis/profile_export.py +++ b/package/PartSeg/_roi_analysis/profile_export.py @@ -45,7 +45,7 @@ def preview_object(self, ob): class ProfileDictViewer(ObjectPreview): """ - Preview of :py:class"`SegmentationProfile`. + Preview of :py:class:`SegmentationProfile`. Serialized using :py:meth:`ObjectPreview.pretty_print`. """ @@ -66,8 +66,8 @@ def __init__(self, export_dict, viewer, parent=None): for el in sorted(export_dict.keys()): item = QListWidgetItem(el) # noinspection PyTypeChecker - item.setFlags(item.flags() | Qt.ItemIsUserCheckable) - item.setCheckState(Qt.Checked) + item.setFlags(item.flags() | Qt.ItemFlag.ItemIsUserCheckable) + item.setCheckState(Qt.CheckState.Checked) self.list_view.addItem(item) self.checked_num = len(export_dict) @@ -100,7 +100,7 @@ def __init__(self, export_dict, viewer, parent=None): self.setLayout(layout) def checked_change(self, item): - if item.checkState() == Qt.Unchecked: + if item.checkState() == Qt.CheckState.Unchecked: self.checked_num -= 1 else: self.checked_num += 1 @@ -118,14 +118,14 @@ def preview(self): def check_change(self): item = self.list_view.currentItem() # type: QListWidgetItem index = self.list_view.currentRow() - checked = item.checkState() == Qt.Checked + checked = item.checkState() == Qt.CheckState.Checked self.check_state[index] = checked self.export_btn.setEnabled(np.any(self.check_state)) def uncheck_all(self): for index in range(self.list_view.count()): item = self.list_view.item(index) - item.setCheckState(Qt.Unchecked) + item.setCheckState(Qt.CheckState.Unchecked) self.check_state[...] = False self.export_btn.setDisabled(True) self.checked_num = 0 @@ -133,7 +133,7 @@ def uncheck_all(self): def check_all(self): for index in range(self.list_view.count()): item = self.list_view.item(index) - item.setCheckState(Qt.Checked) + item.setCheckState(Qt.CheckState.Checked) self.checked_num = len(self.export_dict) self.check_state[...] = True self.export_btn.setDisabled(False) @@ -142,7 +142,7 @@ def get_export_list(self): res = [] for num in range(self.list_view.count()): item = self.list_view.item(num) - if item.checkState() == Qt.Checked: + if item.checkState() == Qt.CheckState.Checked: res.append(str(item.text())) return res @@ -190,8 +190,8 @@ def __init__( item = QTreeWidgetItem() item.setText(0, name) # noinspection PyTypeChecker - item.setFlags(item.flags() | Qt.ItemIsUserCheckable) - item.setCheckState(0, Qt.Checked) + item.setFlags(item.flags() | Qt.ItemFlag.ItemIsUserCheckable) + item.setCheckState(0, Qt.CheckState.Checked) self.list_view.addTopLevelItem(item) if name in conflicts: group = QButtonGroup() @@ -288,7 +288,7 @@ def preview(self): self.local_viewer.clear() def checked_change(self, item, _): - if item.checkState(0) == Qt.Unchecked: + if item.checkState(0) == Qt.CheckState.Unchecked: self.checked_num -= 1 if self.list_view.itemWidget(item, 1) is not None: self.list_view.itemWidget(item, 1).setDisabled(True) @@ -309,7 +309,7 @@ def get_import_list(self): res = [] for index in range(self.list_view.topLevelItemCount()): item = self.list_view.topLevelItem(index) - if item.checkState(0) == Qt.Checked: + if item.checkState(0) == Qt.CheckState.Checked: chk = self.list_view.itemWidget(item, 2) if chk is not None and typing.cast(QRadioButton, chk).isChecked(): res.append((item.text(0), typing.cast(QLineEdit, self.list_view.itemWidget(item, 3)).text())) @@ -321,13 +321,13 @@ def get_import_list(self): def uncheck_all(self): for index in range(self.list_view.topLevelItemCount()): item = self.list_view.topLevelItem(index) - item.setCheckState(0, Qt.Unchecked) + item.setCheckState(0, Qt.CheckState.Unchecked) self.import_btn.setDisabled(True) self.checked_num = 0 def check_all(self): for index in range(self.list_view.topLevelItemCount()): item = self.list_view.topLevelItem(index) - item.setCheckState(0, Qt.Checked) + item.setCheckState(0, Qt.CheckState.Checked) self.checked_num = len(self.import_dict) self.import_btn.setDisabled(False) From fa5f9cd391a6803caf478514baa4f6e9a82687e8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 8 Dec 2023 23:49:51 +0100 Subject: [PATCH 04/51] ci: Upload raw coverage information (#1044) For simpler debug upload rav coverage information ## Summary by CodeRabbit - **Chores** - Improved CI/CD pipeline by adding a step to upload coverage reports, enhancing visibility into code quality metrics. --- .github/workflows/base_test_workflow.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index b4628d778..2d6043638 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -97,7 +97,8 @@ jobs: ./report-*.json retention-days: 7 - - uses: actions/upload-artifact@v3 + - name: Upload coverage report ${{ inputs.tox_args }} + uses: actions/upload-artifact@v3 if: ${{ inputs.coverage }} with: name: coverage_report ${{ inputs.tox_args }} @@ -105,6 +106,13 @@ jobs: ./htmlcov retention-days: 7 + - name: Upload coverage raw data + uses: actions/upload-artifact@v3 + with: + name: coverage_raw ${{ inputs.tox_args }} + path: ./coverage.xml + retention-days: 7 + - uses: codecov/codecov-action@v3 if: ${{ inputs.coverage }} with: From 3ecab34b494c4eed77322fd2e27224aea75467c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:24:19 +0100 Subject: [PATCH 05/51] build(deps): bump aganders3/headless-gui from 1 to 2 (#1047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [aganders3/headless-gui](https://github.com/aganders3/headless-gui) from 1 to 2.
Release notes

Sourced from aganders3/headless-gui's releases.

Version 2.0 is not a major change, but it is technically breaking as the default virtual screen size has changed. If you are not relying heavily on the virtual screen size or bit depth you are probably safe to just update. If you want to update and keep the old default, set xvfb-screen-size: "1024x768x16".

What's Changed

Full Changelog: https://github.com/aganders3/headless-gui/compare/v1...v2.0

Version 1.2

What's Changed

New Contributors

Full Changelog: https://github.com/aganders3/headless-gui/compare/v1...v1.2

v1.1

What's Changed

New Contributors

Full Changelog: https://github.com/aganders3/headless-gui/compare/v1...v1.1

Commits
  • 9f7725f Fix printing of screen size in output
  • 7c0bc5d Bump @​babel/traverse from 7.20.1 to 7.23.2 (#8)
  • 946613f Add screen size configuration, update default (#9)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=aganders3/headless-gui&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/base_test_workflow.yml | 2 +- .github/workflows/test_napari_repo.yml | 2 +- .github/workflows/test_prereleases.yml | 4 ++-- .github/workflows/tests.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index 2d6043638..08fbeb601 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -80,7 +80,7 @@ jobs: pip list - name: Test with tox - uses: aganders3/headless-gui@v1 + uses: aganders3/headless-gui@v2 timeout-minutes: ${{ inputs.timeout }} with: run: python -m tox ${{ inputs.tox_args }} diff --git a/.github/workflows/test_napari_repo.yml b/.github/workflows/test_napari_repo.yml index 409b31c0d..d676c0636 100644 --- a/.github/workflows/test_napari_repo.yml +++ b/.github/workflows/test_napari_repo.yml @@ -61,7 +61,7 @@ jobs: - name: Test with tox # run tests using pip install --pre - uses: aganders3/headless-gui@v1 + uses: aganders3/headless-gui@v2 timeout-minutes: 60 with: run: tox diff --git a/.github/workflows/test_prereleases.yml b/.github/workflows/test_prereleases.yml index 076819453..cc5f44655 100644 --- a/.github/workflows/test_prereleases.yml +++ b/.github/workflows/test_prereleases.yml @@ -71,7 +71,7 @@ jobs: - name: Test with tox linux # run tests using pip install --pre - uses: aganders3/headless-gui@v1 + uses: aganders3/headless-gui@v2 timeout-minutes: 60 with: run: python -m tox -v --pre @@ -127,7 +127,7 @@ jobs: name: bundle path: dist2/ - name: Test bundle - uses: aganders3/headless-gui@v1 + uses: aganders3/headless-gui@v2 timeout-minutes: 60 with: run: dist/PartSeg/PartSeg _test diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a2541531..f6d1e8c5e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -171,7 +171,7 @@ jobs: run: sed -e "s/{sys_platform}/{platform}/g" tox.ini -i - name: Test with tox - uses: aganders3/headless-gui@v1 + uses: aganders3/headless-gui@v2 with: run: conda run -n test --no-capture-output tox -e py39-PySide2-conda timeout-minutes: 60 From be16d14f3feb7926444a3e25efa4480f92a00e6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:26:57 +0100 Subject: [PATCH 06/51] build(deps): bump actions/checkout from 3 to 4 (#1045) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
Release notes

Sourced from actions/checkout's releases.

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

v3.5.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v3.5.1...v3.5.2

v3.5.1

What's Changed

New Contributors

... (truncated)

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/semgrep.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml index 26c48814b..b65d27d01 100644 --- a/.github/workflows/semgrep.yml +++ b/.github/workflows/semgrep.yml @@ -28,7 +28,7 @@ jobs: steps: # Fetch project source with GitHub Actions Checkout. - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Run the "semgrep ci" command on the command line of the docker image. - run: semgrep ci env: From 7ef0b010fbbaf57140b40487fb0b67a0f65a6d3d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 13:01:06 +0100 Subject: [PATCH 07/51] ci: [pre-commit.ci] pre-commit autoupdate (#1036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 23.10.1 → 23.11.0](https://github.com/psf/black-pre-commit-mirror/compare/23.10.1...23.11.0) - [github.com/astral-sh/ruff-pre-commit: v0.1.3 → v0.1.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.3...v0.1.7) - [github.com/pre-commit/mirrors-mypy: v1.6.1 → v1.7.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.1...v1.7.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14d1496cb..90ddc860a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.10.1 + rev: 23.11.0 hooks: - id: black pass_filenames: true @@ -25,7 +25,7 @@ repos: - id: setup-cfg-fmt args: ["--include-version-classifiers", "--max-py-version", "3.11"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.3 + rev: v0.1.7 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade @@ -49,7 +49,7 @@ repos: - mdformat-toc - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.6.1' # Use the sha / tag you want to point at + rev: 'v1.7.1' # Use the sha / tag you want to point at hooks: - id: mypy files: ^package/PartSegImage/.+\.py From 33f108ae118d8a5e070554ffcda7d2e00e1f286e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:13:07 +0100 Subject: [PATCH 08/51] build(deps): bump hynek/build-and-inspect-python-package from 1 to 2 (#1050) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 1 to 2.
Release notes

Sourced from hynek/build-and-inspect-python-package's releases.

v2.0.0

This release switches to actions/upload-artifact v4, which is incompatible with older versions of actions/download-artifact (and vice versa).

  • If you're using download-artifact@v3, do not upgrade.
  • If you want to use download-artifact@v4, you must upgrade.

v1.5.4

Fixed

  • Stop trying to cache. Fixes Error: No file in /home/runner/work/pytest-cpp/pytest-cpp matched to [**/requirements.txt or **/pyproject.toml], make sure you have checked out the target repository #76

v1.5.3

Changed

  • Hopefully nothing, but this release comes from the main branch again.

v1.5.2

Fixed

  • Turns out it made a huge difference. This release is branched directly from v1.5 and only updates the dependencies.

v1.5.1

Changed

  • Updates of the tools we use. Notably this fixes check-wheel-contents on Python 3.12.

  • This shouldn't make any difference, but all management and command running is now done by PDM. #57

v1.5.0

Added

  • Set SOURCE_DATE_EPOCH based on the timestamp of the last commit for build reproducibility. #30
  • The tree output now has ISO timestamps.

Changed

  • Use 3.x version specifier in setup-python for the venv used by our tools. As of writing, that's 3.11.

v1.4.1

Contains only a fix for a deprecation warning.

v1.4

Added

  • The contents listing of the SDist, the contents listing of the wheel, and the package metadata are now conveniently added to the CI run summary. So, you don't have to click through the build logs or download anything to give it a quick glimpse.

... (truncated)

Changelog

Sourced from hynek/build-and-inspect-python-package's changelog.

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hynek/build-and-inspect-python-package&package-manager=github_actions&previous-version=1&new-version=2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f6d1e8c5e..3c76f0e5f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -184,4 +184,4 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: hynek/build-and-inspect-python-package@v1 + - uses: hynek/build-and-inspect-python-package@v2 From c35e623efa08daf398ff7600b58f040109a77513 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 18 Dec 2023 16:14:23 +0100 Subject: [PATCH 09/51] ci: Run coverage upload in separate steep (#1053) To reduce codecov upload failure impact, move it to a separate job ## Summary by CodeRabbit - **Refactor** - Renamed the workflow to "Base Test Workflow" for clarity. - **Chores** - Updated artifact naming for better identification of coverage reports. - Streamlined the CI process by removing the coverage data upload step and discontinuing the use of a third-party action for codecov. - **New Features** - Introduced a dedicated workflow for handling coverage report uploads. - **Documentation** - No visible changes to end-user documentation. --- .github/workflows/base_test_workflow.yml | 23 +++--------- .github/workflows/upload_coverage.yml | 46 ++++++++++++++++++++++++ setup.cfg | 8 +++-- tox.ini | 12 +++---- 4 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/upload_coverage.yml diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index 08fbeb601..b566c423c 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -1,3 +1,5 @@ +name: Base Test Workflow + on: workflow_call: inputs: @@ -97,25 +99,10 @@ jobs: ./report-*.json retention-days: 7 - - name: Upload coverage report ${{ inputs.tox_args }} + - name: Upload coverage data uses: actions/upload-artifact@v3 if: ${{ inputs.coverage }} with: - name: coverage_report ${{ inputs.tox_args }} + name: coverage reports path: | - ./htmlcov - retention-days: 7 - - - name: Upload coverage raw data - uses: actions/upload-artifact@v3 - with: - name: coverage_raw ${{ inputs.tox_args }} - path: ./coverage.xml - retention-days: 7 - - - uses: codecov/codecov-action@v3 - if: ${{ inputs.coverage }} - with: - file: ./coverage.xml - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} + ./.coverage.* diff --git a/.github/workflows/upload_coverage.yml b/.github/workflows/upload_coverage.yml new file mode 100644 index 000000000..dc3ee5cae --- /dev/null +++ b/.github/workflows/upload_coverage.yml @@ -0,0 +1,46 @@ +name: Coverage upload + +on: + workflow_run: + workflows: + - Tests + types: + - completed + +jobs: + upload_coverage: + name: Upload coverage + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + cache-dependency-path: setup.cfg + cache: 'pip' + + - name: Install Dependencies + run: | + pip install --upgrade pip + pip install codecov + + - name: Download coverage data + uses: actions/download-artifact@v3 + with: + name: coverage reports + path: coverage + + - name: combine coverage data + run: | + python -Im coverage combine coverage + python -Im coverage xml -o coverage.xml + + # Report and write to summary. + python -Im coverage report --format=markdown --skip-empty --skip-covered >> $GITHUB_STEP_SUMMARY + + - name: Upload coverage data + uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/setup.cfg b/setup.cfg index 9ec2700f1..cdebd7b39 100644 --- a/setup.cfg +++ b/setup.cfg @@ -79,7 +79,6 @@ package_dir = =package tests_require = pytest - pytest-cov pytest-qt lxml @@ -120,9 +119,9 @@ pyside2 = pyside6 = PySide6 test = + coverage lxml pytest>=7.0.0 - pytest-cov pytest-qt pytest-timeout scikit-image @@ -166,7 +165,10 @@ source = PartSeg PartSegCore PartSegImage -omit = .tox/* +omit = + .tox/* + **/changelog.py + **/version.py parallel = True [coverage:report] diff --git a/tox.ini b/tox.ini index ca93aafa7..aa65f5893 100644 --- a/tox.ini +++ b/tox.ini @@ -63,7 +63,7 @@ extras = test commands = - python -m pytest package/tests --no-cov --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + python -m pytest package/tests --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json [testenv:py39-PySide2-conda] conda_env=environment.yml @@ -80,14 +80,14 @@ deps = 417: napari==0.4.17 repo: git+https://github.com/napari/napari.git commands = - !repo: python -m pytest -v package/tests/test_PartSeg/test_napari_widgets.py --no-cov --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json - repo: python -m pytest --no-cov --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + !repo: python -m pytest -v package/tests/test_PartSeg/test_napari_widgets.py --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + repo: python -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json -[testenv:py{38,39,310,311s}-PyQt5-coverage] +[testenv:py{38,39,310,311}-PyQt5-coverage] deps = {[testenv]deps} commands = - python -m pytest --cov-report=xml --cov-report html --cov-append --cov {envsitepackagesdir}/PartSeg --cov {envsitepackagesdir}/PartSegCore --cov {envsitepackagesdir}/PartSegImage --cov package/tests --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + coverage run -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json [testenv:py38-PyQt5-minimal] min_req = 1 @@ -100,7 +100,7 @@ deps = {[base]deps} setuptools_scm[toml]>=3.4 commands = - python -m pytest --cov-report=xml --cov-report html --cov-append --cov {envsitepackagesdir}/PartSeg --cov {envsitepackagesdir}/PartSegCore --cov {envsitepackagesdir}/PartSegImage --cov package/tests --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + coverage run -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json [testenv:py{38,39,310}-{PyQt5, PySide2,PyQt6,PySide6}-azure] deps = From c6ee6c9773e860619c4f3ff680aeafb4f26aa499 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 18 Dec 2023 17:31:43 +0100 Subject: [PATCH 10/51] ci: Generate local report in `Tests` workflow and use proper script for fetch report (#1054) ## Summary by CodeRabbit - **Chores** - Improved the CI workflow by introducing a new job for preparing coverage data. - Streamlined coverage data handling by leveraging GitHub Actions scripting capabilities for artifact management. --- .github/workflows/tests.yml | 35 ++++++++++++++++++++ .github/workflows/upload_coverage.yml | 47 ++++++++++++--------------- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3c76f0e5f..3024262bb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -116,6 +116,41 @@ jobs: tox_args: "-e py38-PyQt5-minimal" coverage: true + coverage_prepare: + name: Prepare coverage + runs-on: ubuntu-latest + needs: [test_coverage, test_minimal] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + cache-dependency-path: setup.cfg + cache: 'pip' + - name: Install Dependencies + run: | + pip install --upgrade pip + pip install codecov + + - name: Download coverage data + uses: actions/download-artifact@v3 + with: + name: coverage reports + path: coverage + - name: combine coverage data + run: | + python -Im coverage combine coverage + python -Im coverage xml -o coverage.xml + # Report and write to summary. + python -Im coverage report --format=markdown --skip-empty --skip-covered >> $GITHUB_STEP_SUMMARY + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: coverage_xml + path: coverage.xml + retention-days: 5 + test_conda: name: Test PartSeg conda runs-on: ubuntu-20.04 diff --git a/.github/workflows/upload_coverage.yml b/.github/workflows/upload_coverage.yml index dc3ee5cae..4d4565034 100644 --- a/.github/workflows/upload_coverage.yml +++ b/.github/workflows/upload_coverage.yml @@ -12,33 +12,28 @@ jobs: name: Upload coverage runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: "3.x" - cache-dependency-path: setup.cfg - cache: 'pip' - - - name: Install Dependencies - run: | - pip install --upgrade pip - pip install codecov - - - name: Download coverage data - uses: actions/download-artifact@v3 + - name: Download Coverage Data + uses: actions/github-script@v6 with: - name: coverage reports - path: coverage - - - name: combine coverage data - run: | - python -Im coverage combine coverage - python -Im coverage xml -o coverage.xml - - # Report and write to summary. - python -Im coverage report --format=markdown --skip-empty --skip-covered >> $GITHUB_STEP_SUMMARY - + script: | + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "coverage_xml" + })[0]; + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + let fs = require('fs'); + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/coverage_xml.zip`, Buffer.from(download.data)); + - name: 'Unzip artifact' + run: unzip coverage_xml.zip - name: Upload coverage data uses: codecov/codecov-action@v3 with: From 2d0c9085a000457cffb1459b9b0fd940a578f739 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 18 Dec 2023 19:08:08 +0100 Subject: [PATCH 11/51] ci: Move coverage back to main workflow (#1055) ## Summary by CodeRabbit - **New Features** - Integrated coverage data upload to Codecov in the CI workflow. - **Chores** - Ensured CI fails upon errors during coverage data upload. - **Documentation** - Updated CI workflow documentation to reflect new changes. --- .github/workflows/tests.yml | 6 ++++ .github/workflows/upload_coverage.yml | 41 --------------------------- 2 files changed, 6 insertions(+), 41 deletions(-) delete mode 100644 .github/workflows/upload_coverage.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3024262bb..be7d50d2f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -151,6 +151,12 @@ jobs: path: coverage.xml retention-days: 5 + - name: Upload coverage data + uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + test_conda: name: Test PartSeg conda runs-on: ubuntu-20.04 diff --git a/.github/workflows/upload_coverage.yml b/.github/workflows/upload_coverage.yml deleted file mode 100644 index 4d4565034..000000000 --- a/.github/workflows/upload_coverage.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Coverage upload - -on: - workflow_run: - workflows: - - Tests - types: - - completed - -jobs: - upload_coverage: - name: Upload coverage - runs-on: ubuntu-latest - steps: - - name: Download Coverage Data - uses: actions/github-script@v6 - with: - script: | - let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.payload.workflow_run.id, - }); - let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { - return artifact.name == "coverage_xml" - })[0]; - let download = await github.rest.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - let fs = require('fs'); - fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/coverage_xml.zip`, Buffer.from(download.data)); - - name: 'Unzip artifact' - run: unzip coverage_xml.zip - - name: Upload coverage data - uses: codecov/codecov-action@v3 - with: - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} From c92832e29b891ee6022ede311fe4ec7e1ce7cc85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:33:00 +0100 Subject: [PATCH 12/51] build(deps): bump actions/setup-python from 4 to 5 (#1046) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
Release notes

Sourced from actions/setup-python's releases.

v5.0.0

What's Changed

In scope of this release, we update node version runtime from node16 to node20 (actions/setup-python#772). Besides, we update dependencies to the latest versions.

Full Changelog: https://github.com/actions/setup-python/compare/v4.8.0...v5.0.0

v4.8.0

What's Changed

In scope of this release we added support for GraalPy (actions/setup-python#694). You can use this snippet to set up GraalPy:

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
  with:
    python-version: 'graalpy-22.3'
- run: python my_script.py

Besides, the release contains such changes as:

New Contributors

Full Changelog: https://github.com/actions/setup-python/compare/v4...v4.8.0

v4.7.1

What's Changed

Full Changelog: https://github.com/actions/setup-python/compare/v4...v4.7.1

v4.7.0

In scope of this release, the support for reading python version from pyproject.toml was added (actions/setup-python#669).

      - name: Setup Python
        uses: actions/setup-python@v4
</tr></table>

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .github/workflows/base_test_workflow.yml | 2 +- .github/workflows/test_napari_repo.yml | 2 +- .github/workflows/test_prereleases.yml | 4 ++-- .github/workflows/upgrade-dependencies.yml | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index b566c423c..dec303b12 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -42,7 +42,7 @@ jobs: runs-on: ${{ inputs.os }} steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 name: Install Python ${{ inputs.python_version }} with: python-version: ${{ inputs.python_version }} diff --git a/.github/workflows/test_napari_repo.yml b/.github/workflows/test_napari_repo.yml index d676c0636..4607e36fb 100644 --- a/.github/workflows/test_napari_repo.yml +++ b/.github/workflows/test_napari_repo.yml @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} diff --git a/.github/workflows/test_prereleases.yml b/.github/workflows/test_prereleases.yml index cc5f44655..eb8cadfd7 100644 --- a/.github/workflows/test_prereleases.yml +++ b/.github/workflows/test_prereleases.yml @@ -43,7 +43,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} cache: 'pip' @@ -100,7 +100,7 @@ jobs: runs-on: "ubuntu-latest" steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 name: Install Python 3.9 with: python-version: 3.9 diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index f9a50855d..a5dbd8658 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -22,22 +22,22 @@ jobs: ssh-key: ${{ secrets.DEPLOY_KEY }} # START PYTHON DEPENDENCIES - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.8" cache: pip cache-dependency-path: 'setup.cfg' - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.9" cache: pip cache-dependency-path: 'setup.cfg' - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.10" cache: pip cache-dependency-path: 'setup.cfg' - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip From fd794ef51f1606af59d103c215a9222f8c91b71f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:33:14 +0100 Subject: [PATCH 13/51] build(deps): bump github/codeql-action from 2 to 3 (#1051) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
Release notes

Sourced from github/codeql-action's releases.

CodeQL Bundle v2.15.4

Bundles CodeQL CLI v2.15.4

Includes the following CodeQL language packs from github/codeql@codeql-cli/v2.15.4:

CodeQL Bundle

Bundles CodeQL CLI v2.15.3

Includes the following CodeQL language packs from github/codeql@codeql-cli/v2.15.3:

CodeQL Bundle

Bundles CodeQL CLI v2.15.2

Includes the following CodeQL language packs from github/codeql@codeql-cli/v2.15.2:

... (truncated)

Changelog

Sourced from github/codeql-action's changelog.

Commits
  • 3a9f6a8 update javascript files
  • cc4fead update version in various hardcoded locations
  • 183559c Merge branch 'main' into update-bundle/codeql-bundle-v2.15.4
  • 5b52b36 reintroduce PR check that confirm action can be still be compiled on node16
  • 5b19bef change to node20 for all actions
  • f2d0c2e upgrade node type definitions
  • d651fbc change to node20 for all actions
  • 382a50a Merge pull request #2021 from github/mergeback/v2.22.9-to-main-c0d1daa7
  • 458b422 Update checked-in dependencies
  • 5e0f9db Update changelog and version after v2.22.9
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=2&new-version=3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 22a7fc5ab..130eb0832 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,7 +47,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -58,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -72,4 +72,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 From fb5720dbc7cef89147f0ed81fcd123100483c1e9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:33:36 +0100 Subject: [PATCH 14/51] ci: [pre-commit.ci] pre-commit autoupdate (#1056) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 23.11.0 → 23.12.1](https://github.com/psf/black-pre-commit-mirror/compare/23.11.0...23.12.1) - [github.com/astral-sh/ruff-pre-commit: v0.1.7 → v0.1.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.7...v0.1.9) - [github.com/pre-commit/mirrors-mypy: v1.7.1 → v1.8.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.7.1...v1.8.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90ddc860a..d91fd7320 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.11.0 + rev: 23.12.1 hooks: - id: black pass_filenames: true @@ -25,7 +25,7 @@ repos: - id: setup-cfg-fmt args: ["--include-version-classifiers", "--max-py-version", "3.11"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.7 + rev: v0.1.9 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade @@ -49,7 +49,7 @@ repos: - mdformat-toc - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.7.1' # Use the sha / tag you want to point at + rev: 'v1.8.0' # Use the sha / tag you want to point at hooks: - id: mypy files: ^package/PartSegImage/.+\.py From 41ffcfec51fc95368fceb82f969f0294d42c0fa4 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 4 Jan 2024 14:34:04 +0100 Subject: [PATCH 15/51] test: [Automatic] Constraints upgrades: `imagecodecs`, `imageio`, `ipykernel`, `magicgui`, `pandas`, `pyinstaller`, `qtawesome`, `sentry-sdk`, `tifffile` (#1048) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * app-model * attrs * babel * coverage * dask * fsspec * imagecodecs * imageio * importlib-metadata * ipykernel * jsonschema-specifications * jupyter-core * lxml * magicgui * pandas * pint * platformdirs * prompt-toolkit * psutil * pydantic-compat * pyinstaller * pyinstaller-hooks-contrib * pytest * pytest-qt * pyzmq * qtawesome * referencing * rpds-py * sentry-sdk * setuptools * tifffile * typing-extensions * tzdata ## Summary by CodeRabbit - **Package Updates** - Upgraded various dependencies across different Python versions to enhance performance and compatibility. - Notable package updates include improvements to `pandas`, `pytest`, `lxml`, and `ipython` among others. Co-authored-by: Czaki --- requirements/constraints_py3.10.txt | 85 ++++++++++++++--------------- requirements/constraints_py3.11.txt | 84 ++++++++++++++-------------- requirements/constraints_py3.8.txt | 65 +++++++++++----------- requirements/constraints_py3.9.txt | 75 ++++++++++++------------- 4 files changed, 149 insertions(+), 160 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index db6d0c0b4..ed29f2fa5 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -8,7 +8,7 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.2 +app-model==0.2.4 # via napari appdirs==1.4.4 # via @@ -17,11 +17,11 @@ appdirs==1.4.4 # npe2 asttokens==2.4.1 # via stack-data -attrs==23.1.0 +attrs==23.2.0 # via # jsonschema # referencing -babel==2.13.1 +babel==2.14.0 # via sphinx build==1.0.3 # via npe2 @@ -42,13 +42,11 @@ cloudpickle==3.0.0 # via dask comm==0.2.0 # via ipykernel -coverage==7.3.2 - # via - # coverage - # pytest-cov +coverage==7.4.0 + # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.0 +dask==2023.12.1 # via # dask # napari @@ -74,7 +72,7 @@ fonticon-fontawesome6==6.4.0 # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.0 +fsspec==2023.12.2 # via dask h5py==3.10.0 # via PartSeg (setup.cfg) @@ -84,9 +82,9 @@ hsluv==5.0.4 # via vispy idna==3.6 # via requests -imagecodecs==2023.9.18 +imagecodecs==2024.1.1 # via PartSeg (setup.cfg) -imageio==2.33.0 +imageio==2.33.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -95,18 +93,18 @@ imageio==2.33.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via dask in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.27.1 +ipykernel==6.28.0 # via # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.18.1 +ipython==8.19.0 # via # PartSeg (setup.cfg) # ipykernel @@ -119,13 +117,13 @@ jinja2==3.1.2 # sphinx jsonschema==4.20.0 # via napari -jsonschema-specifications==2023.11.2 +jsonschema-specifications==2023.12.1 # via jsonschema jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.0 +jupyter-core==5.5.1 # via # ipykernel # jupyter-client @@ -142,9 +140,9 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==4.9.3 +lxml==5.0.0 # via PartSeg (setup.cfg) -magicgui==0.8.0 +magicgui==0.8.1 # via # PartSeg (setup.cfg) # napari @@ -224,7 +222,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.3 +pandas==2.1.4 # via # PartSeg (setup.cfg) # napari @@ -243,9 +241,9 @@ pillow==10.1.0 # imageio # napari # scikit-image -pint==0.22 +pint==0.23 # via napari -platformdirs==4.0.0 +platformdirs==4.1.0 # via # jupyter-core # pooch @@ -253,9 +251,9 @@ pluggy==1.3.0 # via pytest pooch==1.8.0 # via scikit-image -prompt-toolkit==3.0.41 +prompt-toolkit==3.0.43 # via ipython -psutil==5.9.6 +psutil==5.9.7 # via # ipykernel # napari @@ -279,6 +277,9 @@ pydantic==1.10.13 # app-model # napari # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model pygments==2.17.2 # via # PartSeg (setup.cfg) @@ -288,9 +289,9 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.2.0 +pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.10 +pyinstaller-hooks-contrib==2023.11 # via pyinstaller pyopengl==3.1.7 # via napari @@ -318,25 +319,22 @@ pyside2==5.15.2.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) -pyside6==6.6.0 ; python_version >= "3.10" +pyside6==6.6.1 ; python_version >= "3.10" # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) -pyside6-addons==6.6.0 +pyside6-addons==6.6.1 # via pyside6 -pyside6-essentials==6.6.0 +pyside6-essentials==6.6.1 # via # pyside6 # pyside6-addons -pytest==7.4.3 +pytest==7.4.4 # via # PartSeg (setup.cfg) - # pytest-cov # pytest-qt # pytest-timeout -pytest-cov==4.1.0 - # via PartSeg (setup.cfg) -pytest-qt==4.2.0 +pytest-qt==4.3.1 # via PartSeg (setup.cfg) pytest-timeout==2.2.0 # via PartSeg (setup.cfg) @@ -351,12 +349,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.1 +pyzmq==25.1.2 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.2.3 +qtawesome==1.3.0 # via PartSeg (setup.cfg) qtconsole==5.5.1 # via @@ -371,7 +369,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.31.1 +referencing==0.32.0 # via # jsonschema # jsonschema-specifications @@ -383,7 +381,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.13.2 +rpds-py==0.16.2 # via # jsonschema # referencing @@ -396,13 +394,13 @@ scipy==1.11.4 # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.38.0 +sentry-sdk==1.39.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) shiboken2==5.15.2.1 # via pyside2 -shiboken6==6.6.0 +shiboken6==6.6.1 # via # pyside6 # pyside6-addons @@ -441,7 +439,7 @@ superqt==0.6.1 # napari sympy==1.12 # via PartSeg (setup.cfg) -tifffile==2023.9.26 +tifffile==2023.12.9 # via # PartSeg (setup.cfg) # czifile @@ -451,7 +449,6 @@ tifffile==2023.9.26 tomli==2.0.1 # via # build - # coverage # npe2 # pyproject-hooks # pytest @@ -481,7 +478,7 @@ traitlets==5.14.0 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via # app-model # magicgui @@ -491,7 +488,7 @@ typing-extensions==4.8.0 # pydantic # superqt # typer -tzdata==2023.3 +tzdata==2023.4 # via pandas urllib3==2.1.0 # via @@ -514,5 +511,5 @@ zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.2 +setuptools==69.0.3 # via pyinstaller diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 50e6c2bbd..2750e73c5 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -8,7 +8,7 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.2 +app-model==0.2.4 # via napari appdirs==1.4.4 # via @@ -17,11 +17,11 @@ appdirs==1.4.4 # npe2 asttokens==2.4.1 # via stack-data -attrs==23.1.0 +attrs==23.2.0 # via # jsonschema # referencing -babel==2.13.1 +babel==2.14.0 # via sphinx build==1.0.3 # via npe2 @@ -42,13 +42,11 @@ cloudpickle==3.0.0 # via dask comm==0.2.0 # via ipykernel -coverage==7.3.2 - # via - # coverage - # pytest-cov +coverage==7.4.0 + # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.0 +dask==2023.12.1 # via # dask # napari @@ -70,7 +68,7 @@ fonticon-fontawesome6==6.4.0 # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.0 +fsspec==2023.12.2 # via dask h5py==3.10.0 # via PartSeg (setup.cfg) @@ -80,9 +78,9 @@ hsluv==5.0.4 # via vispy idna==3.6 # via requests -imagecodecs==2023.9.18 +imagecodecs==2024.1.1 # via PartSeg (setup.cfg) -imageio==2.33.0 +imageio==2.33.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -91,18 +89,18 @@ imageio==2.33.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via dask in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.27.1 +ipykernel==6.28.0 # via # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.18.1 +ipython==8.19.0 # via # PartSeg (setup.cfg) # ipykernel @@ -115,13 +113,13 @@ jinja2==3.1.2 # sphinx jsonschema==4.20.0 # via napari -jsonschema-specifications==2023.11.2 +jsonschema-specifications==2023.12.1 # via jsonschema jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.0 +jupyter-core==5.5.1 # via # ipykernel # jupyter-client @@ -138,9 +136,9 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==4.9.3 +lxml==5.0.0 # via PartSeg (setup.cfg) -magicgui==0.8.0 +magicgui==0.8.1 # via # PartSeg (setup.cfg) # napari @@ -220,7 +218,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.3 +pandas==2.1.4 # via # PartSeg (setup.cfg) # napari @@ -239,9 +237,9 @@ pillow==10.1.0 # imageio # napari # scikit-image -pint==0.22 +pint==0.23 # via napari -platformdirs==4.0.0 +platformdirs==4.1.0 # via # jupyter-core # pooch @@ -249,9 +247,9 @@ pluggy==1.3.0 # via pytest pooch==1.8.0 # via scikit-image -prompt-toolkit==3.0.41 +prompt-toolkit==3.0.43 # via ipython -psutil==5.9.6 +psutil==5.9.7 # via # ipykernel # napari @@ -275,6 +273,9 @@ pydantic==1.10.13 # app-model # napari # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model pygments==2.17.2 # via # PartSeg (setup.cfg) @@ -284,9 +285,9 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.2.0 +pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.10 +pyinstaller-hooks-contrib==2023.11 # via pyinstaller pyopengl==3.1.7 # via napari @@ -314,25 +315,22 @@ pyside2==5.13.2 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) -pyside6==6.6.0 ; python_version >= "3.10" +pyside6==6.6.1 ; python_version >= "3.10" # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) -pyside6-addons==6.6.0 +pyside6-addons==6.6.1 # via pyside6 -pyside6-essentials==6.6.0 +pyside6-essentials==6.6.1 # via # pyside6 # pyside6-addons -pytest==7.4.3 +pytest==7.4.4 # via # PartSeg (setup.cfg) - # pytest-cov # pytest-qt # pytest-timeout -pytest-cov==4.1.0 - # via PartSeg (setup.cfg) -pytest-qt==4.2.0 +pytest-qt==4.3.1 # via PartSeg (setup.cfg) pytest-timeout==2.2.0 # via PartSeg (setup.cfg) @@ -347,12 +345,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.1 +pyzmq==25.1.2 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.2.3 +qtawesome==1.3.0 # via PartSeg (setup.cfg) qtconsole==5.5.1 # via @@ -367,7 +365,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.31.1 +referencing==0.32.0 # via # jsonschema # jsonschema-specifications @@ -379,7 +377,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.13.2 +rpds-py==0.16.2 # via # jsonschema # referencing @@ -392,13 +390,13 @@ scipy==1.11.4 # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.38.0 +sentry-sdk==1.39.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.0 +shiboken6==6.6.1 # via # pyside6 # pyside6-addons @@ -437,7 +435,7 @@ superqt==0.6.1 # napari sympy==1.12 # via PartSeg (setup.cfg) -tifffile==2023.9.26 +tifffile==2023.12.9 # via # PartSeg (setup.cfg) # czifile @@ -470,7 +468,7 @@ traitlets==5.14.0 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via # app-model # magicgui @@ -480,7 +478,7 @@ typing-extensions==4.8.0 # pydantic # superqt # typer -tzdata==2023.3 +tzdata==2023.4 # via pandas urllib3==2.1.0 # via @@ -503,5 +501,5 @@ zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.2 +setuptools==69.0.3 # via pyinstaller diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index 7f2c8b6e5..350e979d2 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -8,7 +8,7 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.2 +app-model==0.2.4 # via napari appdirs==1.4.4 # via @@ -17,11 +17,11 @@ appdirs==1.4.4 # npe2 asttokens==2.4.1 # via stack-data -attrs==23.1.0 +attrs==23.2.0 # via # jsonschema # referencing -babel==2.13.1 +babel==2.14.0 # via sphinx backcall==0.2.0 # via ipython @@ -44,10 +44,8 @@ cloudpickle==3.0.0 # via dask comm==0.2.0 # via ipykernel -coverage==7.3.2 - # via - # coverage - # pytest-cov +coverage==7.4.0 + # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) dask==2023.5.0 @@ -74,7 +72,7 @@ fonticon-fontawesome6==6.4.0 # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.0 +fsspec==2023.12.2 # via dask h5py==3.10.0 # via PartSeg (setup.cfg) @@ -86,7 +84,7 @@ idna==3.6 # via requests imagecodecs==2023.3.16 # via PartSeg (setup.cfg) -imageio==2.33.0 +imageio==2.33.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -95,7 +93,7 @@ imageio==2.33.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via # build # dask @@ -110,7 +108,7 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.27.1 +ipykernel==6.28.0 # via # PartSeg (setup.cfg) # napari-console @@ -128,13 +126,13 @@ jinja2==3.1.2 # sphinx jsonschema==4.20.0 # via napari -jsonschema-specifications==2023.11.2 +jsonschema-specifications==2023.12.1 # via jsonschema jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.0 +jupyter-core==5.5.1 # via # ipykernel # jupyter-client @@ -151,9 +149,9 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==4.9.3 +lxml==5.0.0 # via PartSeg (setup.cfg) -magicgui==0.8.0 +magicgui==0.8.1 # via # PartSeg (setup.cfg) # napari @@ -259,7 +257,7 @@ pint==0.21.1 # via napari pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==4.0.0 +platformdirs==4.1.0 # via # jupyter-core # pooch @@ -267,9 +265,9 @@ pluggy==1.3.0 # via pytest pooch==1.8.0 # via scikit-image -prompt-toolkit==3.0.41 +prompt-toolkit==3.0.43 # via ipython -psutil==5.9.6 +psutil==5.9.7 # via # ipykernel # napari @@ -293,6 +291,9 @@ pydantic==1.10.13 # app-model # napari # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model pygments==2.17.2 # via # PartSeg (setup.cfg) @@ -302,9 +303,9 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.2.0 +pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.10 +pyinstaller-hooks-contrib==2023.11 # via pyinstaller pyopengl==3.1.7 # via napari @@ -342,15 +343,12 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==7.4.3 +pytest==7.4.4 # via # PartSeg (setup.cfg) - # pytest-cov # pytest-qt # pytest-timeout -pytest-cov==4.1.0 - # via PartSeg (setup.cfg) -pytest-qt==4.2.0 +pytest-qt==4.3.1 # via PartSeg (setup.cfg) pytest-timeout==2.2.0 # via PartSeg (setup.cfg) @@ -369,12 +367,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.1 +pyzmq==25.1.2 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.2.3 +qtawesome==1.3.0 # via PartSeg (setup.cfg) qtconsole==5.5.1 # via @@ -389,7 +387,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.31.1 +referencing==0.32.0 # via # jsonschema # jsonschema-specifications @@ -401,7 +399,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.13.2 +rpds-py==0.16.2 # via # jsonschema # referencing @@ -414,7 +412,7 @@ scipy==1.10.1 # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.38.0 +sentry-sdk==1.39.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -469,7 +467,6 @@ tifffile==2023.7.10 tomli==2.0.1 # via # build - # coverage # npe2 # pyproject-hooks # pytest @@ -499,7 +496,7 @@ traitlets==5.14.0 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via # app-model # ipython @@ -510,7 +507,7 @@ typing-extensions==4.8.0 # rich # superqt # typer -tzdata==2023.3 +tzdata==2023.4 # via pandas urllib3==2.1.0 # via @@ -535,5 +532,5 @@ zipp==3.17.0 # importlib-resources # The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.2 +setuptools==69.0.3 # via pyinstaller diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index 8d3f44005..623ddbf9c 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -8,7 +8,7 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.2 +app-model==0.2.4 # via napari appdirs==1.4.4 # via @@ -17,11 +17,11 @@ appdirs==1.4.4 # npe2 asttokens==2.4.1 # via stack-data -attrs==23.1.0 +attrs==23.2.0 # via # jsonschema # referencing -babel==2.13.1 +babel==2.14.0 # via sphinx build==1.0.3 # via npe2 @@ -42,13 +42,11 @@ cloudpickle==3.0.0 # via dask comm==0.2.0 # via ipykernel -coverage==7.3.2 - # via - # coverage - # pytest-cov +coverage==7.4.0 + # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.0 +dask==2023.12.1 # via # dask # napari @@ -74,7 +72,7 @@ fonticon-fontawesome6==6.4.0 # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.0 +fsspec==2023.12.2 # via dask h5py==3.10.0 # via PartSeg (setup.cfg) @@ -84,9 +82,9 @@ hsluv==5.0.4 # via vispy idna==3.6 # via requests -imagecodecs==2023.9.18 +imagecodecs==2024.1.1 # via PartSeg (setup.cfg) -imageio==2.33.0 +imageio==2.33.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -95,7 +93,7 @@ imageio==2.33.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via # build # dask @@ -106,7 +104,7 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.27.1 +ipykernel==6.28.0 # via # PartSeg (setup.cfg) # napari-console @@ -124,13 +122,13 @@ jinja2==3.1.2 # sphinx jsonschema==4.20.0 # via napari -jsonschema-specifications==2023.11.2 +jsonschema-specifications==2023.12.1 # via jsonschema jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.0 +jupyter-core==5.5.1 # via # ipykernel # jupyter-client @@ -147,9 +145,9 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==4.9.3 +lxml==5.0.0 # via PartSeg (setup.cfg) -magicgui==0.8.0 +magicgui==0.8.1 # via # PartSeg (setup.cfg) # napari @@ -229,7 +227,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.3 +pandas==2.1.4 # via # PartSeg (setup.cfg) # napari @@ -248,9 +246,9 @@ pillow==10.1.0 # imageio # napari # scikit-image -pint==0.22 +pint==0.23 # via napari -platformdirs==4.0.0 +platformdirs==4.1.0 # via # jupyter-core # pooch @@ -258,9 +256,9 @@ pluggy==1.3.0 # via pytest pooch==1.8.0 # via scikit-image -prompt-toolkit==3.0.41 +prompt-toolkit==3.0.43 # via ipython -psutil==5.9.6 +psutil==5.9.7 # via # ipykernel # napari @@ -284,6 +282,9 @@ pydantic==1.10.13 # app-model # napari # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model pygments==2.17.2 # via # PartSeg (setup.cfg) @@ -293,9 +294,9 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.2.0 +pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.10 +pyinstaller-hooks-contrib==2023.11 # via pyinstaller pyopengl==3.1.7 # via napari @@ -333,15 +334,12 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==7.4.3 +pytest==7.4.4 # via # PartSeg (setup.cfg) - # pytest-cov # pytest-qt # pytest-timeout -pytest-cov==4.1.0 - # via PartSeg (setup.cfg) -pytest-qt==4.2.0 +pytest-qt==4.3.1 # via PartSeg (setup.cfg) pytest-timeout==2.2.0 # via PartSeg (setup.cfg) @@ -356,12 +354,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.1 +pyzmq==25.1.2 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.2.3 +qtawesome==1.3.0 # via PartSeg (setup.cfg) qtconsole==5.5.1 # via @@ -376,7 +374,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.31.1 +referencing==0.32.0 # via # jsonschema # jsonschema-specifications @@ -388,7 +386,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.13.2 +rpds-py==0.16.2 # via # jsonschema # referencing @@ -401,7 +399,7 @@ scipy==1.11.4 # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.38.0 +sentry-sdk==1.39.1 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -446,7 +444,7 @@ superqt==0.6.1 # napari sympy==1.12 # via PartSeg (setup.cfg) -tifffile==2023.9.26 +tifffile==2023.12.9 # via # PartSeg (setup.cfg) # czifile @@ -456,7 +454,6 @@ tifffile==2023.9.26 tomli==2.0.1 # via # build - # coverage # npe2 # pyproject-hooks # pytest @@ -486,7 +483,7 @@ traitlets==5.14.0 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.8.0 +typing-extensions==4.9.0 # via # app-model # ipython @@ -497,7 +494,7 @@ typing-extensions==4.8.0 # pydantic # superqt # typer -tzdata==2023.3 +tzdata==2023.4 # via pandas urllib3==2.1.0 # via @@ -520,5 +517,5 @@ zipp==3.17.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.2 +setuptools==69.0.3 # via pyinstaller From b003a95733d955d5515cfe51cae537184d3f8f53 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:21:20 +0100 Subject: [PATCH 16/51] ci: [pre-commit.ci] pre-commit autoupdate (#1059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.9 → v0.1.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.9...v0.1.13) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 2 +- package/tests/test_PartSegCore/test_io.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d91fd7320..fc10a5186 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: setup-cfg-fmt args: ["--include-version-classifiers", "--max-py-version", "3.11"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.9 + rev: v0.1.14 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade diff --git a/package/tests/test_PartSegCore/test_io.py b/package/tests/test_PartSegCore/test_io.py index effe75e44..b61be80b2 100644 --- a/package/tests/test_PartSegCore/test_io.py +++ b/package/tests/test_PartSegCore/test_io.py @@ -234,7 +234,7 @@ def perform_roi_info_history_test( alt2[alt2 > 0] = i + 5 roi_info2 = ROIInfo( roi=project.roi_info.roi, - annotations={i: f"a{i}_{j}" for j in range(1, 5)}, + annotations={j: f"a{i}_{j}" for j in range(1, 5)}, alternative={f"test{i}": alt2}, ) history.append( @@ -257,7 +257,7 @@ def perform_roi_info_history_test( assert set(roi_info3.alternative) == {f"test{i}"} assert np.all(roi_info3.alternative[f"test{i}"][alt1 > 0] == i + 5) assert np.all(roi_info3.alternative[f"test{i}"][alt1 == 0] == 0) - assert roi_info3.annotations == {i: f"a{i}_{j}" for j in range(1, 5)} + assert roi_info3.annotations == {j: f"a{i}_{j}" for j in range(1, 5)} assert proj2.history[i].roi_extraction_parameters == {"algorithm_name": f"task_{i}", "values": {"a": 1}} From 51f8a371fa4b86cedac8f1a46e9c95f4a2834e9f Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 22 Jan 2024 18:51:44 +0100 Subject: [PATCH 17/51] docs: Allow to use newer release of build docs dependencies (#1057) ## Summary by CodeRabbit - **Documentation** - Updated documentation build process to support Python 3.11 and Ubuntu 22.04. - Improved documentation dependencies for better compatibility and performance. --- .github/workflows/upgrade-dependencies.yml | 1 + .readthedocs.yml | 11 +- azure-pipelines.yml | 2 +- .../PartSeg/common_gui/universal_gui_part.py | 2 +- requirements/constraints_py3.11_docs.txt | 482 ++++++++++++++++++ setup.cfg | 6 +- tox.ini | 2 +- 7 files changed, 495 insertions(+), 11 deletions(-) create mode 100644 requirements/constraints_py3.11_docs.txt diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index a5dbd8658..3e8ba7541 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -53,6 +53,7 @@ jobs: python${pyv} -m pip install -U pip pip-tools python${pyv} -m piptools compile --upgrade -o requirements/constraints_py${pyv}.txt setup.cfg requirements/version_denylist.txt ${flags} done + python3.11 -m piptools compile --upgrade -o requirements/constraints_py3.11_docs.txt setup.cfg requirements/version_denylist.txt --allow-unsafe --strip-extras --extra docs --extra pyqt6 # END PYTHON DEPENDENCIES - name: Check updated packages diff --git a/.readthedocs.yml b/.readthedocs.yml index 07f499679..3c20789fb 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -17,15 +17,16 @@ sphinx: formats: all build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: - python: "3.9" + python: "3.11" # Optionally set the version of Python and requirements required to build your docs python: install: - - requirements: requirements/constraints_py3.9.txt - - requirements: requirements/requirements_dev.txt + - requirements: requirements/constraints_py3.11_docs.txt - method: pip - path: .[docs] + path: . + extra_requirements: + - docs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 44c68fdca..eb9d61640 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -74,7 +74,7 @@ stages: variables: pip_cache_dir: $(Pipeline.Workspace)/.pip steps: - - {task: UsePythonVersion@0, inputs: {versionSpec: '3.9', architecture: x64}} + - {task: UsePythonVersion@0, inputs: {versionSpec: '3.11', architecture: x64}} - template: .azure-pipelines/pip_cache.yaml parameters: key: doc | requirements/constraints_py3.9.txt | "$(PY)" diff --git a/package/PartSeg/common_gui/universal_gui_part.py b/package/PartSeg/common_gui/universal_gui_part.py index 3c012db23..4de04142b 100644 --- a/package/PartSeg/common_gui/universal_gui_part.py +++ b/package/PartSeg/common_gui/universal_gui_part.py @@ -83,7 +83,7 @@ class EnumComboBox(QEnumComboBox): For proper showing labels overload the ``__str__`` function of given :py:class:`enum.Enum` """ - def __init__(self, enum: type(EnumType), parent=None): + def __init__(self, enum, parent=None): warnings.warn( "EnumComboBox is deprecated, use superqt.QEnumComboBox instead", category=DeprecationWarning, stacklevel=2 ) diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt new file mode 100644 index 000000000..7b6519e7e --- /dev/null +++ b/requirements/constraints_py3.11_docs.txt @@ -0,0 +1,482 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --allow-unsafe --extra=docs --extra=pyqt6 --output-file=requirements/constraints_py3.11_docs.txt --strip-extras requirements/version_denylist.txt setup.cfg +# +alabaster==0.7.16 + # via sphinx +app-model==0.2.4 + # via napari +appdirs==1.4.4 + # via + # PartSeg (setup.cfg) + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +autodoc-pydantic==1.9.0 + # via PartSeg (setup.cfg) +babel==2.14.0 + # via sphinx +build==1.0.3 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2023.11.17 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.1 + # via ipykernel +czifile==2019.7.2 + # via PartSeg (setup.cfg) +dask==2024.1.0 + # via + # dask + # napari +debugpy==1.8.0 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 + # via PartSeg (setup.cfg) +docstring-parser==0.15 + # via magicgui +docutils==0.20.1 + # via + # sphinx + # sphinx-qt-documentation +et-xmlfile==1.1.0 + # via openpyxl +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 + # via PartSeg (setup.cfg) +freetype-py==2.4.0 + # via vispy +fsspec==2023.12.2 + # via dask +h5py==3.10.0 + # via PartSeg (setup.cfg) +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.6 + # via requests +imagecodecs==2024.1.1 + # via PartSeg (setup.cfg) +imageio==2.33.1 + # via + # -r requirements/version_denylist.txt + # PartSeg (setup.cfg) + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +importlib-metadata==7.0.1 + # via dask +in-n-out==0.1.9 + # via app-model +ipykernel==6.29.0 + # via + # PartSeg (setup.cfg) + # napari-console + # qtconsole +ipython==8.20.0 + # via + # PartSeg (setup.cfg) + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via + # numpydoc + # sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.1 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.3 + # via + # napari + # scikit-image +local-migrator==0.1.9 + # via + # PartSeg (setup.cfg) + # nme +locket==1.0.0 + # via partd +magicgui==0.8.1 + # via + # PartSeg (setup.cfg) + # napari +mahotas==1.4.13 + # via PartSeg (setup.cfg) +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.4 + # via jinja2 +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +mypy-extensions==1.0.0 + # via psygnal +napari==0.4.19rc3 + # via PartSeg (setup.cfg) +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.2.1 + # via scikit-image +nme==0.1.8 + # via PartSeg (setup.cfg) +npe2==0.7.3 + # via + # -r requirements/version_denylist.txt + # napari +numpy==1.26.3 + # via + # PartSeg (setup.cfg) + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.6.0 + # via napari +oiffile==2023.8.30 + # via PartSeg (setup.cfg) +openpyxl==3.1.2 + # via PartSeg (setup.cfg) +packaging==23.2 + # via + # PartSeg (setup.cfg) + # build + # dask + # ipykernel + # local-migrator + # pooch + # qtconsole + # qtpy + # scikit-image + # sphinx + # superqt + # vispy +pandas==2.2.0 + # via + # PartSeg (setup.cfg) + # napari +parso==0.8.3 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.2 + # via PartSeg (setup.cfg) +partsegdata==0.10.0 + # via PartSeg (setup.cfg) +pexpect==4.9.0 + # via ipython +pillow==10.2.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.1.0 + # via + # jupyter-core + # pooch +pooch==1.8.0 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.9.5 + # via + # PartSeg (setup.cfg) + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.14 + # via + # -r requirements/version_denylist.txt + # PartSeg (setup.cfg) + # app-model + # autodoc-pydantic + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # PartSeg (setup.cfg) + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyopengl==3.1.7 + # via napari +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 + # via -r requirements/version_denylist.txt +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via + # -r requirements/version_denylist.txt + # pyqt5 +pyqt6==6.6.1 + # via PartSeg (setup.cfg) +pyqt6-qt6==6.6.1 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.13.2 + # via -r requirements/version_denylist.txt +pyside6==6.6.1 ; python_version >= "3.10" + # via -r requirements/version_denylist.txt +pyside6-addons==6.6.1 + # via pyside6 +pyside6-essentials==6.6.1 + # via + # pyside6 + # pyside6-addons +python-dateutil==2.8.2 + # via + # jupyter-client + # pandas +pytz==2023.3.post1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==25.1.2 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.0 + # via PartSeg (setup.cfg) +qtconsole==5.5.1 + # via + # PartSeg (setup.cfg) + # napari-console +qtpy==2.4.1 + # via + # PartSeg (setup.cfg) + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.32.1 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # PartSeg (setup.cfg) + # pooch + # pyconify + # sphinx +rich==13.7.0 + # via npe2 +rpds-py==0.17.1 + # via + # jsonschema + # referencing +scikit-image==0.22.0 + # via + # napari + # scikit-image +scipy==1.12.0 + # via + # PartSeg (setup.cfg) + # napari + # scikit-image +sentry-sdk==1.39.2 + # via + # -r requirements/version_denylist.txt + # PartSeg (setup.cfg) +shiboken2==5.13.2 + # via pyside2 +shiboken6==6.6.1 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 + # via PartSeg (setup.cfg) +six==1.16.0 + # via + # PartSeg (setup.cfg) + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.2.6 + # via + # PartSeg (setup.cfg) + # autodoc-pydantic + # numpydoc + # sphinx-autodoc-typehints + # sphinx-qt-documentation +sphinx-autodoc-typehints==1.25.2 + # via PartSeg (setup.cfg) +sphinx-qt-documentation==0.4.1 + # via PartSeg (setup.cfg) +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.1 + # via + # PartSeg (setup.cfg) + # magicgui + # napari +sympy==1.12 + # via PartSeg (setup.cfg) +tabulate==0.9.0 + # via numpydoc +tifffile==2023.12.9 + # via + # PartSeg (setup.cfg) + # czifile + # napari + # oiffile + # scikit-image +tomli-w==1.0.0 + # via npe2 +toolz==0.12.0 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.1 + # via napari +traceback-with-variables==2.0.4 + # via PartSeg (setup.cfg) +traitlets==5.14.1 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.9.0 + # via npe2 +typing-extensions==4.9.0 + # via + # app-model + # magicgui + # napari + # pint + # psygnal + # pydantic + # superqt + # typer +tzdata==2023.4 + # via pandas +urllib3==2.1.0 + # via + # requests + # sentry-sdk +vispy==0.14.1 + # via + # PartSeg (setup.cfg) + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 + # via PartSeg (setup.cfg) +xlsxwriter==3.1.9 + # via PartSeg (setup.cfg) +zipp==3.17.0 + # via importlib-metadata diff --git a/setup.cfg b/setup.cfg index cdebd7b39..21a86175a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -98,10 +98,10 @@ all = PyOpenGL-accelerate>=3.1.5 PyQt5!=5.15.0,>=5.12.3 docs = - autodoc-pydantic==1.7.2 + autodoc-pydantic sphinx!=3.0.0,!=3.5.0 - sphinx-autodoc-typehints==1.18.3 - sphinx-qt-documentation==0.4 + sphinx-autodoc-typehints + sphinx-qt-documentation pyinstaller = %(all)s PyInstaller diff --git a/tox.ini b/tox.ini index aa65f5893..8daedc412 100644 --- a/tox.ini +++ b/tox.ini @@ -122,7 +122,7 @@ commands = [testenv:docs] deps = {[testenv]deps} - -rrequirements/constraints_py3.9.txt + -rrequirements/constraints_py3.11_docs.txt allowlist_externals = make tar From a004be5133c519fcaad82eace07e09a6cfd381d0 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Tue, 23 Jan 2024 01:47:00 +0100 Subject: [PATCH 18/51] test: [Automatic] Constraints upgrades: `ipykernel`, `numpy`, `pandas`, `partsegcore-compiled-backend`, `pydantic`, `scipy`, `sentry-sdk` (#1058) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * alabaster * comm * dask * ipykernel * jinja2 * jsonschema * jupyter-core * lxml * markupsafe * nest-asyncio * numpy * pandas * partsegcore-compiled-backend * pillow * psutil * pydantic * pyinstaller-hooks-contrib * referencing * rpds-py * scipy * sentry-sdk * sphinxcontrib-applehelp * sphinxcontrib-devhelp * sphinxcontrib-htmlhelp * sphinxcontrib-qthelp * sphinxcontrib-serializinghtml * traitlets * wcwidth ## Summary by CodeRabbit - **Documentation** - Updated software dependencies across various Python versions for enhanced compatibility and performance. - **New Features** - Upgraded key packages to their latest versions, ensuring users benefit from the latest improvements and features. - **Bug Fixes** - Addressed potential security vulnerabilities and bugs by updating outdated packages. Please note that these updates may improve performance, security, and stability of the application. Users are encouraged to update to the latest version to take advantage of these improvements. --------- Co-authored-by: Czaki --- requirements/constraints_py3.10.txt | 63 +++++++++++++++-------------- requirements/constraints_py3.11.txt | 63 +++++++++++++++-------------- requirements/constraints_py3.8.txt | 40 +++++++++--------- requirements/constraints_py3.9.txt | 62 +++++++++++++++------------- 4 files changed, 121 insertions(+), 107 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index ed29f2fa5..9400dc0be 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -4,7 +4,7 @@ # # pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.10.txt --strip-extras requirements/version_denylist.txt setup.cfg # -alabaster==0.7.13 +alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller @@ -40,13 +40,13 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.0 +comm==0.2.1 # via ipykernel coverage==7.4.0 # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.1 +dask==2024.1.0 # via # dask # napari @@ -99,23 +99,23 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.28.0 +ipykernel==6.29.0 # via # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.19.0 +ipython==8.20.0 # via # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 # via ipython -jinja2==3.1.2 +jinja2==3.1.3 # via # numpydoc # sphinx -jsonschema==4.20.0 +jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema @@ -123,7 +123,7 @@ jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.1 +jupyter-core==5.7.1 # via # ipykernel # jupyter-client @@ -140,7 +140,7 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==5.0.0 +lxml==5.1.0 # via PartSeg (setup.cfg) magicgui==0.8.1 # via @@ -150,7 +150,7 @@ mahotas==1.4.13 # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.3 +markupsafe==2.1.4 # via jinja2 matplotlib-inline==0.1.6 # via @@ -172,7 +172,7 @@ napari-plugin-engine==0.2.0 # napari-svg napari-svg==0.1.10 # via napari -nest-asyncio==1.5.8 +nest-asyncio==1.6.0 # via ipykernel networkx==3.2.1 # via scikit-image @@ -182,7 +182,7 @@ npe2==0.7.3 # via # -r requirements/version_denylist.txt # napari -numpy==1.26.2 +numpy==1.26.3 # via # PartSeg (setup.cfg) # czifile @@ -215,6 +215,7 @@ packaging==23.2 # local-migrator # pooch # pyinstaller + # pyinstaller-hooks-contrib # pytest # qtconsole # qtpy @@ -222,7 +223,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.4 +pandas==2.2.0 # via # PartSeg (setup.cfg) # napari @@ -230,13 +231,13 @@ parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.1 +partsegcore-compiled-backend==0.15.2 # via PartSeg (setup.cfg) partsegdata==0.10.0 # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython -pillow==10.1.0 +pillow==10.2.0 # via # imageio # napari @@ -253,7 +254,7 @@ pooch==1.8.0 # via scikit-image prompt-toolkit==3.0.43 # via ipython -psutil==5.9.7 +psutil==5.9.8 # via # ipykernel # napari @@ -270,7 +271,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.13 +pydantic==1.10.14 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -291,7 +292,7 @@ pygments==2.17.2 # superqt pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.11 +pyinstaller-hooks-contrib==2024.0 # via pyinstaller pyopengl==3.1.7 # via napari @@ -369,7 +370,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.32.0 +referencing==0.32.1 # via # jsonschema # jsonschema-specifications @@ -381,7 +382,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.16.2 +rpds-py==0.17.1 # via # jsonschema # referencing @@ -389,12 +390,12 @@ scikit-image==0.22.0 # via # PartSeg (setup.cfg) # napari -scipy==1.11.4 +scipy==1.12.0 # via # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.1 +sentry-sdk==1.39.2 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -418,17 +419,17 @@ sphinx==4.5.0 # via # napari # numpydoc -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.8 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.6 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.5 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.7 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython @@ -467,7 +468,7 @@ tqdm==4.66.1 # via napari traceback-with-variables==2.0.4 # via PartSeg (setup.cfg) -traitlets==5.14.0 +traitlets==5.14.1 # via # comm # ipykernel @@ -499,7 +500,7 @@ vispy==0.12.2 # PartSeg (setup.cfg) # napari # napari-svg -wcwidth==0.2.12 +wcwidth==0.2.13 # via prompt-toolkit wrapt==1.16.0 # via napari @@ -512,4 +513,6 @@ zipp==3.17.0 # The following packages are considered to be unsafe in a requirements file: setuptools==69.0.3 - # via pyinstaller + # via + # pyinstaller + # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 2750e73c5..a90e0a8ad 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -4,7 +4,7 @@ # # pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.11.txt --strip-extras requirements/version_denylist.txt setup.cfg # -alabaster==0.7.13 +alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller @@ -40,13 +40,13 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.0 +comm==0.2.1 # via ipykernel coverage==7.4.0 # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.1 +dask==2024.1.0 # via # dask # napari @@ -95,23 +95,23 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.28.0 +ipykernel==6.29.0 # via # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.19.0 +ipython==8.20.0 # via # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 # via ipython -jinja2==3.1.2 +jinja2==3.1.3 # via # numpydoc # sphinx -jsonschema==4.20.0 +jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema @@ -119,7 +119,7 @@ jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.1 +jupyter-core==5.7.1 # via # ipykernel # jupyter-client @@ -136,7 +136,7 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==5.0.0 +lxml==5.1.0 # via PartSeg (setup.cfg) magicgui==0.8.1 # via @@ -146,7 +146,7 @@ mahotas==1.4.13 # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.3 +markupsafe==2.1.4 # via jinja2 matplotlib-inline==0.1.6 # via @@ -168,7 +168,7 @@ napari-plugin-engine==0.2.0 # napari-svg napari-svg==0.1.10 # via napari -nest-asyncio==1.5.8 +nest-asyncio==1.6.0 # via ipykernel networkx==3.2.1 # via scikit-image @@ -178,7 +178,7 @@ npe2==0.7.3 # via # -r requirements/version_denylist.txt # napari -numpy==1.26.2 +numpy==1.26.3 # via # PartSeg (setup.cfg) # czifile @@ -211,6 +211,7 @@ packaging==23.2 # local-migrator # pooch # pyinstaller + # pyinstaller-hooks-contrib # pytest # qtconsole # qtpy @@ -218,7 +219,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.4 +pandas==2.2.0 # via # PartSeg (setup.cfg) # napari @@ -226,13 +227,13 @@ parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.1 +partsegcore-compiled-backend==0.15.2 # via PartSeg (setup.cfg) partsegdata==0.10.0 # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython -pillow==10.1.0 +pillow==10.2.0 # via # imageio # napari @@ -249,7 +250,7 @@ pooch==1.8.0 # via scikit-image prompt-toolkit==3.0.43 # via ipython -psutil==5.9.7 +psutil==5.9.8 # via # ipykernel # napari @@ -266,7 +267,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.13 +pydantic==1.10.14 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -287,7 +288,7 @@ pygments==2.17.2 # superqt pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.11 +pyinstaller-hooks-contrib==2024.0 # via pyinstaller pyopengl==3.1.7 # via napari @@ -365,7 +366,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.32.0 +referencing==0.32.1 # via # jsonschema # jsonschema-specifications @@ -377,7 +378,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.16.2 +rpds-py==0.17.1 # via # jsonschema # referencing @@ -385,12 +386,12 @@ scikit-image==0.22.0 # via # PartSeg (setup.cfg) # napari -scipy==1.11.4 +scipy==1.12.0 # via # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.1 +sentry-sdk==1.39.2 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -414,17 +415,17 @@ sphinx==4.5.0 # via # napari # numpydoc -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.8 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.6 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.5 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.7 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython @@ -457,7 +458,7 @@ tqdm==4.66.1 # via napari traceback-with-variables==2.0.4 # via PartSeg (setup.cfg) -traitlets==5.14.0 +traitlets==5.14.1 # via # comm # ipykernel @@ -489,7 +490,7 @@ vispy==0.12.2 # PartSeg (setup.cfg) # napari # napari-svg -wcwidth==0.2.12 +wcwidth==0.2.13 # via prompt-toolkit wrapt==1.16.0 # via napari @@ -502,4 +503,6 @@ zipp==3.17.0 # The following packages are considered to be unsafe in a requirements file: setuptools==69.0.3 - # via pyinstaller + # via + # pyinstaller + # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index 350e979d2..ab1b43ff6 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -42,7 +42,7 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.0 +comm==0.2.1 # via ipykernel coverage==7.4.0 # via PartSeg (setup.cfg) @@ -99,6 +99,7 @@ importlib-metadata==7.0.1 # dask # jupyter-client # pyinstaller + # pyinstaller-hooks-contrib # sphinx importlib-resources==6.1.1 # via @@ -108,7 +109,7 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.28.0 +ipykernel==6.29.0 # via # PartSeg (setup.cfg) # napari-console @@ -120,11 +121,11 @@ ipython==8.12.3 # napari-console jedi==0.19.1 # via ipython -jinja2==3.1.2 +jinja2==3.1.3 # via # numpydoc # sphinx -jsonschema==4.20.0 +jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema @@ -132,7 +133,7 @@ jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.1 +jupyter-core==5.7.1 # via # ipykernel # jupyter-client @@ -149,7 +150,7 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==5.0.0 +lxml==5.1.0 # via PartSeg (setup.cfg) magicgui==0.8.1 # via @@ -159,7 +160,7 @@ mahotas==1.4.13 # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.3 +markupsafe==2.1.4 # via jinja2 matplotlib-inline==0.1.6 # via @@ -181,7 +182,7 @@ napari-plugin-engine==0.2.0 # napari-svg napari-svg==0.1.10 # via napari -nest-asyncio==1.5.8 +nest-asyncio==1.6.0 # via ipykernel networkx==3.1 # via scikit-image @@ -225,6 +226,7 @@ packaging==23.2 # local-migrator # pooch # pyinstaller + # pyinstaller-hooks-contrib # pytest # qtconsole # qtpy @@ -248,7 +250,7 @@ pexpect==4.9.0 # via ipython pickleshare==0.7.5 # via ipython -pillow==10.1.0 +pillow==10.2.0 # via # imageio # napari @@ -267,7 +269,7 @@ pooch==1.8.0 # via scikit-image prompt-toolkit==3.0.43 # via ipython -psutil==5.9.7 +psutil==5.9.8 # via # ipykernel # napari @@ -284,7 +286,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.13 +pydantic==1.10.14 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -305,7 +307,7 @@ pygments==2.17.2 # superqt pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.11 +pyinstaller-hooks-contrib==2024.0 # via pyinstaller pyopengl==3.1.7 # via napari @@ -387,7 +389,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.32.0 +referencing==0.32.1 # via # jsonschema # jsonschema-specifications @@ -399,7 +401,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.16.2 +rpds-py==0.17.1 # via # jsonschema # referencing @@ -412,7 +414,7 @@ scipy==1.10.1 # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.1 +sentry-sdk==1.39.2 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -485,7 +487,7 @@ tqdm==4.66.1 # via napari traceback-with-variables==2.0.4 # via PartSeg (setup.cfg) -traitlets==5.14.0 +traitlets==5.14.1 # via # comm # ipykernel @@ -518,7 +520,7 @@ vispy==0.12.2 # PartSeg (setup.cfg) # napari # napari-svg -wcwidth==0.2.12 +wcwidth==0.2.13 # via prompt-toolkit wrapt==1.16.0 # via napari @@ -533,4 +535,6 @@ zipp==3.17.0 # The following packages are considered to be unsafe in a requirements file: setuptools==69.0.3 - # via pyinstaller + # via + # pyinstaller + # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index 623ddbf9c..6e5706fb1 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -4,7 +4,7 @@ # # pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.9.txt --strip-extras requirements/version_denylist.txt setup.cfg # -alabaster==0.7.13 +alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller @@ -40,13 +40,13 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.0 +comm==0.2.1 # via ipykernel coverage==7.4.0 # via PartSeg (setup.cfg) czifile==2019.7.2 # via PartSeg (setup.cfg) -dask==2023.12.1 +dask==2024.1.0 # via # dask # napari @@ -99,12 +99,13 @@ importlib-metadata==7.0.1 # dask # jupyter-client # pyinstaller + # pyinstaller-hooks-contrib # sphinx in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.28.0 +ipykernel==6.29.0 # via # PartSeg (setup.cfg) # napari-console @@ -116,11 +117,11 @@ ipython==8.18.1 # napari-console jedi==0.19.1 # via ipython -jinja2==3.1.2 +jinja2==3.1.3 # via # numpydoc # sphinx -jsonschema==4.20.0 +jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema @@ -128,7 +129,7 @@ jupyter-client==8.6.0 # via # ipykernel # qtconsole -jupyter-core==5.5.1 +jupyter-core==5.7.1 # via # ipykernel # jupyter-client @@ -145,7 +146,7 @@ local-migrator==0.1.9 # nme locket==1.0.0 # via partd -lxml==5.0.0 +lxml==5.1.0 # via PartSeg (setup.cfg) magicgui==0.8.1 # via @@ -155,7 +156,7 @@ mahotas==1.4.13 # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.3 +markupsafe==2.1.4 # via jinja2 matplotlib-inline==0.1.6 # via @@ -177,7 +178,7 @@ napari-plugin-engine==0.2.0 # napari-svg napari-svg==0.1.10 # via napari -nest-asyncio==1.5.8 +nest-asyncio==1.6.0 # via ipykernel networkx==3.2.1 # via scikit-image @@ -187,7 +188,7 @@ npe2==0.7.3 # via # -r requirements/version_denylist.txt # napari -numpy==1.26.2 +numpy==1.26.3 # via # PartSeg (setup.cfg) # czifile @@ -220,6 +221,7 @@ packaging==23.2 # local-migrator # pooch # pyinstaller + # pyinstaller-hooks-contrib # pytest # qtconsole # qtpy @@ -227,7 +229,7 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.1.4 +pandas==2.2.0 # via # PartSeg (setup.cfg) # napari @@ -235,13 +237,13 @@ parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.1 +partsegcore-compiled-backend==0.15.2 # via PartSeg (setup.cfg) partsegdata==0.10.0 # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython -pillow==10.1.0 +pillow==10.2.0 # via # imageio # napari @@ -258,7 +260,7 @@ pooch==1.8.0 # via scikit-image prompt-toolkit==3.0.43 # via ipython -psutil==5.9.7 +psutil==5.9.8 # via # ipykernel # napari @@ -275,7 +277,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.13 +pydantic==1.10.14 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -296,7 +298,7 @@ pygments==2.17.2 # superqt pyinstaller==6.3.0 # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2023.11 +pyinstaller-hooks-contrib==2024.0 # via pyinstaller pyopengl==3.1.7 # via napari @@ -374,7 +376,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.32.0 +referencing==0.32.1 # via # jsonschema # jsonschema-specifications @@ -386,7 +388,7 @@ requests==2.31.0 # sphinx rich==13.7.0 # via npe2 -rpds-py==0.16.2 +rpds-py==0.17.1 # via # jsonschema # referencing @@ -394,12 +396,12 @@ scikit-image==0.22.0 # via # PartSeg (setup.cfg) # napari -scipy==1.11.4 +scipy==1.12.0 # via # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.1 +sentry-sdk==1.39.2 # via # -r requirements/version_denylist.txt # PartSeg (setup.cfg) @@ -423,17 +425,17 @@ sphinx==4.5.0 # via # napari # numpydoc -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.8 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.6 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.5 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.7 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython @@ -472,7 +474,7 @@ tqdm==4.66.1 # via napari traceback-with-variables==2.0.4 # via PartSeg (setup.cfg) -traitlets==5.14.0 +traitlets==5.14.1 # via # comm # ipykernel @@ -505,7 +507,7 @@ vispy==0.12.2 # PartSeg (setup.cfg) # napari # napari-svg -wcwidth==0.2.12 +wcwidth==0.2.13 # via prompt-toolkit wrapt==1.16.0 # via napari @@ -518,4 +520,6 @@ zipp==3.17.0 # The following packages are considered to be unsafe in a requirements file: setuptools==69.0.3 - # via pyinstaller + # via + # pyinstaller + # pyinstaller-hooks-contrib From de43a4f75b6bffef950e5bfc21346bf5e09f72f8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 25 Jan 2024 10:53:16 +0100 Subject: [PATCH 19/51] ci: Update `actions/upload-artifact` and `actions/download-artifact` from 3 to 4 (#1062) ## Summary by CodeRabbit - **Chores** - Updated versions of GitHub Actions for improved artifact handling and coverage reporting. --- .github/workflows/base_test_workflow.yml | 10 +++++----- .github/workflows/test_napari_repo.yml | 4 ++-- .github/workflows/test_prereleases.yml | 8 ++++---- .github/workflows/tests.yml | 15 ++++++++------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index dec303b12..a77ab2706 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -71,7 +71,7 @@ jobs: - name: Download test data if: ${{ inputs.test_data }} - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: test_data path: test_data @@ -92,17 +92,17 @@ jobs: BACKEND: ${{ inputs.qt_backend }} PIP_CONSTRAINT: requirements/constraints_py${{ inputs.python_version }}.txt - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: - name: upload pytest timing reports as json + name: timing-report-${{ inputs.os }}-py-${{ inputs.python_version }}-${{ inputs.napari }}-${{ inputs.qt_backend }}-${{ inputs.coverage }} path: | ./report-*.json retention-days: 7 - name: Upload coverage data - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: ${{ inputs.coverage }} with: - name: coverage reports + name: cov-reports-${{ inputs.os }}-py-${{ inputs.python_version }}-${{ inputs.napari }}-${{ inputs.qt_backend }} path: | ./.coverage.* diff --git a/.github/workflows/test_napari_repo.yml b/.github/workflows/test_napari_repo.yml index 4607e36fb..1c38781aa 100644 --- a/.github/workflows/test_napari_repo.yml +++ b/.github/workflows/test_napari_repo.yml @@ -15,7 +15,7 @@ jobs: - shell: bash run: bash build_utils/download_data.sh - name: Upload test data - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test_data path: test_data @@ -54,7 +54,7 @@ jobs: pip install setuptools tox tox-gh-actions - name: Download test data - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: test_data path: test_data diff --git a/.github/workflows/test_prereleases.yml b/.github/workflows/test_prereleases.yml index eb8cadfd7..dfbe0b68f 100644 --- a/.github/workflows/test_prereleases.yml +++ b/.github/workflows/test_prereleases.yml @@ -23,7 +23,7 @@ jobs: - shell: bash run: bash build_utils/download_data.sh - name: Upload test data - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test_data path: test_data @@ -59,7 +59,7 @@ jobs: - uses: tlambert03/setup-qt-libs@v1 - name: Download test data - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: test_data path: test_data @@ -115,14 +115,14 @@ jobs: pip-sync pip install . - name: upload requirements - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: requirements path: requirements.txt - name: Run PyInstaller run: python build_utils/create_and_pack_executable.py - name: Upload bundle - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: bundle path: dist2/ diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index be7d50d2f..2d0d85b3f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: - shell: bash run: bash build_utils/download_data.sh - name: Upload test data - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test_data path: test_data @@ -102,8 +102,8 @@ jobs: uses: ./.github/workflows/base_test_workflow.yml with: test_data: True - python_version: "3.8" - tox_args: "-e py38-PyQt5-coverage" + python_version: "3.10" + tox_args: "-e py310-PyQt5-coverage" coverage: true test_minimal: @@ -133,10 +133,11 @@ jobs: pip install codecov - name: Download coverage data - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: coverage reports + pattern: cov-reports-* path: coverage + merge-multiple: true - name: combine coverage data run: | python -Im coverage combine coverage @@ -176,7 +177,7 @@ jobs: - uses: tlambert03/setup-qt-libs@v1 - name: Download test data - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: test_data path: test_data @@ -201,7 +202,7 @@ jobs: run: bash build_utils/create_environment_yml.sh - name: Upload environment file - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: environment path: environment.yml From 2e1bfa950414ed41d47f09fe664f6f585b9c6632 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 01:10:26 +0100 Subject: [PATCH 20/51] ci: [pre-commit.ci] pre-commit autoupdate (#1064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 23.12.1 → 24.1.1](https://github.com/psf/black-pre-commit-mirror/compare/23.12.1...24.1.1) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- package/PartSeg/_roi_mask/batch_proceed.py | 8 +++++--- package/PartSeg/common_backend/__init__.py | 1 + package/PartSeg/common_gui/advanced_tabs.py | 1 + package/PartSeg/common_gui/error_report.py | 1 + package/PartSeg/common_gui/label_create.py | 1 + package/PartSeg/common_gui/qt_console.py | 1 + package/PartSeg/common_gui/qt_modal.py | 1 + package/PartSeg/common_gui/universal_gui_part.py | 1 - package/PartSeg/plugins/old_partseg/old_partseg.py | 8 +++++--- package/PartSeg/state_store.py | 1 + package/PartSegCore/algorithm_describe_base.py | 14 ++++++++------ .../analysis/batch_processing/batch_backend.py | 1 + .../analysis/batch_processing/parallel_backend.py | 1 + package/PartSegCore/class_generator.py | 8 +++++--- package/PartSegCore/mask_partition_utils.py | 1 + package/PartSegCore/register.py | 1 + package/PartSegCore/segmentation/__init__.py | 1 + package/PartSegCore/segmentation/watershed.py | 1 + package/PartSegCore/sphinx/auto_parameters.py | 1 + 20 files changed, 38 insertions(+), 17 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fc10a5186..fa0ec69a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black pass_filenames: true diff --git a/package/PartSeg/_roi_mask/batch_proceed.py b/package/PartSeg/_roi_mask/batch_proceed.py index b52d55a61..26ed5db2e 100644 --- a/package/PartSeg/_roi_mask/batch_proceed.py +++ b/package/PartSeg/_roi_mask/batch_proceed.py @@ -80,9 +80,11 @@ def run_calculation(self): # noqa: PLR0912 # FIXME state2 = StackSettings.transform_state( project_tuple, segmentation.roi_info, - {i: segmentation.parameters for i in segmentation.roi_info.bound_info} - if segmentation.roi_info is not None - else {}, + ( + {i: segmentation.parameters for i in segmentation.roi_info.bound_info} + if segmentation.roi_info is not None + else {} + ), [], ) if isinstance(task.save_prefix, tuple): diff --git a/package/PartSeg/common_backend/__init__.py b/package/PartSeg/common_backend/__init__.py index a9aceb234..55a72f255 100644 --- a/package/PartSeg/common_backend/__init__.py +++ b/package/PartSeg/common_backend/__init__.py @@ -1,6 +1,7 @@ """ This module contains non gui Qt based components """ + import os.path from typing import TYPE_CHECKING diff --git a/package/PartSeg/common_gui/advanced_tabs.py b/package/PartSeg/common_gui/advanced_tabs.py index d7c0f6709..d60c3a3a6 100644 --- a/package/PartSeg/common_gui/advanced_tabs.py +++ b/package/PartSeg/common_gui/advanced_tabs.py @@ -2,6 +2,7 @@ This module contains base for the advanced window for PartSeg. At this moment controlling colormaps tabs and developer PartSegCore """ + import importlib import sys from contextlib import suppress diff --git a/package/PartSeg/common_gui/error_report.py b/package/PartSeg/common_gui/error_report.py index d56c7420e..9b76a3574 100644 --- a/package/PartSeg/common_gui/error_report.py +++ b/package/PartSeg/common_gui/error_report.py @@ -3,6 +3,7 @@ .. _sentry: https://sentry.io """ + import getpass import io import os diff --git a/package/PartSeg/common_gui/label_create.py b/package/PartSeg/common_gui/label_create.py index e478daad8..cc226eacf 100644 --- a/package/PartSeg/common_gui/label_create.py +++ b/package/PartSeg/common_gui/label_create.py @@ -1,6 +1,7 @@ """ This module contains widgets to create and manage labels scheme """ + import json import typing from copy import deepcopy diff --git a/package/PartSeg/common_gui/qt_console.py b/package/PartSeg/common_gui/qt_console.py index 9cc3c4b64..5465b48bb 100644 --- a/package/PartSeg/common_gui/qt_console.py +++ b/package/PartSeg/common_gui/qt_console.py @@ -1,6 +1,7 @@ """ Code from https://github.com/napari/napari-console """ + # pylint: disable=no-value-for-parameter,unexpected-keyword-arg import re import sys diff --git a/package/PartSeg/common_gui/qt_modal.py b/package/PartSeg/common_gui/qt_modal.py index 0ab34b1a0..ca4071afa 100644 --- a/package/PartSeg/common_gui/qt_modal.py +++ b/package/PartSeg/common_gui/qt_modal.py @@ -1,4 +1,5 @@ """from napari._qt.dialog.modal """ + from qtpy.QtCore import QPoint, QRect, Qt from qtpy.QtGui import QCursor, QGuiApplication, QKeyEvent from qtpy.QtWidgets import QDialog, QFrame, QVBoxLayout diff --git a/package/PartSeg/common_gui/universal_gui_part.py b/package/PartSeg/common_gui/universal_gui_part.py index 4de04142b..88bafcd70 100644 --- a/package/PartSeg/common_gui/universal_gui_part.py +++ b/package/PartSeg/common_gui/universal_gui_part.py @@ -2,7 +2,6 @@ This module contains simple, useful widgets which implementation is too short to create separated files for them """ - import math import typing import warnings diff --git a/package/PartSeg/plugins/old_partseg/old_partseg.py b/package/PartSeg/plugins/old_partseg/old_partseg.py index a4b2c2dd1..f1c2a2f31 100644 --- a/package/PartSeg/plugins/old_partseg/old_partseg.py +++ b/package/PartSeg/plugins/old_partseg/old_partseg.py @@ -45,9 +45,11 @@ def _load(cls, tar_file: tarfile.TarFile, file_path: str) -> ProjectTuple: "channel": 0, "minimum_size": algorithm_dict["minimum_size"], "threshold": {"name": "Manual", "values": {"threshold": algorithm_dict["threshold"]}}, - "noise_removal": {"name": "Gauss", "values": {"gauss_type": DimensionType.Layer, "radius": 1.0}} - if algorithm_dict["use_gauss"] - else {"name": "None", "values": {}}, + "noise_removal": ( + {"name": "Gauss", "values": {"gauss_type": DimensionType.Layer, "radius": 1.0}} + if algorithm_dict["use_gauss"] + else {"name": "None", "values": {}} + ), "side_connection": True, } diff --git a/package/PartSeg/state_store.py b/package/PartSeg/state_store.py index 848dd2c9f..e8ad6fdea 100644 --- a/package/PartSeg/state_store.py +++ b/package/PartSeg/state_store.py @@ -1,6 +1,7 @@ """ Module with default values of application state """ + import os import sys diff --git a/package/PartSegCore/algorithm_describe_base.py b/package/PartSegCore/algorithm_describe_base.py index 0064152d3..d0589fed7 100644 --- a/package/PartSegCore/algorithm_describe_base.py +++ b/package/PartSegCore/algorithm_describe_base.py @@ -191,12 +191,14 @@ def get_default_values(cls): if cls.__new_style__: return cls.__argument_class__() # pylint: disable=not-callable return { - el.name: { - "name": el.default_value, - "values": el.possible_values[el.default_value].get_default_values(), - } - if issubclass(el.value_type, AlgorithmDescribeBase) - else el.default_value + el.name: ( + { + "name": el.default_value, + "values": el.possible_values[el.default_value].get_default_values(), + } + if issubclass(el.value_type, AlgorithmDescribeBase) + else el.default_value + ) for el in cls.get_fields() if isinstance(el, AlgorithmProperty) } diff --git a/package/PartSegCore/analysis/batch_processing/batch_backend.py b/package/PartSegCore/analysis/batch_processing/batch_backend.py index b62b61d9a..4691228a9 100644 --- a/package/PartSegCore/analysis/batch_processing/batch_backend.py +++ b/package/PartSegCore/analysis/batch_processing/batch_backend.py @@ -20,6 +20,7 @@ } """ + import contextlib import json import logging diff --git a/package/PartSegCore/analysis/batch_processing/parallel_backend.py b/package/PartSegCore/analysis/batch_processing/parallel_backend.py index e066d8475..ba35572f2 100644 --- a/package/PartSegCore/analysis/batch_processing/parallel_backend.py +++ b/package/PartSegCore/analysis/batch_processing/parallel_backend.py @@ -14,6 +14,7 @@ } """ + import logging import multiprocessing import os diff --git a/package/PartSegCore/class_generator.py b/package/PartSegCore/class_generator.py index a04c32629..83b2c07cf 100644 --- a/package/PartSegCore/class_generator.py +++ b/package/PartSegCore/class_generator.py @@ -238,9 +238,11 @@ def _make_class(typename, types, defaults_dict, base_classes, readonly): del global_state[typename] signature = ", ".join( - f"{name_}: {translate_dict[type_]} = {pprint.pformat(defaults_dict[name_])}" - if name_ in defaults_dict - else f"{name_}: {translate_dict[type_]}" + ( + f"{name_}: {translate_dict[type_]} = {pprint.pformat(defaults_dict[name_])}" + if name_ in defaults_dict + else f"{name_}: {translate_dict[type_]}" + ) for name_, type_ in types.items() ) diff --git a/package/PartSegCore/mask_partition_utils.py b/package/PartSegCore/mask_partition_utils.py index 6c90a063e..55918d60e 100644 --- a/package/PartSegCore/mask_partition_utils.py +++ b/package/PartSegCore/mask_partition_utils.py @@ -8,6 +8,7 @@ Both class from this module are designed for spherical mask, but may be useful als for others. """ + import typing import numpy as np diff --git a/package/PartSegCore/register.py b/package/PartSegCore/register.py index 4d2b38b4e..e23d7185b 100644 --- a/package/PartSegCore/register.py +++ b/package/PartSegCore/register.py @@ -12,6 +12,7 @@ register_dict: holds information where register given operation type. Strongly suggest to use register function instead. """ + from enum import Enum from typing import Type diff --git a/package/PartSegCore/segmentation/__init__.py b/package/PartSegCore/segmentation/__init__.py index c839cffca..66ea9df0f 100644 --- a/package/PartSegCore/segmentation/__init__.py +++ b/package/PartSegCore/segmentation/__init__.py @@ -1,6 +1,7 @@ """ This module contains roi_extraction algorithms """ + import os import sys diff --git a/package/PartSegCore/segmentation/watershed.py b/package/PartSegCore/segmentation/watershed.py index a3d41bc30..26e85c24b 100644 --- a/package/PartSegCore/segmentation/watershed.py +++ b/package/PartSegCore/segmentation/watershed.py @@ -1,6 +1,7 @@ """ This module contains PartSeg wrappers for function for :py:mod:`..sprawl_utils.find_split`. """ + import warnings from abc import ABC from enum import Enum diff --git a/package/PartSegCore/sphinx/auto_parameters.py b/package/PartSegCore/sphinx/auto_parameters.py index 84ae4f3f4..041b46aea 100644 --- a/package/PartSegCore/sphinx/auto_parameters.py +++ b/package/PartSegCore/sphinx/auto_parameters.py @@ -1,6 +1,7 @@ """ This module contain utilities to document Register class. """ + import inspect from typing import Any, Dict From b37d520f4343ba5f36f14df449190d3437e99d5b Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 4 Feb 2024 18:51:46 +0100 Subject: [PATCH 21/51] ci: Group actions update (#1065) ## Summary by CodeRabbit - **Chores** - Updated Dependabot configuration to group action updates more efficiently. --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 38f4f5f2b..160897d57 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,3 +6,7 @@ updates: interval: "weekly" target-branch: "develop" + groups: + github-actions: + patterns: + - "actions/*" From 0e4b301ffd4c5dfae7aac8e05eb037830e5986b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:49:50 +0100 Subject: [PATCH 22/51] build(deps): bump peter-evans/create-pull-request from 5 to 6 (#1067) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5 to 6.
Release notes

Sourced from peter-evans/create-pull-request's releases.

Create Pull Request v6.0.0

Behaviour changes

  • The default values for author and committer have changed. See "What's new" below for details. If you are overriding the default values you will not be affected by this change.
  • On completion, the action now removes the temporary git remote configuration it adds when using push-to-fork. This should not affect you unless you were using the temporary configuration for some other purpose after the action completes.

What's new

  • Updated runtime to Node.js 20
    • The action now requires a minimum version of v2.308.0 for the Actions runner. Update self-hosted runners to v2.308.0 or later to ensure compatibility.
  • The default value for author has been changed to ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>. The change adds the ${{ github.actor_id }}+ prefix to the email address to align with GitHub's standard format for the author email address.
  • The default value for committer has been changed to github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>. This is to align with the default GitHub Actions bot user account.
  • Adds input git-token, the Personal Access Token (PAT) that the action will use for git operations. This input defaults to the value of token. Use this input if you would like the action to use a different token for git operations than the one used for the GitHub API.
  • push-to-fork now supports pushing to sibling repositories in the same network.
  • Previously, when using push-to-fork, the action did not remove temporary git remote configuration it adds during execution. This has been fixed and the configuration is now removed when the action completes.
  • If the pull request body is truncated due to exceeding the maximum length, the action will now suffix the body with the message "...[Pull request body truncated]" to indicate that the body has been truncated.
  • The action now uses --unshallow only when necessary, rather than as a default argument of git fetch. This should improve performance, particularly for large git repositories with extensive commit history.
  • The action can now be executed on one GitHub server and create pull requests on a different GitHub server. Server products include GitHub hosted (github.com), GitHub Enterprise Server (GHES), and GitHub Enterprise Cloud (GHEC). For example, the action can be executed on GitHub hosted and create pull requests on a GHES or GHEC instance.

What's Changed

New Contributors

Full Changelog: https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.0.0

Create Pull Request v5.0.2

⚙️ Fixes an issue that occurs when using push-to-fork and both base and head repositories are in the same org/user account.

What's Changed

Full Changelog: https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2

Create Pull Request v5.0.1

What's Changed

Full Changelog: https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1

Commits
  • b1ddad2 feat: v6 (#2717)
  • bb80902 build(deps-dev): bump @​types/node from 18.19.8 to 18.19.10 (#2712)
  • e0037d4 build(deps): bump peter-evans/create-or-update-comment from 3 to 4 (#2702)
  • 94b1f99 build(deps): bump peter-evans/find-comment from 2 to 3 (#2703)
  • 69c27ea build(deps-dev): bump ts-jest from 29.1.1 to 29.1.2 (#2685)
  • 7ea722a build(deps-dev): bump prettier from 3.2.2 to 3.2.4 (#2684)
  • 5ee839a build(deps-dev): bump @​types/node from 18.19.7 to 18.19.8 (#2683)
  • 60fc256 build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (#2660)
  • 0c67723 build(deps-dev): bump @​types/node from 18.19.5 to 18.19.7 (#2661)
  • 4e288e8 build(deps-dev): bump prettier from 3.1.1 to 3.2.2 (#2659)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/create-pull-request&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/upgrade-dependencies.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index 3e8ba7541..c75463834 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -67,7 +67,7 @@ jobs: echo "EOF" >> $GITHUB_OUTPUT - name: Create PR updating vendored modules - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: commit-message: Update bundle dependencies. branch: ${{ env.BRANCH_NAME }} From 703a27491385b14c31442541ed6638a1af5a53ce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:53:31 +0100 Subject: [PATCH 23/51] ci: [pre-commit.ci] pre-commit autoupdate (#1068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.14 → v0.2.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.14...v0.2.0) ## Summary by CodeRabbit - **Refactor** - Improved code robustness by utilizing the `get` method for dictionary access across several modules. This enhances error handling and code readability. - **Bug Fixes** - Adjusted data type handling in file attribute management for consistency and reliability. - **Chores** - Updated the version of a development tool to enhance the setup configuration formatting process. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 2 +- package/PartSeg/_roi_mask/main_window.py | 2 +- .../PartSeg/common_gui/algorithms_description.py | 2 +- package/PartSegCore/analysis/load_functions.py | 2 +- package/PartSegCore/analysis/save_functions.py | 12 ++++++------ package/PartSegCore/mask/io_functions.py | 4 ++-- package/PartSegCore/project_info.py | 2 +- package/PartSegCore/utils.py | 2 +- pyproject.toml | 16 +++++++++------- 9 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa0ec69a2..dd01b017f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: setup-cfg-fmt args: ["--include-version-classifiers", "--max-py-version", "3.11"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.14 + rev: v0.2.0 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade diff --git a/package/PartSeg/_roi_mask/main_window.py b/package/PartSeg/_roi_mask/main_window.py index 870c30de1..9312a0f58 100644 --- a/package/PartSeg/_roi_mask/main_window.py +++ b/package/PartSeg/_roi_mask/main_window.py @@ -97,7 +97,7 @@ def prev_mask(self): history.roi_extraction_parameters["selected"], history.roi_extraction_parameters["parameters"], ) - self.settings.mask = seg["mask"] if "mask" in seg else None + self.settings.mask = seg.get("mask") self.close() diff --git a/package/PartSeg/common_gui/algorithms_description.py b/package/PartSeg/common_gui/algorithms_description.py index 6494678f7..1ae140ed4 100644 --- a/package/PartSeg/common_gui/algorithms_description.py +++ b/package/PartSeg/common_gui/algorithms_description.py @@ -572,7 +572,7 @@ def algorithm_choose(self, name): if name not in self.widgets_dict: if name not in self.property.possible_values: return - start_dict = {} if name not in self.starting_values else self.starting_values[name] + start_dict = self.starting_values.get(name, {}) self.widgets_dict[name] = self._get_form_widget(self.property.possible_values[name], start_dict) self.layout().addWidget(self.widgets_dict[name]) diff --git a/package/PartSegCore/analysis/load_functions.py b/package/PartSegCore/analysis/load_functions.py index ade502d74..0e94df33c 100644 --- a/package/PartSegCore/analysis/load_functions.py +++ b/package/PartSegCore/analysis/load_functions.py @@ -100,7 +100,7 @@ def load_project_from_tar(tar_file, file_path): if version == Version("1.0"): seg_dict = np.load(tar_to_buff(tar_file, "segmentation.npz")) - mask = seg_dict["mask"] if "mask" in seg_dict else None + mask = seg_dict.get("mask") roi = seg_dict["segmentation"] else: roi = tifffile.imread(tar_to_buff(tar_file, "segmentation.tif")) diff --git a/package/PartSegCore/analysis/save_functions.py b/package/PartSegCore/analysis/save_functions.py index 8dd395a4e..f21f60744 100644 --- a/package/PartSegCore/analysis/save_functions.py +++ b/package/PartSegCore/analysis/save_functions.py @@ -122,14 +122,14 @@ def _save_cmap( meta_group.attrs[key] = val grp = cmap_file["Chimera"] - grp.attrs["CLASS"] = np.string_("GROUP") - grp.attrs["TITLE"] = np.string_("") - grp.attrs["VERSION"] = np.string_("1.0") + grp.attrs["CLASS"] = np.bytes_("GROUP") + grp.attrs["TITLE"] = np.bytes_("") + grp.attrs["VERSION"] = np.bytes_("1.0") grp = cmap_file["Chimera/image1"] - grp.attrs["CLASS"] = np.string_("GROUP") - grp.attrs["TITLE"] = np.string_("") - grp.attrs["VERSION"] = np.string_("1.0") + grp.attrs["CLASS"] = np.bytes_("GROUP") + grp.attrs["TITLE"] = np.bytes_("") + grp.attrs["VERSION"] = np.bytes_("1.0") grp.attrs["step"] = np.array(spacing, dtype=np.float32)[::-1] * UNIT_SCALE[cmap_profile["units"].value] return cmap_file diff --git a/package/PartSegCore/mask/io_functions.py b/package/PartSegCore/mask/io_functions.py index 1a90d7a1d..96f6d4c39 100644 --- a/package/PartSegCore/mask/io_functions.py +++ b/package/PartSegCore/mask/io_functions.py @@ -293,11 +293,11 @@ def load_stack_segmentation_from_tar(tar_file: tarfile.TarFile, file_path: str, step_changed(6) return MaskProjectTuple( file_path=file_path, - image=metadata["base_file"] if "base_file" in metadata else None, + image=metadata.get("base_file"), roi_info=roi_info, selected_components=metadata["components"], mask=mask, - roi_extraction_parameters=metadata["parameters"] if "parameters" in metadata else None, + roi_extraction_parameters=metadata.get("parameters"), history=history, spacing=([10 ** (-9), *list(spacing)]) if spacing is not None else None, frame_thickness=metadata.get("frame_thickness", FRAME_THICKNESS), diff --git a/package/PartSegCore/project_info.py b/package/PartSegCore/project_info.py index 59149e9c3..507fd1b29 100644 --- a/package/PartSegCore/project_info.py +++ b/package/PartSegCore/project_info.py @@ -72,7 +72,7 @@ def get_roi_info_and_mask(self) -> Tuple[ROIInfo, Optional[np.ndarray]]: self.arrays.seek(0) alternative = {name: array for name, array in seg.items() if name not in {"roi", "mask"}} roi_info = ROIInfo(seg["roi"], annotations=self.annotations, alternative=alternative) - mask = seg["mask"] if "mask" in seg else None + mask = seg.get("mask") return roi_info, mask diff --git a/package/PartSegCore/utils.py b/package/PartSegCore/utils.py index f2baaf7bf..5e737a7a0 100644 --- a/package/PartSegCore/utils.py +++ b/package/PartSegCore/utils.py @@ -169,7 +169,7 @@ def __setitem__(self, k, v) -> None: if k in self._dict and isinstance(self._dict[k], EventedDict): self._dict[k].setted.disconnect(self._propagate_setitem) self._dict[k].deleted.disconnect(self._propagate_del) - old_value = self._dict[k] if k in self._dict else None + old_value = self._dict.get(k) with suppress(ValueError): if old_value == v: return diff --git a/pyproject.toml b/pyproject.toml index fa8df02fc..deff93322 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,11 @@ exclude = ''' [tool.ruff] line-length = 120 +exclude = ["examples/call_simple_threshold.py"] +target-version = "py38" +fix = true + +[tool.ruff.lint] select = [ "F", # Pyflakes "E", "W", # pycodestyle @@ -65,22 +70,19 @@ select = [ ignore = ["A003", "SIM108", "ARG002", "ARG003", "ARG004", "PLR2004", "PLR0913" # should be reenabled in future version ] -exclude = ["examples/call_simple_threshold.py"] -target-version = "py38" -fix = true -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party=['PartSeg', 'PartSegData','PartSegCore','PartSegImage', 'PartSegCore_compiled_backend'] -[tool.ruff.flake8-tidy-imports] +[tool.ruff.lint.flake8-tidy-imports] # Disallow all relative imports. ban-relative-imports = "all" -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 15 -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "docs/conf.py" = ["A001"] "package/tests/**" = ["ARG", "PLC1901", "S101", "RUF012"] "package/PartSegCore/sphinx/*" = ["ARG"] From b5193ae57f54e3b74f5d88addf4ee6668a309c17 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 7 Feb 2024 23:07:16 +0100 Subject: [PATCH 24/51] refactor: Migrate from setup.cfg to `pyproject.toml` (#1070) ## Summary by CodeRabbit - **Chores** - Updated pre-commit hooks, removing `setup-cfg-fmt` and upgrading `ruff-pre-commit` to version `v0.2.0`. - Updated Python version in the workflow configuration from "3.9" to "3.11". - Replaced dependency extraction method with a Python script to convert `pyproject.toml` file to YAML format. - Dynamically generated dependencies using a Python script instead of a shell script, updating Python version to `3.11` in the generated `environment.yml` file. - Added `pyproject_toml_to_yaml.py` to convert `pyproject.toml` dependencies to YAML with modifications for specific dependencies. --- .github/workflows/tests.yml | 4 +- .pre-commit-config.yaml | 5 - build_utils/create_environment_yml.sh | 7 +- build_utils/pyproject_toml_to_yaml.py | 13 ++ pyproject.toml | 227 +++++++++++++++++++++++++- setup.cfg | 190 --------------------- tox.ini | 3 +- 7 files changed, 246 insertions(+), 203 deletions(-) create mode 100644 build_utils/pyproject_toml_to_yaml.py delete mode 100644 setup.cfg diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2d0d85b3f..66589cea6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -172,7 +172,7 @@ jobs: use-mamba: true channels: conda-forge channel-priority: strict - python-version: "3.9" + python-version: "3.11" - uses: tlambert03/setup-qt-libs@v1 @@ -215,7 +215,7 @@ jobs: - name: Test with tox uses: aganders3/headless-gui@v2 with: - run: conda run -n test --no-capture-output tox -e py39-PySide2-conda + run: conda run -n test --no-capture-output tox -e py311-PySide2-conda timeout-minutes: 60 check-package: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd01b017f..ee1830ba6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,11 +19,6 @@ repos: exclude: .*\.md - id: debug-statements - id: mixed-line-ending -- repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.5.0 - hooks: - - id: setup-cfg-fmt - args: ["--include-version-classifiers", "--max-py-version", "3.11"] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.2.0 hooks: diff --git a/build_utils/create_environment_yml.sh b/build_utils/create_environment_yml.sh index 06359fe05..9cd8c0b8c 100644 --- a/build_utils/create_environment_yml.sh +++ b/build_utils/create_environment_yml.sh @@ -2,7 +2,7 @@ set -euo pipefail -dependencies=$(bash build_utils/setup_cfg_to_yaml.sh 'install_requires =') +dependencies=$(python build_utils/pyproject_toml_to_yaml.py) cat < environment.yml name: test @@ -10,7 +10,6 @@ channels: - conda-forge dependencies: $dependencies - - python=3.9 - - pip: - - fonticon-fontawesome6 + - pyside2 + - python=3.11 EOF diff --git a/build_utils/pyproject_toml_to_yaml.py b/build_utils/pyproject_toml_to_yaml.py new file mode 100644 index 000000000..81c871765 --- /dev/null +++ b/build_utils/pyproject_toml_to_yaml.py @@ -0,0 +1,13 @@ +from pathlib import Path + +import tomllib + +base_dir = Path(__file__).parent.parent +pyproject_toml = base_dir / "pyproject.toml" + +with pyproject_toml.open("rb") as f: + data = tomllib.load(f) +dependencies = data["project"]["dependencies"] +dependencies_str = "\n".join([f" - {v}" for v in dependencies]) +dependencies_str = dependencies_str.replace("qtconsole", "qtconsole-base") +print(dependencies_str) diff --git a/pyproject.toml b/pyproject.toml index deff93322..0cfeabc90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,236 @@ [build-system] # Minimum requirements for the build system to execute. -requires = ["setuptools>=42.0.0", "wheel>=0.34.2", "setuptools_scm[toml]>=8"] # PEP 508 specifications. +requires = ["setuptools>=61.2.0", "setuptools_scm[toml]>=8"] # PEP 508 specifications. build-backend = "setuptools.build_meta" [tool.setuptools_scm] write_to = "package/PartSeg/version.py" +[project] +name = "PartSeg" +description = "PartSeg is python GUI and set of napari plugins for bio imaging analysis especially nucleus analysis," +authors = [ + { name = "Grzegorz Bokota", email = "g.bokota@uw.edu.pl" }, +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Framework :: napari", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering :: Bio-Informatics", + "Topic :: Scientific/Engineering :: Image Processing", + "Topic :: Scientific/Engineering :: Visualization", +] +keywords = [ + "bioimaging", + "GUI", +] +requires-python = ">=3.8" +dependencies = [ + "IPython>=7.7.0", + "PartSegCore-compiled-backend>=0.13.11,<0.16.0", + "PartSegData==0.10.0", + "QtAwesome!=1.2.0,>=1.0.3", + "QtPy>=1.10.0", + "SimpleITK>=2.0.0", + "appdirs>=1.4.4", + "czifile>=2019.5.22", + "defusedxml>=0.6.0", + "fonticon-fontawesome6>=6.1.1", + "h5py>=3.3.0", + "imagecodecs>=2020.5.30", + "imageio>=2.5.0", + "ipykernel>=5.2.0", + "local-migrator>=0.1.7", + "magicgui!=0.5.0,>=0.4.0", + "mahotas>=1.4.10", + "napari>=0.4.14", + "nme>=0.1.7", + "numpy>=1.18.5", + "oiffile>=2020.1.18", + "openpyxl>=2.5.7", + "packaging>=20.0", + "pandas>=1.1.0", + "psygnal>=0.3.1", + "pydantic>=1.8.1,<2", + "pygments>=2.4.0", + "qtconsole>=4.7.7", + "requests>=2.18.0", + "scipy>=1.4.1", + "sentry-sdk>=0.14.3", + "six>=1.11.0", + "superqt>=0.3.0", + "sympy>=1.1.1", + "tifffile>=2020.9.30", + "traceback-with-variables>=2.0.4", + "vispy>=0.9.4", + "xlrd>=1.1.0", + "xlsxwriter>=2.0.0", +] +dynamic = [ + "version", +] +[project.readme] +file = "Readme.md" +content-type = "text/markdown" + +[project.license] +text = "BSD-3-Clause" + +[project.urls] +Homepage = "https://4dnucleome.cent.uw.edu.pl/PartSeg/" +Documentation = "https://partseg.readthedocs.io/en/stable/" +"Source Code" = "https://github.com/4DNucleome/PartSeg" +"User Support" = "https://github.com/4DNucleome/PartSeg/issues" +"Bug Tracker" = "https://github.com/4DNucleome/PartSeg/issues" + +[project.entry-points."napari.manifest"] +PartSeg = "PartSeg:napari.yaml" + +[project.optional-dependencies] +accelerate = [ + "PyOpenGL-accelerate>=3.1.5", +] +all = [ + "PyOpenGL-accelerate>=3.1.5", + "PyQt5!=5.15.0,>=5.12.3", +] +docs = [ + "autodoc-pydantic", + "sphinx!=3.0.0,!=3.5.0", + "sphinx-autodoc-typehints", + "sphinx-qt-documentation", +] +pyinstaller = [ + "PyOpenGL-accelerate>=3.1.5", + "PyQt5!=5.15.0,>=5.12.3", + "PyInstaller", + "pydantic<2", +] +pyqt = [ + "PyQt5!=5.15.0,>=5.12.3", +] +pyqt5 = [ + "PyQt5!=5.15.0,>=5.12.3", +] +pyqt6 = [ + "PyQt6", +] +pyside = [ + "PySide2!=5.15.0,>=5.12.3", +] +pyside2 = [ + "PySide2!=5.15.0,>=5.12.3", +] +pyside6 = [ + "PySide6", +] +test = [ + "coverage", + "lxml", + "pytest>=7.0.0", + "pytest-qt", + "pytest-timeout", + "scikit-image", +] +testing = [ + "pytest", + "pytest-qt", + "lxml", +] + +[project.scripts] +PartSeg = "PartSeg.launcher_main:main" + +[tool.setuptools] +include-package-data = true +platforms = [ + "Linux", + "Windows", + "MacOs", +] +license-files = [ + "License.txt", +] + +[tool.setuptools.package-dir] +"" = "package" + +[tool.setuptools.packages.find] +where = [ + "package", +] +namespaces = false + +[tool.setuptools.package-data] +partsegcore = [ + "napari.yaml", +] + +[tool.pytest.ini_options] +addopts = "--maxfail=5 --durations=5" +testpaths = [ + "package/tests", +] +junit_family = "legacy" +timeout = 900 +filterwarnings = [ + "ignore:invalid value encountered", + "ignore:The 'junit_family' encountered", + "ignore:numpy.ufunc size changed, may indicate", + "ignore:tostring.*is deprecated", + "ignore:emitter camera is deprecated,", + "ignore:`np.float` is a deprecated alias", + "ignore:divide by zero encountered in true_divide", + "ignore:the imp module is deprecated in favour of importlib", + "ignore:distutils Version classes are deprecated.", + "ignore:Please import PackageMetadata from 'npe2' or from 'npe2.manifest'", + "ignore:Please use `zoom` from the `scipy.ndimage` namespace", + "ignore:Converting `np.character` to a dtype", + "ignore:Public access to Window.qt_viewer", +] +markers = [ + "enablethread: Allow to use thread in test", + "enabledialog: Allow to use dialog in test", + "no_patch_add_layer: Do not patch napari viewer", + "windows_ci_skip: Skip test when running on windows CI", + "pyside_skip: Skip test when using pyside qt backend", +] + +[tool.coverage.paths] +source = [ + "package", + "*/site-packages", +] + +[tool.coverage.run] +source = [ + "PartSeg", + "PartSegCore", + "PartSegImage", +] +omit = [ + ".tox/*", + "**/changelog.py", + "**/version.py", +] +parallel = true + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "raise NotImplementedError", + "if typing.TYPE_CHECKING", + "raise RuntimeError()", +] + [tool.black] line-length = 120 target-version = ['py38'] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 21a86175a..000000000 --- a/setup.cfg +++ /dev/null @@ -1,190 +0,0 @@ -[metadata] -name = PartSeg -description = PartSeg is python GUI and set of napari plugins for bio imaging analysis especially nucleus analysis, -long_description = file: Readme.md -long_description_content_type = text/markdown -url = https://4dnucleome.cent.uw.edu.pl/PartSeg/ -author = Grzegorz Bokota -author_email = g.bokota@cent.uw.edu.pl -license = BSD-3-Clause -license_files = License.txt -platforms = Linux, Windows, MacOs -classifiers = - Development Status :: 3 - Alpha - Framework :: napari - License :: OSI Approved :: BSD License - Operating System :: OS Independent - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: Implementation :: CPython - Topic :: Scientific/Engineering :: Bio-Informatics - Topic :: Scientific/Engineering :: Image Processing - Topic :: Scientific/Engineering :: Visualization -keywords = bioimaging, GUI -project_urls = - Documentation = https://partseg.readthedocs.io/en/stable/ - Source Code = https://github.com/4DNucleome/PartSeg - User Support = https://github.com/4DNucleome/PartSeg/issues - Bug Tracker = https://github.com/4DNucleome/PartSeg/issues - -[options] -packages = find: -install_requires = - IPython>=7.7.0 - PartSegCore-compiled-backend>=0.13.11,<0.16.0 - PartSegData==0.10.0 - QtAwesome!=1.2.0,>=1.0.3 - QtPy>=1.10.0 - SimpleITK>=2.0.0 - appdirs>=1.4.4 - czifile>=2019.5.22 - defusedxml>=0.6.0 - fonticon-fontawesome6>=6.1.1 - h5py>=3.3.0 - imagecodecs>=2020.5.30 - imageio>=2.5.0 - ipykernel>=5.2.0 - local-migrator>=0.1.7 - magicgui!=0.5.0,>=0.4.0 - mahotas>=1.4.10 - napari>=0.4.14 - nme>=0.1.7 - numpy>=1.18.5 - oiffile>=2020.1.18 - openpyxl>=2.5.7 - packaging>=20.0 - pandas>=1.1.0 - psygnal>=0.3.1 - pydantic>=1.8.1,<2 - pygments>=2.4.0 - qtconsole>=4.7.7 - requests>=2.18.0 - scipy>=1.4.1 - sentry-sdk>=0.14.3 - six>=1.11.0 - superqt>=0.3.0 - sympy>=1.1.1 - tifffile>=2020.9.30 - traceback-with-variables>=2.0.4 - vispy>=0.9.4 - xlrd>=1.1.0 - xlsxwriter>=2.0.0 -python_requires = >=3.8 -include_package_data = True -package_dir = - =package -tests_require = - pytest - pytest-qt - lxml - -[options.packages.find] -where = package - -[options.entry_points] -console_scripts = - PartSeg = PartSeg.launcher_main:main -napari.manifest = - PartSeg = PartSeg:napari.yaml - -[options.extras_require] -accelerate = - PyOpenGL-accelerate>=3.1.5 -all = - PyOpenGL-accelerate>=3.1.5 - PyQt5!=5.15.0,>=5.12.3 -docs = - autodoc-pydantic - sphinx!=3.0.0,!=3.5.0 - sphinx-autodoc-typehints - sphinx-qt-documentation -pyinstaller = - %(all)s - PyInstaller - pydantic<2 -pyqt = - PyQt5!=5.15.0,>=5.12.3 -pyqt5 = - PyQt5!=5.15.0,>=5.12.3 -pyqt6 = - PyQt6 -pyside = - PySide2!=5.15.0,>=5.12.3 -pyside2 = - PySide2!=5.15.0,>=5.12.3 -pyside6 = - PySide6 -test = - coverage - lxml - pytest>=7.0.0 - pytest-qt - pytest-timeout - scikit-image - -[options.package_data] -partsegcore = napari.yaml - -[tool:pytest] -addopts = --maxfail=5 --durations=5 -testpaths = package/tests -junit_family = legacy -timeout = 900 -filterwarnings = - ignore:invalid value encountered - ignore:The 'junit_family' encountered - ignore:numpy.ufunc size changed, may indicate - ignore:tostring.*is deprecated - ignore:emitter camera is deprecated, - ignore:`np.float` is a deprecated alias - ignore:divide by zero encountered in true_divide - ignore:the imp module is deprecated in favour of importlib - ignore:distutils Version classes are deprecated. - ignore:Please import PackageMetadata from 'npe2' or from 'npe2.manifest' - ignore:Please use `zoom` from the `scipy.ndimage` namespace - ignore:Converting `np.character` to a dtype - ignore:Public access to Window.qt_viewer -markers = - enablethread: Allow to use thread in test - enabledialog: Allow to use dialog in test - no_patch_add_layer: Do not patch napari viewer - windows_ci_skip: Skip test when running on windows CI - pyside_skip: Skip test when using pyside qt backend - -[coverage:paths] -source = - package - */site-packages - -[coverage:run] -source = - PartSeg - PartSegCore - PartSegImage -omit = - .tox/* - **/changelog.py - **/version.py -parallel = True - -[coverage:report] -exclude_lines = - pragma: no cover - raise NotImplementedError - if typing.TYPE_CHECKING - raise RuntimeError() - -[flake8] -max-line-length = 120 -ignore = E203,W503,C901 -max-complexity = 18 -exclude = package/PartSeg/changelog.py, build/**, .eggs/** -banned-modules = PyQt5 = use qtpy - PySide2 = use qtpy - -[pylint.FORMAT] -max-line-length = 120 diff --git a/tox.ini b/tox.ini index 8daedc412..801ff1463 100644 --- a/tox.ini +++ b/tox.ini @@ -65,7 +65,7 @@ extras = commands = python -m pytest package/tests --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json -[testenv:py39-PySide2-conda] +[testenv:py311-PySide2-conda] conda_env=environment.yml deps= pytest @@ -112,6 +112,7 @@ deps = deps = {[testenv]deps} jupyter[all] + jupyter[all] matplotlib -crequirements/constraints_py3.9.txt setenv = From 174cf5c8bb55abeacd6bb7836fefc1679afe7a91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 09:24:00 +0100 Subject: [PATCH 25/51] build(deps): bump codecov/codecov-action from 3 to 4 (#1066) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
Release notes

Sourced from codecov/codecov-action's releases.

v4.0.0

v4 of the Codecov Action uses the CLI as the underlying upload. The CLI has helped to power new features including local upload, the global upload token, and new upcoming features.

Breaking Changes

  • The Codecov Action runs as a node20 action due to node16 deprecation. See this post from GitHub on how to migrate.
  • Tokenless uploading is unsupported. However, PRs made from forks to the upstream public repos will support tokenless (e.g. contributors to OS projects do not need the upstream repo's Codecov token). This doc shows instructions on how to add the Codecov token.
  • OS platforms have been added, though some may not be automatically detected. To see a list of platforms, see our CLI download page
  • Various arguments to the Action have been changed. Please be aware that the arguments match with the CLI's needs

v3 versions and below will not have access to CLI features (e.g. global upload token, ATS).

What's Changed

... (truncated)

Changelog

Sourced from codecov/codecov-action's changelog.

4.0.0-beta.2

Fixes

  • #1085 not adding -n if empty to do-upload command

4.0.0-beta.1

v4 represents a move from the universal uploader to the Codecov CLI. Although this will unlock new features for our users, the CLI is not yet at feature parity with the universal uploader.

Breaking Changes

  • No current support for aarch64 and alpine architectures.
  • Tokenless uploading is unsuported
  • Various arguments to the Action have been removed

3.1.4

Fixes

  • #967 Fix typo in README.md
  • #971 fix: add back in working dir
  • #969 fix: CLI option names for uploader

Dependencies

  • #970 build(deps-dev): bump @​types/node from 18.15.12 to 18.16.3
  • #979 build(deps-dev): bump @​types/node from 20.1.0 to 20.1.2
  • #981 build(deps-dev): bump @​types/node from 20.1.2 to 20.1.4

3.1.3

Fixes

  • #960 fix: allow for aarch64 build

Dependencies

  • #957 build(deps-dev): bump jest-junit from 15.0.0 to 16.0.0
  • #958 build(deps): bump openpgp from 5.7.0 to 5.8.0
  • #959 build(deps-dev): bump @​types/node from 18.15.10 to 18.15.12

3.1.2

Fixes

  • #718 Update README.md
  • #851 Remove unsupported path_to_write_report argument
  • #898 codeql-analysis.yml
  • #901 Update README to contain correct information - inputs and negate feature
  • #955 fix: add in all the extra arguments for uploader

Dependencies

  • #819 build(deps): bump openpgp from 5.4.0 to 5.5.0
  • #835 build(deps): bump node-fetch from 3.2.4 to 3.2.10
  • #840 build(deps): bump ossf/scorecard-action from 1.1.1 to 2.0.4
  • #841 build(deps): bump @​actions/core from 1.9.1 to 1.10.0
  • #843 build(deps): bump @​actions/github from 5.0.3 to 5.1.1
  • #869 build(deps): bump node-fetch from 3.2.10 to 3.3.0
  • #872 build(deps-dev): bump jest-junit from 13.2.0 to 15.0.0
  • #879 build(deps): bump decode-uri-component from 0.2.0 to 0.2.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=codecov/codecov-action&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 66589cea6..5adc7cee9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -153,7 +153,7 @@ jobs: retention-days: 5 - name: Upload coverage data - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From e324cbfbab5207c296ab722c46860c6891a58a2e Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sat, 10 Feb 2024 01:26:02 +0100 Subject: [PATCH 26/51] ci: remove requirement of 2 builds upload to codecov.io (#1073) --- codecov.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/codecov.yml b/codecov.yml index 319f08909..39539d9bc 100644 --- a/codecov.yml +++ b/codecov.yml @@ -22,9 +22,5 @@ coverage: target: auto threshold: 1% # coverage can drop by up to 0.5% while still posting success paths: [ 'package/tests/.*' ] -codecov: - notify: - after_n_builds: 2 comment: require_changes: true # if true: only post the PR comment if coverage changes - after_n_builds: 2 From 882ac1820a06194f10be6ac26848b4aa08d40a70 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sat, 10 Feb 2024 23:18:59 +0100 Subject: [PATCH 27/51] ci: Re add tests to coverage report (#1074) --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0cfeabc90..303af6062 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -215,6 +215,7 @@ source = [ "PartSeg", "PartSegCore", "PartSegImage", + "package/tests", ] omit = [ ".tox/*", From 15f1707a18fd68a832ab65ac5b556e1e6edd2123 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 11 Feb 2024 13:37:09 +0100 Subject: [PATCH 28/51] test: Improve test of PartSegImage (#1072) ## Summary by CodeRabbit - **New Features** - Enhanced image handling capabilities, including improved support for different channel types and more robust image saving functionality. - **Bug Fixes** - Fixed issues related to warnings and error handling in image processing methods. - **Tests** - Added new tests for image reading and writing functionalities, ensuring robust handling of various image formats and metadata preservation. - **Refactor** - Updated method signatures and internal logic for better clarity and efficiency in handling image data. - **Documentation** - Added comments to clarify test coverage exceptions and future code checks. --- package/PartSegImage/channel_class.py | 3 +- package/PartSegImage/image.py | 28 +++--- package/PartSegImage/image_reader.py | 10 +- package/tests/test_PartSegImage/test_image.py | 96 ++++++++++++++++++- .../test_PartSegImage/test_image_reader.py | 13 +++ .../test_PartSegImage/test_image_writer.py | 21 ++++ pyproject.toml | 7 +- 7 files changed, 150 insertions(+), 28 deletions(-) diff --git a/package/PartSegImage/channel_class.py b/package/PartSegImage/channel_class.py index 51b245fc6..5a02a9259 100644 --- a/package/PartSegImage/channel_class.py +++ b/package/PartSegImage/channel_class.py @@ -17,7 +17,7 @@ class Channel: In autogenerated interface field with this type limits input values to number of current image channels """ - def __init__(self, value: Union[str, int]): + def __init__(self, value: Union[str, int, "Channel"]): if isinstance(value, Channel): value = value.value if not isinstance(value, (str, int)): @@ -50,6 +50,7 @@ def __get_validators__(cls): @classmethod def __modify_schema__(cls, field_schema): + # TODO check if still required field_schema["title"] = "Channel" field_schema["type"] = "object" field_schema["properties"] = {"value": {"title": "value", "anyOf": [{"type": "string"}, {"type": "integer"}]}} diff --git a/package/PartSegImage/image.py b/package/PartSegImage/image.py index e49d80f19..30b26ba69 100644 --- a/package/PartSegImage/image.py +++ b/package/PartSegImage/image.py @@ -3,6 +3,7 @@ import warnings from collections.abc import Iterable from contextlib import suppress +from typing import Union import numpy as np @@ -110,7 +111,7 @@ def __init__( name: str = "", ): # TODO add time distance to image spacing - if axes_order is None: + if axes_order is None: # pragma: no cover warnings.warn( f"axes_order should be provided, Currently it uses {self.__class__}.axis_order", category=DeprecationWarning, @@ -259,7 +260,7 @@ def channel_names(self) -> typing.List[str]: return self._channel_names[:] @property - def channel_pos(self) -> int: + def channel_pos(self) -> int: # pragma: no cover """Channel axis. Need to have 'C' in :py:attr:`axis_order`""" warnings.warn( "channel_pos is deprecated and code its using may not work properly", category=FutureWarning, stacklevel=2 @@ -412,8 +413,6 @@ def fit_mask_to_image(self, array: np.ndarray) -> np.ndarray: if np.max(array) == 1: return array.astype(np.uint8) unique = np.unique(array) - if unique.size == 2 and unique[1] == 1: - return array.astype(np.uint8) if unique.size == 1: if unique[0] != 0: return np.ones(array.shape, dtype=np.uint8) @@ -425,9 +424,11 @@ def get_image_for_save(self) -> np.ndarray: """ :return: numpy array in imagej tiff order axes """ - return self._reorder_axes( - np.stack(self._channel_arrays, axis=self.axis_order.index("C")), self.axis_order, "TZCYX" - ) + if "C" in self.axis_order: + return self._reorder_axes( + np.stack(self._channel_arrays, axis=self.axis_order.index("C")), self.axis_order, "TZCYX" + ) + return self._reorder_axes(self._channel_arrays[0], self.axis_order, "TZCYX") def get_mask_for_save(self) -> typing.Optional[np.ndarray]: """ @@ -511,13 +512,10 @@ def get_data_by_axis(self, **kwargs) -> np.ndarray: """ slices: typing.List[typing.Union[int, slice]] = [slice(None) for _ in range(len(self.array_axis_order))] axis_pos = self.get_array_axis_positions() + if "c" in kwargs: + kwargs["C"] = kwargs.pop("c") if "C" in kwargs and isinstance(kwargs["C"], str): kwargs["C"] = self.channel_names.index(kwargs["C"]) - if "c" in kwargs: - if isinstance(kwargs["c"], str): - kwargs["C"] = self.channel_names.index(kwargs.pop("c")) - else: - kwargs["C"] = kwargs.pop("c") channel = kwargs.pop("C", slice(None) if "C" in self.axis_order else 0) if isinstance(channel, Channel): @@ -531,8 +529,6 @@ def get_data_by_axis(self, **kwargs) -> np.ndarray: axis_order = axis_order.replace(name.upper(), "") slices_t = tuple(slices) - if isinstance(channel, str): - channel = self._channel_names.index(channel) if isinstance(channel, int): return self._channel_arrays[channel][slices_t] return np.stack([x[slices_t] for x in self._channel_arrays[channel]], axis=axis_order.index("C")) @@ -553,11 +549,11 @@ def clip_array(self, array: np.ndarray, **kwargs: typing.Union[int, slice]) -> n slices[axis_pos[n]] = kwargs[name] return array[tuple(slices)] - def get_channel(self, num) -> np.ndarray: + def get_channel(self, num: Union[int, str, Channel]) -> np.ndarray: """ Alias for :py:func:`get_sub_data` with argument ``c=num`` - :param int | str num: channel num to be extracted + :param int | str | Channel num: channel num or name to be extracted :return: given channel array :rtype: numpy.ndarray """ diff --git a/package/PartSegImage/image_reader.py b/package/PartSegImage/image_reader.py index 5a62a69d3..dab513f8c 100644 --- a/package/PartSegImage/image_reader.py +++ b/package/PartSegImage/image_reader.py @@ -63,7 +63,7 @@ def set_default_spacing(self, spacing): # one micrometer spacing = (10 ** (-6), *spacing) if len(spacing) != 3: - raise ValueError(f"wrong spacing {spacing}") + raise ValueError(f"wrong spacing {spacing}") # pragma: no cover self.default_spacing = spacing @abstractmethod @@ -158,7 +158,7 @@ def update_array_shape(cls, array: np.ndarray, axes: str): raise NotImplementedError( f"Data type not supported ({e.args[0]}). Please contact with author for update code" ) from e - if len(final_mapping) != len(set(final_mapping)): + if len(final_mapping) != len(set(final_mapping)): # pragma: no cover raise NotImplementedError("Data type not supported. Please contact with author for update code") if len(array.shape) < len(cls.return_order()): array = np.reshape(array, array.shape + (1,) * (len(cls.return_order()) - len(array.shape))) @@ -219,11 +219,11 @@ def read(self, image_path: typing.Union[str, BytesIO, Path], mask_path=None, ext if ext == ".czi": return CziImageReader.read_image(image_path, mask_path, self.callback_function, self.default_spacing) if ext in [".oif", ".oib"]: - if isinstance(image_path, BytesIO): # pragma: no cover + if isinstance(image_path, BytesIO): raise NotImplementedError("Oif format is not supported for BytesIO") return OifImagReader.read_image(image_path, mask_path, self.callback_function, self.default_spacing) if ext == ".obsep": - if isinstance(image_path, BytesIO): # pragma: no cover + if isinstance(image_path, BytesIO): raise NotImplementedError("Obsep format is not supported for BytesIO") return ObsepImageReader.read_image(image_path, mask_path, self.callback_function, self.default_spacing) return TiffImageReader.read_image(image_path, mask_path, self.callback_function, self.default_spacing) @@ -334,7 +334,7 @@ def read(self, image_path: typing.Union[str, Path], mask_path=None, ext=None) -> xml_doc = ElementTree.parse(image_path).getroot() channels = xml_doc.findall("net/node/node/attribute[@name='image type']") if not channels: - raise ValueError("Information about channel images not found") + raise ValueError("Information about channel images not found") # pragma: no cover channel_list = [ *self._search_for_files(directory, channels, required=True), *self._search_for_files(directory, channels, "_deconv"), diff --git a/package/tests/test_PartSegImage/test_image.py b/package/tests/test_PartSegImage/test_image.py index 042ebf39d..cc1bb1da0 100644 --- a/package/tests/test_PartSegImage/test_image.py +++ b/package/tests/test_PartSegImage/test_image.py @@ -5,7 +5,7 @@ import pytest from skimage.morphology import diamond -from PartSegImage import Image, ImageWriter, TiffImageReader +from PartSegImage import Channel, Image, ImageWriter, TiffImageReader from PartSegImage.image import FRAME_THICKNESS @@ -115,6 +115,14 @@ def test_image_mask(self): self.image_class( np.zeros(initial_shape), (5, 5, 5), mask=np.zeros((1, 10, 50, 50)), axes_order=self.image_class.axis_order ) + mask = np.zeros((1, 10, 50, 50)) + mask[0, 2:-2] = 1 + im = self.image_class(np.zeros(initial_shape), (5, 5, 5), mask=mask, axes_order=self.image_class.axis_order) + assert np.all(im.mask == mask) + + def test_image_mask_exception(self): + if "C" not in self.image_class.axis_order: + pytest.skip("Lack of channel axis") data_shape = (1,) * (len(self.image_class.axis_order) - 4) + (10, 50, 50, 4) with pytest.raises(ValueError, match="Wrong array shape"): self.image_class( @@ -130,10 +138,6 @@ def test_image_mask(self): mask=np.zeros(data_shape), axes_order=self.image_class.axis_order, ) - mask = np.zeros((1, 10, 50, 50)) - mask[0, 2:-2] = 1 - im = self.image_class(np.zeros(initial_shape), (5, 5, 5), mask=mask, axes_order=self.image_class.axis_order) - assert np.all(im.mask == mask) def test_reorder_axes(self): fixed_array = self.image_class.reorder_axes(np.zeros((10, 20)), axes="XY") @@ -242,11 +246,19 @@ def test_set_mask_reorder(self): assert image.mask.shape == self.mask_shape((1, 10, 20, 30), "TZYX") def test_get_image_for_save(self): + if "C" not in self.image_class.array_axis_order: + pytest.skip("No channel axis") image = self.image_class(np.zeros((1, 10, 3, 20, 30), np.uint8), (1, 1, 1), "", axes_order="TZCYX") assert image.get_image_for_save().shape == (1, 10, 3, 20, 30) image = self.image_class(np.zeros((1, 10, 20, 30, 3), np.uint8), (1, 1, 1), "", axes_order="TZYXC") assert image.get_image_for_save().shape == (1, 10, 3, 20, 30) + def test_get_image_for_save_no_channel(self): + image = self.image_class(np.zeros((1, 10, 20, 30), np.uint8), (1, 1, 1), "", axes_order="TZYX") + assert image.get_image_for_save().shape == (1, 10, 1, 20, 30) + image = self.image_class(np.zeros((1, 10, 20, 30), np.uint8), (1, 1, 1), "", axes_order="TZYX") + assert image.get_image_for_save().shape == (1, 10, 1, 20, 30) + def test_get_mask_for_save(self): image = self.image_class(np.zeros((1, 10, 3, 20, 30), np.uint8), (1, 1, 1), "", axes_order="TZCYX") assert image.get_mask_for_save() is None @@ -366,6 +378,8 @@ def test_get_um_spacing(self): assert image.get_um_spacing() == (1, 1) def test_save(self, tmp_path): + if "C" not in self.image_class.axis_order: + pytest.skip("No channel axis") data = np.zeros((1, 10, 20, 30, 3), np.uint8) data[..., :10, 0] = 2 data[..., :10, 1] = 20 @@ -397,6 +411,11 @@ def test_get_axis_positions(self): assert set(image.get_axis_positions()) == set(image.axis_order) assert len(set(image.get_axis_positions().values())) == len(image.axis_order) + def test_get_data(self): + data = np.zeros((10, 10), np.uint8) + image = self.image_class(data, (1, 1), axes_order="XY") + assert np.all(image.get_data() == data) + class ChangeChannelPosImage(Image): axis_order = "TZCYX" @@ -406,6 +425,21 @@ class TestInheritanceImageChannelPos(TestImageBase): image_class = ChangeChannelPosImage +class NoChannelImage(Image): + axis_order = "TZYX" + + +class TestInheritanceNoChannelImage(TestImageBase): + image_class = NoChannelImage + + def prepare_image_initial_shape(self, shape, channel): + return self.prepare_mask_shape(shape) + + def needed_layer_shape(self, shape, axes: str, drop: str): + axes = axes.replace("C", "") + return super().needed_layer_shape(shape, axes, drop) + + class ChangeTimePosImage(Image): axis_order = "ZTYXC" @@ -442,6 +476,7 @@ def test_merge_chanel(self, check_dtype): assert res_image.channels == 2 assert np.all(res_image.get_channel(0) == 0) assert np.all(res_image.get_channel(1) == 1) + assert np.all(res_image.get_channel(Channel(1)) == 1) assert res_image.dtype == check_dtype def test_merge_fail(self): @@ -485,6 +520,29 @@ def test_merge_channel_name(self): res_image = image1.merge(image3, "C") assert res_image.channel_names == ["channel 1", "channel 3", "channel 5"] + def test_channel_name_form_str(self): + image1 = Image( + data=np.zeros((1, 4, 10, 10), dtype=np.uint8), + axes_order="CZXY", + image_spacing=(1, 1, 1), + channel_names=["channel 1"], + ) + assert image1.channel_names == ["channel 1"] + image2 = Image( + data=np.zeros((2, 4, 10, 10), dtype=np.uint8), + axes_order="CZXY", + image_spacing=(1, 1, 1), + channel_names="channel", + ) + assert image2.channel_names == ["channel", "channel 2"] + image3 = Image( + data=np.zeros((2, 4, 10, 10), dtype=np.uint8), + axes_order="CZXY", + image_spacing=(1, 1, 1), + channel_names="channel 1", + ) + assert image3.channel_names == ["channel 1", "channel 2"] + def test_different_axes_order(self): image1 = Image(data=np.zeros((3, 10, 10), dtype=np.uint8), axes_order="ZXY", image_spacing=(1, 1, 1)) image2 = ChangeChannelPosImage( @@ -495,6 +553,14 @@ def test_different_axes_order(self): assert isinstance(res_image, Image) assert isinstance(image2.merge(image1, "C"), ChangeChannelPosImage) + def test_get_data_by_axis(self): + image = Image(data=np.zeros((2, 3, 10, 10), dtype=np.uint8), axes_order="CZXY", image_spacing=(1, 1, 1)) + assert image.get_data_by_axis(c=0).shape == (1, 3, 10, 10) + assert image.get_data_by_axis(C=1).shape == (1, 3, 10, 10) + assert image.get_data_by_axis(z=0).shape == (2, 1, 10, 10) + assert image.get_data_by_axis(Z=1).shape == (2, 1, 10, 10) + assert image.get_data_by_axis(C="channel 1").shape == (1, 3, 10, 10) + def test_cut_with_roi(): data = np.zeros((3, 23, 23), np.uint8) @@ -512,3 +578,23 @@ def test_cut_with_roi(): assert cut_image[0].shape == (1, 1, 15, 15) assert np.all(cut_image[0][0, 0, 2:-2, 2:-2][diam > 0]) assert np.all(cut_mask[0, 0, 2:-2, 2:-2] == diam) + + +def test_str_and_repr_mask_presence(): + image = Image(np.zeros((10, 10), np.uint8), (1, 1), "test", axes_order="XY") + assert "mask: False" in str(image) + assert "mask=False" in repr(image) + assert "coloring: None" in str(image) + + image.set_mask(np.zeros((10, 10), np.uint8)) + + assert "mask: True" in str(image) + assert "mask=True" in repr(image) + + +def test_channel_from_channel(): + ch1 = Channel(1) + ch2 = Channel(2) + ch3 = Channel(ch1) + assert ch1 == ch3 + assert ch1 != ch2 diff --git a/package/tests/test_PartSegImage/test_image_reader.py b/package/tests/test_PartSegImage/test_image_reader.py index e95dd94cb..029d602bc 100644 --- a/package/tests/test_PartSegImage/test_image_reader.py +++ b/package/tests/test_PartSegImage/test_image_reader.py @@ -97,6 +97,19 @@ def test_generic_reader(self, data_test_dir): GenericImageReader.read_image(os.path.join(data_test_dir, "Image0003_01.oif")) GenericImageReader.read_image(os.path.join(data_test_dir, "N2A_H2BGFP_dapi_falloidin_cycling1.oib")) + def test_generic_reader_from_buffer(self, data_test_dir): + file_path = os.path.join(data_test_dir, "stack1_components", "stack1_component1.tif") + with open(file_path, "rb") as f_p: + buffer = BytesIO(f_p.read()) + GenericImageReader().read(buffer) + with open(file_path, "rb") as f_p: + buffer = BytesIO(f_p.read()) + GenericImageReader().read(buffer, ext=".tif") + with pytest.raises(NotImplementedError, match="Oif format is not supported"): + GenericImageReader().read(buffer, ext=".oif") + with pytest.raises(NotImplementedError, match="Obsep format is not supported"): + GenericImageReader().read(buffer, ext=".obsep") + def test_decode_int(self): assert TiffImageReader.decode_int(0) == [0, 0, 0, 0] assert TiffImageReader.decode_int(15) == [0, 0, 0, 15] diff --git a/package/tests/test_PartSegImage/test_image_writer.py b/package/tests/test_PartSegImage/test_image_writer.py index e39fdbd1d..477115a40 100644 --- a/package/tests/test_PartSegImage/test_image_writer.py +++ b/package/tests/test_PartSegImage/test_image_writer.py @@ -1,4 +1,5 @@ import numpy as np +import numpy.testing as npt import pytest import tifffile from lxml import etree # nosec @@ -32,6 +33,9 @@ def test_save_mask(tmp_path): read_mask = TiffImageReader.read_image(tmp_path / "mask.tif") assert np.all(np.isclose(read_mask.spacing, image.spacing)) + image.set_mask(None) + ImageWriter.save_mask(image, tmp_path / "mask2.tif") + assert not (tmp_path / "mask2.tif").exists() @pytest.mark.parametrize("z_size", [1, 10]) @@ -75,6 +79,23 @@ def test_scaling_imagej(tmp_path): assert np.all(np.isclose(image.spacing, read_image.spacing)) +def test_scaling_imagej_fail(tmp_path): + image = Image(np.zeros((10, 50, 50), dtype=np.float64), (30, 0.1, 0.1), axes_order="ZYX") + with pytest.raises(ValueError, match="Data type float64"): + IMAGEJImageWriter.save(image, tmp_path / "image.tif") + + +def test_imagej_write_all_metadata(tmp_path, data_test_dir): + image = TiffImageReader.read_image(data_test_dir / "stack1_components" / "stack1_component1.tif") + assert "coloring: " in str(image) + assert "coloring: None" not in str(image) + IMAGEJImageWriter.save(image, tmp_path / "image.tif") + + image2 = TiffImageReader.read_image(tmp_path / "image.tif") + + npt.assert_array_equal(image2.default_coloring, image.default_coloring) + + def test_save_mask_imagej(tmp_path): data = np.zeros((10, 40, 40), dtype=np.uint8) data[1:-1, 1:-1, 1:-1] = 1 diff --git a/pyproject.toml b/pyproject.toml index 303af6062..f0918c432 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -228,8 +228,13 @@ parallel = true exclude_lines = [ "pragma: no cover", "raise NotImplementedError", - "if typing.TYPE_CHECKING", "raise RuntimeError()", + "pass", +] +exclude_also = [ + "if __name__ == .__main__.:", + "if TYPE_CHECKING:", + "if typing.TYPE_CHECKING:", ] [tool.black] From 7ff8d842c4f386469055afbe3b41f4735ab59b4f Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 12 Feb 2024 10:46:17 +0100 Subject: [PATCH 29/51] ci: Switch from setup.cfg to pyproject.toml in workflows (#1076) ## Summary by CodeRabbit - **Chores** - Updated GitHub Actions workflows to use `pyproject.toml` for dependency management and Python setup, enhancing compatibility across Python versions 3.8 to 3.11. --- .github/workflows/base_test_workflow.yml | 2 +- .github/workflows/tests.yml | 2 +- .github/workflows/upgrade-dependencies.yml | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index a77ab2706..44469e606 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -47,7 +47,7 @@ jobs: with: python-version: ${{ inputs.python_version }} cache: 'pip' - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' # - name: Install ubuntu libraries # if: runner.os == 'Linux' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5adc7cee9..30442c574 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -125,7 +125,7 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.x" - cache-dependency-path: setup.cfg + cache-dependency-path: pyproject.toml cache: 'pip' - name: Install Dependencies run: | diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index c75463834..04aff8493 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -26,22 +26,22 @@ jobs: with: python-version: "3.8" cache: pip - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' - uses: actions/setup-python@v5 with: python-version: "3.9" cache: pip - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' - uses: actions/setup-python@v5 with: python-version: "3.10" cache: pip - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' - uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' - name: Upgrade Python dependencies # ADD YOUR CUSTOM DEPENDENCY UPGRADE COMMANDS BELOW run: | @@ -51,9 +51,9 @@ jobs: for pyv in 3.8 3.9 3.10 3.11; do python${pyv} -m pip install -U pip pip-tools - python${pyv} -m piptools compile --upgrade -o requirements/constraints_py${pyv}.txt setup.cfg requirements/version_denylist.txt ${flags} + python${pyv} -m piptools compile --upgrade -o requirements/constraints_py${pyv}.txt pyproject.toml requirements/version_denylist.txt ${flags} done - python3.11 -m piptools compile --upgrade -o requirements/constraints_py3.11_docs.txt setup.cfg requirements/version_denylist.txt --allow-unsafe --strip-extras --extra docs --extra pyqt6 + python3.11 -m piptools compile --upgrade -o requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --allow-unsafe --strip-extras --extra docs --extra pyqt6 # END PYTHON DEPENDENCIES - name: Check updated packages From 2f07fb0c219effc7095e13e936d7a41ffcc2bd92 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 12 Feb 2024 12:04:09 +0100 Subject: [PATCH 30/51] ci: Fix compiling pyinstaller pre-deps (#1075) Fix lack of workflow update in #1070 ## Summary by CodeRabbit - **Chores** - Updated dependency management process in the workflow to use `pyproject.toml` for generating requirements. --- .github/workflows/test_prereleases.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_prereleases.yml b/.github/workflows/test_prereleases.yml index dfbe0b68f..03a2f9f4e 100644 --- a/.github/workflows/test_prereleases.yml +++ b/.github/workflows/test_prereleases.yml @@ -8,9 +8,12 @@ on: branches: - master - develop - - bugfix/fix_pre_tests schedule: - cron: '0 */12 * * *' # every 12 hours + pull_request: + paths: + - '.github/workflows/test_prereleases.yml' + - 'pyproject.toml' # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -47,7 +50,7 @@ jobs: with: python-version: ${{ matrix.python }} cache: 'pip' - cache-dependency-path: 'setup.cfg' + cache-dependency-path: 'pyproject.toml' - name: Install Windows OpenGL if: runner.os == 'Windows' @@ -111,7 +114,7 @@ jobs: pip install pip-tools - name: Compile and install PyInstaller requirements run: | - pip-compile --upgrade -o requirements.txt setup.cfg --extra pyinstaller --pre + pip-compile --upgrade -o requirements.txt pyproject.toml --extra pyinstaller --pre pip-sync pip install . - name: upload requirements From c9e0efa961f79dc76c3da584a8d1688a4c0b50cd Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 12 Feb 2024 23:20:53 +0100 Subject: [PATCH 31/51] ci: Add codespell to pre-commit and fix pointed bugs (#1078) ## Summary by CodeRabbit - **Bug Fixes** - Corrected various typos across documentation, comments, and informational messages for improved clarity and accuracy. - Addressed a bug causing a corrupted state when saving calculation plans to Excel. - **New Features** - Improved napari integration with widgets for colormap and labels control. - Added functionality for copying labels along the z-axis. - Added randomization option for correlation calculation and an ImageJ TIFF writer for images. - **Documentation** - Updated and clarified descriptions in tutorials and API overview documents. - Semantic changes in feature descriptions for better understanding. - **Chores** - Ensured compatibility with Python 3.11 on CI. - Updated dependencies to require napari version 0.4.12 or higher. - Added `codespell` pre-commit hook to improve code quality. --- .napari/DESCRIPTION.md | 2 +- .pre-commit-config.yaml | 7 +++ changelog.md | 16 +++--- docs/PartSegCore/color_image.rst | 2 +- .../interface-overview/interface-overview.rst | 54 +++++++++---------- package/PartSeg/_roi_analysis/main_window.py | 4 +- package/PartSeg/_roi_mask/stack_settings.py | 2 +- .../common_backend/partially_const_dict.py | 4 +- .../common_backend/python_syntax_highlight.py | 2 +- package/PartSeg/common_gui/channel_control.py | 4 +- .../PartSeg/common_gui/colormap_creator.py | 2 +- package/PartSeg/common_gui/main_window.py | 4 +- .../common_gui/multiple_file_widget.py | 2 +- package/PartSeg/common_gui/numpy_qimage.py | 2 +- package/PartSeg/common_gui/qt_console.py | 4 +- .../roi_extraction_algorithms.py | 2 +- .../PartSegCore/analysis/calculation_plan.py | 4 +- .../PartSegCore/analysis/measurement_base.py | 3 +- .../analysis/measurement_calculation.py | 2 +- package/PartSegCore/convex_fill.py | 2 +- .../image_transforming/image_projection.py | 2 +- package/PartSegCore/mask_partition_utils.py | 2 +- .../segmentation/algorithm_base.py | 2 +- package/PartSegCore/segmentation/watershed.py | 2 +- package/PartSegCore/utils.py | 2 +- package/PartSegImage/channel_class.py | 2 +- package/PartSegImage/image.py | 6 +-- package/tests/test_PartSeg/test_sentry.py | 18 +++---- .../0.13.1/mask/segmentation_settings.json | 2 +- pyproject.toml | 6 ++- tutorials/api-overview/api-overview.md | 2 +- .../tutorial-batch.md | 2 +- .../Neuron_types_example.ipynb | 20 +++---- 33 files changed, 102 insertions(+), 90 deletions(-) diff --git a/.napari/DESCRIPTION.md b/.napari/DESCRIPTION.md index a93924adf..85c320dac 100644 --- a/.napari/DESCRIPTION.md +++ b/.napari/DESCRIPTION.md @@ -17,7 +17,7 @@ https://user-images.githubusercontent.com/3826210/149146100-973498c7-7d2e-4298-a The above video presents simple segmentation and measurement of various parameters of this segmentation (ROI). -As bellow described, algorithms are the result of porting PartSeg utilities to napari +As below described, algorithms are the result of porting PartSeg utilities to napari then detailed description could be found in PartSeg documentation/ ## ROI Extraction (Segmentation, pixel labeling) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ee1830ba6..0cf269959 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -49,6 +49,13 @@ repos: - id: mypy files: ^package/PartSegImage/.+\.py +- repo: https://github.com/codespell-project/codespell + rev: v2.2.6 + hooks: + - id: codespell + additional_dependencies: + - tomli + ci: autoupdate_commit_msg: 'ci: [pre-commit.ci] pre-commit autoupdate' diff --git a/changelog.md b/changelog.md index 80a8cfdf5..6d7ee7dbd 100644 --- a/changelog.md +++ b/changelog.md @@ -27,11 +27,11 @@ - Bump os version for main tests workflow. (#979) - Ensure that the module `PartSegCore.channel_class` is present in bundle (#980) - Lower npe2 schema version to work with older napari version (#981) -- Generate test report per platfom (#978) +- Generate test report per platform (#978) - Importing plugins in bundle keeping proper module names (#983) - Fix napari repo workflow (#985) -- Fix bug in read tiff files with double `Q` in axes but one related to dummy dimmension (#992) -- Fix bug that lead to corupted state when saving calculation plan to excel file (#995) +- Fix bug in read tiff files with double `Q` in axes but one related to dummy dimension (#992) +- Fix bug that lead to corrupted state when saving calculation plan to excel file (#995) - Enable python 3.11 test on CI, fix minor errors (#869) ### Features @@ -113,12 +113,12 @@ - Add option to create projection alongside z-axis (#919) - Add napari image custom representation for better error report via sentry (#861) - Add import and export operation for labels and colormaps (#936) -- Implement napari widgets for colormap and lables control (#935) +- Implement napari widgets for colormap and labels control (#935) - Add forget all button to multiple files widget (#942) - Do not abort processing whole mask segmentation project during exception on single component (#943) - Add distance based watersheed to flow methods (#915) -- Add napari widgets for all group of algoritms (#958) -- Add napari widget to copy lables along z-axis (#968) +- Add napari widgets for all group of algorithms (#958) +- Add napari widget to copy labels along z-axis (#968) ### Miscellaneous Tasks @@ -292,7 +292,7 @@ ### Refactor - Refactor the creation batch plan widgets and add tests for it (#587) -- Drop napari bellow 0.4.12 (#592) +- Drop napari below 0.4.12 (#592) - Update the order of ROI Mask algorithms to be the same as in older PartSeg versions (#600) ## 0.14.0 - 2022-04-14 @@ -415,7 +415,7 @@ ### Features - Add randomization option for correlation calculation (#421) -- Add Imagej TIFF writter for image. (#405) +- Add Imagej TIFF writer for image. (#405) - Mask create widget for napari (#395) - In napari roi extraction method show information from roi extraction method (#408) - Add `*[0-9].tif` button in batch processing window (#412) diff --git a/docs/PartSegCore/color_image.rst b/docs/PartSegCore/color_image.rst index 7753ebb22..c7b6fdc65 100644 --- a/docs/PartSegCore/color_image.rst +++ b/docs/PartSegCore/color_image.rst @@ -15,6 +15,6 @@ This module contains utils needed for transform multichannel image to RGB .. py:data:: default_colormap_dict - Dict with default colormaps avaliable in PartSeg. + Dict with default colormaps available in PartSeg. a diff --git a/docs/interface-overview/interface-overview.rst b/docs/interface-overview/interface-overview.rst index fd6e4fd35..a39a53595 100644 --- a/docs/interface-overview/interface-overview.rst +++ b/docs/interface-overview/interface-overview.rst @@ -34,10 +34,10 @@ On top of the window there are 6 buttons: The path can be absolute (may not work on another computer) or relative (may not work when the saved file has been moved). * **Advanced settings** - currently contains only colormap and labeling administration. -* **Mask manager** - Allows to add new mask based on the current segmentation. New mask can be adjusted by dilation, filling of holes existing in current segmentation or by reverisng segmented area. +* **Mask manager** - Allows to add new mask based on the current segmentation. New mask can be adjusted by dilation, filling of holes existing in current segmentation or by reversing segmented area. * **Simple measurements** - a subset of selected, basic measurements for quick analysis. The full list is available in `Measurements`_ in ROI analysis -1. `Multiple files panel`_ anables managing multiple files. Each loaded image is shown as raw image, and can be saved after each segmentation as a separate state. It allows for comparison of segmentations performed with different parameters. This panel is visible by default, but can be hidden in the `image tab`_. +1. `Multiple files panel`_ enables managing multiple files. Each loaded image is shown as raw image, and can be saved after each segmentation as a separate state. It allows for comparison of segmentations performed with different parameters. This panel is visible by default, but can be hidden in the `image tab`_. 2. Colorbar - Shows relation of the currently used color map and brightness values for the selected channel. The selection of colormap is described in the `Image View`_. 3. `Image View`_. Shows a preview of the current file and its segmentation result. @@ -78,11 +78,11 @@ On top of the window there are 6 buttons: 13. Selects all checkboxes. 14. Removes selection from all checkboxes. 15. Selection of a single component. Selection/deselection of components can be done by clicking on a component in `Image view`_. - or enebling apopriate checkbox. Pointing checkbox with a coursor highlits selected component in `Image view`_. + or enabling appropriate checkbox. Pointing checkbox with a cursor highlights selected component in `Image view`_. Only components selected in checkboxes are saved using **Save components** tab. - Components wich are selected are omitted, when the next round of segmentation is performed. + Components which are selected are omitted, when the next round of segmentation is performed. -16. When selected allows for comaprison of segmentations made with different parameters. To do so enable **Save selected components** checkbox, than perform segmentation and select chosen components. Next save segmentation by **Save Segmenation**. Use **Unselect all** and perform another segmentation with a diffeternt parameters. Select chosen components and load previously done segmentation using **Load Segmentation**. Now selected components from both segmentations are displayed in the `Image view`_ and each is represented as a separate checkbox. The same can be done using `Multiple files panel`_ and saving each segmentation as a separate state using **Save state** tab. +16. When selected allows for comparison of segmentations made with different parameters. To do so enable **Save selected components** checkbox, than perform segmentation and select chosen components. Next save segmentation by **Save Segmentation**. Use **Unselect all** and perform another segmentation with a different parameters. Select chosen components and load previously done segmentation using **Load Segmentation**. Now selected components from both segmentations are displayed in the `Image view`_ and each is represented as a separate checkbox. The same can be done using `Multiple files panel`_ and saving each segmentation as a separate state using **Save state** tab. 17. Opens the window with a preview of segmentation parameters for each component. **Reuse parameters** button from this window restores selected parameters. @@ -110,7 +110,7 @@ ROI Analysis GUI .. image:: images/main_window.png :alt: Main Roi Analysis GUI -Bottons visible in the top row of the main window: +Buttons visible in the top row of the main window: * **Open** - loads data. @@ -168,9 +168,9 @@ In PartSeg there are three defined ways of saving segmentation. The first two options save only segmentation parameters: * **Profile** - saves parameters set for segmentation algorithm. -* **Pipeline** - saves sequence of segmentation, mask created based on this segmentation with help of **Mask manager** and next round of segmentation, which is made within masked area. This steps can be repeated several times to create pipiline, which can be later used in batch processing. +* **Pipeline** - saves sequence of segmentation, mask created based on this segmentation with help of **Mask manager** and next round of segmentation, which is made within masked area. This steps can be repeated several times to create pipeline, which can be later used in batch processing. -The list of profiles and pipelines and their properties is avaliable in +The list of profiles and pipelines and their properties is available in **Properties** tab of **Settings and Measurement**. The third option is to save the current work as a project. Project will contain: @@ -188,7 +188,7 @@ This bottom enables popup window with 4 tabs: Properties, Color control, Measure Properties ^^^^^^^^^^ -Shows properties of the currnet image, list of profiles and pipelines and their properties. +Shows properties of the current image, list of profiles and pipelines and their properties. .. image:: images/segmentation_advanced.png :alt: View on Properties Tab in Settings and Measurement. @@ -199,7 +199,7 @@ Shows properties of the currnet image, list of profiles and pipelines and their 4. List of segmentation pipelines. 5. Preview of properties of the selected Profile/pipeline. -Additionally, bellow the preview of propertes 6 buttons are avaliable to control export, import, deletion and renaming of pipelines and profiles. +Additionally, below the preview of properties 6 buttons are available to control export, import, deletion and renaming of pipelines and profiles. Measurements settings @@ -213,7 +213,7 @@ The upper part of this window is designed to manage existing sets of measurement 1. Contains a list of already defined measurement sets. 2. Gives a preview of properties of selected measurement set. - Four botton placed below the list of efined measurement sets are used to + Four button placed below the list of defined measurement sets are used to delete, export, import, and edit of saved sets of measurement. @@ -227,16 +227,16 @@ The upper part of this window is designed to manage existing sets of measurement 6. Selects how the measurement element handles area components. - * **No** - measurment will be made for the whole segmented area. - * **Yes** - measurment will be made for each component separately. - * **Mean** - measurment will be made for each component of area and then mean value will be calculated. + * **No** - measurement will be made for the whole segmented area. + * **Yes** - measurement will be made for each component separately. + * **Mean** - measurement will be made for each component of area and then mean value will be calculated. 7. Adding selected elements to created measurement set * **→** - Moves the element to the list on the right (newly created measurement set). * **←** - Moves the element to the list on the left. Allows to define new element for the future use. * **Ratio** - Allows to create a ratio of two measurements from the list. - First select the numerator, next selecte **Ratio** then select the denominator and confirm with selecing **Ratio** again. + First select the numerator, next select **Ratio** then select the denominator and confirm with selecting **Ratio** again. * **Clear** - clears chosen element from the list 8. Controls the position of the single elements on the list: @@ -251,9 +251,9 @@ Measurements .. image:: images/measurement_calculate.png :alt: View on measurement calculation widget. -This widget can be enabled as the left panel of the main window by chosing Measurments tab placed above left window. +This widget can be enabled as the left panel of the main window by choosing Measurements tab placed above left window. -1. Shows numerical features calculated for the currently segmented area using selected measurment set . +1. Shows numerical features calculated for the currently segmented area using selected measurement set . 2. Selects measurement set. 3. Removes result showed in 1. and replaces it with the result of the new calculation. 4. Adds the new result of the new calculation to the existing ones. @@ -332,7 +332,7 @@ Prepare batch plan Execute batch ^^^^^^^^^^^^^ .. image:: images/batch_select_files.png - :alt: Wiew on widget for select files to proceed. + :alt: View on widget for select files to proceed. .. _select multiple files: @@ -366,7 +366,7 @@ Execute batch Can be adjusted during runtime. 9. Error log. For a report double click on the entry. 10. Information about task status. -11. Launches batch calculation, by opening a popout window described bellow, which allows to check if everything is set correctly. +11. Launches batch calculation, by opening a popout window described below, which allows to check if everything is set correctly. .. image:: images/batch_check_ok.png :alt: View on Properties Tab in Settings and Measurement. @@ -380,7 +380,7 @@ Execute batch 3. Settings for a resulting spreadsheet localisation and name 4. Gives information if PartSeg can find all the needed data for each entry. - The image placed bellow image shows a View on Properties Tab in Settings and Measurement containing errors. + The image placed below image shows a View on Properties Tab in Settings and Measurement containing errors. .. image:: images/batch_check_bad.png :alt: View on Properties Tab in Settings and Measurement. @@ -435,9 +435,9 @@ The zoom of the image can be also changed by a Ctrl+Mouse scroll. 2. Changes view to a 3D rendering. 3. Channel view control. Only Channels with a selected checkbox are visible. `Color map`_ for the current channel can be selected when clicking in the triangle in the upper right corner - |channel_select|. This triangle is visible when the coursor is placed over the widget. -4. Switches the view of segmenation between showing only segmentation borders or the whole segmented area. -5. Set the opacity of segmenattion view. + |channel_select|. This triangle is visible when the cursor is placed over the widget. +4. Switches the view of segmentation between showing only segmentation borders or the whole segmented area. +5. Set the opacity of segmentation view. 6. Marks mask visible or not. 7. Controls which layer is visible. If the image contains time data, then a similar @@ -481,7 +481,7 @@ Color maps * Color maps are available for channels with a checked checkbox and can be selected in the `Image View`_ controls aaa * Only custom created color maps can be deleted with a |delete| button. -* Some of the existing color maps and all custom created masps can be used as a base for +* Some of the existing color maps and all custom created maps can be used as a base for creation of a new color map using the |edit| button. Color Map creator @@ -502,7 +502,7 @@ Select labels In this tab, users can select the coloring scheme of segmentation components labels. * Current scheme is chosen with the radio button (|radio_button|) on the left. -* Custom creted schemes can be deleted with the |delete| button. +* Custom created schemes can be deleted with the |delete| button. * New scheme can be defined based on the old one using the |edit| button. Create labels @@ -543,12 +543,12 @@ of current segmentation into a new mask. 1. Select to use dilation (2d or 3d) with a set radius in pixels. If dilation is in 3d then the radius in the z plane is calculated base on the image spacing. Negative values of the radius will reduce the mask size. 2. Select to fill up holes in a current segmentation. Holes are parts of the background, which are not connected (in 2d or 3d - depends on selection) to a border of the image. - If the maximum size is set to -1 then all holes within segmentation area will be included in the segemntation. + If the maximum size is set to -1 then all holes within segmentation area will be included in the segmentation. 3. **Save components** allows to create a new mask made of multiple components present in current segmentation. **Clip to previous mask** option is useful when using positive radius in Dilate mask to fit it in a previously defined mask. 4. Creates a mask based on the negative of the current selection (disables **Save components** option). 5. Shows calculated dilation radius in x, y, z for the current image. -6. Undos of last masking operation. +6. Undo of last masking operation. 7. Creates a new mask or draws back to the previously undone one. 8. Cleans redo history. 9. Takes mask creation parameters from the next mask and to set in the interface. diff --git a/package/PartSeg/_roi_analysis/main_window.py b/package/PartSeg/_roi_analysis/main_window.py index f44a476f0..bfcfb326e 100644 --- a/package/PartSeg/_roi_analysis/main_window.py +++ b/package/PartSeg/_roi_analysis/main_window.py @@ -190,7 +190,7 @@ def save_pipeline(self): return values = self._settings.get_algorithm(f"algorithms.{name}", {}) if isinstance(values, (dict, EventedDict)) and len(values) == 0: - QMessageBox.information(self, "Some problem", "Pleas run execution again", QMessageBox.Ok) + QMessageBox.information(self, "Some problem", "Please run execution again", QMessageBox.Ok) return current_segmentation = ROIExtractionProfile(name="Unknown", algorithm=name, values=values) @@ -546,7 +546,7 @@ def __init__( # noqa: PLR0915 self.channel_info = "result_image" self.files_num = 2 self.setMinimumWidth(600) - # thi isinstance is only for hinting in IDE + # this isinstance is only for type hinting in IDE self.main_menu = MainMenu(self.settings, self) self.channel_control2 = ChannelProperty(self.settings, start_name="result_image") self.raw_image = CompareImageView(self.settings, self.channel_control2, "raw_image") diff --git a/package/PartSeg/_roi_mask/stack_settings.py b/package/PartSeg/_roi_mask/stack_settings.py index 956d31dae..0907daf69 100644 --- a/package/PartSeg/_roi_mask/stack_settings.py +++ b/package/PartSeg/_roi_mask/stack_settings.py @@ -281,7 +281,7 @@ def transform_state( ) def compare_history(self, history: typing.List[HistoryElement]): - # TODO check dict comparision + # TODO check dict comparison if len(history) != self.history_size(): return False return not any( diff --git a/package/PartSeg/common_backend/partially_const_dict.py b/package/PartSeg/common_backend/partially_const_dict.py index b1d666142..714552679 100644 --- a/package/PartSeg/common_backend/partially_const_dict.py +++ b/package/PartSeg/common_backend/partially_const_dict.py @@ -18,7 +18,7 @@ class PartiallyConstDict(QObject, MutableMapping, Generic[T], metaclass=QtMeta): item_added = Signal(object) """Signal with item added to dict""" item_removed = Signal(object) - """Signal with item remove fom dict""" + """Signal with item remove from dict""" const_item_dict: ClassVar[Dict[str, Any]] = {} """Dict with non removable elements""" @@ -69,7 +69,7 @@ def _refresh_order(self): def get_position(self, key: str) -> int: """ - Get item position as unique int. For soring purpose + Get item position as unique int. For sorting purpose :raise KeyError: if element not in dict """ diff --git a/package/PartSeg/common_backend/python_syntax_highlight.py b/package/PartSeg/common_backend/python_syntax_highlight.py index d5731bee7..81f6744b8 100644 --- a/package/PartSeg/common_backend/python_syntax_highlight.py +++ b/package/PartSeg/common_backend/python_syntax_highlight.py @@ -73,7 +73,7 @@ def highlightBlock(self, text): # dirty, dirty hack # The core problem is that pygemnts by default use string streams, - # that will not handle QTextCharFormat, so wee need use `data` property to work around this. + # that will not handle QTextCharFormat, so we need use `data` property to work around this. for i in range(len(text)): with contextlib.suppress(IndexError): self.setFormat(i, 1, self.formatter.data[p + i]) diff --git a/package/PartSeg/common_gui/channel_control.py b/package/PartSeg/common_gui/channel_control.py index 49dd20abe..abd759fa1 100644 --- a/package/PartSeg/common_gui/channel_control.py +++ b/package/PartSeg/common_gui/channel_control.py @@ -87,7 +87,7 @@ class ColorComboBox(QComboBox): """ Combobox showing colormap instead of text - :param id_num: id which be emmit in signals. Designed to inform which channel information is changed + :param id_num: id which be emit in signals. Designed to inform which channel information is changed :param colors: list of colors which should be able to choose. All needs to be keys in `color_dict` :param color_dict: dict from name to colormap definition :param colormap: initial colormap @@ -281,7 +281,7 @@ def set_color(self, val: str): class ChannelProperty(QWidget): """ - For manipulate chanel properties. + For manipulate channel properties. 1. Apply gaussian blur to channel 2. Fixed range for coloring diff --git a/package/PartSeg/common_gui/colormap_creator.py b/package/PartSeg/common_gui/colormap_creator.py index 3c8b406fd..acd03206e 100644 --- a/package/PartSeg/common_gui/colormap_creator.py +++ b/package/PartSeg/common_gui/colormap_creator.py @@ -149,7 +149,7 @@ def mouseMoveEvent(self, e: QMouseEvent) -> None: def mouseDoubleClickEvent(self, event: QMouseEvent) -> None: """ - If click near marker remove it. Otherwise emmit `double_click` signal with event position factor. + If click near marker remove it. Otherwise emit `double_click` signal with event position factor. """ ratio = self._get_ratio(event) if ratio is None: diff --git a/package/PartSeg/common_gui/main_window.py b/package/PartSeg/common_gui/main_window.py index fb40539bf..75bef3744 100644 --- a/package/PartSeg/common_gui/main_window.py +++ b/package/PartSeg/common_gui/main_window.py @@ -235,7 +235,7 @@ def napari_viewer_show(self): def additional_layers_show(self, with_channels=False): if not self.settings.additional_layers: - QMessageBox().information(self, "No data", "Last executed algoritm does not provide additional data") + QMessageBox().information(self, "No data", "Last executed algorithm does not provide additional data") return viewer = Viewer(title="Additional output", settings=self.settings, partseg_viewer_name=self.channel_info) viewer.theme = self.settings.theme_name @@ -384,6 +384,6 @@ def _toggle_scale_bar(self): """Remove after drop napari 0.4.16""" if NAPARI_LE_4_16 and self._scale_bar_warning and self.settings.theme_name == "light": # pragma: no cover QMessageBox.warning( - self, "Not supported", "Scale bar is not supported for light theme and napari bellow 0.4.17" + self, "Not supported", "Scale bar is not supported for light theme and napari below 0.4.17" ) self._scale_bar_warning = False diff --git a/package/PartSeg/common_gui/multiple_file_widget.py b/package/PartSeg/common_gui/multiple_file_widget.py index ec956cc09..7cd6d4ab6 100644 --- a/package/PartSeg/common_gui/multiple_file_widget.py +++ b/package/PartSeg/common_gui/multiple_file_widget.py @@ -257,7 +257,7 @@ def save_state(self): self.save_state_action(state, custom_name) def save_state_action(self, state: ProjectInfoBase, custom_name): - # TODO left elipsis + # TODO left ellipsis if isinstance(state, list): self.add_states(state) return diff --git a/package/PartSeg/common_gui/numpy_qimage.py b/package/PartSeg/common_gui/numpy_qimage.py index dedfe21e8..d90bd2b6d 100644 --- a/package/PartSeg/common_gui/numpy_qimage.py +++ b/package/PartSeg/common_gui/numpy_qimage.py @@ -36,7 +36,7 @@ def convert_colormap_to_image(colormap: Colormap) -> NumpyQImage: def create_colormap_image(colormap: str, color_dict: ColorMapDict) -> NumpyQImage: """ - Convert named colormap to image of szie (512, 1) + Convert named colormap to image of size (512, 1) :param colormap: must be key in color_dict :param color_dict: dict mapping name to definition of colormap diff --git a/package/PartSeg/common_gui/qt_console.py b/package/PartSeg/common_gui/qt_console.py index 5465b48bb..63e3ce639 100644 --- a/package/PartSeg/common_gui/qt_console.py +++ b/package/PartSeg/common_gui/qt_console.py @@ -56,8 +56,8 @@ class QtConsole(RichJupyterWidget): # pylint: disable=abstract-method """Qt view for the console, an integrated iPython terminal in napari. Parameters ---------- - user_variables : dict - Dictionary of user variables to declare in console name space. + main_window : BaseMainWindow + Parent widget. Attributes ---------- kernel_client : qtconsole.inprocess.QtInProcessKernelClient, diff --git a/package/PartSeg/plugins/napari_widgets/roi_extraction_algorithms.py b/package/PartSeg/plugins/napari_widgets/roi_extraction_algorithms.py index ead22050d..b96d217d3 100644 --- a/package/PartSeg/plugins/napari_widgets/roi_extraction_algorithms.py +++ b/package/PartSeg/plugins/napari_widgets/roi_extraction_algorithms.py @@ -236,7 +236,7 @@ def set_result(self, result: ROIExtractionResult): show_info(result.info_text) if len(result.roi_info.bound_info) == 0: if not result.info_text: - show_info("There is no ROI in result. Pleas check algorithm parameters.") + show_info("There is no ROI in result. Please check algorithm parameters.") return roi = result.roi if self.sender() is not None: diff --git a/package/PartSegCore/analysis/calculation_plan.py b/package/PartSegCore/analysis/calculation_plan.py index e728e4447..26898e3ab 100644 --- a/package/PartSegCore/analysis/calculation_plan.py +++ b/package/PartSegCore/analysis/calculation_plan.py @@ -552,7 +552,7 @@ def __repr__(self): def get_measurements(self, node: typing.Optional[CalculationTree] = None) -> typing.List[MeasurementCalculate]: """ - Get all measurement Calculation bellow given node + Get all measurement Calculation below given node :param node: Node for start, if absent then start from plan root :return: list of measurements @@ -807,7 +807,7 @@ def get_el_name(el): # noqa: C901, PLR0911, PLR0912 raise ValueError(f"Unknown type {type(el)}") def pretty_print(self) -> str: - return f"Calcualation Plan: {self.name}\n{self._pretty_print(self.execution_tree, 0)}" + return f"Calculation Plan: {self.name}\n{self._pretty_print(self.execution_tree, 0)}" def _pretty_print(self, elem: CalculationTree, indent) -> str: if isinstance(elem.operation, str): diff --git a/package/PartSegCore/analysis/measurement_base.py b/package/PartSegCore/analysis/measurement_base.py index 753da9ff9..711010e86 100644 --- a/package/PartSegCore/analysis/measurement_base.py +++ b/package/PartSegCore/analysis/measurement_base.py @@ -331,7 +331,8 @@ def get_channel_num(self, measurement_dict: Dict[str, "MeasurementMethodBase"]) class MeasurementMethodBase(AlgorithmDescribeBase, ABC): """ This is base class For all measurement calculation classes - based on text_info[0] the measurement name wil be generated, based_on text_info[1] the description is generated + based on text_info[0] the measurement name will be generated, + based_on text_info[1] the description is generated """ __argument_class__ = BaseModel diff --git a/package/PartSegCore/analysis/measurement_calculation.py b/package/PartSegCore/analysis/measurement_calculation.py index 4e4b0eba1..eada3d98f 100644 --- a/package/PartSegCore/analysis/measurement_calculation.py +++ b/package/PartSegCore/analysis/measurement_calculation.py @@ -565,7 +565,7 @@ def calculate( :param roi: array with segmentation labeled as positive integers :param result_units: units which should be used to present results. :param range_changed: callback function to set information about steps range - :param step_changed: callback function fo set information about steps done + :param step_changed: callback function for set information about steps done :param time: which data point should be measured :return: measurements """ diff --git a/package/PartSegCore/convex_fill.py b/package/PartSegCore/convex_fill.py index fe7ae3696..fc782dffe 100644 --- a/package/PartSegCore/convex_fill.py +++ b/package/PartSegCore/convex_fill.py @@ -4,7 +4,7 @@ try: from scipy.spatial import QhullError except ImportError: - # Scipy bellow 1.8.0 + # Scipy below 1.8.0 from scipy.spatial.qhull import QhullError # this two functions are from # https://stackoverflow.com/questions/37117878/generating-a-filled-polygon-inside-a-numpy-array/37123933#37123933 diff --git a/package/PartSegCore/image_transforming/image_projection.py b/package/PartSegCore/image_transforming/image_projection.py index b55deb17b..76c86e13b 100644 --- a/package/PartSegCore/image_transforming/image_projection.py +++ b/package/PartSegCore/image_transforming/image_projection.py @@ -18,7 +18,7 @@ class ProjectionType(Enum): class ImageProjectionParams(BaseModel): - projection_type: ProjectionType = Field(ProjectionType.MAX, suffix="Mask and ROI projection will allways use max") + projection_type: ProjectionType = Field(ProjectionType.MAX, suffix="Mask and ROI projection will always use max") keep_mask = False keep_roi = False diff --git a/package/PartSegCore/mask_partition_utils.py b/package/PartSegCore/mask_partition_utils.py index 55918d60e..ae3054098 100644 --- a/package/PartSegCore/mask_partition_utils.py +++ b/package/PartSegCore/mask_partition_utils.py @@ -6,7 +6,7 @@ Better option is to implement this utils as class based with base class :py:class:`AlgorithmDescribeBase`. Then do not need to manage algorithm parameters in places where it is used. -Both class from this module are designed for spherical mask, but may be useful als for others. +Both class from this module are designed for spherical mask, but may be useful also for others. """ import typing diff --git a/package/PartSegCore/segmentation/algorithm_base.py b/package/PartSegCore/segmentation/algorithm_base.py index 09106c2e5..5e9d61382 100644 --- a/package/PartSegCore/segmentation/algorithm_base.py +++ b/package/PartSegCore/segmentation/algorithm_base.py @@ -228,7 +228,7 @@ def set_image(self, image): self.mask = None def set_parameters(self, _params=None, **kwargs): - # FIXME when drop python 3.7 use postional only argument + # FIXME when drop python 3.7 use positional only argument if _params is not None: if isinstance(_params, dict): kwargs = _params diff --git a/package/PartSegCore/segmentation/watershed.py b/package/PartSegCore/segmentation/watershed.py index 26e85c24b..4ad3bc245 100644 --- a/package/PartSegCore/segmentation/watershed.py +++ b/package/PartSegCore/segmentation/watershed.py @@ -48,7 +48,7 @@ def sprawl( :param sprawl_area: Mask area to which sprawl should be limited :param core_objects: Starting objects for sprawl :param data: density information - :param components_num: numer of components in core_objects + :param components_num: number of components in core_objects :param spacing: Image spacing. Needed for sprawls which use metrics :param side_connection: :param operator: diff --git a/package/PartSegCore/utils.py b/package/PartSegCore/utils.py index 5e737a7a0..4de5fa36d 100644 --- a/package/PartSegCore/utils.py +++ b/package/PartSegCore/utils.py @@ -251,7 +251,7 @@ class ProfileDict: Dict for storing recursive data. The path is dot separated. :param klass: class of stored data. Same as in :py:class:`EventedDict` - :parma kwargs: initial data + :param kwargs: initial data >>> dkt = ProfileDict() >>> dkt.set(["aa", "bb", "c1"], 7) diff --git a/package/PartSegImage/channel_class.py b/package/PartSegImage/channel_class.py index 5a02a9259..581827aa2 100644 --- a/package/PartSegImage/channel_class.py +++ b/package/PartSegImage/channel_class.py @@ -13,7 +13,7 @@ def check_type(value): class Channel: """ - This class is introduced to distinguish numerical algorithm parameter from choose chanel. + This class is introduced to distinguish numerical algorithm parameter from choose channel. In autogenerated interface field with this type limits input values to number of current image channels """ diff --git a/package/PartSegImage/image.py b/package/PartSegImage/image.py index 30b26ba69..25080fb4e 100644 --- a/package/PartSegImage/image.py +++ b/package/PartSegImage/image.py @@ -379,7 +379,7 @@ def mask(self) -> typing.Optional[np.ndarray]: @staticmethod def _fit_array_to_image(base_shape, array: np.ndarray) -> np.ndarray: - """change shape of array with inserting singe dimensional entries""" + """change shape of array with inserting single dimensional entries""" shape = list(array.shape) for i, el in enumerate(base_shape): if el == 1 and el != shape[i]: @@ -392,11 +392,11 @@ def _fit_array_to_image(base_shape, array: np.ndarray) -> np.ndarray: def fit_array_to_image(self, array: np.ndarray) -> np.ndarray: """ - Change shape of array with inserting singe dimensional entries + Change shape of array with inserting single dimensional entries :param np.ndarray array: array to be fitted - :return: reshaped array witha added missing 1 in shape + :return: reshaped array with added missing 1 in shape :raises ValueError: if cannot fit array """ diff --git a/package/tests/test_PartSeg/test_sentry.py b/package/tests/test_PartSeg/test_sentry.py index 1f79889f3..ae0369fbe 100644 --- a/package/tests/test_PartSeg/test_sentry.py +++ b/package/tests/test_PartSeg/test_sentry.py @@ -39,11 +39,11 @@ def test_sentry_serialize_clip(monkeypatch): event, _hint = sentry_sdk.utils.event_from_exception(e) event["message"] = message - cliped = serialize(event) - assert len(cliped["message"]) == DEFAULT_ERROR_REPORT + clipped = serialize(event) + assert len(clipped["message"]) == DEFAULT_ERROR_REPORT monkeypatch.setattr(sentry_sdk.utils, CONST_NAME, 10**4) - cliped = serialize(event) - assert len(cliped["message"]) == 5000 + clipped = serialize(event) + assert len(clipped["message"]) == 5000 def test_sentry_variables_clip(monkeypatch): @@ -57,12 +57,12 @@ def test_sentry_variables_clip(monkeypatch): vars_dict = event["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"] for letter in letters: assert letter in vars_dict - cliped = serialize(event) - assert len(cliped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) == 10 + clipped = serialize(event) + assert len(clipped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) == 10 monkeypatch.setattr(sentry_sdk.serializer, "MAX_DATABAG_BREADTH", 100) - cliped = serialize(event) - assert len(cliped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) == len(vars_dict) - assert len(cliped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) > 10 + clipped = serialize(event) + assert len(clipped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) == len(vars_dict) + assert len(clipped["exception"]["values"][0]["stacktrace"]["frames"][0]["vars"]) > 10 client = Client("https://aaa@test.pl/77") Hub.current.bind_client(client) diff --git a/package/tests/test_data/old_saves/0.13.1/mask/segmentation_settings.json b/package/tests/test_data/old_saves/0.13.1/mask/segmentation_settings.json index 5cf654176..32d248147 100644 --- a/package/tests/test_data/old_saves/0.13.1/mask/segmentation_settings.json +++ b/package/tests/test_data/old_saves/0.13.1/mask/segmentation_settings.json @@ -1 +1 @@ -{"__ProfileDict__": true, "default": {"algorithm_widget_state": {"Threshold": {"channel": 0, "noise_filtering": {"None": {}, "Gauss": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": {"Manual": {"threshold": 8000.0}, "Otsu": {"masked": true, "bins": 128}, "Li": {"masked": true, "bins": 256}, "Renyi Entropy": {"masked": true, "bins": 256}, "Shanbhag": {"masked": true, "bins": 256}, "Triangle": {"masked": true, "bins": 256}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}, "Opening": {"smooth_border_radius": 2}, "Vote": {"neighbourhood_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.watershed.NeighType", "value": 18}, "support_level": 1}}, "side_connection": false, "minimum_size": 500, "use_convex": true}, "Threshold Flow": {"channel": 0, "noise_filtering": {"None": {}}, "threshold": {"Base/Core": {"core_threshold": {"Manual": {"threshold": 8000.0}}, "base_threshold": {"Manual": {"threshold": 8000.0}}}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}}, "side_connection": false, "minimum_size": 8000, "sprawl_type": {"MultiScale Opening sprawl": {"step_limits": 100, "reflective": false}, "MultiScale Opening": {"step_limits": 100, "reflective": false}}, "use_convex": false}, "Only Threshold": {"channel": 0, "noise_filtering": {"None": {}, "Gauss": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": 5000}, "Auto Threshold": {"channel": 0, "noise_filtering": {"None": {}}, "threshold": {"Manual": {"threshold": 8000.0}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}}, "side_connection": false, "minimum_size": 8000, "suggested_size": 200000, "use_convex": false}, "Cellpose cyto": {"cell_channel": 0, "nucleus_channel": 0, "diameter": 30}}, "algorithms": {"Threshold": {"channel": 0, "threshold": {"name": "Manual", "values": {"threshold": 8000}}, "minimum_size": 500, "close_holes": true, "smooth_border": {"name": "None", "values": {}}, "noise_filtering": {"name": "Gauss", "values": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "close_holes_size": 200, "side_connection": false, "use_convex": true}, "Threshold Flow": {"channel": 0, "noise_filtering": {"name": "None", "values": {}}, "threshold": {"name": "Base/Core", "values": {"core_threshold": {"name": "Manual", "values": {"threshold": 8000}}, "base_threshold": {"name": "Manual", "values": {"threshold": 8000}}}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"name": "None", "values": {}}, "side_connection": false, "minimum_size": 8000, "sprawl_type": {"name": "MultiScale Opening", "values": {"step_limits": 100, "reflective": false}}, "use_convex": false}, "Only Threshold": {"channel": 0, "noise_filtering": {"name": "Gauss", "values": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": 5000}, "Auto Threshold": {"channel": 0, "noise_filtering": {"name": "None", "values": {}}, "threshold": {"name": "Manual", "values": {"threshold": 8000}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"name": "None", "values": {}}, "side_connection": false, "minimum_size": 8000, "suggested_size": 200000, "use_convex": false}, "Cellpose cyto": {}}, "current_algorithm": "Threshold", "multiple_files_widget": false, "units_value": {"__Enum__": true, "__subtype__": "PartSegCore.universal_const.Units", "value": 2}, "io": {"load_image_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "load_data_filter": "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)", "history": ["/home/czaki/Dropbox/segmentation/stage_9_003", "/home/czaki/Projekty", "/home/czaki/Dropbox/segmentation/stage_9_002", "/home/czaki/Dropbox/stage_9_002", "/home/czaki/Dokumenty/smFish/first_data", "/home/czaki/Projekty/partseg/test_data", "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui/dane partseg", "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "/home/czaki/Pobrane/tmp", "/home/czaki/Obrazy"], "save_batch": "/home/czaki", "save_components_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "save_segmentation_directory": "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "open_segmentation_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "batch_directory": "/home/czaki", "multiple_open_directory": "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "multiple_open_filter": "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)", "files_open_history": [[["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Projekty/PartSeg/test_data/obsep/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/dots2.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv/data.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv/channnel 1.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/dots1.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/Cy5.TIF"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/Cy5_deconv.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"], [["/home/czaki/Projekty/PartSeg/test_data/test_nucleus.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"]], "load_image_file": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/test.obsep", "dir_location_history": ["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "/home/czaki/Projekty/PartSeg/test_data/obsep", "/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv", "/home/czaki/Dokumenty/smFish/stage_7_004_with_points", "/home/czaki/Projekty/PartSeg/test_data", "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/components", "/home/czaki/Dokumenty/smFish/segmentation/20.07.02 smFISH Col-0/5_007", "/home/czaki/Dropbox/segmentation/stage_9_003", "/home/czaki/Dokumenty/smFish/segmentation/20.07.02 smFISH Col-0/5_009", "/home/czaki/Dokumenty/smFish/smFISH data 2/stage_4_006"]}, "simple_measurements": {"units": {"__Enum__": true, "__subtype__": "PartSegCore.universal_const.Units", "value": 1}}, "mask_manager": {"mask_property": {"__Serializable__": true, "__subtype__": "PartSegCore.mask_create.MaskProperty", "dilate": {"__RadiusType__": true, "value": 0}, "dilate_radius": 0, "fill_holes": {"__RadiusType__": true, "value": 0}, "max_holes_size": 0, "save_components": false, "clip_to_mask": false, "reversed_mask": false}}}} +{"__ProfileDict__": true, "default": {"algorithm_widget_state": {"Threshold": {"channel": 0, "noise_filtering": {"None": {}, "Gauss": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": {"Manual": {"threshold": 8000.0}, "Otsu": {"masked": true, "bins": 128}, "Li": {"masked": true, "bins": 256}, "Renyi Entropy": {"masked": true, "bins": 256}, "Shanbhag": {"masked": true, "bins": 256}, "Triangle": {"masked": true, "bins": 256}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}, "Opening": {"smooth_border_radius": 2}, "Vote": {"neighbourhood_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.watershed.NeighType", "value": 18}, "support_level": 1}}, "side_connection": false, "minimum_size": 500, "use_convex": true}, "Threshold Flow": {"channel": 0, "noise_filtering": {"None": {}}, "threshold": {"Base/Core": {"core_threshold": {"Manual": {"threshold": 8000.0}}, "base_threshold": {"Manual": {"threshold": 8000.0}}}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}}, "side_connection": false, "minimum_size": 8000, "sprawl_type": {"MultiScale Opening sprawl": {"step_limits": 100, "reflective": false}, "MultiScale Opening": {"step_limits": 100, "reflective": false}}, "use_convex": false}, "Only Threshold": {"channel": 0, "noise_filtering": {"None": {}, "Gauss": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": 5000}, "Auto Threshold": {"channel": 0, "noise_filtering": {"None": {}}, "threshold": {"Manual": {"threshold": 8000.0}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"None": {}}, "side_connection": false, "minimum_size": 8000, "suggested_size": 200000, "use_convex": false}, "Cellpose cyto": {"cell_channel": 0, "nucleus_channel": 0, "diameter": 30}}, "algorithms": {"Threshold": {"channel": 0, "threshold": {"name": "Manual", "values": {"threshold": 8000}}, "minimum_size": 500, "close_holes": true, "smooth_border": {"name": "None", "values": {}}, "noise_filtering": {"name": "Gauss", "values": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "close_holes_size": 200, "side_connection": false, "use_convex": true}, "Threshold Flow": {"channel": 0, "noise_filtering": {"name": "None", "values": {}}, "threshold": {"name": "Base/Core", "values": {"core_threshold": {"name": "Manual", "values": {"threshold": 8000}}, "base_threshold": {"name": "Manual", "values": {"threshold": 8000}}}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"name": "None", "values": {}}, "side_connection": false, "minimum_size": 8000, "sprawl_type": {"name": "MultiScale Opening", "values": {"step_limits": 100, "reflective": false}}, "use_convex": false}, "Only Threshold": {"channel": 0, "noise_filtering": {"name": "Gauss", "values": {"dimension_type": {"__Enum__": true, "__subtype__": "PartSegCore.segmentation.noise_filtering.DimensionType", "value": 1}, "radius": 1.0}}, "threshold": 5000}, "Auto Threshold": {"channel": 0, "noise_filtering": {"name": "None", "values": {}}, "threshold": {"name": "Manual", "values": {"threshold": 8000}}, "close_holes": true, "close_holes_size": 200, "smooth_border": {"name": "None", "values": {}}, "side_connection": false, "minimum_size": 8000, "suggested_size": 200000, "use_convex": false}, "Cellpose cyto": {}}, "current_algorithm": "Threshold", "multiple_files_widget": false, "units_value": {"__Enum__": true, "__subtype__": "PartSegCore.universal_const.Units", "value": 2}, "io": {"load_image_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "load_data_filter": "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)", "history": ["/home/czaki/Dropbox/segmentation/stage_9_003", "/home/czaki/Projekty", "/home/czaki/Dropbox/segmentation/stage_9_002", "/home/czaki/Dropbox/stage_9_002", "/home/czaki/Dokumenty/smFish/first_data", "/home/czaki/Projekty/partseg/test_data", "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui/dane partseg", "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "/home/czaki/Pobrane/tmp", "/home/czaki/Obrazy"], "save_batch": "/home/czaki", "save_components_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "save_segmentation_directory": "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "open_segmentation_directory": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "batch_directory": "/home/czaki", "multiple_open_directory": "/home/czaki/Projekty/partseg/publications/article_text/figures/fig_gui", "multiple_open_filter": "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)", "files_open_history": [[["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Projekty/PartSeg/test_data/obsep/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/dots2.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv/data.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv/channel 1.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/stage_7_004_with_points/test.obsep"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif *.obsep)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/dots1.csv"], "Points (*.csv)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/Cy5.TIF"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"], [["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/Cy5_deconv.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"], [["/home/czaki/Projekty/PartSeg/test_data/test_nucleus.tif"], "Image(*.tif *.tiff *.lsm *.czi *.oib *.oif)"]], "load_image_file": "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/test.obsep", "dir_location_history": ["/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points", "/home/czaki/Projekty/PartSeg/test_data/obsep", "/home/czaki/Dokumenty/smFish/stage_7_004_with_points/dots.csv", "/home/czaki/Dokumenty/smFish/stage_7_004_with_points", "/home/czaki/Projekty/PartSeg/test_data", "/home/czaki/Dokumenty/smFish/smFISH_7_001_with_points/components", "/home/czaki/Dokumenty/smFish/segmentation/20.07.02 smFISH Col-0/5_007", "/home/czaki/Dropbox/segmentation/stage_9_003", "/home/czaki/Dokumenty/smFish/segmentation/20.07.02 smFISH Col-0/5_009", "/home/czaki/Dokumenty/smFish/smFISH data 2/stage_4_006"]}, "simple_measurements": {"units": {"__Enum__": true, "__subtype__": "PartSegCore.universal_const.Units", "value": 1}}, "mask_manager": {"mask_property": {"__Serializable__": true, "__subtype__": "PartSegCore.mask_create.MaskProperty", "dilate": {"__RadiusType__": true, "value": 0}, "dilate_radius": 0, "fill_holes": {"__RadiusType__": true, "value": 0}, "max_holes_size": 0, "save_components": false, "clip_to_mask": false, "reversed_mask": false}}}} diff --git a/pyproject.toml b/pyproject.toml index f0918c432..df120169c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -299,7 +299,7 @@ select = [ "RUF", # Ruff-specific rules ] ignore = ["A003", "SIM108", "ARG002", "ARG003", "ARG004", "PLR2004", - "PLR0913" # should be reenabled in future version + "PLR0913" # should be re-enabled in a future version ] [tool.ruff.lint.isort] @@ -347,3 +347,7 @@ ignore_missing_imports = true [tool.check-wheel-contents] toplevel = ["PartSeg", "PartSegCore", "PartSegImage"] + +[tool.codespell] +skip = "package/tests/test_data/ome.xsd.xml,launcher.spec,publications,dist,_build" +ignore-words-list = "setted" diff --git a/tutorials/api-overview/api-overview.md b/tutorials/api-overview/api-overview.md index d93fcecbf..d7741eee2 100644 --- a/tutorials/api-overview/api-overview.md +++ b/tutorials/api-overview/api-overview.md @@ -25,7 +25,7 @@ There are three classes from this file. This is designed for preprocess step of removing noise from image. Currently only "None" and gauss blur are available. Other implementations should inherit from `NoiseRemovalBase` from this file. - They need to implement `noise_remove(cls, chanel: np.ndarray, spacing: typing.Iterable[float], arguments: dict) -> np.ndarray` + They need to implement `noise_remove(cls, channel: np.ndarray, spacing: typing.Iterable[float], arguments: dict) -> np.ndarray` interface where `arguments` contains data defined in `get_fields()` - Threshold - `partseg_utils.segmentation.threshold`. There are two registers here: diff --git a/tutorials/tutorial-batch-processing/tutorial-batch.md b/tutorials/tutorial-batch-processing/tutorial-batch.md index 324ad1a0d..48aacb307 100644 --- a/tutorials/tutorial-batch-processing/tutorial-batch.md +++ b/tutorials/tutorial-batch-processing/tutorial-batch.md @@ -93,7 +93,7 @@ Now select each of the elements that need replacement and update using the *Repl 1. In case some errors are detected during batch processing, a list of files and descriptions of errors appears in the bottom left panel (8). Information on errors is automatically sent out and helps us to improve the next version of Partseg. -2. For files with complete segmentation failure a separate spreadsheet entitled "Erorrs" with a list of files will be created to inform the user. +2. For files with complete segmentation failure a separate spreadsheet entitled "Errors" with a list of files will be created to inform the user. 3. Files can be transferred directly from the spreadsheet to the “input file” widget for batch processing. diff --git a/tutorials/tutorial_neuron_types/Neuron_types_example.ipynb b/tutorials/tutorial_neuron_types/Neuron_types_example.ipynb index e50ae193d..15c104e78 100644 --- a/tutorials/tutorial_neuron_types/Neuron_types_example.ipynb +++ b/tutorials/tutorial_neuron_types/Neuron_types_example.ipynb @@ -13,7 +13,7 @@ "## Motivation\n", "Often biologist work on mixed population of cells, where subpopulations can be detected based on specific markers, like presence or absence of particular tags or proteins.\n", "\n", - "For quantitative measurements we want to process as many cases as possible. Yet, processing of hundreds of stacks and grouping them manually is laborious and otherwise could require hours of manual sorting of imaging data. Therefore automatic recognition of specific types of cells is necessary. This motivates collaboration between experimental biologists and bioinformaticians. Here we present how PartSeg components can be used as part of a larger application implemented in as Jupyter notebook. The pipeline allows to automatize quantitative analysis of different neuronal subtypes.\n", + "For quantitative measurements we want to process as many cases as possible. Yet, processing of hundreds of stacks and grouping them manually is laborious and otherwise could require hours of manual sorting of imaging data. Therefore automatic recognition of specific types of cells is necessary. This motivates collaboration between experimental biologists and bioinformaticians. Here we present how PartSeg components can be used as part of a larger application implemented in as Jupyter notebook. The pipeline allows to automate quantitative analysis of different neuronal subtypes.\n", "\n", "We argue that exposing the functionality of PartSeg in Python rather than designing a plugin or scripting module for PartSeg is preferable for bioinformaticians as Python is a general and well-known (low entry-cost) programming language with wealth of scientific libraries. At the same time keeping the UI simple and uncluttered is preferable for experimental biologists (again low entry-cost).\n", "\n", @@ -126,7 +126,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Parameters of segmentaion " + "### Parameters of segmentation " ] }, { @@ -237,7 +237,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Load segmentaion" + "## Load segmentation" ] }, { @@ -254,7 +254,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Veriffy segmentaion \n", + "## Veriffy segmentation \n", "In example stack DMSO_120min_2_4.lsm on standard parameters, there are two cases that should be filtered. \n", "1. Three nucleus that are too close and are segmented as one component (number 1)\n", "2. Nucleus that touch border of image (numbers 10, 11, 12)\n", @@ -322,7 +322,7 @@ " # radius is 3, 9, 9 because voxel size is 210x70x70nm and voxel size is in pixels, not physicla units\n", " dilate_sitk = sitk.BinaryContour(sitk.GetImageFromArray(current_component_area.astype(np.uint8)))\n", " dilate_mask = sitk.GetArrayFromImage(sitk.BinaryDilate(dilate_sitk, (3, 9 ,9)))\n", - " # dilate_mask = dilate(current_component_area, (3, 9 ,9), False) # slower than two above lines but combined witrh next gave same result\n", + " # dilate_mask = dilate(current_component_area, (3, 9 ,9), False) # slower than two above lines but combined with next gave same result\n", " dilate_mask[current_component_area] = 0\n", " value_green = np.percentile(image.get_channel(1)[0][current_component_area], 75)\n", " # print(component_number, value_red, value_green)\n", @@ -346,7 +346,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Save cutted nucleus " + "### Save catted nucleus " ] }, { @@ -436,7 +436,7 @@ " # radius is 3, 9, 9 because voxel size is 210x70x70nm and voxel size is in pixels, not physicla units\n", " dilate_sitk = sitk.BinaryContour(sitk.GetImageFromArray(current_component_area.astype(np.uint8)))\n", " dilate_mask = sitk.GetArrayFromImage(sitk.BinaryDilate(dilate_sitk, (3, 9 ,9)))\n", - " # dilate_mask = dilate(current_component_area, (3, 9 ,9), False) # slower than two above lines but combined witrh next gave same result\n", + " # dilate_mask = dilate(current_component_area, (3, 9 ,9), False) # slower than two above lines but combined with next gave same result\n", " dilate_mask[current_component_area] = 0\n", " value_green = np.percentile(image.get_channel(1)[0][current_component_area], 75)\n", " # print(component_number, value_red, value_green, np.percentile(image.get_channel(1)[current_component_area], 50))\n", @@ -495,7 +495,7 @@ "cutted_neurons_dict = dict()\n", "\n", "for file_path in glob(os.path.join(data_path, \"*.lsm\")):\n", - " print(\"proces\", os.path.basename(file_path))\n", + " print(\"process\", os.path.basename(file_path))\n", " cutted_neurons_dict[file_path] = segmentation_function(file_path, segment)\n", " \n" ] @@ -526,7 +526,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Setup measurment\n", + "### Setup measurement\n", "It can be set manually using classes from `PartSegCore..analysis.measurement_calculation`" ] }, @@ -731,7 +731,7 @@ "outputs": [], "source": [ "for file_path in glob(os.path.join(data_path, \"*.lsm\")):\n", - " print(\"proces\", os.path.basename(file_path))\n", + " print(\"process\", os.path.basename(file_path))\n", " segment = ThresholdAlgorithm()\n", " segment.set_parameters(parameters)\n", " image = TiffImageReader.read_image(file_path)\n", From c380ad6a5cd1e1eb142d9ebe51fb269ad550d8d1 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Tue, 13 Feb 2024 14:57:46 +0100 Subject: [PATCH 32/51] chore: Add new ruff rules and apply them (#1079) ## Summary by CodeRabbit - **Refactor** - Enhanced import handling for improved code organization and readability. - Implemented logging in place of print statements for better error tracking. - Streamlined code by removing unused and commented-out sections. - **Bug Fixes** - Improved exception handling in utility methods to prevent `KeyError` occurrences. - Corrected naming inconsistency in the `DoubleThreshold` class for clarity. - **Documentation** - Added targeted comments to address performance-related linting warnings. - **Tests** - Optimized test setups and assertions for enhanced test coverage and reliability. - **Chores** - Conducted code cleanup by removing redundant code and print statements from test files. --- docs/conf.py | 10 --- package/PartSeg/_launcher/main_window.py | 6 +- package/PartSeg/_roi_analysis/batch_window.py | 1 - package/PartSeg/_roi_analysis/export_batch.py | 3 +- .../_roi_analysis/measurement_widget.py | 8 +- package/PartSeg/_roi_mask/main_window.py | 10 +-- .../PartSeg/_roi_mask/simple_measurements.py | 2 +- .../PartSeg/common_backend/base_settings.py | 2 +- package/PartSeg/common_backend/except_hook.py | 3 +- .../common_backend/segmentation_thread.py | 4 +- package/PartSeg/common_gui/advanced_tabs.py | 9 +- .../PartSeg/common_gui/custom_save_dialog.py | 1 - package/PartSeg/common_gui/error_report.py | 2 +- .../common_gui/multiple_file_widget.py | 1 - .../PartSeg/common_gui/napari_image_view.py | 8 +- package/PartSeg/common_gui/qt_console.py | 11 --- .../napari_widgets/measurement_widget.py | 6 +- .../PartSegCore/algorithm_describe_base.py | 2 +- .../batch_processing/batch_backend.py | 84 ++++++++++--------- .../batch_processing/parallel_backend.py | 6 +- .../analysis/calculate_pipeline.py | 4 +- .../PartSegCore/analysis/calculation_plan.py | 2 - .../PartSegCore/analysis/load_functions.py | 7 +- .../analysis/measurement_calculation.py | 1 - package/PartSegCore/class_generator.py | 2 - package/PartSegCore/mask/io_functions.py | 2 - package/PartSegCore/segmentation/threshold.py | 1 - package/PartSegCore/utils.py | 31 ++++--- package/tests/conftest.py | 1 - .../test_PartSeg/test_channel_control.py | 5 -- .../tests/test_PartSeg/test_common_backend.py | 11 +-- .../test_PartSegCore/test_class_register.py | 4 +- .../test_segmentation_proceses.py | 7 +- pyproject.toml | 20 +++-- 34 files changed, 129 insertions(+), 148 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index b65ca5b79..b852b24b5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,16 +4,6 @@ # list see the documentation: # http://www.sphinx-doc.org/en/master/config -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - from datetime import date import PartSeg diff --git a/package/PartSeg/_launcher/main_window.py b/package/PartSeg/_launcher/main_window.py index 1d27cc5b7..71f6f7c30 100644 --- a/package/PartSeg/_launcher/main_window.py +++ b/package/PartSeg/_launcher/main_window.py @@ -2,7 +2,7 @@ import os import warnings from functools import partial -from typing import Type +from typing import TYPE_CHECKING, Type from qtpy.QtCore import QSize, Qt, QThread, Signal from qtpy.QtGui import QIcon @@ -12,10 +12,12 @@ from PartSeg.common_backend import napari_get_settings from PartSeg.common_backend.base_settings import BaseSettings, get_stylesheet, get_theme, napari_template from PartSeg.common_backend.load_backup import import_config -from PartSeg.common_gui.main_window import BaseMainWindow from PartSegData import icons_dir from PartSegImage import TiffImageReader +if TYPE_CHECKING: + from PartSeg.common_gui.main_window import BaseMainWindow + class Prepare(QThread): def __init__(self, module: str): diff --git a/package/PartSeg/_roi_analysis/batch_window.py b/package/PartSeg/_roi_analysis/batch_window.py index 769ec816a..97e6f92b3 100644 --- a/package/PartSeg/_roi_analysis/batch_window.py +++ b/package/PartSeg/_roi_analysis/batch_window.py @@ -160,7 +160,6 @@ def task_cancel_remove(self): else: self.calculation_manager.cancel_calculation(task.calculation) self.task_que.takeRow(index.row()) - print(task) def new_task(self): self.whole_progress.setMaximum(self.calculation_manager.calculation_size) diff --git a/package/PartSeg/_roi_analysis/export_batch.py b/package/PartSeg/_roi_analysis/export_batch.py index 45a2c8a45..d65b98889 100644 --- a/package/PartSeg/_roi_analysis/export_batch.py +++ b/package/PartSeg/_roi_analysis/export_batch.py @@ -1,4 +1,5 @@ import json +import logging import os import tarfile import time @@ -391,7 +392,7 @@ def sleep_with_rate(response: requests.Response): reset = int(response.headers["X-RateLimit-Reset"]) sleep_time = reset - time.time() if sleep_time > 0: - print(f"Sleeping for {sleep_time} seconds") + logging.info("Sleeping for {sleep_time} seconds", extra={"sleep_time": sleep_time}) time.sleep(sleep_time) diff --git a/package/PartSeg/_roi_analysis/measurement_widget.py b/package/PartSeg/_roi_analysis/measurement_widget.py index 8d515df63..b658dadb9 100644 --- a/package/PartSeg/_roi_analysis/measurement_widget.py +++ b/package/PartSeg/_roi_analysis/measurement_widget.py @@ -234,7 +234,7 @@ def copy_to_clipboard(self): for c in range(self.info_field.columnCount()): try: s += str(self.info_field.item(r, c).text()) + "\t" - except AttributeError: + except AttributeError: # noqa: PERF203 s += "\t" s = s[:-1] + "\n" # eliminate last '\t' self.clip.setText(s) @@ -295,7 +295,7 @@ def keyPressEvent(self, e: QKeyEvent): for c in range(selected[0].leftColumn(), selected[0].rightColumn() + 1): try: s += str(self.info_field.item(r, c).text()) + "\t" - except AttributeError: + except AttributeError: # noqa: PERF203 s += "\t" s = s[:-1] + "\n" # eliminate last '\t' self.clip.setText(s) @@ -366,10 +366,6 @@ def append_measurement_result(self): return units = self.units_choose.currentEnum() - # FIXME find which errors should be displayed as warning - # def exception_hook(exception): - # QMessageBox.warning(self, "Calculation error", f"Error during calculation: {exception}") - for num in compute_class.get_channels_num(): if num >= self.settings.image.channels: QMessageBox.warning( diff --git a/package/PartSeg/_roi_mask/main_window.py b/package/PartSeg/_roi_mask/main_window.py index 9312a0f58..eb4373ef1 100644 --- a/package/PartSeg/_roi_mask/main_window.py +++ b/package/PartSeg/_roi_mask/main_window.py @@ -89,8 +89,6 @@ def prev_mask(self): history.arrays.seek(0) seg = np.load(history.arrays) history.arrays.seek(0) - # TODO Check me - # self.settings.roi = seg["segmentation"] self.settings._set_roi_info( # pylint: disable=protected-access ROIInfo(seg["segmentation"]), False, @@ -353,10 +351,8 @@ def save_result(self): return res = dial.get_result() potential_names = self.settings.get_file_names_for_save_result(res.save_destination) - conflict = [] - for el in potential_names: - if os.path.exists(el): - conflict.append(el) + conflict = [el for el in potential_names if os.path.exists(el)] + if conflict: # TODO modify because of long lists conflict_str = "\n".join(conflict) @@ -532,8 +528,6 @@ def __init__(self, settings: StackSettings, image_view: StackImageView): # noqa self.choose_components.check_change_signal.connect(image_view.refresh_selected) self.choose_components.mouse_leave.connect(image_view.component_unmark) self.choose_components.mouse_enter.connect(image_view.component_mark) - # WARNING works only with one channels algorithms - # SynchronizeValues.add_synchronization("channels_chose", widgets_list) self.chosen_list = [] self.progress_bar2 = QProgressBar() self.progress_bar2.setHidden(True) diff --git a/package/PartSeg/_roi_mask/simple_measurements.py b/package/PartSeg/_roi_mask/simple_measurements.py index 00517c822..2cd4b256b 100644 --- a/package/PartSeg/_roi_mask/simple_measurements.py +++ b/package/PartSeg/_roi_mask/simple_measurements.py @@ -152,7 +152,7 @@ def keyPressEvent(self, e: QKeyEvent): for c in range(selected[0].leftColumn(), selected[0].rightColumn() + 1): try: s += str(self.result_view.item(r, c).text()) + "\t" - except AttributeError: + except AttributeError: # noqa: PERF203 s += "\t" s = s[:-1] + "\n" # eliminate last '\t' QApplication.clipboard().setText(s) diff --git a/package/PartSeg/common_backend/base_settings.py b/package/PartSeg/common_backend/base_settings.py index 528e8bfca..644009b63 100644 --- a/package/PartSeg/common_backend/base_settings.py +++ b/package/PartSeg/common_backend/base_settings.py @@ -718,7 +718,7 @@ def dump(self, folder_path: Union[Path, str, None] = None): dump_string = json.dumps(el.values, cls=self.json_encoder_class, indent=2) with open(os.path.join(folder_path, el.file_name), "w", encoding="utf-8") as ff: ff.write(dump_string) - except Exception as e: # pylint: disable=broad-except + except Exception as e: # pylint: disable=broad-except # noqa: PERF203 errors_list.append((e, os.path.join(folder_path, el.file_name))) if errors_list: logger.error(errors_list) diff --git a/package/PartSeg/common_backend/except_hook.py b/package/PartSeg/common_backend/except_hook.py index c28bc0ef8..80b48a280 100644 --- a/package/PartSeg/common_backend/except_hook.py +++ b/package/PartSeg/common_backend/except_hook.py @@ -1,3 +1,4 @@ +import logging import sys import sentry_sdk @@ -34,7 +35,7 @@ def my_excepthook(type_, value, trace_back): except ImportError: sys.__excepthook__(type_, value, trace_back) elif isinstance(value, KeyboardInterrupt): - print("KeyboardInterrupt close", file=sys.stderr) + logging.warning("KeyboardInterrupt close") sys.exit(1) else: # then call the default handler diff --git a/package/PartSeg/common_backend/segmentation_thread.py b/package/PartSeg/common_backend/segmentation_thread.py index dbc0d37b2..29d79a04a 100644 --- a/package/PartSeg/common_backend/segmentation_thread.py +++ b/package/PartSeg/common_backend/segmentation_thread.py @@ -1,5 +1,5 @@ import dataclasses -import sys +import logging from qtpy.QtCore import QMutex, QThread, Signal @@ -48,7 +48,7 @@ def run(self): """the calculation are done here""" if self.algorithm.image is None: # assertion for running algorithm without image - print(f"No image in class {self.algorithm.__class__}", file=sys.stderr) + logging.error("No image in class {cls_name}", extra={"cls_name": self.algorithm.__class__}) return try: segment_data = self.algorithm.calculation_run_wrap(self.send_info) diff --git a/package/PartSeg/common_gui/advanced_tabs.py b/package/PartSeg/common_gui/advanced_tabs.py index d60c3a3a6..81983d661 100644 --- a/package/PartSeg/common_gui/advanced_tabs.py +++ b/package/PartSeg/common_gui/advanced_tabs.py @@ -4,7 +4,7 @@ """ import importlib -import sys +import logging from contextlib import suppress from typing import List @@ -65,14 +65,15 @@ def __init__(self, parent=None): def reload_algorithm_action(self): """Function for reload plugins and algorithms""" + msg = "Reloading {mod_name}" for val in register.reload_module_list: - print(val, file=sys.stderr) + logging.info(msg, extra={"mod_name": val.__name__}) importlib.reload(val) for el in plugins.get_plugins(): - print(el, file=sys.stderr) + logging.info(msg, extra={"mod_name": el.__name__}) importlib.reload(el) for el in core_plugins.get_plugins(): - print(el, file=sys.stderr) + logging.info(msg, extra={"mod_name": el.__name__}) importlib.reload(el) importlib.reload(register) importlib.reload(plugins) diff --git a/package/PartSeg/common_gui/custom_save_dialog.py b/package/PartSeg/common_gui/custom_save_dialog.py index 7164a54af..ab443d3f4 100644 --- a/package/PartSeg/common_gui/custom_save_dialog.py +++ b/package/PartSeg/common_gui/custom_save_dialog.py @@ -86,7 +86,6 @@ def __init__( layout = self.layout() if isinstance(layout, QGridLayout): - # print(layout.columnCount(), layout.rowCount()) # noinspection PyArgumentList layout.addWidget(widget, 0, layout.columnCount(), layout.rowCount(), 1) else: diff --git a/package/PartSeg/common_gui/error_report.py b/package/PartSeg/common_gui/error_report.py index 9b76a3574..7e8c78306 100644 --- a/package/PartSeg/common_gui/error_report.py +++ b/package/PartSeg/common_gui/error_report.py @@ -184,7 +184,7 @@ def create_issue(self): for name in ["napari", "numpy", "SimpleITK", "PartSegData", "PartSegCore_compiled_backend"]: try: versions_dkt[name] = version(name) - except PackageNotFoundError: # pragma: no cover + except PackageNotFoundError: # pragma: no cover # noqa: PERF203 versions_dkt[name] = "not found" data["body"] += "Packages: \n```\n" + "\n".join(f"{k}=={v}" for k, v in versions_dkt.items()) + "\n```\n" diff --git a/package/PartSeg/common_gui/multiple_file_widget.py b/package/PartSeg/common_gui/multiple_file_widget.py index 7cd6d4ab6..341e045d8 100644 --- a/package/PartSeg/common_gui/multiple_file_widget.py +++ b/package/PartSeg/common_gui/multiple_file_widget.py @@ -261,7 +261,6 @@ def save_state_action(self, state: ProjectInfoBase, custom_name): if isinstance(state, list): self.add_states(state) return - # state: ProjectInfoBase = self.get_state() if not isinstance(state, ProjectInfoBase): # workaround for PointsInfo load return normed_file_path = os.path.normpath(state.file_path) diff --git a/package/PartSeg/common_gui/napari_image_view.py b/package/PartSeg/common_gui/napari_image_view.py index cb02eb08a..406038a50 100644 --- a/package/PartSeg/common_gui/napari_image_view.py +++ b/package/PartSeg/common_gui/napari_image_view.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, field from enum import Enum from functools import partial -from typing import Dict, List, MutableMapping, Optional, Tuple, Union +from typing import TYPE_CHECKING, Dict, List, MutableMapping, Optional, Tuple, Union import napari import numpy as np @@ -23,7 +23,6 @@ from superqt import QEnumComboBox, ensure_main_thread from vispy.color import Color, Colormap from vispy.geometry.rect import Rect -from vispy.scene import BaseCamera from PartSeg.common_backend.base_settings import BaseSettings from PartSeg.common_gui.advanced_tabs import RENDERING_LIST, RENDERING_MODE_NAME_STR, SEARCH_ZOOM_FACTOR_STR @@ -34,6 +33,9 @@ from PartSegCore.roi_info import ROIInfo from PartSegImage import Image +if TYPE_CHECKING: + from vispy.scene import BaseCamera + try: from napari._qt.qt_viewer_buttons import QtViewerPushButton as QtViewerPushButton_ except ImportError: @@ -643,7 +645,7 @@ def _add_image(self, image_data: Tuple[ImageInfo, bool]): for i, layer in enumerate(image_info.layers): try: self._add_layer_util(i, layer, filters) - except AssertionError: + except AssertionError: # noqa: PERF203 layer.colormap = "gray" self._add_layer_util(i, layer, filters) diff --git a/package/PartSeg/common_gui/qt_console.py b/package/PartSeg/common_gui/qt_console.py index 63e3ce639..edad24fb5 100644 --- a/package/PartSeg/common_gui/qt_console.py +++ b/package/PartSeg/common_gui/qt_console.py @@ -135,12 +135,6 @@ def __init__(self, main_window: "BaseMainWindow"): self.enable_calltips = False - # Set stylings - # self._update_theme() - - # TODO: Try to get console from jupyter to run without a shift click - # self.execute_on_complete_input = True - def _update_theme(self, event=None): """Update the napari GUI theme.""" from napari.qt import get_stylesheet @@ -154,9 +148,6 @@ def _update_theme(self, event=None): theme = get_theme(self.viewer.theme) self.style_sheet = template(raw_stylesheet, **theme) - # After napari 0.4.6 the following syntax will be allowed - # self.style_sheet = get_stylesheet(self.viewer.theme) - # Set syntax styling and highlighting using theme self.syntax_style = theme["syntax_style"] bracket_color = QColor(*str_to_rgb(theme["highlight"])) @@ -164,8 +155,6 @@ def _update_theme(self, event=None): def closeEvent(self, event): """Clean up the integrated console in napari.""" - # Disconnect theme update - # self.viewer.events.theme.disconnect(self._update_theme) if self.kernel_client is not None: self.kernel_client.stop_channels() diff --git a/package/PartSeg/plugins/napari_widgets/measurement_widget.py b/package/PartSeg/plugins/napari_widgets/measurement_widget.py index 62cd7c0f2..95ac9ea1e 100644 --- a/package/PartSeg/plugins/napari_widgets/measurement_widget.py +++ b/package/PartSeg/plugins/napari_widgets/measurement_widget.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import TYPE_CHECKING, Optional from magicgui.widgets import create_widget from napari import Viewer @@ -13,9 +13,11 @@ from PartSeg.plugins import register as register_plugins from PartSeg.plugins.napari_widgets._settings import get_settings from PartSeg.plugins.napari_widgets.utils import NapariFormDialog, generate_image -from PartSegCore.analysis.measurement_calculation import MeasurementProfile, MeasurementResult from PartSegCore.roi_info import ROIInfo +if TYPE_CHECKING: + from PartSegCore.analysis.measurement_calculation import MeasurementProfile, MeasurementResult + class NapariMeasurementSettings(MeasurementSettings): def form_dialog(self, arguments): diff --git a/package/PartSegCore/algorithm_describe_base.py b/package/PartSegCore/algorithm_describe_base.py index d0589fed7..862881d23 100644 --- a/package/PartSegCore/algorithm_describe_base.py +++ b/package/PartSegCore/algorithm_describe_base.py @@ -38,7 +38,7 @@ def __init__( self, name: str, user_name: str, - default_value: typing.Union[str, int, float, object], + default_value: typing.Union[str, float, object], options_range=None, possible_values=None, value_type=None, diff --git a/package/PartSegCore/analysis/batch_processing/batch_backend.py b/package/PartSegCore/analysis/batch_processing/batch_backend.py index 4691228a9..1a614d855 100644 --- a/package/PartSegCore/analysis/batch_processing/batch_backend.py +++ b/package/PartSegCore/analysis/batch_processing/batch_backend.py @@ -21,6 +21,8 @@ """ +from __future__ import annotations + import contextlib import json import logging @@ -28,19 +30,17 @@ import os import threading import traceback -import uuid from collections import OrderedDict from enum import Enum from os import path from queue import Queue from traceback import StackSummary -from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Type, Union +from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, Tuple, Union import numpy as np import pandas as pd import SimpleITK import tifffile -import xlsxwriter from PartSegCore.algorithm_describe_base import ROIExtractionProfile from PartSegCore.analysis.algorithm_description import AnalysisAlgorithmSelection @@ -65,17 +65,23 @@ from PartSegCore.analysis.io_utils import ProjectTuple from PartSegCore.analysis.load_functions import LoadImageForBatch, LoadMaskSegmentation, LoadProject from PartSegCore.analysis.measurement_base import has_mask_components, has_roi_components -from PartSegCore.analysis.measurement_calculation import MeasurementResult from PartSegCore.analysis.save_functions import save_dict from PartSegCore.json_hooks import PartSegEncoder from PartSegCore.mask_create import calculate_mask from PartSegCore.project_info import AdditionalLayerDescription, HistoryElement from PartSegCore.roi_info import ROIInfo -from PartSegCore.segmentation import RestartableAlgorithm from PartSegCore.segmentation.algorithm_base import ROIExtractionAlgorithm, report_empty_fun from PartSegCore.utils import iterate_names from PartSegImage import Image, TiffImageReader +if TYPE_CHECKING: + import uuid + + import xlsxwriter + + from PartSegCore.analysis.measurement_calculation import MeasurementResult + from PartSegCore.segmentation import RestartableAlgorithm + # https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3#ID0EDBD=Newer_versions # page with excel limits MAX_CHAR_IN_EXCEL_CELL = 30_000 # real limit is 32_767 but it is better to have some margin @@ -84,7 +90,7 @@ class ResponseData(NamedTuple): path_to_file: str - values: List[MeasurementResult] + values: list[MeasurementResult] CalculationResultList = List[ResponseData] @@ -94,7 +100,7 @@ class ResponseData(NamedTuple): def get_data_loader( root_type: RootType, file_path: str -) -> Tuple[Union[Type[LoadMaskSegmentation], Type[LoadProject], Type[LoadImageForBatch]], bool]: +) -> tuple[type[LoadMaskSegmentation | LoadProject | LoadImageForBatch], bool]: """ Get data loader for given root type. Return indicator if file extension match to loader. @@ -123,7 +129,7 @@ def prepare_error_data(exception: Exception) -> ErrorInfo: return exception, traceback.extract_tb(exception.__traceback__) -def do_calculation(file_info: Tuple[int, str], calculation: BaseCalculation) -> WrappedResult: +def do_calculation(file_info: tuple[int, str], calculation: BaseCalculation) -> WrappedResult: """ Main function which will be used for run calculation. It create :py:class:`.CalculationProcess` and call it method @@ -153,12 +159,12 @@ def __init__(self): self.reused_mask = set() self.mask_dict = {} self.calculation = None - self.measurement: List[MeasurementResult] = [] - self.image: Optional[Image] = None - self.roi_info: Optional[ROIInfo] = None - self.additional_layers: Dict[str, AdditionalLayerDescription] = {} - self.mask: Optional[np.ndarray] = None - self.history: List[HistoryElement] = [] + self.measurement: list[MeasurementResult] = [] + self.image: Image | None = None + self.roi_info: ROIInfo | None = None + self.additional_layers: dict[str, AdditionalLayerDescription] = {} + self.mask: np.ndarray | None = None + self.history: list[HistoryElement] = [] self.algorithm_parameters: dict = {} self.results: CalculationResultList = [] @@ -173,7 +179,7 @@ def _reset_image_cache(self): self.reused_mask = set() @staticmethod - def load_data(operation, calculation: FileCalculation) -> Union[ProjectTuple, List[ProjectTuple]]: + def load_data(operation, calculation: FileCalculation) -> ProjectTuple | list[ProjectTuple]: metadata = {"default_spacing": calculation.voxel_size} loader, ext_match = get_data_loader(operation, calculation.file_path) @@ -228,7 +234,7 @@ def do_calculation(self, calculation: FileCalculation) -> CalculationResultList: self._reset_image_cache() return self.results - def iterate_over(self, node: Union[CalculationTree, List[CalculationTree]]): + def iterate_over(self, node: CalculationTree | list[CalculationTree]): """ Execute calculation on node children or list oof nodes @@ -241,7 +247,7 @@ def iterate_over(self, node: Union[CalculationTree, List[CalculationTree]]): for el in node: self.recursive_calculation(el) - def step_load_mask(self, operation: MaskMapper, children: List[CalculationTree]): + def step_load_mask(self, operation: MaskMapper, children: list[CalculationTree]): """ Load mask using mask mapper (mask can be defined with suffix, substitution, or file with mapping saved, then iterate over ``children`` nodes. @@ -258,7 +264,7 @@ def step_load_mask(self, operation: MaskMapper, children: List[CalculationTree]) mask = mask_file.asarray() mask = TiffImageReader.update_array_shape(mask, mask_file.series[0].axes) if "C" in TiffImageReader.image_class.axis_order: - pos: List[Union[slice, int]] = [slice(None) for _ in range(mask.ndim)] + pos: list[slice | int] = [slice(None) for _ in range(mask.ndim)] pos[TiffImageReader.image_class.axis_order.index("C")] = 0 mask = mask[tuple(pos)] @@ -273,7 +279,7 @@ def step_load_mask(self, operation: MaskMapper, children: List[CalculationTree]) self.iterate_over(children) self.mask = old_mask - def step_segmentation(self, operation: ROIExtractionProfile, children: List[CalculationTree]): + def step_segmentation(self, operation: ROIExtractionProfile, children: list[CalculationTree]): """ Perform segmentation and iterate over ``children`` nodes @@ -298,7 +304,7 @@ def step_segmentation(self, operation: ROIExtractionProfile, children: List[Calc self.iterate_over(children) self.roi_info, self.additional_layers, self.algorithm_parameters = backup_data - def step_mask_use(self, operation: MaskUse, children: List[CalculationTree]): + def step_mask_use(self, operation: MaskUse, children: list[CalculationTree]): """ use already defined mask and iterate over ``children`` nodes @@ -311,7 +317,7 @@ def step_mask_use(self, operation: MaskUse, children: List[CalculationTree]): self.iterate_over(children) self.mask = old_mask - def step_mask_operation(self, operation: Union[MaskSum, MaskIntersection], children: List[CalculationTree]): + def step_mask_operation(self, operation: MaskSum | MaskIntersection, children: list[CalculationTree]): """ Generate new mask by sum or intersection of existing and iterate over ``children`` nodes @@ -351,7 +357,7 @@ def step_save(self, operation: Save): os.makedirs(save_dir, exist_ok=True) save_class.save(save_path, project_tuple, operation.values) - def step_mask_create(self, operation: MaskCreate, children: List[CalculationTree]): + def step_mask_create(self, operation: MaskCreate, children: list[CalculationTree]): """ Create mask from current segmentation state using definition @@ -387,7 +393,7 @@ def step_measurement(self, operation: MeasurementCalculate): """ channel = operation.channel if channel == -1: - segmentation_class: Type[ROIExtractionAlgorithm] = AnalysisAlgorithmSelection.get( + segmentation_class: type[ROIExtractionAlgorithm] = AnalysisAlgorithmSelection.get( self.algorithm_parameters["algorithm_name"] ) if segmentation_class is None: # pragma: no cover @@ -441,9 +447,9 @@ class BatchResultDescription(NamedTuple): Tuple to handle information about part of calculation result. """ - errors: List[Tuple[str, ErrorInfo]] #: list of errors occurred during calculation + errors: list[tuple[str, ErrorInfo]] #: list of errors occurred during calculation global_counter: int #: total number of calculated steps - jobs_status: Dict[uuid.UUID, int] #: for each job information about progress + jobs_status: dict[uuid.UUID, int] #: for each job information about progress class CalculationManager: @@ -455,7 +461,7 @@ class CalculationManager: def __init__(self): self.batch_manager = BatchManager() self.calculation_queue = Queue() - self.calculation_dict: Dict[uuid.UUID, Calculation] = OrderedDict() + self.calculation_dict: dict[uuid.UUID, Calculation] = OrderedDict() self.calculation_sizes = [] self.calculation_size = 0 self.calculation_done = 0 @@ -522,8 +528,8 @@ def get_results(self) -> BatchResultDescription: :return: information about calculation status :rtype: BatchResultDescription """ - responses: List[Tuple[uuid.UUID, WrappedResult]] = self.batch_manager.get_result() - new_errors: List[Tuple[str, ErrorInfo]] = [] + responses: list[tuple[uuid.UUID, WrappedResult]] = self.batch_manager.get_result() + new_errors: list[tuple[str, ErrorInfo]] = [] for uuid_id, (ind, result_list) in responses: self.calculation_done += 1 self.counter_dict[uuid_id] += 1 @@ -555,7 +561,7 @@ class SheetData: Store single sheet information """ - def __init__(self, name: str, columns: List[Tuple[str, str]], raw=False): + def __init__(self, name: str, columns: list[tuple[str, str]], raw=False): if len(columns) != len(set(columns)): raise ValueError(f"Columns should be unique: {columns}") self.name = name @@ -564,7 +570,7 @@ def __init__(self, name: str, columns: List[Tuple[str, str]], raw=False): else: self.columns = pd.MultiIndex.from_tuples([("name", "units"), *columns]) self.data_frame = pd.DataFrame([], columns=self.columns) - self.row_list: List[Any] = [] + self.row_list: list[Any] = [] def add_data(self, data, ind): if len(data) != len(self.columns): @@ -582,7 +588,7 @@ def add_data_list(self, data, ind): for x in data: self.add_data(x, ind) - def get_data_to_write(self) -> Tuple[str, pd.DataFrame]: + def get_data_to_write(self) -> tuple[str, pd.DataFrame]: """ Get data for write @@ -649,7 +655,7 @@ def finished(self): """check if any data wait on write to disc""" return not self.writing and self.wrote_queue.empty() - def good_sheet_name(self, name: str) -> Tuple[bool, str]: + def good_sheet_name(self, name: str) -> tuple[bool, str]: """ Check if sheet name can be used in current file. Return False if: @@ -732,7 +738,7 @@ def add_data_part(self, calculation: BaseCalculation): self.sheet_set.update(sheet_list) self.calculation_info[calculation.uuid] = calculation.calculation_plan - def wrote_data(self, uuid_id: uuid.UUID, data: ResponseData, ind: Optional[int] = None): + def wrote_data(self, uuid_id: uuid.UUID, data: ResponseData, ind: int | None = None): """ Add information to be stored in output file @@ -805,7 +811,7 @@ def wrote_data_to_file(self): @classmethod def write_to_excel( - cls, file_path: str, data: Tuple[List[Tuple[str, pd.DataFrame]], List[CalculationPlan], List[Tuple[str, str]]] + cls, file_path: str, data: tuple[list[tuple[str, pd.DataFrame]], list[CalculationPlan], list[tuple[str, str]]] ): with pd.ExcelWriter(file_path) as writer: # pylint: disable=abstract-class-instantiated new_sheet_names = [] @@ -866,7 +872,7 @@ def write_calculation_plan(writer: pd.ExcelWriter, calculation_plan: Calculation sheet.set_column(2, 2, max(map(len, calculation_plan_pretty))) - def get_errors(self) -> List[ErrorInfo]: + def get_errors(self) -> list[ErrorInfo]: """ Get list of errors occurred in last write """ @@ -888,7 +894,7 @@ class DataWriter: """ def __init__(self): - self.file_dict: Dict[str, FileData] = {} + self.file_dict: dict[str, FileData] = {} def is_empty_sheet(self, file_path: str, sheet_name: str) -> bool: """ @@ -918,9 +924,7 @@ def remove_data_part(self, calculation: BaseCalculation): if calculation.measurement_file_path in self.file_dict: self.file_dict[calculation.measurement_file_path].remove_data_part(calculation) - def add_result( - self, data: ResponseData, calculation: BaseCalculation, ind: Optional[int] = None - ) -> List[ErrorInfo]: + def add_result(self, data: ResponseData, calculation: BaseCalculation, ind: int | None = None) -> list[ErrorInfo]: """ Add calculation result to file writer @@ -945,7 +949,7 @@ def finish(self): for file_data in self.file_dict.values(): file_data.finish() - def calculation_finished(self, calculation) -> List[ErrorInfo]: + def calculation_finished(self, calculation) -> list[ErrorInfo]: """ Force write data for given calculation. diff --git a/package/PartSegCore/analysis/batch_processing/parallel_backend.py b/package/PartSegCore/analysis/batch_processing/parallel_backend.py index ba35572f2..068fb7fc2 100644 --- a/package/PartSegCore/analysis/batch_processing/parallel_backend.py +++ b/package/PartSegCore/analysis/batch_processing/parallel_backend.py @@ -18,7 +18,6 @@ import logging import multiprocessing import os -import sys import time import traceback import uuid @@ -231,10 +230,7 @@ def calculate_task(self, val: Tuple[Any, uuid.UUID]): res = fun(data, global_data) self.result_queue.put((task_uuid, res)) except Exception as e: # pragma: no cover # pylint: disable=broad-except - traceback.print_exc() - exc_type, _exc_obj, exc_tb = sys.exc_info() - f_name = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] - print(exc_type, f_name, exc_tb.tb_lineno, file=sys.stderr) + logging.exception("Exception in worker") self.result_queue.put((task_uuid, (-1, [(e, traceback.extract_tb(e.__traceback__))]))) def run(self): diff --git a/package/PartSegCore/analysis/calculate_pipeline.py b/package/PartSegCore/analysis/calculate_pipeline.py index e82bcef4f..54712e755 100644 --- a/package/PartSegCore/analysis/calculate_pipeline.py +++ b/package/PartSegCore/analysis/calculate_pipeline.py @@ -9,10 +9,12 @@ from PartSegCore.mask_create import calculate_mask from PartSegCore.project_info import HistoryElement from PartSegCore.roi_info import ROIInfo -from PartSegCore.segmentation import RestartableAlgorithm from PartSegCore.segmentation.algorithm_base import AdditionalLayerDescription, ROIExtractionResult from PartSegImage import Image +if typing.TYPE_CHECKING: + from PartSegCore.segmentation import RestartableAlgorithm + def _empty_fun(_a1, _a2): """Empty function for calculation run callback""" diff --git a/package/PartSegCore/analysis/calculation_plan.py b/package/PartSegCore/analysis/calculation_plan.py index 26898e3ab..3d94d96b6 100644 --- a/package/PartSegCore/analysis/calculation_plan.py +++ b/package/PartSegCore/analysis/calculation_plan.py @@ -1,6 +1,5 @@ import logging import os -import sys import textwrap import typing import uuid @@ -767,7 +766,6 @@ def get_el_name(el): # noqa: C901, PLR0911, PLR0912 :return: str """ if el.__class__.__name__ not in CalculationPlan.correct_name: - print(el, el.__class__.__name__, file=sys.stderr) raise ValueError(f"Unknown type {el.__class__.__name__}") if isinstance(el, RootType): return f"Root: {el}" diff --git a/package/PartSegCore/analysis/load_functions.py b/package/PartSegCore/analysis/load_functions.py index 0e94df33c..8b0b43b93 100644 --- a/package/PartSegCore/analysis/load_functions.py +++ b/package/PartSegCore/analysis/load_functions.py @@ -1,7 +1,7 @@ import contextlib import json +import logging import os -import sys import tarfile import typing from contextlib import suppress @@ -126,7 +126,10 @@ def load_project_from_tar(tar_file, file_path): history=history, algorithm_parameters=algorithm_dict, ) - print("This project is from new version of PartSeg:", version, project_version_info, file=sys.stderr) + logging.warning( + "This project {proj_ver} is from new version of PartSeg: {version} ", + extra={"version": version, "proj_ver": project_version_info}, + ) return ProjectTuple( file_path=file_path, image=image, diff --git a/package/PartSegCore/analysis/measurement_calculation.py b/package/PartSegCore/analysis/measurement_calculation.py index eada3d98f..27939a465 100644 --- a/package/PartSegCore/analysis/measurement_calculation.py +++ b/package/PartSegCore/analysis/measurement_calculation.py @@ -415,7 +415,6 @@ def _calculate_leaf_value( if node.per_component == PerComponent.No: return method.calculate_property(**kw) # TODO use cache for per component calculate - # kw["_cache"] = False val = [] if method.area_type(node.area) == AreaType.ROI and node.per_component != PerComponent.Per_Mask_component: components = segmentation_mask_map.roi_components diff --git a/package/PartSegCore/class_generator.py b/package/PartSegCore/class_generator.py index 83b2c07cf..f219f0676 100644 --- a/package/PartSegCore/class_generator.py +++ b/package/PartSegCore/class_generator.py @@ -149,8 +149,6 @@ def extract_type_name(type_): def extract_type_info(type_): # noinspection PyUnresolvedReferences - # if issubclass(type_, (typing.Any, typing.Union)): - # return str(type_), type_.__module__ if not hasattr(type_, "__module__"): return type_.__name__, None diff --git a/package/PartSegCore/mask/io_functions.py b/package/PartSegCore/mask/io_functions.py index 96f6d4c39..58ad92d28 100644 --- a/package/PartSegCore/mask/io_functions.py +++ b/package/PartSegCore/mask/io_functions.py @@ -447,8 +447,6 @@ def load( callback_function=partial(proxy_callback, range_changed, step_changed), default_spacing=metadata["default_spacing"], ) - # noinspection PyProtectedMember - # image.file_path = load_locations[0] return dataclasses.replace( seg, file_path=image.file_path, image=image, roi_info=seg.roi_info.fit_to_image(image) ) diff --git a/package/PartSegCore/segmentation/threshold.py b/package/PartSegCore/segmentation/threshold.py index 490452587..917839f75 100644 --- a/package/PartSegCore/segmentation/threshold.py +++ b/package/PartSegCore/segmentation/threshold.py @@ -305,7 +305,6 @@ class DoubleThreshold(BaseThreshold): @classmethod def get_name(cls): - # return "Double Choose" return "Base/Core" @classmethod diff --git a/package/PartSegCore/utils.py b/package/PartSegCore/utils.py index 4de5fa36d..2a41ee40f 100644 --- a/package/PartSegCore/utils.py +++ b/package/PartSegCore/utils.py @@ -335,17 +335,16 @@ def set(self, key_path: typing.Union[typing.Sequence[str], str], value): if isinstance(key_path, str): key_path = key_path.split(".") curr_dict = self.my_dict - - for i, key in enumerate(key_path[:-1]): - try: + i = 0 + try: + for i, key in enumerate(key_path[:-1]): # noqa: B007 # TODO add check if next step element is dict and create custom information curr_dict = curr_dict[key] - except KeyError: - for key2 in key_path[i:-1]: - with curr_dict.setted.blocked(): - curr_dict[key2] = {} - curr_dict = curr_dict[key2] - break + except KeyError: + for key2 in key_path[i:-1]: + with curr_dict.setted.blocked(): + curr_dict[key2] = {} + curr_dict = curr_dict[key2] if isinstance(value, dict): value = EventedDict(**value) curr_dict[key_path[-1]] = value @@ -381,15 +380,15 @@ def get(self, key_path: typing.Union[list, str], default=None): if isinstance(key_path, str): key_path = key_path.split(".") curr_dict = self.my_dict - for key in key_path: - try: + try: + for key in key_path: curr_dict = curr_dict[key] - except KeyError as e: - if default is None: - raise e + except KeyError as e: + if default is None: + raise e - val = copy.deepcopy(default) - return self.set(key_path, val) + val = copy.deepcopy(default) + return self.set(key_path, val) return curr_dict diff --git a/package/tests/conftest.py b/package/tests/conftest.py index 13aa38928..01f707c3e 100644 --- a/package/tests/conftest.py +++ b/package/tests/conftest.py @@ -27,7 +27,6 @@ def data_test_dir(): """Return path to directory with test data that need to be downloaded""" return Path(__file__).absolute().parent.parent.parent / "test_data" - # return os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "test_data") @pytest.fixture(autouse=True) diff --git a/package/tests/test_PartSeg/test_channel_control.py b/package/tests/test_PartSeg/test_channel_control.py index 919725507..106bae4f1 100644 --- a/package/tests/test_PartSeg/test_channel_control.py +++ b/package/tests/test_PartSeg/test_channel_control.py @@ -114,11 +114,6 @@ def test_base(self, qtbot): with qtbot.waitSignal(box.currentTextChanged): box.set_color(starting_colors[index]) img = np.array(make_colorbar(dkt[starting_colors[index]][0], size=(1, 512))) - print(array_from_image(box.image), array_from_image(box.image).size) - print(img) - print(img.flatten(), img.size, img.shape) - print(dkt[starting_colors[index]][0]) - print(box.image, box.image.size(), box.image.depth()) assert np.all(array_from_image(box.image) == img.flatten()) box.hide() diff --git a/package/tests/test_PartSeg/test_common_backend.py b/package/tests/test_PartSeg/test_common_backend.py index 1530e1941..735a1a9b4 100644 --- a/package/tests/test_PartSeg/test_common_backend.py +++ b/package/tests/test_PartSeg/test_common_backend.py @@ -96,7 +96,7 @@ def exec_mock(self): except_hook.show_warning(header, text, exception) assert len(exec_list) == 1 - def test_my_excepthook(self, monkeypatch, capsys): + def test_my_excepthook(self, monkeypatch, caplog): catch_list = [] error_list = [] exit_list = [] @@ -126,7 +126,8 @@ def import_raise(_value): monkeypatch.setattr(state_store, "show_error_dialog", False) except_hook.my_excepthook(KeyboardInterrupt, KeyboardInterrupt(), []) assert exit_list == [1] - assert capsys.readouterr().err == "KeyboardInterrupt close\n" + assert "KeyboardInterrupt close\n" in caplog.text + caplog.clear() except_hook.my_excepthook(RuntimeError, RuntimeError("aaa"), []) assert len(catch_list) == 1 @@ -137,7 +138,7 @@ def import_raise(_value): except_hook.my_excepthook(KeyboardInterrupt, KeyboardInterrupt(), []) assert exit_list == [1, 1] - assert capsys.readouterr().err == "KeyboardInterrupt close\n" + assert "KeyboardInterrupt close\n" in caplog.text except_hook.my_excepthook(RuntimeError, RuntimeError("aaa"), []) assert len(error_list) == 1 @@ -247,12 +248,12 @@ def callback_fun2(a, b): class TestSegmentationThread: - def test_empty_image(self, capsys): + def test_empty_image(self, caplog): thr = segmentation_thread.SegmentationThread(ROIExtractionAlgorithmForTest()) assert thr.get_info_text() == "text" thr.set_parameters(a=1) thr.run() - assert capsys.readouterr().err.startswith("No image in") + assert "No image in" in caplog.text def test_run(self, qtbot): algorithm = ROIExtractionAlgorithmForTest() diff --git a/package/tests/test_PartSegCore/test_class_register.py b/package/tests/test_PartSegCore/test_class_register.py index b8e8dfead..5c756cf97 100644 --- a/package/tests/test_PartSegCore/test_class_register.py +++ b/package/tests/test_PartSegCore/test_class_register.py @@ -83,7 +83,9 @@ class ClassToCall: @classmethod @update_argument("arg") def call_func(cls, aa, arg: MigrateClass): - print(aa, arg.a) + assert arg.a == 1 + assert arg.b == 2 + assert aa == 1 ClassToCall.call_func(aa=1, arg={"a": 1, "b": 2}) ClassToCall.call_func(1, {"a": 1, "b": 2}) diff --git a/package/tests/test_PartSegCore/test_segmentation_proceses.py b/package/tests/test_PartSegCore/test_segmentation_proceses.py index 045223399..8e8269ff9 100644 --- a/package/tests/test_PartSegCore/test_segmentation_proceses.py +++ b/package/tests/test_PartSegCore/test_segmentation_proceses.py @@ -1,17 +1,20 @@ # pylint: disable=no-self-use import os.path +from typing import TYPE_CHECKING import numpy as np import pytest -from PartSegCore.algorithm_describe_base import ROIExtractionProfile from PartSegCore.analysis.algorithm_description import AnalysisAlgorithmSelection from PartSegCore.io_utils import load_metadata_base -from PartSegCore.segmentation.algorithm_base import ROIExtractionAlgorithm from PartSegCore.utils import check_loaded_dict from PartSegImage import TiffImageReader +if TYPE_CHECKING: + from PartSegCore.algorithm_describe_base import ROIExtractionProfile + from PartSegCore.segmentation.algorithm_base import ROIExtractionAlgorithm + def empty(_a, _b): pass # pragma: no cover diff --git a/pyproject.toml b/pyproject.toml index df120169c..5793e653b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -277,8 +277,9 @@ select = [ "UP", # pyupgrade "A", # flake8-builtins "YTT", # flake8-2020 +# "ANN", # flake8-annotations "S", # flake8-bandit - # "BLE", # flake8-blind-except +# "BLE", # flake8-blind-except "B", # lake8-bugbear "A", #flake8-builtins "C4", # flake8-comprehensions @@ -286,20 +287,27 @@ select = [ "ICN", # flake8-import-conventions "G", # flake8-logging-format "PIE", # flake8-pie + "T20", # flake8-print + "PYI", "PT", # flake8-pytest-style "Q", # flake8-quotes "RSE", # flake8-raise "RET", # flake8-return "SIM", # flake8-simplify "TID", # flake8-tidy-imports + "TCH", # flake8-type-checking "ARG", # flake8-unused-arguments +# "PTH", # flake8-use-pathlib + "ERA", # eradicate "PGH", # pygrep-hooks "PLC", "PLE", "PLR", "PLW", # pylint "NPY", # NumPy-specific rules + "PERF", # perflint "RUF", # Ruff-specific rules ] ignore = ["A003", "SIM108", "ARG002", "ARG003", "ARG004", "PLR2004", - "PLR0913" # should be re-enabled in a future version + "PLR0913", # should be re-enabled in a future version + "ANN101", "ANN102", ] [tool.ruff.lint.isort] @@ -315,13 +323,15 @@ max-complexity = 15 [tool.ruff.lint.per-file-ignores] "docs/conf.py" = ["A001"] -"package/tests/**" = ["ARG", "PLC1901", "S101", "RUF012"] +"package/tests/**" = ["ARG", "PLC1901", "S101", "RUF012", "ANN", "FBT"] "package/PartSegCore/sphinx/*" = ["ARG"] "package/tests/**.py" = ["PLR2004"] "package/PartSegCore/_old_json_hooks.py" = ["PLR0912", "PLR0911"] -"package/PartSegCore/class_generator.py" = ["PLR0912"] -"build_utils/**.py" = ["S603", "S607"] +"package/PartSegCore/class_generator.py" = ["PLR0912", "T20"] +"build_utils/**.py" = ["S603", "S607", "T20"] +"examples/**.py" = ["T20"] "package/PartSeg/common_gui/show_directory_dialog.py" = ["S603", "S606", "S607"] +"package/PartSeg/launcher_main.py" = ["T20"] [tool.check-manifest] ignore = [".travis.yml", "package/PartSeg/changelog.py", "package/PartSeg/version.py"] From be76bc5b456246f87b270195cdbd74518f329bd3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 18:17:34 +0100 Subject: [PATCH 33/51] ci: [pre-commit.ci] pre-commit autoupdate (#1080) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.2.0 → v0.2.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.0...v0.2.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0cf269959..ef3974397 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: debug-statements - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.2.1 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade From e82298f3cbc6c406ce9ce6166b4f94ffa7082e04 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 14 Feb 2024 16:38:08 +0100 Subject: [PATCH 34/51] test: Improve test suite for `PartSegCore` (#1077) ## Summary by CodeRabbit - **New Features** - Enhanced file input/output capabilities with new methods for better file extension handling. - Improved deprecation warnings for certain outdated functionalities. - **Bug Fixes** - Adjusted exception handling in file loading processes to improve error reporting. - **Tests** - Introduced new test functions and assertions to cover a broader range of scenarios, including file handling and plugin functionalities. - Extended testing for algorithm descriptions and error handling. - **Refactor** - Removed deprecated file order correction logic to streamline file handling processes. - **Chores** - Updated documentation and comments to reflect changes in exception handling and deprecation warnings. --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../PartSegCore/algorithm_describe_base.py | 41 ++-- .../PartSegCore/analysis/load_functions.py | 5 - package/PartSegCore/autofit.py | 6 +- package/PartSegCore/io_utils.py | 79 +++----- package/PartSegCore/mask/io_functions.py | 2 +- package/PartSegCore/napari_plugins/loader.py | 4 +- .../test_algorithm_describe_base.py | 183 +++++++++++++++++- package/tests/test_PartSegCore/test_io.py | 170 +++++++++++++++- .../test_PartSegCore/test_napari_plugins.py | 13 ++ pyproject.toml | 1 + 10 files changed, 418 insertions(+), 86 deletions(-) diff --git a/package/PartSegCore/algorithm_describe_base.py b/package/PartSegCore/algorithm_describe_base.py index 862881d23..c47a15cf0 100644 --- a/package/PartSegCore/algorithm_describe_base.py +++ b/package/PartSegCore/algorithm_describe_base.py @@ -3,7 +3,6 @@ import typing import warnings from abc import ABC, ABCMeta, abstractmethod -from enum import Enum from functools import wraps from local_migrator import REGISTER, class_to_str @@ -211,6 +210,8 @@ def get_fields_from_algorithm(ald_desc: AlgorithmDescribeBase) -> typing.List[ty def is_static(fun): + if fun is None: + return False args = inspect.getfullargspec(fun).args return True if len(args) == 0 else args[0] != "self" @@ -256,6 +257,9 @@ def __eq__(self, other): and self.suggested_base_class == other.suggested_base_class ) + def __ne__(self, other): + return not self.__eq__(other) + def __getitem__(self, item) -> AlgorithmType: # FIXME add better strategy to get proper class when there is conflict of names try: @@ -278,11 +282,11 @@ def register( self.check_function(value, "get_name", True) try: name = value.get_name() - except NotImplementedError: - raise ValueError(f"Class {value} need to implement get_name class method") from None + except (NotImplementedError, AttributeError): + raise ValueError(f"Class {value} need to implement classmethod 'get_name'") from None if name in self and not replace: raise ValueError( - f"Object {self[name]} with this name: {name} already exist and register is not in replace mode" + f"Object {self[name]} with this name: '{name}' already exist and register is not in replace mode" ) if not isinstance(name, str): raise ValueError(f"Function get_name of class {value} need return string not {type(name)}") @@ -292,8 +296,8 @@ def register( for old_name in old_names: if old_name in self._old_mapping and not replace: raise ValueError( - f"Old value mapping for name {old_name} already registered." - f" Currently pointing to {self._old_mapping[name]}" + f"Old value mapping for name '{old_name}' already registered." + f" Currently pointing to {self._old_mapping[old_name]}" ) self._old_mapping[old_name] = name return value @@ -304,23 +308,23 @@ def check_function(ob, function_name, is_class): if not is_class and not inspect.isfunction(fun): raise ValueError(f"Class {ob} need to define method {function_name}") if is_class and not inspect.ismethod(fun) and not is_static(fun): - raise ValueError(f"Class {ob} need to define classmethod {function_name}") + raise ValueError(f"Class {ob} need to define classmethod '{function_name}'") def __setitem__(self, key: str, value: AlgorithmType): if not issubclass(value, AlgorithmDescribeBase): raise ValueError( - f"Class {value} need to inherit from {AlgorithmDescribeBase.__module__}.AlgorithmDescribeBase" + f"Class {value} need to be subclass of {AlgorithmDescribeBase.__module__}.AlgorithmDescribeBase" ) self.check_function(value, "get_name", True) self.check_function(value, "get_fields", True) try: val = value.get_name() - except NotImplementedError: - raise ValueError(f"Method get_name of class {value} need to be implemented") from None + except (NotImplementedError, AttributeError): + raise ValueError(f"Class {value} need to implement classmethod 'get_name'") from None if not isinstance(val, str): raise ValueError(f"Function get_name of class {value} need return string not {type(val)}") if key != val: - raise ValueError("Object need to be registered under name returned by gey_name function") + raise ValueError("Object need to be registered under name returned by get_name function") if not value.__new_style__: try: val = value.get_fields() @@ -415,7 +419,7 @@ def register( :param replace: replace existing algorithm, be patient with :param old_names: list of old names for registered class """ - return cls.__register__.register(value, replace, old_names) + return cls.__register__.register(value, replace=replace, old_names=old_names) @classmethod def get_default(cls): @@ -535,19 +539,6 @@ def _pretty_print( res += "\n" return res[:-1] - @classmethod - def print_dict(cls, dkt, indent=0, name: str = "") -> str: - if isinstance(dkt, Enum): - return dkt.name - if not isinstance(dkt, typing.MutableMapping): - # FIXME update in future method of proper printing channel number - if name.startswith("channel") and isinstance(dkt, int): - return str(dkt + 1) - return str(dkt) - return "\n" + "\n".join( - " " * indent + f"{k.replace('_', ' ')}: {cls.print_dict(v, indent + 2, k)}" for k, v in dkt.items() - ) - def __eq__(self, other): return ( isinstance(other, self.__class__) diff --git a/package/PartSegCore/analysis/load_functions.py b/package/PartSegCore/analysis/load_functions.py index 8b0b43b93..5b918ca18 100644 --- a/package/PartSegCore/analysis/load_functions.py +++ b/package/PartSegCore/analysis/load_functions.py @@ -221,11 +221,6 @@ def get_short_name(cls): def number_of_files(cls): return 2 - @classmethod - def correct_files_order(cls, paths): - name1, name2 = (os.path.basename(os.path.splitext(x)[0]) for x in paths) - return [name1, name2] if name2.endswith("_mask") else paths - @classmethod def load( cls, diff --git a/package/PartSegCore/autofit.py b/package/PartSegCore/autofit.py index b5db4e47a..c49d6f8dd 100644 --- a/package/PartSegCore/autofit.py +++ b/package/PartSegCore/autofit.py @@ -1,3 +1,4 @@ +import warnings from math import acos, pi, sqrt import numpy as np @@ -41,7 +42,7 @@ def find_density_orientation(img, voxel_size, cutoff=1): return vectors, w_n -def get_rotation_parameters(isometric_matrix): +def get_rotation_parameters(isometric_matrix): # pragma: no cover """ If 3x3 isometric matrix is not rotation matrix function transform it into rotation matrix @@ -49,6 +50,7 @@ def get_rotation_parameters(isometric_matrix): :param isometric_matrix: 3x3 np.ndarray with determinant equal 1 or -1 :return: rotation_matrix, rotation axis, rotation angel """ + warnings.warn("This function is deprecated", FutureWarning, stacklevel=2) if np.linalg.det(isometric_matrix) < 0: isometric_matrix = np.dot(np.diag([-1, 1, 1]), isometric_matrix) angel = acos((np.sum(np.diag(isometric_matrix)) - 1) / 2) * 180 / pi @@ -78,7 +80,7 @@ def density_mass_center(image, voxel_size=(1.0, 1.0, 1.0)): if len(voxel_size) != image.ndim: if len(voxel_size) != len(iter_dim): - raise ValueError("Cannot fit voxel size to array") + raise ValueError("Cannot fit voxel size to array") # pragma: no cover voxel_size_array = [0] * image.ndim for i, item in enumerate(iter_dim): voxel_size_array[item] = voxel_size[i] diff --git a/package/PartSegCore/io_utils.py b/package/PartSegCore/io_utils.py index f9870b93e..2d4066df7 100644 --- a/package/PartSegCore/io_utils.py +++ b/package/PartSegCore/io_utils.py @@ -1,3 +1,4 @@ +import io import json import os import re @@ -42,7 +43,7 @@ def check_segmentation_type(tar_file: TarFile) -> SegmentationType: return SegmentationType.analysis if "metadata.json" in names: return SegmentationType.mask - raise WrongFileTypeException + raise WrongFileTypeException # pragma: no cover def get_tarinfo(name, buffer: typing.Union[BytesIO, StringIO]): @@ -56,7 +57,23 @@ def get_tarinfo(name, buffer: typing.Union[BytesIO, StringIO]): return tar_info -class SaveBase(AlgorithmDescribeBase, ABC): +class _IOBase(AlgorithmDescribeBase, ABC): + @classmethod + def get_name_with_suffix(cls): + return cls.get_name() + + @classmethod + def get_extensions(cls) -> typing.List[str]: + match = re.match(r".*\((.*)\)", cls.get_name()) + if match is None: + raise ValueError(f"No extensions found in {cls.get_name()}") + extensions = match[1].split(" ") + if not all(x.startswith("*.") for x in extensions): + raise ValueError(f"Error with parsing extensions in {cls.get_name()}") + return [x[1:] for x in extensions] + + +class SaveBase(_IOBase, ABC): need_functions: typing.ClassVar[typing.List[str]] = [ "save", "get_short_name", @@ -91,15 +108,6 @@ def save( """ raise NotImplementedError - @classmethod - def get_name_with_suffix(cls): - return cls.get_name() - - @classmethod - def get_default_extension(cls): - match = re.search(r"\(\*(\.\w+)", cls.get_name_with_suffix()) - return match[1] if match else "" - @classmethod def need_segmentation(cls): return True @@ -109,23 +117,17 @@ def need_mask(cls): return False @classmethod - def get_extensions(cls) -> typing.List[str]: - match = re.match(r".*\((.*)\)", cls.get_name()) - if match is None: - raise ValueError(f"No extensions found in {cls.get_name()}") - extensions = match[1].split(" ") - if not all(x.startswith("*.") for x in extensions): - raise ValueError(f"Error with parsing extensions in {cls.get_name()}") - return [x[1:] for x in extensions] + def get_default_extension(cls): + match = re.search(r"\(\*(\.\w+)", cls.get_name_with_suffix()) + return match[1] if match else "" -class LoadBase(AlgorithmDescribeBase, ABC): +class LoadBase(_IOBase, ABC): need_functions: typing.ClassVar[typing.List[str]] = [ "load", "get_short_name", "get_name_with_suffix", "number_of_files", - "correct_files_order", "get_next_file", "partial", ] @@ -155,20 +157,6 @@ def load( """ raise NotImplementedError - @classmethod - def get_name_with_suffix(cls): - return cls.get_name() - - @classmethod - def get_extensions(cls) -> typing.List[str]: - match = re.match(r".*\((.*)\)", cls.get_name()) - if match is None: - raise ValueError(f"No extensions found in {cls.get_name()}") - extensions = match[1].split(" ") - if not all(x.startswith("*.") for x in extensions): - raise ValueError(f"Error with parsing extensions in {cls.get_name()}") - return [x[1:] for x in extensions] - @classmethod def get_fields(cls): return [] @@ -178,10 +166,6 @@ def number_of_files(cls): """Number of files required for load method""" return 1 - @classmethod - def correct_files_order(cls, paths): - return paths - @classmethod def get_next_file(cls, file_paths: typing.List[str]): return file_paths[0] @@ -192,19 +176,19 @@ def partial(cls): return False -def load_metadata_base(data: typing.Union[str, Path]): +def load_metadata_base(data: typing.Union[str, Path, typing.TextIO]): try: - if isinstance(data, typing.TextIO): + if isinstance(data, io.TextIOBase): decoded_data = json.load(data, object_hook=partseg_object_hook) elif os.path.exists(data): with open(data, encoding="utf-8") as ff: decoded_data = json.load(ff, object_hook=partseg_object_hook) else: decoded_data = json.loads(data, object_hook=partseg_object_hook) - except ValueError as e: + except ValueError as e: # pragma: no cover try: decoded_data = json.loads(str(data), object_hook=partseg_object_hook) - except Exception: # pragma: no cover + except Exception: raise e # noqa: B904 return decoded_data @@ -299,7 +283,7 @@ def open_tar_file( tar_file = TarFile.open(fileobj=file_data) file_path = "" else: - raise ValueError(f"wrong type of file_ argument: {type(file_data)}") + raise ValueError(f"wrong type of file_data argument: {type(file_data)}") return tar_file, file_path @@ -325,13 +309,14 @@ def save( cls, save_location: typing.Union[str, BytesIO, Path], project_info, - parameters: dict, + parameters: typing.Optional[dict] = None, range_changed=None, step_changed=None, ): if project_info.image.mask is None and project_info.mask is not None: ImageWriter.save_mask(project_info.image.substitute(mask=project_info.mask), save_location) - ImageWriter.save_mask(project_info.image, save_location) + else: + ImageWriter.save_mask(project_info.image, save_location) def tar_to_buff(tar_file, member_name) -> BytesIO: @@ -352,7 +337,7 @@ def save( cls, save_location: typing.Union[str, BytesIO, Path], project_info, - parameters: dict, + parameters: typing.Optional[dict] = None, range_changed=None, step_changed=None, ): diff --git a/package/PartSegCore/mask/io_functions.py b/package/PartSegCore/mask/io_functions.py index 58ad92d28..2ec87fb53 100644 --- a/package/PartSegCore/mask/io_functions.py +++ b/package/PartSegCore/mask/io_functions.py @@ -106,7 +106,7 @@ def get_raw_mask_copy(self): return MaskProjectTuple(file_path=self.file_path, image=self.image.substitute(), mask=self.mask) @property - def roi(self): + def roi(self): # pragma: no cover warnings.warn("roi is deprecated", DeprecationWarning, stacklevel=2) return self.roi_info.roi diff --git a/package/PartSegCore/napari_plugins/loader.py b/package/PartSegCore/napari_plugins/loader.py index 0af87a324..0d96e7f7e 100644 --- a/package/PartSegCore/napari_plugins/loader.py +++ b/package/PartSegCore/napari_plugins/loader.py @@ -95,9 +95,9 @@ def partseg_loader(loader: typing.Type[LoadBase], path: str): try: project_info = loader.load(load_locations) - except WrongFileTypeException: + except WrongFileTypeException: # pragma: no cover return None if isinstance(project_info, (ProjectTuple, MaskProjectTuple)): return project_to_layers(project_info) - return None + return None # pragma: no cover diff --git a/package/tests/test_PartSegCore/test_algorithm_describe_base.py b/package/tests/test_PartSegCore/test_algorithm_describe_base.py index 408beb464..bee4ad813 100644 --- a/package/tests/test_PartSegCore/test_algorithm_describe_base.py +++ b/package/tests/test_PartSegCore/test_algorithm_describe_base.py @@ -21,6 +21,28 @@ from PartSegImage import Channel +def test_algorithm_property(): + ap = AlgorithmProperty("test", "Test", 1) + assert ap.name == "test" + assert "user_name='Test'" in repr(ap) + + +def test_algorithm_property_warn(): + with pytest.warns(DeprecationWarning, match="use value_type instead"): + ap = AlgorithmProperty("test", "Test", 1, property_type=int) + assert ap.value_type == int + + +def test_algorithm_property_no_kwargs(): + with pytest.raises(ValueError, match="are not expected"): + AlgorithmProperty("test", "Test", 1, a=1) + + +def test_algorithm_property_list_exc(): + with pytest.raises(ValueError, match="should be one of possible values"): + AlgorithmProperty("test", "Test", 1, possible_values=[2, 3], value_type=list) + + def test_get_description_class(): class SampleClass: __test_class__ = _GetDescriptionClass() @@ -77,6 +99,160 @@ def get_fields(cls) -> typing.List[typing.Union[AlgorithmProperty, str]]: assert TestSelection["test1"] is Class1 + assert TestSelection.__register__ != TestSelection2.__register__ + + ts = TestSelection(name="test1", values={}) + assert ts.algorithm() == Class1 + + +def test_register_errors(): + class TestSelection(AlgorithmSelection): + pass + + class Alg1: + pass + + class Alg2(AlgorithmDescribeBase): + pass + + class Alg3(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return 1 + + @classmethod + def get_fields(cls): + return [] # pragma: no cover + + with pytest.raises(ValueError, match="Class .* need to define classmethod 'get_name'"): + TestSelection.register(Alg1) + + with pytest.raises(ValueError, match="Class .* need to implement classmethod 'get_name'"): + TestSelection.register(Alg2) + + with pytest.raises(ValueError, match="Class .* need to implement classmethod 'get_name'"): + TestSelection.__register__["test1"] = Alg2 + + with pytest.raises(ValueError, match="Function get_name of class .* need return string not .*int"): + TestSelection.register(Alg3) + + +def test_register_name_collision(): + class TestSelection(AlgorithmSelection): + pass + + class Alg1(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return "1" + + @classmethod + def get_fields(cls): + return [] + + class Alg2(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return "1" + + @classmethod + def get_fields(cls): + return [] # pragma: no cover + + class Alg3(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return "2" + + @classmethod + def get_fields(cls): + return [] + + TestSelection.register(Alg1, old_names=["0"]) + with pytest.raises( + ValueError, match="Object .* with this name: '1' already exist and register is not in replace mode" + ): + TestSelection.register(Alg2) + + assert len(TestSelection.__register__) == 1 + + with pytest.raises(ValueError, match="Old value mapping for name '0' already registered"): + TestSelection.register(Alg3, old_names=["0"]) + + +def test_register_not_subclass(): + class TestSelection(AlgorithmSelection): + pass + + class Alg1: + @classmethod + def get_name(cls): + return "1" + + @classmethod + def get_fields(cls): + return [] # pragma: no cover + + with pytest.raises(ValueError, match="Class .* need to be subclass of .*AlgorithmDescribeBase"): + TestSelection.register(Alg1) + + +def test_register_validate_name_assignment(): + class TestSelection(AlgorithmSelection): + pass + + class Alg1(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return "1" + + @classmethod + def get_fields(cls): + return [] # pragma: no cover + + class Alg2(Alg1): + @classmethod + def get_name(cls): + return 2 + + with pytest.raises(ValueError, match="need return string"): + TestSelection.__register__["1"] = Alg2 + + with pytest.raises(ValueError, match="under name returned by get_name function"): + TestSelection.__register__["2"] = Alg1 + + +def test_register_get_fields_validity(): + class TestSelection(AlgorithmSelection): + pass + + class Alg1(AlgorithmDescribeBase): + @classmethod + def get_name(cls): + return "1" + + @classmethod + def get_fields(cls): + raise NotImplementedError + + class Alg2(Alg1): + @classmethod + def get_fields(cls): + return () + + with pytest.raises(ValueError, match="need to be implemented"): + TestSelection.register(Alg1) + with pytest.raises(ValueError, match="need return list not"): + TestSelection.register(Alg2) + + +def test_register_no_default_value(): + class TestSelection(AlgorithmSelection): + pass + + with pytest.raises(ValueError, match="Register does not contain any algorithm"): + TestSelection.get_default() + def test_algorithm_selection_convert_subclass(clean_register): class TestSelection(AlgorithmSelection): @@ -362,8 +538,11 @@ def test_roi_extraction_profile(self): ROIExtractionProfile("aaa", "aaa", {}) def test_pretty_print(self): - prof1 = ROIExtractionProfile(name="aaa", algorithm="aaa", values={}) - assert f"{prof1}\n " == prof1.pretty_print(AnalysisAlgorithmSelection) + + prof1 = ROIExtractionProfile(name="aaa", algorithm="Lower threshold", values={}) + assert prof1.pretty_print(AnalysisAlgorithmSelection).startswith("ROI extraction profile name:") + prof1 = ROIExtractionProfile(name="", algorithm="Lower threshold", values={}) + assert prof1.pretty_print(AnalysisAlgorithmSelection).startswith("ROI extraction profile\n") prof2 = ROIExtractionProfile( name="aaa", algorithm=LowerThresholdAlgorithm.get_name(), diff --git a/package/tests/test_PartSegCore/test_io.py b/package/tests/test_PartSegCore/test_io.py index b61be80b2..bdcddff08 100644 --- a/package/tests/test_PartSegCore/test_io.py +++ b/package/tests/test_PartSegCore/test_io.py @@ -8,6 +8,7 @@ from copy import deepcopy from enum import Enum from glob import glob +from io import BytesIO from pathlib import Path from typing import Type @@ -29,17 +30,22 @@ LoadBase, LoadPlanExcel, LoadPlanJson, + LoadPoints, SaveBase, + SaveMaskAsTiff, SaveROIAsNumpy, + SaveScreenshot, find_problematic_entries, find_problematic_leafs, load_metadata_base, load_metadata_part, + open_tar_file, ) from PartSegCore.json_hooks import PartSegEncoder, partseg_object_hook from PartSegCore.mask.history_utils import create_history_element_from_segmentation_tuple from PartSegCore.mask.io_functions import ( LoadROI, + LoadROIFromTIFF, LoadROIImage, LoadROIParameters, LoadStackImage, @@ -200,6 +206,10 @@ def test_save_roi_info_mask_project(self, stack_segmentation2, tmp_path): self.perform_roi_info_test(stack_segmentation2, tmp_path, SaveROI, LoadROI) def perform_roi_info_test(self, project, save_path, save_method: Type[SaveBase], load_method: Type[LoadBase]): + assert save_method.get_short_name().lower() == save_method.get_short_name() + assert save_method.get_short_name().isalpha() + assert load_method.get_short_name().lower() == load_method.get_short_name() + assert load_method.get_short_name().isalpha() alt1 = np.copy(project.roi_info.roi) alt1[alt1 > 0] += 3 roi_info = ROIInfo( @@ -303,7 +313,7 @@ def test_modernize_0_9_2_3(self, bundle_test_dir): data = load_metadata_base(file_path) def test_update_name(self): - data = load_metadata_base(update_name_json) + data = load_metadata_base(UPDATE_NAME_JSON) mp = data["problematic set"] assert isinstance(mp, MeasurementProfile) assert isinstance(mp.chosen_fields[0], MeasurementEntry) @@ -327,6 +337,13 @@ def test_load_workflow(self, bundle_test_dir): for entry in measurement_profile.chosen_fields: assert entry.calculation_tree.name in MEASUREMENT_DICT + def test_load_workflow_from_text(self, bundle_test_dir): + with open(os.path.join(bundle_test_dir, "workflow.json")) as ff: + data_text = ff.read() + assert isinstance(load_metadata_base(data_text)["workflow"], CalculationPlan) + with open(os.path.join(bundle_test_dir, "workflow.json")) as ff: + isinstance(load_metadata_base(ff)["workflow"], CalculationPlan) + class TestSegmentationMask: def test_load_seg(self, data_test_dir): @@ -475,6 +492,32 @@ def test_load_project_with_history(self, tmp_path, stack_segmentation1, mask_pro cmp_dict = {str(k): v for k, v in stack_segmentation1.roi_extraction_parameters.items()} assert str(res.history[0].roi_extraction_parameters["parameters"]) == str(cmp_dict) + def test_mask_project_tuple(self): + mask = np.zeros((10, 10), dtype=np.uint8) + mask[1:-1, 1:-1] = 2 + mask2 = np.copy(mask) + mask2[2:-2, 2:-2] = 4 + roi_info = ROIInfo(mask2) + mask_prop = MaskProperty.simple_mask() + elem = HistoryElement.create(roi_info, mask, {}, mask_prop) + proj = MaskProjectTuple( + file_path="test_data.tiff", + image=Image(np.zeros((10, 10), dtype=np.uint8), (1, 1), "", axes_order="YX"), + mask=mask, + roi_info=roi_info, + history=[elem], + selected_components=[1, 2], + roi_extraction_parameters={}, + ) + assert not proj.is_raw() + assert proj.is_masked() + raw_proj = proj.get_raw_copy() + assert raw_proj.is_raw() + assert not raw_proj.is_masked() + raw_masked_proj = proj.get_raw_mask_copy() + assert raw_masked_proj.is_masked() + assert raw_masked_proj.is_raw() + class TestSaveFunctions: @staticmethod @@ -643,6 +686,7 @@ def test_json_parameters_mask_2(stack_segmentation1, tmp_path): @pytest.mark.parametrize("file_path", (Path(__file__).parent.parent / "test_data" / "notebook").glob("*.json")) def test_load_notebook_json(file_path): + """Check if all notebook files can be loaded""" load_metadata_base(file_path) @@ -755,7 +799,120 @@ def test_load_image_for_batch(data_test_dir): assert proj.mask is None -update_name_json = """ +def test_save_base_extension_parse_no_ext(): + class Save(SaveBase): + @classmethod + def get_name(cls) -> str: + return "Sample save" + + with pytest.raises(ValueError, match="No extensions"): + Save.get_extensions() + + +def test_save_base_extension_parse_malformatted_ext(): + class Save(SaveBase): + @classmethod + def get_name(cls) -> str: + return "Sample save (a.txt)" + + with pytest.raises(ValueError, match="Error with parsing"): + Save.get_extensions() + + +def test_load_points(tmp_path): + data_path = tmp_path / "sample.csv" + with data_path.open("w") as fp: + fp.write(POINTS_DATA) + + res = LoadPoints.load([data_path]) + assert res.file_path == data_path + assert res.points.shape == (5, 4) + + assert LoadPoints.get_short_name() == "point_csv" + + +def test_open_tar_file_with_tarfile_object(tmp_path): + tar_file_path = tmp_path / "test.tar" + tar_file = tarfile.TarFile.open(tar_file_path, "w") + tar_file.close() + result_tar_file, result_file_path = open_tar_file(tar_file) + assert isinstance(result_tar_file, tarfile.TarFile) + assert result_file_path == "" + + +def test_open_tar_file_with_path(tmp_path): + tar_file_path = tmp_path / "test.tar" + tar_file = tarfile.TarFile.open(tar_file_path, "w") + tar_file.close() + result_tar_file, result_file_path = open_tar_file(tar_file_path) + assert isinstance(result_tar_file, tarfile.TarFile) + assert result_file_path == str(tar_file_path) + + +def test_open_tar_file_with_buffer(tmp_path): + buffer = BytesIO() + tar_file = tarfile.TarFile.open(fileobj=buffer, mode="w") + tar_file.close() + buffer.seek(0) + result_tar_file, result_file_path = open_tar_file(buffer) + assert isinstance(result_tar_file, tarfile.TarFile) + assert result_file_path == "" + + +def test_open_tar_file_with_invalid_type(tmp_path): + with pytest.raises(ValueError, match="wrong type of file_data argument"): + open_tar_file(123) + + +def test_save_mask_as_tiff(tmp_path, analysis_segmentation2): + file_path = tmp_path / "test.tiff" + file_path2 = tmp_path / "test2.tiff" + assert analysis_segmentation2.image.mask is None + SaveMaskAsTiff.save(file_path, analysis_segmentation2) + assert file_path.exists() + assert tifffile.TiffFile(str(file_path)).asarray().shape == analysis_segmentation2.mask.squeeze().shape + seg = dataclasses.replace( + analysis_segmentation2, image=analysis_segmentation2.image.substitute(mask=analysis_segmentation2.mask) + ) + SaveMaskAsTiff.save(file_path2, seg) + assert file_path2.exists() + assert tifffile.TiffFile(str(file_path2)).asarray().shape == analysis_segmentation2.mask.squeeze().shape + + +class TestSaveScreenshot: + def test_get_name(self): + assert SaveScreenshot.get_default_extension() == ".png" + assert SaveScreenshot.get_name().startswith("Screenshot") + assert SaveScreenshot.get_short_name() == "screenshot" + assert SaveScreenshot.get_fields() == [] + assert {".png", ".jpg", ".jpeg"}.issubset(set(SaveScreenshot.get_extensions())) + + def test_saving(self, tmp_path): + file_path = tmp_path / "test.png" + data = np.zeros((100, 100, 3), dtype=np.uint8) + SaveScreenshot.save(file_path, data) + assert file_path.exists() + assert file_path.stat().st_size > 0 + + +class TestLoadROIFromTIFF: + def test_get_name(self): + assert LoadROIFromTIFF.get_name().startswith("ROI from tiff") + assert LoadROIFromTIFF.get_short_name() == "roi_tiff" + assert set(LoadROIFromTIFF.get_extensions()) == {".tiff", ".tif"} + + def test_load(self, tmp_path): + data = np.zeros((100, 100), dtype=np.uint8) + data[10:20, 10:20] = 1 + data[30:40, 30:40] = 2 + tifffile.imwrite(tmp_path / "test.tiff", data=data) + res = LoadROIFromTIFF.load([tmp_path / "test.tiff"]) + assert isinstance(res, MaskProjectTuple) + assert res.image is None + assert res.roi_info.roi.shape == (1, 1, 100, 100) + + +UPDATE_NAME_JSON = """ {"problematic set": { "__MeasurementProfile__": true, "name": "problematic set", @@ -834,3 +991,12 @@ def test_load_image_for_batch(data_test_dir): } } """ + + +POINTS_DATA = """index,axis-0,axis-1,axis-2,axis-3 +0.0,0.0,22.0,227.90873370570543,65.07832834070409 +1.0,0.0,22.0,91.94021739981048,276.7482348060973 +2.0,0.0,22.0,194.83531082048773,380.3782931797794 +3.0,0.0,22.0,391.07095327277943,268.6636259303818 +4.0,0.0,22.0,152.20734354620717,256.1692217292996 +""" diff --git a/package/tests/test_PartSegCore/test_napari_plugins.py b/package/tests/test_PartSegCore/test_napari_plugins.py index 5ade78169..206de59e9 100644 --- a/package/tests/test_PartSegCore/test_napari_plugins.py +++ b/package/tests/test_PartSegCore/test_napari_plugins.py @@ -6,6 +6,7 @@ import pytest from napari.layers import Image, Labels, Layer +from PartSegCore.analysis import ProjectTuple from PartSegCore.mask.io_functions import LoadROIFromTIFF from PartSegCore.napari_plugins.load_image import napari_get_reader as napari_get_reader_image from PartSegCore.napari_plugins.load_mask_project import napari_get_reader as napari_get_reader_mask @@ -20,6 +21,7 @@ napari_write_labels as napari_write_labels_tiff, ) from PartSegImage import GenericImageReader +from PartSegImage import Image as PImage def test_project_to_layers_analysis(analysis_segmentation): @@ -41,6 +43,16 @@ def test_project_to_layers_analysis(analysis_segmentation): assert not l3.visible +def test_project_to_layers_roi(): + data = np.zeros((1, 1, 10, 10, 10), dtype=np.uint8) + img = PImage(data, image_spacing=(1, 1, 1), name="ROI") + proj = ProjectTuple(file_path="", image=img) + res = project_to_layers(proj) + assert len(res) == 1 + assert isinstance(res[0][0], np.ndarray) + assert res[0][2] == "labels" + + def test_project_to_layers_mask(stack_segmentation1): res = project_to_layers(stack_segmentation1) assert len(res) == 2 @@ -108,6 +120,7 @@ def test_save_load_axis_order(tmp_path): assert napari_write_labels_tiff(data_path, *layer.as_layer_data_tuple()[:2]) proj = LoadROIFromTIFF.load([data_path]) assert proj.roi_info.roi.shape == data.shape + assert napari_write_labels_tiff(str(tmp_path / "test.seg"), *layer.as_layer_data_tuple()[:2]) is None @pytest.fixture(params=[(1, 4), (1, 3), (3, 4), (3, 3), (10, 4)]) diff --git a/pyproject.toml b/pyproject.toml index 5793e653b..1d825f27a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -221,6 +221,7 @@ omit = [ ".tox/*", "**/changelog.py", "**/version.py", + "**/PartSegCore/class_generator.py", ] parallel = true From 370ab25c151063ee8cb0d624a252f8000a6615a9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:06:17 +0100 Subject: [PATCH 35/51] ci: [pre-commit.ci] pre-commit autoupdate (#1081) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.1.1 → 24.2.0](https://github.com/psf/black-pre-commit-mirror/compare/24.1.1...24.2.0) - [github.com/astral-sh/ruff-pre-commit: v0.2.1 → v0.2.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.1...v0.2.2) - [github.com/asottile/pyupgrade: v3.15.0 → v3.15.1](https://github.com/asottile/pyupgrade/compare/v3.15.0...v3.15.1) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 6 +++--- package/tests/test_PartSeg/test_common_backend.py | 2 +- package/tests/test_PartSeg/test_common_gui.py | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef3974397..a27346095 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.1.1 + rev: 24.2.0 hooks: - id: black pass_filenames: true @@ -20,11 +20,11 @@ repos: - id: debug-statements - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.1 + rev: v0.2.2 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 + rev: v3.15.1 hooks: - id: pyupgrade args: ["--py38-plus"] diff --git a/package/tests/test_PartSeg/test_common_backend.py b/package/tests/test_PartSeg/test_common_backend.py index 735a1a9b4..c77996583 100644 --- a/package/tests/test_PartSeg/test_common_backend.py +++ b/package/tests/test_PartSeg/test_common_backend.py @@ -467,7 +467,7 @@ def question(*args, **kwargs): @pytest.fixture() def image(tmp_path): - data = np.random.random((10, 10, 2)) + data = np.random.default_rng().uniform(size=(10, 10, 2)) return Image(data=data, image_spacing=(10, 10), axes_order="XYC", file_path=str(tmp_path / "test.tiff")) diff --git a/package/tests/test_PartSeg/test_common_gui.py b/package/tests/test_PartSeg/test_common_gui.py index 536e4361e..d76c21fb3 100644 --- a/package/tests/test_PartSeg/test_common_gui.py +++ b/package/tests/test_PartSeg/test_common_gui.py @@ -152,7 +152,8 @@ def __str__(self): def _example_tiff_files(tmp_path): for i in range(5): ImageWriter.save( - Image(np.random.random((10, 10)), image_spacing=(1, 1), axes_order="XY"), tmp_path / f"img_{i}.tif" + Image(np.random.default_rng().uniform(size=(10, 10)), image_spacing=(1, 1), axes_order="XY"), + tmp_path / f"img_{i}.tif", ) From 309994500d4ab14fb26f9b525684157fc4411e3a Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 28 Feb 2024 23:19:17 +0100 Subject: [PATCH 36/51] ci: Fix upgrade depenecies workflow (#1083) The PR #1076 has broken upgrade dependence workflow. This PR is fixing it. ## Summary by CodeRabbit - **Chores** - Updated the Python version to 3.11 and improved the dependency upgrade process. - Enhanced the package update checking script to support the latest Python packaging standards. --- .github/workflows/upgrade-dependencies.yml | 25 +++++----------------- build_utils/check_updated_packages.py | 15 +++++++------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index 04aff8493..e73c8f9d9 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -22,21 +22,7 @@ jobs: ssh-key: ${{ secrets.DEPLOY_KEY }} # START PYTHON DEPENDENCIES - - uses: actions/setup-python@v5 - with: - python-version: "3.8" - cache: pip - cache-dependency-path: 'pyproject.toml' - - uses: actions/setup-python@v5 - with: - python-version: "3.9" - cache: pip - cache-dependency-path: 'pyproject.toml' - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - cache: pip - cache-dependency-path: 'pyproject.toml' + - uses: actions/setup-python@v5 with: python-version: "3.11" @@ -46,14 +32,13 @@ jobs: # ADD YOUR CUSTOM DEPENDENCY UPGRADE COMMANDS BELOW run: | set -x - flags="--extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6" - flags+=" --extra test --extra pyinstaller --allow-unsafe --strip-extras --resolver=backtracking" + pip install -U uv + flags=(--extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller) for pyv in 3.8 3.9 3.10 3.11; do - python${pyv} -m pip install -U pip pip-tools - python${pyv} -m piptools compile --upgrade -o 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}.txt pyproject.toml requirements/version_denylist.txt "${flags[@]}" done - python3.11 -m piptools compile --upgrade -o requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --allow-unsafe --strip-extras --extra docs --extra pyqt6 + uv pip compile --python-version 3.11 --upgrade --output-file requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --extra docs --extra pyqt6 # END PYTHON DEPENDENCIES - name: Check updated packages diff --git a/build_utils/check_updated_packages.py b/build_utils/check_updated_packages.py index 4e472986e..e49a8d0ea 100644 --- a/build_utils/check_updated_packages.py +++ b/build_utils/check_updated_packages.py @@ -2,9 +2,10 @@ import re import subprocess # nosec import sys -from configparser import ConfigParser from pathlib import Path +from tomllib import loads + name_re = re.compile(r"[\w-]+") changed_name_re = re.compile(r"\+([\w-]+)") @@ -31,12 +32,14 @@ sys.exit(0) -config = ConfigParser() -config.read(src_dir / "setup.cfg") +config = loads((src_dir / "pyproject.toml").read_text()) + +metadata = config["project"] + packages = ( - config["options"]["install_requires"].split("\n") - + config["options.extras_require"]["pyinstaller"].split("\n") - + config["options.extras_require"]["all"].split("\n") + metadata["dependencies"] + + metadata["optional-dependencies"]["pyinstaller"] + + metadata["optional-dependencies"]["all"] ) packages = [name_re.match(package).group().lower() for package in packages if name_re.match(package)] From 55962c3c4dec44377d3edeeca243c26901ef0430 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 29 Feb 2024 01:05:50 +0100 Subject: [PATCH 37/51] test: [Automatic] Constraints upgrades: `imageio`, `ipykernel`, `local-migrator`, `napari`, `numpy`, `pandas`, `partsegcore-compiled-backend`, `pyinstaller`, `sentry-sdk`, `tifffile`, `vispy`, `xlsxwriter` (#1063) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * certifi * coverage * dask * debugpy * docutils * fsspec * imageio * ipykernel * local-migrator * markupsafe * napari * npe2 * numpy * numpydoc * pandas * partsegcore-compiled-backend * platformdirs * pluggy * pooch * pyinstaller * pyinstaller-hooks-contrib * pyqt6-qt6 * pyside6 * pytest * pytest-qt * pytz * referencing * rich * rpds-py * sentry-sdk * setuptools * sphinx * tabulate * tifffile * toolz * tqdm * typing-extensions * tzdata * urllib3 * vispy * xlsxwriter ## Summary by CodeRabbit - **Chores** - Updated various package versions across Python 3.8, 3.9, 3.10, and 3.11 environments to ensure compatibility and security. - **New Features** - Enhanced test failure reports with better formatting of captured exceptions. - **Tests** - Updated testing workflow to use the latest Windows operating system for improved reliability and performance. Co-authored-by: Czaki <3826210+Czaki@users.noreply.github.com> --- requirements/constraints_py3.10.txt | 201 +++++++---------------- requirements/constraints_py3.11.txt | 200 +++++++--------------- requirements/constraints_py3.11_docs.txt | 155 +++++------------ requirements/constraints_py3.8.txt | 185 +++++++-------------- requirements/constraints_py3.9.txt | 193 +++++++--------------- 5 files changed, 283 insertions(+), 651 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 9400dc0be..22c121474 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -1,9 +1,5 @@ -# -# This file is autogenerated by pip-compile with Python 3.10 -# by the following command: -# -# pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.10.txt --strip-extras requirements/version_denylist.txt setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.10 --output-file requirements/constraints_py3.10.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller alabaster==0.7.16 # via sphinx altgraph==0.17.4 @@ -12,7 +8,6 @@ app-model==0.2.4 # via napari appdirs==1.4.4 # via - # PartSeg (setup.cfg) # napari # npe2 asttokens==2.4.1 @@ -27,7 +22,7 @@ build==1.0.3 # via npe2 cachey==0.2.1 # via napari -certifi==2023.11.17 +certifi==2024.2.2 # via # napari # requests @@ -42,23 +37,18 @@ cloudpickle==3.0.0 # via dask comm==0.2.1 # via ipykernel -coverage==7.4.0 - # via PartSeg (setup.cfg) +coverage==7.4.3 czifile==2019.7.2 - # via PartSeg (setup.cfg) -dask==2024.1.0 - # via - # dask - # napari -debugpy==1.8.0 +dask==2024.2.1 + # via napari +debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 - # via PartSeg (setup.cfg) docstring-parser==0.15 # via magicgui -docutils==0.17.1 +docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -69,13 +59,11 @@ exceptiongroup==1.2.0 executing==2.0.1 # via stack-data fonticon-fontawesome6==6.4.0 - # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.2 +fsspec==2024.2.0 # via dask h5py==3.10.0 - # via PartSeg (setup.cfg) heapdict==1.0.1 # via cachey hsluv==5.0.4 @@ -83,11 +71,8 @@ hsluv==5.0.4 idna==3.6 # via requests imagecodecs==2024.1.1 - # via PartSeg (setup.cfg) -imageio==2.33.1 +imageio==2.34.0 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # napari # napari-svg # scikit-image @@ -99,14 +84,12 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.0 +ipykernel==6.29.3 # via - # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.20.0 +ipython==8.22.1 # via - # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 @@ -134,23 +117,17 @@ lazy-loader==0.3 # via # napari # scikit-image -local-migrator==0.1.9 - # via - # PartSeg (setup.cfg) - # nme +local-migrator==0.1.10 + # via nme locket==1.0.0 # via partd lxml==5.1.0 - # via PartSeg (setup.cfg) magicgui==0.8.1 - # via - # PartSeg (setup.cfg) - # napari + # via napari mahotas==1.4.13 - # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.4 +markupsafe==2.1.5 # via jinja2 matplotlib-inline==0.1.6 # via @@ -162,8 +139,7 @@ mpmath==1.3.0 # via sympy mypy-extensions==1.0.0 # via psygnal -napari==0.4.18 - # via PartSeg (setup.cfg) +napari==0.4.19.post1 napari-console==0.0.9 # via napari napari-plugin-engine==0.2.0 @@ -177,14 +153,10 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 - # via PartSeg (setup.cfg) -npe2==0.7.3 - # via - # -r requirements/version_denylist.txt - # napari -numpy==1.26.3 +npe2==0.7.4 + # via napari +numpy==1.26.4 # via - # PartSeg (setup.cfg) # czifile # dask # h5py @@ -200,15 +172,12 @@ numpy==1.26.3 # scipy # tifffile # vispy -numpydoc==1.5.0 +numpydoc==1.6.0 # via napari oiffile==2023.8.30 - # via PartSeg (setup.cfg) openpyxl==3.1.2 - # via PartSeg (setup.cfg) packaging==23.2 # via - # PartSeg (setup.cfg) # build # dask # ipykernel @@ -223,18 +192,14 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.2.0 - # via - # PartSeg (setup.cfg) - # napari +pandas==2.2.1 + # via napari parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.2 - # via PartSeg (setup.cfg) +partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 - # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython pillow==10.2.0 @@ -244,13 +209,15 @@ pillow==10.2.0 # scikit-image pint==0.23 # via napari -platformdirs==4.1.0 +platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.3.0 - # via pytest -pooch==1.8.0 +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 # via scikit-image prompt-toolkit==3.0.43 # via ipython @@ -260,7 +227,6 @@ psutil==5.9.8 # napari psygnal==0.9.5 # via - # PartSeg (setup.cfg) # app-model # magicgui # napari @@ -273,8 +239,6 @@ pyconify==0.1.6 # via superqt pydantic==1.10.14 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # app-model # napari # npe2 @@ -283,67 +247,49 @@ pydantic-compat==0.1.2 # via app-model pygments==2.17.2 # via - # PartSeg (setup.cfg) # ipython # napari # qtconsole # rich # sphinx # superqt -pyinstaller==6.3.0 - # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2024.0 +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 # via pyinstaller pyopengl==3.1.7 # via napari pyopengl-accelerate==3.1.7 - # via PartSeg (setup.cfg) pyproject-hooks==1.0.0 # via build pyqt5==5.15.10 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) pyqt5-qt5==5.15.2 # via pyqt5 pyqt5-sip==12.13.0 - # via - # -r requirements/version_denylist.txt - # pyqt5 + # via pyqt5 pyqt6==6.6.1 - # via PartSeg (setup.cfg) -pyqt6-qt6==6.6.1 +pyqt6-qt6==6.6.2 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6==6.6.1 ; python_version >= "3.10" - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6-addons==6.6.1 +pyside6==6.6.2 +pyside6-addons==6.6.2 # via pyside6 -pyside6-essentials==6.6.1 +pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==7.4.4 +pytest==8.0.2 # via - # PartSeg (setup.cfg) # pytest-qt # pytest-timeout -pytest-qt==4.3.1 - # via PartSeg (setup.cfg) +pytest-qt==4.4.0 pytest-timeout==2.2.0 - # via PartSeg (setup.cfg) python-dateutil==2.8.2 # via # jupyter-client # pandas -pytz==2023.3.post1 +pytz==2024.1 # via pandas pyyaml==6.0.1 # via @@ -356,69 +302,58 @@ pyzmq==25.1.2 # jupyter-client # qtconsole qtawesome==1.3.0 - # via PartSeg (setup.cfg) qtconsole==5.5.1 - # via - # PartSeg (setup.cfg) - # napari-console + # via napari-console qtpy==2.4.1 # via - # PartSeg (setup.cfg) # magicgui # napari # napari-console # qtawesome # qtconsole # superqt -referencing==0.32.1 +referencing==0.33.0 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via - # PartSeg (setup.cfg) # pooch # pyconify # sphinx -rich==13.7.0 +rich==13.7.1 # via npe2 -rpds-py==0.17.1 +rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 - # via - # PartSeg (setup.cfg) - # napari + # via napari scipy==1.12.0 # via - # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.2 +sentry-sdk==1.40.6 +setuptools==69.1.1 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) + # pyinstaller + # pyinstaller-hooks-contrib shiboken2==5.15.2.1 # via pyside2 -shiboken6==6.6.1 +shiboken6==6.6.2 # via # pyside6 # pyside6-addons # pyside6-essentials simpleitk==2.3.1 - # via PartSeg (setup.cfg) six==1.16.0 # via - # PartSeg (setup.cfg) # asttokens # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==4.5.0 - # via - # napari - # numpydoc +sphinx==7.2.6 + # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 @@ -435,14 +370,13 @@ stack-data==0.6.3 # via ipython superqt==0.6.1 # via - # PartSeg (setup.cfg) # magicgui # napari sympy==1.12 - # via PartSeg (setup.cfg) -tifffile==2023.12.9 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 # via - # PartSeg (setup.cfg) # czifile # napari # oiffile @@ -451,11 +385,12 @@ tomli==2.0.1 # via # build # npe2 + # numpydoc # pyproject-hooks # pytest tomli-w==1.0.0 # via npe2 -toolz==0.12.0 +toolz==0.12.1 # via # dask # napari @@ -464,10 +399,9 @@ tornado==6.4 # via # ipykernel # jupyter-client -tqdm==4.66.1 +tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 - # via PartSeg (setup.cfg) traitlets==5.14.1 # via # comm @@ -479,7 +413,7 @@ traitlets==5.14.1 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.9.0 +typing-extensions==4.10.0 # via # app-model # magicgui @@ -489,15 +423,14 @@ typing-extensions==4.9.0 # pydantic # superqt # typer -tzdata==2023.4 +tzdata==2024.1 # via pandas -urllib3==2.1.0 +urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.12.2 +vispy==0.14.1 # via - # PartSeg (setup.cfg) # napari # napari-svg wcwidth==0.2.13 @@ -505,14 +438,6 @@ wcwidth==0.2.13 wrapt==1.16.0 # via napari xlrd==2.0.1 - # via PartSeg (setup.cfg) -xlsxwriter==3.1.9 - # via PartSeg (setup.cfg) +xlsxwriter==3.2.0 zipp==3.17.0 # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.3 - # via - # pyinstaller - # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index a90e0a8ad..3e3fe275f 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -1,9 +1,5 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.11.txt --strip-extras requirements/version_denylist.txt setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.11 --output-file requirements/constraints_py3.11.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller alabaster==0.7.16 # via sphinx altgraph==0.17.4 @@ -12,7 +8,6 @@ app-model==0.2.4 # via napari appdirs==1.4.4 # via - # PartSeg (setup.cfg) # napari # npe2 asttokens==2.4.1 @@ -27,7 +22,7 @@ build==1.0.3 # via npe2 cachey==0.2.1 # via napari -certifi==2023.11.17 +certifi==2024.2.2 # via # napari # requests @@ -42,36 +37,29 @@ cloudpickle==3.0.0 # via dask comm==0.2.1 # via ipykernel -coverage==7.4.0 - # via PartSeg (setup.cfg) +coverage==7.4.3 czifile==2019.7.2 - # via PartSeg (setup.cfg) -dask==2024.1.0 - # via - # dask - # napari -debugpy==1.8.0 +dask==2024.2.1 + # via napari +debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 - # via PartSeg (setup.cfg) docstring-parser==0.15 # via magicgui -docutils==0.17.1 +docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl executing==2.0.1 # via stack-data fonticon-fontawesome6==6.4.0 - # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.2 +fsspec==2024.2.0 # via dask h5py==3.10.0 - # via PartSeg (setup.cfg) heapdict==1.0.1 # via cachey hsluv==5.0.4 @@ -79,11 +67,8 @@ hsluv==5.0.4 idna==3.6 # via requests imagecodecs==2024.1.1 - # via PartSeg (setup.cfg) -imageio==2.33.1 +imageio==2.34.0 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # napari # napari-svg # scikit-image @@ -95,14 +80,12 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.0 +ipykernel==6.29.3 # via - # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.20.0 +ipython==8.22.1 # via - # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 @@ -130,23 +113,17 @@ lazy-loader==0.3 # via # napari # scikit-image -local-migrator==0.1.9 - # via - # PartSeg (setup.cfg) - # nme +local-migrator==0.1.10 + # via nme locket==1.0.0 # via partd lxml==5.1.0 - # via PartSeg (setup.cfg) magicgui==0.8.1 - # via - # PartSeg (setup.cfg) - # napari + # via napari mahotas==1.4.13 - # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.4 +markupsafe==2.1.5 # via jinja2 matplotlib-inline==0.1.6 # via @@ -158,8 +135,7 @@ mpmath==1.3.0 # via sympy mypy-extensions==1.0.0 # via psygnal -napari==0.4.18 - # via PartSeg (setup.cfg) +napari==0.4.19.post1 napari-console==0.0.9 # via napari napari-plugin-engine==0.2.0 @@ -173,14 +149,10 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 - # via PartSeg (setup.cfg) -npe2==0.7.3 - # via - # -r requirements/version_denylist.txt - # napari -numpy==1.26.3 +npe2==0.7.4 + # via napari +numpy==1.26.4 # via - # PartSeg (setup.cfg) # czifile # dask # h5py @@ -196,15 +168,12 @@ numpy==1.26.3 # scipy # tifffile # vispy -numpydoc==1.5.0 +numpydoc==1.6.0 # via napari oiffile==2023.8.30 - # via PartSeg (setup.cfg) openpyxl==3.1.2 - # via PartSeg (setup.cfg) packaging==23.2 # via - # PartSeg (setup.cfg) # build # dask # ipykernel @@ -219,18 +188,14 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.2.0 - # via - # PartSeg (setup.cfg) - # napari +pandas==2.2.1 + # via napari parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.2 - # via PartSeg (setup.cfg) +partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 - # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython pillow==10.2.0 @@ -240,13 +205,15 @@ pillow==10.2.0 # scikit-image pint==0.23 # via napari -platformdirs==4.1.0 +platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.3.0 - # via pytest -pooch==1.8.0 +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 # via scikit-image prompt-toolkit==3.0.43 # via ipython @@ -256,7 +223,6 @@ psutil==5.9.8 # napari psygnal==0.9.5 # via - # PartSeg (setup.cfg) # app-model # magicgui # napari @@ -269,8 +235,6 @@ pyconify==0.1.6 # via superqt pydantic==1.10.14 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # app-model # napari # npe2 @@ -279,67 +243,49 @@ pydantic-compat==0.1.2 # via app-model pygments==2.17.2 # via - # PartSeg (setup.cfg) # ipython # napari # qtconsole # rich # sphinx # superqt -pyinstaller==6.3.0 - # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2024.0 +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 # via pyinstaller pyopengl==3.1.7 # via napari pyopengl-accelerate==3.1.7 - # via PartSeg (setup.cfg) pyproject-hooks==1.0.0 # via build pyqt5==5.15.10 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) pyqt5-qt5==5.15.2 # via pyqt5 pyqt5-sip==12.13.0 - # via - # -r requirements/version_denylist.txt - # pyqt5 + # via pyqt5 pyqt6==6.6.1 - # via PartSeg (setup.cfg) -pyqt6-qt6==6.6.1 +pyqt6-qt6==6.6.2 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.13.2 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6==6.6.1 ; python_version >= "3.10" - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6-addons==6.6.1 +pyside6==6.6.2 +pyside6-addons==6.6.2 # via pyside6 -pyside6-essentials==6.6.1 +pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==7.4.4 +pytest==8.0.2 # via - # PartSeg (setup.cfg) # pytest-qt # pytest-timeout -pytest-qt==4.3.1 - # via PartSeg (setup.cfg) +pytest-qt==4.4.0 pytest-timeout==2.2.0 - # via PartSeg (setup.cfg) python-dateutil==2.8.2 # via # jupyter-client # pandas -pytz==2023.3.post1 +pytz==2024.1 # via pandas pyyaml==6.0.1 # via @@ -352,69 +298,58 @@ pyzmq==25.1.2 # jupyter-client # qtconsole qtawesome==1.3.0 - # via PartSeg (setup.cfg) qtconsole==5.5.1 - # via - # PartSeg (setup.cfg) - # napari-console + # via napari-console qtpy==2.4.1 # via - # PartSeg (setup.cfg) # magicgui # napari # napari-console # qtawesome # qtconsole # superqt -referencing==0.32.1 +referencing==0.33.0 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via - # PartSeg (setup.cfg) # pooch # pyconify # sphinx -rich==13.7.0 +rich==13.7.1 # via npe2 -rpds-py==0.17.1 +rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 - # via - # PartSeg (setup.cfg) - # napari + # via napari scipy==1.12.0 # via - # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.2 +sentry-sdk==1.40.6 +setuptools==69.1.1 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) + # pyinstaller + # pyinstaller-hooks-contrib shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.1 +shiboken6==6.6.2 # via # pyside6 # pyside6-addons # pyside6-essentials simpleitk==2.3.1 - # via PartSeg (setup.cfg) six==1.16.0 # via - # PartSeg (setup.cfg) # asttokens # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==4.5.0 - # via - # napari - # numpydoc +sphinx==7.2.6 + # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 @@ -431,21 +366,20 @@ stack-data==0.6.3 # via ipython superqt==0.6.1 # via - # PartSeg (setup.cfg) # magicgui # napari sympy==1.12 - # via PartSeg (setup.cfg) -tifffile==2023.12.9 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 # via - # PartSeg (setup.cfg) # czifile # napari # oiffile # scikit-image tomli-w==1.0.0 # via npe2 -toolz==0.12.0 +toolz==0.12.1 # via # dask # napari @@ -454,10 +388,9 @@ tornado==6.4 # via # ipykernel # jupyter-client -tqdm==4.66.1 +tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 - # via PartSeg (setup.cfg) traitlets==5.14.1 # via # comm @@ -469,7 +402,7 @@ traitlets==5.14.1 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.9.0 +typing-extensions==4.10.0 # via # app-model # magicgui @@ -479,15 +412,14 @@ typing-extensions==4.9.0 # pydantic # superqt # typer -tzdata==2023.4 +tzdata==2024.1 # via pandas -urllib3==2.1.0 +urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.12.2 +vispy==0.14.1 # via - # PartSeg (setup.cfg) # napari # napari-svg wcwidth==0.2.13 @@ -495,14 +427,6 @@ wcwidth==0.2.13 wrapt==1.16.0 # via napari xlrd==2.0.1 - # via PartSeg (setup.cfg) -xlsxwriter==3.1.9 - # via PartSeg (setup.cfg) +xlsxwriter==3.2.0 zipp==3.17.0 # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.3 - # via - # pyinstaller - # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index 7b6519e7e..19c60e811 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -1,16 +1,11 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --allow-unsafe --extra=docs --extra=pyqt6 --output-file=requirements/constraints_py3.11_docs.txt --strip-extras requirements/version_denylist.txt setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.11 --output-file requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --extra docs --extra pyqt6 alabaster==0.7.16 # via sphinx app-model==0.2.4 # via napari appdirs==1.4.4 # via - # PartSeg (setup.cfg) # napari # npe2 asttokens==2.4.1 @@ -20,14 +15,13 @@ attrs==23.2.0 # jsonschema # referencing autodoc-pydantic==1.9.0 - # via PartSeg (setup.cfg) babel==2.14.0 # via sphinx build==1.0.3 # via npe2 cachey==0.2.1 # via napari -certifi==2023.11.17 +certifi==2024.2.2 # via # napari # requests @@ -43,17 +37,13 @@ cloudpickle==3.0.0 comm==0.2.1 # via ipykernel czifile==2019.7.2 - # via PartSeg (setup.cfg) -dask==2024.1.0 - # via - # dask - # napari -debugpy==1.8.0 +dask==2024.2.1 + # via napari +debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 - # via PartSeg (setup.cfg) docstring-parser==0.15 # via magicgui docutils==0.20.1 @@ -65,13 +55,11 @@ et-xmlfile==1.1.0 executing==2.0.1 # via stack-data fonticon-fontawesome6==6.4.0 - # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.2 +fsspec==2024.2.0 # via dask h5py==3.10.0 - # via PartSeg (setup.cfg) heapdict==1.0.1 # via cachey hsluv==5.0.4 @@ -79,11 +67,8 @@ hsluv==5.0.4 idna==3.6 # via requests imagecodecs==2024.1.1 - # via PartSeg (setup.cfg) -imageio==2.33.1 +imageio==2.34.0 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # napari # napari-svg # scikit-image @@ -93,14 +78,12 @@ importlib-metadata==7.0.1 # via dask in-n-out==0.1.9 # via app-model -ipykernel==6.29.0 +ipykernel==6.29.3 # via - # PartSeg (setup.cfg) # napari-console # qtconsole -ipython==8.20.0 +ipython==8.22.1 # via - # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 @@ -128,21 +111,16 @@ lazy-loader==0.3 # via # napari # scikit-image -local-migrator==0.1.9 - # via - # PartSeg (setup.cfg) - # nme +local-migrator==0.1.10 + # via nme locket==1.0.0 # via partd magicgui==0.8.1 - # via - # PartSeg (setup.cfg) - # napari + # via napari mahotas==1.4.13 - # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.4 +markupsafe==2.1.5 # via jinja2 matplotlib-inline==0.1.6 # via @@ -154,8 +132,7 @@ mpmath==1.3.0 # via sympy mypy-extensions==1.0.0 # via psygnal -napari==0.4.19rc3 - # via PartSeg (setup.cfg) +napari==0.4.19.post1 napari-console==0.0.9 # via napari napari-plugin-engine==0.2.0 @@ -169,14 +146,10 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 - # via PartSeg (setup.cfg) -npe2==0.7.3 - # via - # -r requirements/version_denylist.txt - # napari -numpy==1.26.3 +npe2==0.7.4 + # via napari +numpy==1.26.4 # via - # PartSeg (setup.cfg) # czifile # dask # h5py @@ -195,12 +168,9 @@ numpy==1.26.3 numpydoc==1.6.0 # via napari oiffile==2023.8.30 - # via PartSeg (setup.cfg) openpyxl==3.1.2 - # via PartSeg (setup.cfg) packaging==23.2 # via - # PartSeg (setup.cfg) # build # dask # ipykernel @@ -212,18 +182,14 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.2.0 - # via - # PartSeg (setup.cfg) - # napari +pandas==2.2.1 + # via napari parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.2 - # via PartSeg (setup.cfg) +partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 - # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython pillow==10.2.0 @@ -233,11 +199,11 @@ pillow==10.2.0 # scikit-image pint==0.23 # via napari -platformdirs==4.1.0 +platformdirs==4.2.0 # via # jupyter-core # pooch -pooch==1.8.0 +pooch==1.8.1 # via scikit-image prompt-toolkit==3.0.43 # via ipython @@ -247,7 +213,6 @@ psutil==5.9.8 # napari psygnal==0.9.5 # via - # PartSeg (setup.cfg) # app-model # magicgui # napari @@ -260,8 +225,6 @@ pyconify==0.1.6 # via superqt pydantic==1.10.14 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # app-model # autodoc-pydantic # napari @@ -271,7 +234,6 @@ pydantic-compat==0.1.2 # via app-model pygments==2.17.2 # via - # PartSeg (setup.cfg) # ipython # napari # qtconsole @@ -283,26 +245,20 @@ pyopengl==3.1.7 pyproject-hooks==1.0.0 # via build pyqt5==5.15.10 - # via -r requirements/version_denylist.txt pyqt5-qt5==5.15.2 # via pyqt5 pyqt5-sip==12.13.0 - # via - # -r requirements/version_denylist.txt - # pyqt5 + # via pyqt5 pyqt6==6.6.1 - # via PartSeg (setup.cfg) -pyqt6-qt6==6.6.1 +pyqt6-qt6==6.6.2 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.13.2 - # via -r requirements/version_denylist.txt -pyside6==6.6.1 ; python_version >= "3.10" - # via -r requirements/version_denylist.txt -pyside6-addons==6.6.1 +pyside6==6.6.2 +pyside6-addons==6.6.2 # via pyside6 -pyside6-essentials==6.6.1 +pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons @@ -310,7 +266,7 @@ python-dateutil==2.8.2 # via # jupyter-client # pandas -pytz==2023.3.post1 +pytz==2024.1 # via pandas pyyaml==6.0.1 # via @@ -323,76 +279,60 @@ pyzmq==25.1.2 # jupyter-client # qtconsole qtawesome==1.3.0 - # via PartSeg (setup.cfg) qtconsole==5.5.1 - # via - # PartSeg (setup.cfg) - # napari-console + # via napari-console qtpy==2.4.1 # via - # PartSeg (setup.cfg) # magicgui # napari # napari-console # qtawesome # qtconsole # superqt -referencing==0.32.1 +referencing==0.33.0 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via - # PartSeg (setup.cfg) # pooch # pyconify # sphinx -rich==13.7.0 +rich==13.7.1 # via npe2 -rpds-py==0.17.1 +rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 - # via - # napari - # scikit-image + # via napari scipy==1.12.0 # via - # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.2 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) +sentry-sdk==1.40.6 shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.1 +shiboken6==6.6.2 # via # pyside6 # pyside6-addons # pyside6-essentials simpleitk==2.3.1 - # via PartSeg (setup.cfg) six==1.16.0 # via - # PartSeg (setup.cfg) # asttokens # python-dateutil snowballstemmer==2.2.0 # via sphinx sphinx==7.2.6 # via - # PartSeg (setup.cfg) # autodoc-pydantic # numpydoc # sphinx-autodoc-typehints # sphinx-qt-documentation -sphinx-autodoc-typehints==1.25.2 - # via PartSeg (setup.cfg) +sphinx-autodoc-typehints==2.0.0 sphinx-qt-documentation==0.4.1 - # via PartSeg (setup.cfg) sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 @@ -409,23 +349,20 @@ stack-data==0.6.3 # via ipython superqt==0.6.1 # via - # PartSeg (setup.cfg) # magicgui # napari sympy==1.12 - # via PartSeg (setup.cfg) tabulate==0.9.0 # via numpydoc -tifffile==2023.12.9 +tifffile==2024.2.12 # via - # PartSeg (setup.cfg) # czifile # napari # oiffile # scikit-image tomli-w==1.0.0 # via npe2 -toolz==0.12.0 +toolz==0.12.1 # via # dask # napari @@ -434,10 +371,9 @@ tornado==6.4 # via # ipykernel # jupyter-client -tqdm==4.66.1 +tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 - # via PartSeg (setup.cfg) traitlets==5.14.1 # via # comm @@ -449,7 +385,7 @@ traitlets==5.14.1 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.9.0 +typing-extensions==4.10.0 # via # app-model # magicgui @@ -459,15 +395,14 @@ typing-extensions==4.9.0 # pydantic # superqt # typer -tzdata==2023.4 +tzdata==2024.1 # via pandas -urllib3==2.1.0 +urllib3==2.2.1 # via # requests # sentry-sdk vispy==0.14.1 # via - # PartSeg (setup.cfg) # napari # napari-svg wcwidth==0.2.13 @@ -475,8 +410,6 @@ wcwidth==0.2.13 wrapt==1.16.0 # via napari xlrd==2.0.1 - # via PartSeg (setup.cfg) -xlsxwriter==3.1.9 - # via PartSeg (setup.cfg) +xlsxwriter==3.2.0 zipp==3.17.0 # via importlib-metadata diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index ab1b43ff6..b0413d7a4 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -1,9 +1,5 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.8.txt --strip-extras requirements/version_denylist.txt setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.8 --output-file requirements/constraints_py3.8.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller alabaster==0.7.13 # via sphinx altgraph==0.17.4 @@ -12,7 +8,6 @@ app-model==0.2.4 # via napari appdirs==1.4.4 # via - # PartSeg (setup.cfg) # napari # npe2 asttokens==2.4.1 @@ -29,7 +24,7 @@ build==1.0.3 # via npe2 cachey==0.2.1 # via napari -certifi==2023.11.17 +certifi==2024.2.2 # via # napari # requests @@ -44,23 +39,18 @@ cloudpickle==3.0.0 # via dask comm==0.2.1 # via ipykernel -coverage==7.4.0 - # via PartSeg (setup.cfg) +coverage==7.4.3 czifile==2019.7.2 - # via PartSeg (setup.cfg) dask==2023.5.0 - # via - # dask - # napari -debugpy==1.8.0 + # via napari +debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 - # via PartSeg (setup.cfg) docstring-parser==0.15 # via magicgui -docutils==0.17.1 +docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -69,13 +59,11 @@ exceptiongroup==1.2.0 executing==2.0.1 # via stack-data fonticon-fontawesome6==6.4.0 - # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.2 +fsspec==2024.2.0 # via dask h5py==3.10.0 - # via PartSeg (setup.cfg) heapdict==1.0.1 # via cachey hsluv==5.0.4 @@ -83,11 +71,8 @@ hsluv==5.0.4 idna==3.6 # via requests imagecodecs==2023.3.16 - # via PartSeg (setup.cfg) -imageio==2.33.1 +imageio==2.34.0 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # napari # napari-svg # scikit-image @@ -101,7 +86,7 @@ importlib-metadata==7.0.1 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.1.1 +importlib-resources==6.1.2 # via # jsonschema # jsonschema-specifications @@ -109,14 +94,12 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.0 +ipykernel==6.29.3 # via - # PartSeg (setup.cfg) # napari-console # qtconsole ipython==8.12.3 # via - # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 @@ -144,23 +127,17 @@ lazy-loader==0.3 # via # napari # scikit-image -local-migrator==0.1.9 - # via - # PartSeg (setup.cfg) - # nme +local-migrator==0.1.10 + # via nme locket==1.0.0 # via partd lxml==5.1.0 - # via PartSeg (setup.cfg) magicgui==0.8.1 - # via - # PartSeg (setup.cfg) - # napari + # via napari mahotas==1.4.13 - # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.4 +markupsafe==2.1.5 # via jinja2 matplotlib-inline==0.1.6 # via @@ -172,8 +149,7 @@ mpmath==1.3.0 # via sympy mypy-extensions==1.0.0 # via psygnal -napari==0.4.18 - # via PartSeg (setup.cfg) +napari==0.4.19.post1 napari-console==0.0.9 # via napari napari-plugin-engine==0.2.0 @@ -187,14 +163,10 @@ nest-asyncio==1.6.0 networkx==3.1 # via scikit-image nme==0.1.8 - # via PartSeg (setup.cfg) -npe2==0.7.3 - # via - # -r requirements/version_denylist.txt - # napari +npe2==0.7.4 + # via napari numpy==1.24.4 # via - # PartSeg (setup.cfg) # czifile # dask # h5py @@ -211,15 +183,12 @@ numpy==1.24.4 # scipy # tifffile # vispy -numpydoc==1.5.0 +numpydoc==1.6.0 # via napari oiffile==2022.9.29 - # via PartSeg (setup.cfg) openpyxl==3.1.2 - # via PartSeg (setup.cfg) packaging==23.2 # via - # PartSeg (setup.cfg) # build # dask # ipykernel @@ -235,17 +204,13 @@ packaging==23.2 # superqt # vispy pandas==2.0.3 - # via - # PartSeg (setup.cfg) - # napari + # via napari parso==0.8.3 # via jedi partd==1.4.1 # via dask partsegcore-compiled-backend==0.15.1 - # via PartSeg (setup.cfg) partsegdata==0.10.0 - # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython pickleshare==0.7.5 @@ -259,13 +224,15 @@ pint==0.21.1 # via napari pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==4.1.0 +platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.3.0 - # via pytest -pooch==1.8.0 +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 # via scikit-image prompt-toolkit==3.0.43 # via ipython @@ -275,7 +242,6 @@ psutil==5.9.8 # napari psygnal==0.9.5 # via - # PartSeg (setup.cfg) # app-model # magicgui # napari @@ -288,8 +254,6 @@ pyconify==0.1.6 # via superqt pydantic==1.10.14 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # app-model # napari # npe2 @@ -298,67 +262,49 @@ pydantic-compat==0.1.2 # via app-model pygments==2.17.2 # via - # PartSeg (setup.cfg) # ipython # napari # qtconsole # rich # sphinx # superqt -pyinstaller==6.3.0 - # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2024.0 +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 # via pyinstaller pyopengl==3.1.7 # via napari pyopengl-accelerate==3.1.7 - # via PartSeg (setup.cfg) pyproject-hooks==1.0.0 # via build pyqt5==5.15.10 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) pyqt5-qt5==5.15.2 # via pyqt5 pyqt5-sip==12.13.0 - # via - # -r requirements/version_denylist.txt - # pyqt5 + # via pyqt5 pyqt6==6.6.1 - # via PartSeg (setup.cfg) -pyqt6-qt6==6.6.1 +pyqt6-qt6==6.6.2 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6==6.3.1 ; python_version < "3.10" - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) +pyside6==6.3.1 pyside6-addons==6.3.1 # via pyside6 pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==7.4.4 +pytest==8.0.2 # via - # PartSeg (setup.cfg) # pytest-qt # pytest-timeout -pytest-qt==4.3.1 - # via PartSeg (setup.cfg) +pytest-qt==4.4.0 pytest-timeout==2.2.0 - # via PartSeg (setup.cfg) python-dateutil==2.8.2 # via # jupyter-client # pandas -pytz==2023.3.post1 +pytz==2024.1 # via # babel # pandas @@ -375,49 +321,42 @@ pyzmq==25.1.2 # jupyter-client # qtconsole qtawesome==1.3.0 - # via PartSeg (setup.cfg) qtconsole==5.5.1 - # via - # PartSeg (setup.cfg) - # napari-console + # via napari-console qtpy==2.4.1 # via - # PartSeg (setup.cfg) # magicgui # napari # napari-console # qtawesome # qtconsole # superqt -referencing==0.32.1 +referencing==0.33.0 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via - # PartSeg (setup.cfg) # pooch # pyconify # sphinx -rich==13.7.0 +rich==13.7.1 # via npe2 -rpds-py==0.17.1 +rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.21.0 - # via - # PartSeg (setup.cfg) - # napari + # via napari scipy==1.10.1 # via - # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.2 +sentry-sdk==1.40.6 +setuptools==69.1.1 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) + # pyinstaller + # pyinstaller-hooks-contrib shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -426,18 +365,14 @@ shiboken6==6.3.1 # pyside6-addons # pyside6-essentials simpleitk==2.3.1 - # via PartSeg (setup.cfg) six==1.16.0 # via - # PartSeg (setup.cfg) # asttokens # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==4.5.0 - # via - # napari - # numpydoc +sphinx==7.1.2 + # via numpydoc sphinxcontrib-applehelp==1.0.4 # via sphinx sphinxcontrib-devhelp==1.0.2 @@ -454,14 +389,13 @@ stack-data==0.6.3 # via ipython superqt==0.6.1 # via - # PartSeg (setup.cfg) # magicgui # napari sympy==1.12 - # via PartSeg (setup.cfg) +tabulate==0.9.0 + # via numpydoc tifffile==2023.7.10 # via - # PartSeg (setup.cfg) # czifile # napari # oiffile @@ -470,11 +404,12 @@ tomli==2.0.1 # via # build # npe2 + # numpydoc # pyproject-hooks # pytest tomli-w==1.0.0 # via npe2 -toolz==0.12.0 +toolz==0.12.1 # via # dask # napari @@ -483,10 +418,9 @@ tornado==6.4 # via # ipykernel # jupyter-client -tqdm==4.66.1 +tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 - # via PartSeg (setup.cfg) traitlets==5.14.1 # via # comm @@ -498,7 +432,7 @@ traitlets==5.14.1 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.9.0 +typing-extensions==4.10.0 # via # app-model # ipython @@ -509,15 +443,14 @@ typing-extensions==4.9.0 # rich # superqt # typer -tzdata==2023.4 +tzdata==2024.1 # via pandas -urllib3==2.1.0 +urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.12.2 +vispy==0.14.1 # via - # PartSeg (setup.cfg) # napari # napari-svg wcwidth==0.2.13 @@ -525,16 +458,8 @@ wcwidth==0.2.13 wrapt==1.16.0 # via napari xlrd==2.0.1 - # via PartSeg (setup.cfg) -xlsxwriter==3.1.9 - # via PartSeg (setup.cfg) +xlsxwriter==3.2.0 zipp==3.17.0 # via # importlib-metadata # importlib-resources - -# The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.3 - # via - # pyinstaller - # pyinstaller-hooks-contrib diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index 6e5706fb1..fcf3785ff 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -1,9 +1,5 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile --allow-unsafe --extra=pyinstaller --extra=pyqt5 --extra=pyqt6 --extra=pyside2 --extra=pyside6 --extra=test --output-file=requirements/constraints_py3.9.txt --strip-extras requirements/version_denylist.txt setup.cfg -# +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.9 --output-file requirements/constraints_py3.9.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller alabaster==0.7.16 # via sphinx altgraph==0.17.4 @@ -12,7 +8,6 @@ app-model==0.2.4 # via napari appdirs==1.4.4 # via - # PartSeg (setup.cfg) # napari # npe2 asttokens==2.4.1 @@ -27,7 +22,7 @@ build==1.0.3 # via npe2 cachey==0.2.1 # via napari -certifi==2023.11.17 +certifi==2024.2.2 # via # napari # requests @@ -42,23 +37,18 @@ cloudpickle==3.0.0 # via dask comm==0.2.1 # via ipykernel -coverage==7.4.0 - # via PartSeg (setup.cfg) +coverage==7.4.3 czifile==2019.7.2 - # via PartSeg (setup.cfg) -dask==2024.1.0 - # via - # dask - # napari -debugpy==1.8.0 +dask==2024.2.1 + # via napari +debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 - # via PartSeg (setup.cfg) docstring-parser==0.15 # via magicgui -docutils==0.17.1 +docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -69,13 +59,11 @@ exceptiongroup==1.2.0 executing==2.0.1 # via stack-data fonticon-fontawesome6==6.4.0 - # via PartSeg (setup.cfg) freetype-py==2.4.0 # via vispy -fsspec==2023.12.2 +fsspec==2024.2.0 # via dask h5py==3.10.0 - # via PartSeg (setup.cfg) heapdict==1.0.1 # via cachey hsluv==5.0.4 @@ -83,11 +71,8 @@ hsluv==5.0.4 idna==3.6 # via requests imagecodecs==2024.1.1 - # via PartSeg (setup.cfg) -imageio==2.33.1 +imageio==2.34.0 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # napari # napari-svg # scikit-image @@ -105,14 +90,12 @@ in-n-out==0.1.9 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.0 +ipykernel==6.29.3 # via - # PartSeg (setup.cfg) # napari-console # qtconsole ipython==8.18.1 # via - # PartSeg (setup.cfg) # ipykernel # napari-console jedi==0.19.1 @@ -140,23 +123,17 @@ lazy-loader==0.3 # via # napari # scikit-image -local-migrator==0.1.9 - # via - # PartSeg (setup.cfg) - # nme +local-migrator==0.1.10 + # via nme locket==1.0.0 # via partd lxml==5.1.0 - # via PartSeg (setup.cfg) magicgui==0.8.1 - # via - # PartSeg (setup.cfg) - # napari + # via napari mahotas==1.4.13 - # via PartSeg (setup.cfg) markdown-it-py==3.0.0 # via rich -markupsafe==2.1.4 +markupsafe==2.1.5 # via jinja2 matplotlib-inline==0.1.6 # via @@ -168,8 +145,7 @@ mpmath==1.3.0 # via sympy mypy-extensions==1.0.0 # via psygnal -napari==0.4.18 - # via PartSeg (setup.cfg) +napari==0.4.19.post1 napari-console==0.0.9 # via napari napari-plugin-engine==0.2.0 @@ -183,14 +159,10 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 - # via PartSeg (setup.cfg) -npe2==0.7.3 - # via - # -r requirements/version_denylist.txt - # napari -numpy==1.26.3 +npe2==0.7.4 + # via napari +numpy==1.26.4 # via - # PartSeg (setup.cfg) # czifile # dask # h5py @@ -206,15 +178,12 @@ numpy==1.26.3 # scipy # tifffile # vispy -numpydoc==1.5.0 +numpydoc==1.6.0 # via napari oiffile==2023.8.30 - # via PartSeg (setup.cfg) openpyxl==3.1.2 - # via PartSeg (setup.cfg) packaging==23.2 # via - # PartSeg (setup.cfg) # build # dask # ipykernel @@ -229,18 +198,14 @@ packaging==23.2 # sphinx # superqt # vispy -pandas==2.2.0 - # via - # PartSeg (setup.cfg) - # napari +pandas==2.2.1 + # via napari parso==0.8.3 # via jedi partd==1.4.1 # via dask -partsegcore-compiled-backend==0.15.2 - # via PartSeg (setup.cfg) +partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 - # via PartSeg (setup.cfg) pexpect==4.9.0 # via ipython pillow==10.2.0 @@ -250,13 +215,15 @@ pillow==10.2.0 # scikit-image pint==0.23 # via napari -platformdirs==4.1.0 +platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.3.0 - # via pytest -pooch==1.8.0 +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 # via scikit-image prompt-toolkit==3.0.43 # via ipython @@ -266,7 +233,6 @@ psutil==5.9.8 # napari psygnal==0.9.5 # via - # PartSeg (setup.cfg) # app-model # magicgui # napari @@ -279,8 +245,6 @@ pyconify==0.1.6 # via superqt pydantic==1.10.14 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) # app-model # napari # npe2 @@ -289,67 +253,49 @@ pydantic-compat==0.1.2 # via app-model pygments==2.17.2 # via - # PartSeg (setup.cfg) # ipython # napari # qtconsole # rich # sphinx # superqt -pyinstaller==6.3.0 - # via PartSeg (setup.cfg) -pyinstaller-hooks-contrib==2024.0 +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 # via pyinstaller pyopengl==3.1.7 # via napari pyopengl-accelerate==3.1.7 - # via PartSeg (setup.cfg) pyproject-hooks==1.0.0 # via build pyqt5==5.15.10 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) pyqt5-qt5==5.15.2 # via pyqt5 pyqt5-sip==12.13.0 - # via - # -r requirements/version_denylist.txt - # pyqt5 + # via pyqt5 pyqt6==6.6.1 - # via PartSeg (setup.cfg) -pyqt6-qt6==6.6.1 +pyqt6-qt6==6.6.2 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.15.2.1 - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) -pyside6==6.3.1 ; python_version < "3.10" - # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) +pyside6==6.3.1 pyside6-addons==6.3.1 # via pyside6 pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==7.4.4 +pytest==8.0.2 # via - # PartSeg (setup.cfg) # pytest-qt # pytest-timeout -pytest-qt==4.3.1 - # via PartSeg (setup.cfg) +pytest-qt==4.4.0 pytest-timeout==2.2.0 - # via PartSeg (setup.cfg) python-dateutil==2.8.2 # via # jupyter-client # pandas -pytz==2023.3.post1 +pytz==2024.1 # via pandas pyyaml==6.0.1 # via @@ -362,49 +308,42 @@ pyzmq==25.1.2 # jupyter-client # qtconsole qtawesome==1.3.0 - # via PartSeg (setup.cfg) qtconsole==5.5.1 - # via - # PartSeg (setup.cfg) - # napari-console + # via napari-console qtpy==2.4.1 # via - # PartSeg (setup.cfg) # magicgui # napari # napari-console # qtawesome # qtconsole # superqt -referencing==0.32.1 +referencing==0.33.0 # via # jsonschema # jsonschema-specifications requests==2.31.0 # via - # PartSeg (setup.cfg) # pooch # pyconify # sphinx -rich==13.7.0 +rich==13.7.1 # via npe2 -rpds-py==0.17.1 +rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 - # via - # PartSeg (setup.cfg) - # napari + # via napari scipy==1.12.0 # via - # PartSeg (setup.cfg) # napari # scikit-image -sentry-sdk==1.39.2 +sentry-sdk==1.40.6 +setuptools==69.1.1 # via - # -r requirements/version_denylist.txt - # PartSeg (setup.cfg) + # pyinstaller + # pyinstaller-hooks-contrib shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -413,18 +352,14 @@ shiboken6==6.3.1 # pyside6-addons # pyside6-essentials simpleitk==2.3.1 - # via PartSeg (setup.cfg) six==1.16.0 # via - # PartSeg (setup.cfg) # asttokens # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==4.5.0 - # via - # napari - # numpydoc +sphinx==7.2.6 + # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 @@ -441,14 +376,13 @@ stack-data==0.6.3 # via ipython superqt==0.6.1 # via - # PartSeg (setup.cfg) # magicgui # napari sympy==1.12 - # via PartSeg (setup.cfg) -tifffile==2023.12.9 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 # via - # PartSeg (setup.cfg) # czifile # napari # oiffile @@ -457,11 +391,12 @@ tomli==2.0.1 # via # build # npe2 + # numpydoc # pyproject-hooks # pytest tomli-w==1.0.0 # via npe2 -toolz==0.12.0 +toolz==0.12.1 # via # dask # napari @@ -470,10 +405,9 @@ tornado==6.4 # via # ipykernel # jupyter-client -tqdm==4.66.1 +tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 - # via PartSeg (setup.cfg) traitlets==5.14.1 # via # comm @@ -485,7 +419,7 @@ traitlets==5.14.1 # qtconsole typer==0.9.0 # via npe2 -typing-extensions==4.9.0 +typing-extensions==4.10.0 # via # app-model # ipython @@ -496,15 +430,14 @@ typing-extensions==4.9.0 # pydantic # superqt # typer -tzdata==2023.4 +tzdata==2024.1 # via pandas -urllib3==2.1.0 +urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.12.2 +vispy==0.14.1 # via - # PartSeg (setup.cfg) # napari # napari-svg wcwidth==0.2.13 @@ -512,14 +445,6 @@ wcwidth==0.2.13 wrapt==1.16.0 # via napari xlrd==2.0.1 - # via PartSeg (setup.cfg) -xlsxwriter==3.1.9 - # via PartSeg (setup.cfg) +xlsxwriter==3.2.0 zipp==3.17.0 # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -setuptools==69.0.3 - # via - # pyinstaller - # pyinstaller-hooks-contrib From c1eb40e846795824721ad35a21a84fcabda1dc1e Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 29 Feb 2024 14:04:13 +0100 Subject: [PATCH 38/51] ci: block using `mpmath==1.4.0a0` and `sentry-sdk` 2.0.0a1/a2 in pre-test (#1085) ## Summary by CodeRabbit - **Chores** - Improved the pre-release testing workflow to include additional checks for compatibility issues. - Added new requirements `mpmath` and `sentry-sdk` with constraints to the test configuration. --- .github/workflows/test_prereleases.yml | 4 +++- requirements/pre_test_problematic_version.txt | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 requirements/pre_test_problematic_version.txt diff --git a/.github/workflows/test_prereleases.yml b/.github/workflows/test_prereleases.yml index 03a2f9f4e..7ae2e2c3c 100644 --- a/.github/workflows/test_prereleases.yml +++ b/.github/workflows/test_prereleases.yml @@ -14,6 +14,7 @@ on: paths: - '.github/workflows/test_prereleases.yml' - 'pyproject.toml' + - 'requirements/pre_test_problematic_version.txt' # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -83,6 +84,7 @@ jobs: PYVISTA_OFF_SCREEN: True # required for opengl on windows NAPARI: latest BACKEND: PyQt5 + PIP_CONSTRAINT: requirements/pre_test_problematic_version.txt # If something goes wrong, we can open an issue in the repo - name: Report Failures @@ -114,7 +116,7 @@ jobs: pip install pip-tools - name: Compile and install PyInstaller requirements run: | - pip-compile --upgrade -o requirements.txt pyproject.toml --extra pyinstaller --pre + pip-compile --upgrade -o requirements.txt pyproject.toml requirements/pre_test_problematic_version.txt --extra pyinstaller --pre pip-sync pip install . - name: upload requirements diff --git a/requirements/pre_test_problematic_version.txt b/requirements/pre_test_problematic_version.txt new file mode 100644 index 000000000..3803d1cb6 --- /dev/null +++ b/requirements/pre_test_problematic_version.txt @@ -0,0 +1,2 @@ +mpmath!=1.4.0a0 +sentry-sdk!=2.0.0a1,!=2.0.0a2 From c8732397793a38b08465efe4380d627698517198 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Tue, 5 Mar 2024 14:31:05 +0100 Subject: [PATCH 39/51] feat: pydantic 2 compatybility (#1084) ## Summary by CodeRabbit - **Refactor** - Improved compatibility with different Pydantic versions by modifying import strategies and adding new functions. - **Tests** - Added tests for new conversion functionalities and dictionary dumping in `ROIExtractionProfile`. --- .github/workflows/base_test_workflow.yml | 6 +- .github/workflows/test_napari_repo.yml | 4 +- .github/workflows/test_napari_widgets.yml | 6 +- .github/workflows/tests.yml | 8 +- .github/workflows/upgrade-dependencies.yml | 1 + .../PartSeg/common_backend/base_argparser.py | 20 +- .../common_gui/algorithms_description.py | 6 +- .../PartSegCore/algorithm_describe_base.py | 159 +++++- .../image_transforming/image_projection.py | 4 +- package/PartSegCore/utils.py | 24 +- package/PartSegImage/channel_class.py | 35 +- .../tests/test_PartSeg/test_common_backend.py | 7 +- package/tests/test_PartSeg/test_common_gui.py | 15 +- package/tests/test_PartSeg/test_sentry.py | 2 +- .../test_algorithm_describe_base.py | 30 +- .../test_PartSegCore/test_analysis_batch.py | 10 +- .../test_PartSegImage/test_channel_class.py | 56 +++ package/tests/test_PartSegImage/test_image.py | 8 - pyproject.toml | 4 +- requirements/constraints_py3.10.txt | 7 +- .../constraints_py3.10_pydantic_1.txt | 443 +++++++++++++++++ requirements/constraints_py3.11.txt | 7 +- requirements/constraints_py3.11_docs.txt | 14 +- .../constraints_py3.11_pydantic_1.txt | 432 ++++++++++++++++ requirements/constraints_py3.8.txt | 8 +- requirements/constraints_py3.8_pydantic_1.txt | 465 ++++++++++++++++++ requirements/constraints_py3.9.txt | 7 +- requirements/constraints_py3.9_pydantic_1.txt | 450 +++++++++++++++++ requirements/pydantic_1.txt | 1 + requirements/version_denylist.txt | 1 - tox.ini | 17 +- 31 files changed, 2178 insertions(+), 79 deletions(-) create mode 100644 package/tests/test_PartSegImage/test_channel_class.py create mode 100644 requirements/constraints_py3.10_pydantic_1.txt create mode 100644 requirements/constraints_py3.11_pydantic_1.txt create mode 100644 requirements/constraints_py3.8_pydantic_1.txt create mode 100644 requirements/constraints_py3.9_pydantic_1.txt create mode 100644 requirements/pydantic_1.txt diff --git a/.github/workflows/base_test_workflow.yml b/.github/workflows/base_test_workflow.yml index 44469e606..c071407f7 100644 --- a/.github/workflows/base_test_workflow.yml +++ b/.github/workflows/base_test_workflow.yml @@ -34,6 +34,10 @@ on: required: false type: number default: 60 + pydantic: + required: false + type: string + default: "" jobs: @@ -90,7 +94,7 @@ jobs: PYVISTA_OFF_SCREEN: True # required for opengl on windows NAPARI: ${{ inputs.napari }} BACKEND: ${{ inputs.qt_backend }} - PIP_CONSTRAINT: requirements/constraints_py${{ inputs.python_version }}.txt + PIP_CONSTRAINT: requirements/constraints_py${{ inputs.python_version }}${{ inputs.pydantic }}.txt - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/test_napari_repo.yml b/.github/workflows/test_napari_repo.yml index 1c38781aa..0051e217b 100644 --- a/.github/workflows/test_napari_repo.yml +++ b/.github/workflows/test_napari_repo.yml @@ -29,8 +29,8 @@ jobs: fail-fast: false matrix: platform: [ ubuntu-22.04 ] - python: ['3.8', '3.9' , '3.10'] - napari_version: [repo] + python: ['3.8', '3.9' , '3.10', '3.11'] + napari_version: ['repo'] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test_napari_widgets.yml b/.github/workflows/test_napari_widgets.yml index 25b03f79f..360551b7e 100644 --- a/.github/workflows/test_napari_widgets.yml +++ b/.github/workflows/test_napari_widgets.yml @@ -27,7 +27,7 @@ jobs: with: python_version: "3.10" os: ${{ matrix.os }} - napari: "napari417" + napari: "napari419" qt_backend: ${{ matrix.qt_backend }} timeout: 10 @@ -36,10 +36,10 @@ jobs: strategy: fail-fast: false matrix: - napari: ["napari414", "napari415", "napari416"] + napari: ["napari417", "napari418"] qt_backend: ["PyQt5"] include: - - napari: "napari414" + - napari: "napari417" qt_backend: "PySide2" if: github.event_name == 'push' uses: ./.github/workflows/base_test_workflow.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 30442c574..caef4ff85 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,7 +39,7 @@ jobs: strategy: fail-fast: false matrix: - python_version: ["3.8", "3.9", "3.10"] + python_version: ["3.8", "3.9", "3.10", "3.11"] os: ["ubuntu-20.04"] qt_backend: ["PyQt5"] tox_args: [ "" ] @@ -56,13 +56,13 @@ jobs: - python_version: "3.9" os: "ubuntu-22.04" qt_backend: "PySide6" - - python_version: "3.9" + - python_version: "3.10" os: "ubuntu-22.04" qt_backend: "PyQt6" - - python_version: "3.11" + - python_version: "3.10" os: "ubuntu-22.04" qt_backend: "PyQt5" - tox_args: "-vv -e py311-PyQt5-all" + pydantic: "_pydantic_1" with: test_data: True python_version: ${{ matrix.python_version }} diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index e73c8f9d9..fff2e32ab 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -37,6 +37,7 @@ jobs: for pyv in 3.8 3.9 3.10 3.11; 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.11 --upgrade --output-file requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --extra docs --extra pyqt6 # END PYTHON DEPENDENCIES diff --git a/package/PartSeg/common_backend/base_argparser.py b/package/PartSeg/common_backend/base_argparser.py index 0e5b151aa..311d1941d 100644 --- a/package/PartSeg/common_backend/base_argparser.py +++ b/package/PartSeg/common_backend/base_argparser.py @@ -9,17 +9,14 @@ from importlib.metadata import version as package_version from typing import Optional, Sequence -import numpy as np import sentry_sdk import sentry_sdk.serializer import sentry_sdk.utils -from napari.layers import Image from packaging.version import parse as parse_version -from sentry_sdk.utils import safe_repr as _safe_repr from PartSeg import __version__, state_store from PartSeg.common_backend.except_hook import my_excepthook -from PartSegCore.utils import numpy_repr +from PartSegCore.utils import safe_repr SENTRY_GE_1_29 = parse_version(package_version("sentry_sdk")) >= parse_version("1.29.0") @@ -155,18 +152,3 @@ def _setup_sentry(): # pragma: no cover "id": zlib.adler32(f"{getpass.getuser()}#{platform.node()}".encode()), } ) - - -def napari_image_repr(image: Image) -> str: - return ( - f"" - ) - - -def safe_repr(val): - if isinstance(val, np.ndarray): - return numpy_repr(val) - if isinstance(val, Image): - return napari_image_repr(val) - return _safe_repr(val) diff --git a/package/PartSeg/common_gui/algorithms_description.py b/package/PartSeg/common_gui/algorithms_description.py index 1ae140ed4..15a9cec1e 100644 --- a/package/PartSeg/common_gui/algorithms_description.py +++ b/package/PartSeg/common_gui/algorithms_description.py @@ -10,7 +10,6 @@ from magicgui.widgets import ComboBox, EmptyWidget, Widget, create_widget from napari.layers.base import Layer from pydantic import BaseModel -from pydantic.fields import UndefinedType from qtpy.QtCore import QMargins, QObject, Signal from qtpy.QtGui import QHideEvent, QPainter, QPaintEvent, QResizeEvent from qtpy.QtWidgets import ( @@ -50,6 +49,11 @@ ) from PartSegImage import Channel, Image +try: + from pydantic.fields import UndefinedType +except ImportError: # pragma: no cover + from pydantic_core import PydanticUndefinedType as UndefinedType + logger = logging.getLogger(__name__) ignore_logger(__name__) diff --git a/package/PartSegCore/algorithm_describe_base.py b/package/PartSegCore/algorithm_describe_base.py index c47a15cf0..6125b2332 100644 --- a/package/PartSegCore/algorithm_describe_base.py +++ b/package/PartSegCore/algorithm_describe_base.py @@ -1,20 +1,41 @@ import inspect +import math import textwrap import typing import warnings from abc import ABC, ABCMeta, abstractmethod from functools import wraps +from importlib.metadata import version from local_migrator import REGISTER, class_to_str from pydantic import BaseModel as PydanticBaseModel from pydantic import create_model, validator -from pydantic.fields import ModelField, UndefinedType -from pydantic.main import ModelMetaclass +from pydantic.fields import FieldInfo from typing_extensions import Annotated from PartSegCore.utils import BaseModel from PartSegImage import Channel +if typing.TYPE_CHECKING: + from pydantic.fields import ModelField + +try: + # pydantic 1 + from pydantic.fields import UndefinedType + from pydantic.main import ModelMetaclass + + def field_serializer(_): + def decorator(func): + return func + + return decorator + +except ImportError: + # pydantic 2 + from pydantic import field_serializer + from pydantic._internal._model_construction import ModelMetaclass + from pydantic_core import PydanticUndefinedType as UndefinedType + class AlgorithmDescribeNotFound(Exception): """ @@ -379,11 +400,14 @@ class AlgorithmSelection(BaseModel, metaclass=AddRegisterMeta): # pylint: disab """ name: str - values: typing.Union[PydanticBaseModel, typing.Dict[str, typing.Any]] + values: typing.Union[typing.Dict[str, typing.Any], PydanticBaseModel] class_path: str = "" if typing.TYPE_CHECKING: __register__: Register + class Config: + smart_union = True + @validator("name") def check_name(cls, v): if v not in cls.__register__: @@ -397,6 +421,12 @@ def update_class_path(cls, v, values): klass = cls.__register__[values["name"]] return class_to_str(klass) + @field_serializer("values") + def val_serializer(self, value, _info): + if isinstance(value, PydanticBaseModel): + return value.dict() + return value + @validator("values", pre=True) def update_values(cls, v, values): # FIXME add better strategy to get proper class when there is conflict of names @@ -548,7 +578,80 @@ def __eq__(self, other): ) -def _field_to_algorithm_property(name: str, field: "ModelField"): +def _next_after(type_, value, inf): + if issubclass(type_, int): + if inf == math.inf: + return value + 1 + return value - 1 + if hasattr(math, "nextafter"): + # TODO fix after drop python 3.8 + return math.nextafter(value, inf) + return value + + +def _next_after_with_none(type_, value, inf): + if value is None: + return None + return _next_after(type_, value, inf) + + +def _calc_value_range(field_info: FieldInfo): + if field_info.metadata is None: + return (0, 1000) + + import annotated_types as at + + value_range = (0, 1000) + for el in field_info.metadata: + if isinstance(el, at.Ge): + value_range = el.ge, value_range[1] + elif isinstance(el, at.Gt): + value_range = _next_after(field_info.annotation, el.gt, math.inf), value_range[1] + elif isinstance(el, at.Le): + value_range = value_range[0], el.le + elif isinstance(el, at.Lt): + value_range = value_range[0], _next_after(field_info.annotation, el.lt, -math.inf) + return value_range + + +def _field_to_algorithm_property_pydantic_2(name: str, field_info: FieldInfo): + user_name = field_info.title + + value_range = None + possible_values = None + + value_type = field_info.annotation + default_value = field_info.default + help_text = field_info.description + if user_name is None: + user_name = name.replace("_", " ").capitalize() + if not hasattr(value_type, "__origin__"): + if issubclass(value_type, (int, float)): + value_range = _calc_value_range(field_info) + + if issubclass(field_info.annotation, AlgorithmSelection): + value_type = AlgorithmDescribeBase + if isinstance(field_info.default, UndefinedType): + default_value = field_info.default_factory().name + else: + default_value = field_info.default.name + possible_values = field_info.annotation.__register__ + + extra = field_info.json_schema_extra or {} + + return AlgorithmProperty( + name=name, + user_name=user_name, + default_value=default_value, + options_range=value_range, + value_type=value_type, + possible_values=possible_values, + help_text=help_text, + mgi_options=extra.get("options", {}), + ) + + +def _field_to_algorithm_property_pydantic_1(name: str, field: "ModelField"): user_name = field.field_info.title value_range = None possible_values = None @@ -561,8 +664,8 @@ def _field_to_algorithm_property(name: str, field: "ModelField"): if not hasattr(field.type_, "__origin__"): if issubclass(field.type_, (int, float)): value_range = ( - field.field_info.ge or field.field_info.gt or 0, - field.field_info.le or field.field_info.lt or 1000, + field.field_info.ge or _next_after_with_none(field.type_, field.field_info.gt, math.inf) or 0, + field.field_info.le or _next_after_with_none(field.type_, field.field_info.lt, -math.inf) or 1000, ) if issubclass(field.type_, AlgorithmSelection): value_type = AlgorithmDescribeBase @@ -584,7 +687,9 @@ def _field_to_algorithm_property(name: str, field: "ModelField"): ) -def base_model_to_algorithm_property(obj: typing.Type[BaseModel]) -> typing.List[typing.Union[str, AlgorithmProperty]]: +def base_model_to_algorithm_property_pydantic_1( + obj: typing.Type[BaseModel], +) -> typing.List[typing.Union[str, AlgorithmProperty]]: """ Convert pydantic model to list of AlgorithmPropert nad strings. @@ -611,3 +716,43 @@ def base_model_to_algorithm_property(obj: typing.Type[BaseModel]) -> typing.List if "suffix" in value.field_info.extra: res.insert(pos + 1, value.field_info.extra["suffix"]) return res + + +def base_model_to_algorithm_property_pydantic_2( + obj: typing.Type[BaseModel], +) -> typing.List[typing.Union[str, AlgorithmProperty]]: + """ + Convert pydantic model to list of AlgorithmPropert nad strings. + + :param obj: + :return: + """ + res = [] + field_info: FieldInfo + if hasattr(obj, "header") and obj.header(): + res.append(obj.header()) + for name, field_info in obj.__fields__.items(): + ap = _field_to_algorithm_property(name, field_info) + extra = field_info.json_schema_extra or {} + if extra.get("hidden", False): + continue + pos = len(res) + if "position" in extra: + pos = extra["position"] + if "prefix" in extra: + res.insert(pos, extra["prefix"]) + pos += 1 + + res.insert(pos, ap) + + if "suffix" in extra: + res.insert(pos + 1, extra["suffix"]) + return res + + +if version("pydantic") < "2": + _field_to_algorithm_property = _field_to_algorithm_property_pydantic_1 + base_model_to_algorithm_property = base_model_to_algorithm_property_pydantic_1 +else: + _field_to_algorithm_property = _field_to_algorithm_property_pydantic_2 + base_model_to_algorithm_property = base_model_to_algorithm_property_pydantic_2 diff --git a/package/PartSegCore/image_transforming/image_projection.py b/package/PartSegCore/image_transforming/image_projection.py index 76c86e13b..82af1ea35 100644 --- a/package/PartSegCore/image_transforming/image_projection.py +++ b/package/PartSegCore/image_transforming/image_projection.py @@ -19,8 +19,8 @@ class ProjectionType(Enum): class ImageProjectionParams(BaseModel): projection_type: ProjectionType = Field(ProjectionType.MAX, suffix="Mask and ROI projection will always use max") - keep_mask = False - keep_roi = False + keep_mask: bool = False + keep_roi: bool = False def _calc_target_shape(image: Image): diff --git a/package/PartSegCore/utils.py b/package/PartSegCore/utils.py index 2a41ee40f..4fe110377 100644 --- a/package/PartSegCore/utils.py +++ b/package/PartSegCore/utils.py @@ -10,12 +10,15 @@ from types import MethodType import numpy as np +from local_migrator import register_class +from psygnal import Signal from pydantic import BaseModel as PydanticBaseModel +from sentry_sdk.utils import safe_repr as _safe_repr __author__ = "Grzegorz Bokota" -from local_migrator import register_class -from psygnal import Signal +if typing.TYPE_CHECKING: + from napari.layers import Image def bisect(arr, val, comp): @@ -461,3 +464,20 @@ def iterate_names(base_name: str, data_dict, max_length=None) -> typing.Optional if res_name not in data_dict: return res_name return None + + +def napari_image_repr(image: "Image") -> str: + return ( + f"" + ) + + +def safe_repr(val): + from napari.layers import Image + + if isinstance(val, np.ndarray): + return numpy_repr(val) + if isinstance(val, Image): + return napari_image_repr(val) + return _safe_repr(val) diff --git a/package/PartSegImage/channel_class.py b/package/PartSegImage/channel_class.py index 581827aa2..5c20ed6a3 100644 --- a/package/PartSegImage/channel_class.py +++ b/package/PartSegImage/channel_class.py @@ -1,7 +1,18 @@ -from typing import Union +from importlib.metadata import PackageNotFoundError, version +from typing import TYPE_CHECKING, Dict, Union +try: + PYDANTIC_2 = version("pydantic") >= "2.0.0" +except PackageNotFoundError: # pragma: no cover + PYDANTIC_2 = False -def check_type(value): + +if TYPE_CHECKING: + from pydantic import GetJsonSchemaHandler + from pydantic_core.core_schema import CoreSchema + + +def check_type(value): # type: ignore [misc] if isinstance(value, Channel): return value if value.__class__.__module__.startswith("napari"): @@ -11,6 +22,17 @@ def check_type(value): 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. @@ -46,11 +68,18 @@ def as_dict(self): @classmethod def __get_validators__(cls): - yield check_type + yield check_type_ @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"}]}} + + @classmethod + def __get_pydantic_json_schema__(cls, core_schema: "CoreSchema", handler: "GetJsonSchemaHandler"): + json_schema: Dict[str, Union[str, dict]] = {} + cls.__modify_schema__(json_schema) + return json_schema diff --git a/package/tests/test_PartSeg/test_common_backend.py b/package/tests/test_PartSeg/test_common_backend.py index c77996583..4a54ac511 100644 --- a/package/tests/test_PartSeg/test_common_backend.py +++ b/package/tests/test_PartSeg/test_common_backend.py @@ -16,6 +16,7 @@ from packaging.version import parse from qtpy.QtWidgets import QMessageBox +import PartSegCore.utils from PartSeg import state_store from PartSeg.common_backend import ( base_argparser, @@ -188,12 +189,12 @@ def test_custom_parser(self, monkeypatch): parser.parse_args([]) def test_safe_repr(self): - assert base_argparser.safe_repr(1) == "1" - assert base_argparser.safe_repr(np.arange(3)) == "array([0, 1, 2])" + assert PartSegCore.utils.safe_repr(1) == "1" + assert PartSegCore.utils.safe_repr(np.arange(3)) == "array([0, 1, 2])" def test_safe_repr_napari_image(self): assert ( - base_argparser.safe_repr(napari.layers.Image(np.zeros((10, 10, 5)))) + PartSegCore.utils.safe_repr(napari.layers.Image(np.zeros((10, 10, 5)))) == "" ) diff --git a/package/tests/test_PartSeg/test_common_gui.py b/package/tests/test_PartSeg/test_common_gui.py index d76c21fb3..d66e26df1 100644 --- a/package/tests/test_PartSeg/test_common_gui.py +++ b/package/tests/test_PartSeg/test_common_gui.py @@ -885,6 +885,7 @@ class SampleModel(BaseModel): qtbot.add_widget(form) assert form.has_elements() assert isinstance(form.get_values(), SampleModel) + assert form.get_values().check_selection.values == {"field": 1} assert form.get_values() == SampleModel( field1=10, check_selection=SampleSelection(name="1", values={"field": 1}) ) @@ -1096,8 +1097,18 @@ class EnumQtAl(Enum): class ModelQtAl(BaseModel): - field1 = 1 - field2 = 2.0 + field1: int = 1 + field2: float = 2.0 + __hash__ = None + + def __eq__(self, other): # pragma: no cover + """For testing purposes only""" + if isinstance(other, dict): + try: + return self.field1 == other["field1"] and self.field2 == other["field2"] + except KeyError: + return False + return super().__eq__(other) class TestQtAlgorithmProperty: diff --git a/package/tests/test_PartSeg/test_sentry.py b/package/tests/test_PartSeg/test_sentry.py index ae0369fbe..a468eb815 100644 --- a/package/tests/test_PartSeg/test_sentry.py +++ b/package/tests/test_PartSeg/test_sentry.py @@ -11,8 +11,8 @@ from sentry_sdk.hub import Hub from sentry_sdk.serializer import serialize -from PartSeg.common_backend.base_argparser import safe_repr from PartSegCore.analysis.batch_processing.batch_backend import prepare_error_data +from PartSegCore.utils import safe_repr SENTRY_GE_1_29 = parse_version(package_version("sentry_sdk")) >= parse_version("1.29.0") diff --git a/package/tests/test_PartSegCore/test_algorithm_describe_base.py b/package/tests/test_PartSegCore/test_algorithm_describe_base.py index bee4ad813..baba37d35 100644 --- a/package/tests/test_PartSegCore/test_algorithm_describe_base.py +++ b/package/tests/test_PartSegCore/test_algorithm_describe_base.py @@ -1,4 +1,6 @@ # pylint: disable=no-self-use +import math +import sys import typing from enum import Enum @@ -350,6 +352,23 @@ class Sample(BaseModel): assert converted[3].user_name == "Channel" +@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python 3.9 or higher") +def test_gt_lt_conversion(): + class Sample(BaseModel): + field1: int = Field(0, le=100, ge=0, title="Field 1") + field2: int = Field(0, lt=100, gt=0, title="Field 2") + field3: float = Field(0, le=100, ge=0, title="Field 3") + field4: float = Field(0, lt=100, gt=0, title="Field 4") + field5: int = Field(0, title="Field 5") + + converted = base_model_to_algorithm_property(Sample) + assert converted[0].range == (0, 100) + assert converted[1].range == (1, 99) + assert converted[2].range == (0, 100) + assert converted[3].range == (math.nextafter(0, math.inf), math.nextafter(100, -math.inf)) + assert converted[4].range == (0, 1000) + + def test_base_model_to_algorithm_property_algorithm_describe_base(): class SampleSelection(AlgorithmSelection): pass @@ -490,7 +509,7 @@ def get_name(cls) -> str: assert "ceeeec" in SampleAlgorithm.get_doc_from_fields() assert "(default values: 1)" in SampleAlgorithm.get_doc_from_fields() assert len(SampleAlgorithm.get_fields_dict()) == 1 - assert SampleAlgorithm.get_default_values() == {"name": 1} + assert SampleAlgorithm.get_default_values() == DataModel(name=1) def test_new_style_algorithm_with_old_style_subclass(self): class DataModel(BaseModel): @@ -537,6 +556,15 @@ def test_roi_extraction_profile(self): with pytest.warns(FutureWarning): ROIExtractionProfile("aaa", "aaa", {}) + def test_dump_dict(self): + prof = ROIExtractionProfile( + name="aaa", + algorithm=LowerThresholdAlgorithm.get_name(), + values=LowerThresholdAlgorithm.get_default_values(), + ) + assert prof.values.threshold.values.threshold == 8000 + assert prof.dict()["values"]["threshold"]["values"]["threshold"] == 8000 + def test_pretty_print(self): prof1 = ROIExtractionProfile(name="aaa", algorithm="Lower threshold", values={}) diff --git a/package/tests/test_PartSegCore/test_analysis_batch.py b/package/tests/test_PartSegCore/test_analysis_batch.py index 8c97d11b2..a3ccce1e7 100644 --- a/package/tests/test_PartSegCore/test_analysis_batch.py +++ b/package/tests/test_PartSegCore/test_analysis_batch.py @@ -1,5 +1,5 @@ # pylint: disable=no-self-use - +import json import os import shutil import sys @@ -42,6 +42,7 @@ from PartSegCore.analysis.save_functions import save_dict from PartSegCore.image_operations import RadiusType from PartSegCore.io_utils import LoadPlanExcel, SaveBase +from PartSegCore.json_hooks import PartSegEncoder from PartSegCore.mask.io_functions import MaskProjectTuple, SaveROI, SaveROIOptions from PartSegCore.mask_create import MaskProperty from PartSegCore.roi_info import ROIInfo @@ -560,7 +561,7 @@ def test_full_pipeline_long(self, tmpdir, data_test_dir, monkeypatch, calculatio assert str(data["test"]) == str(calculation_plan_long) df2 = pd.read_excel(res_path, header=[0, 1], engine=ENGINE, sheet_name="info test") - assert df2.shape == (154, 3) + assert df2.shape == (152, 3) @pytest.mark.filterwarnings("ignore:This method will be removed") def test_full_pipeline_error(self, tmp_path, data_test_dir, monkeypatch, calculation_plan): @@ -814,3 +815,8 @@ def test_add_data(self): assert sheet_data.get_data_to_write()[0] == "test_name" assert "wait_rows=0" in repr(sheet_data) + + +def test_calculation_plan_serialize(calculation_plan_long): + text = json.dumps(calculation_plan_long, cls=PartSegEncoder, indent=2) + assert text.count("\n") == 7627 diff --git a/package/tests/test_PartSegImage/test_channel_class.py b/package/tests/test_PartSegImage/test_channel_class.py new file mode 100644 index 000000000..99000959e --- /dev/null +++ b/package/tests/test_PartSegImage/test_channel_class.py @@ -0,0 +1,56 @@ +import json + +import pytest +from pydantic import BaseModel + +from PartSegImage import Channel + + +def test_channel_from_channel(): + ch1 = Channel(1) + ch2 = Channel(2) + ch3 = Channel(ch1) + assert ch1 == ch3 + assert ch1 != ch2 + + +def test_representation(): + ch1 = Channel(1) + assert str(ch1) == "2" + assert repr(ch1) == "" + + +def test_as_dict(): + ch1 = Channel(1) + assert ch1.as_dict() == {"value": 1} + ch2 = Channel(**ch1.as_dict()) + assert ch1 == ch2 + + +class Model(BaseModel): + channel: Channel + + +MODEL_SCHEMA = { + "title": "Model", + "type": "object", + "properties": { + "channel": { + "title": "Channel", + "type": "object", + "properties": {"value": {"title": "value", "anyOf": [{"type": "string"}, {"type": "integer"}]}}, + } + }, + "required": ["channel"], +} + + +@pytest.mark.parametrize("value", [Channel(1), 1, Channel("1"), "1"], ids=lambda x: f"value={x!r}") +def test_as_pydantic_field(value): + model = Model(channel=value) + assert isinstance(model.channel, Channel) + assert model.channel == Channel(value) + + +def test_json_schema(): + assert json.loads(Model.schema_json()) == MODEL_SCHEMA diff --git a/package/tests/test_PartSegImage/test_image.py b/package/tests/test_PartSegImage/test_image.py index cc1bb1da0..f0e405ab4 100644 --- a/package/tests/test_PartSegImage/test_image.py +++ b/package/tests/test_PartSegImage/test_image.py @@ -590,11 +590,3 @@ def test_str_and_repr_mask_presence(): assert "mask: True" in str(image) assert "mask=True" in repr(image) - - -def test_channel_from_channel(): - ch1 = Channel(1) - ch2 = Channel(2) - ch3 = Channel(ch1) - assert ch1 == ch3 - assert ch1 != ch2 diff --git a/pyproject.toml b/pyproject.toml index 1d825f27a..7407e7399 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ dependencies = [ "packaging>=20.0", "pandas>=1.1.0", "psygnal>=0.3.1", - "pydantic>=1.8.1,<2", + "pydantic>=1.9.1", "pygments>=2.4.0", "qtconsole>=4.7.7", "requests>=2.18.0", @@ -112,7 +112,7 @@ pyinstaller = [ "PyOpenGL-accelerate>=3.1.5", "PyQt5!=5.15.0,>=5.12.3", "PyInstaller", - "pydantic<2", + "pydantic", ] pyqt = [ "PyQt5!=5.15.0,>=5.12.3", diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 22c121474..68143e03f 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -4,6 +4,8 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller +annotated-types==0.6.0 + # via pydantic app-model==0.2.4 # via napari appdirs==1.4.4 @@ -237,7 +239,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==2.6.3 # via # app-model # napari @@ -245,6 +247,8 @@ pydantic==1.10.14 # pydantic-compat pydantic-compat==0.1.2 # via app-model +pydantic-core==2.16.3 + # via pydantic pygments==2.17.2 # via # ipython @@ -421,6 +425,7 @@ typing-extensions==4.10.0 # pint # psygnal # pydantic + # pydantic-core # superqt # typer tzdata==2024.1 diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt new file mode 100644 index 000000000..b236e430c --- /dev/null +++ b/requirements/constraints_py3.10_pydantic_1.txt @@ -0,0 +1,443 @@ +# 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 pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller --constraint requirements/pydantic_1.txt +alabaster==0.7.16 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +app-model==0.2.4 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +build==1.0.3 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.1 + # via ipykernel +coverage==7.4.3 +czifile==2019.7.2 +dask==2024.2.1 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.15 + # via magicgui +docutils==0.20.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +exceptiongroup==1.2.0 + # via + # ipython + # pytest +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.2.0 + # via dask +h5py==3.10.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.6 + # via requests +imagecodecs==2024.1.1 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +importlib-metadata==7.0.1 + # via dask +in-n-out==0.1.9 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.3 + # via + # napari-console + # qtconsole +ipython==8.22.1 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via + # numpydoc + # sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.1 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.3 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.1.0 +magicgui==0.8.1 + # via napari +mahotas==1.4.13 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +mypy-extensions==1.0.0 + # via psygnal +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.2.1 + # via scikit-image +nme==0.1.8 +npe2==0.7.4 + # via napari +numpy==1.26.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.6.0 + # via napari +oiffile==2023.8.30 +openpyxl==3.1.2 +packaging==23.2 + # via + # build + # dask + # ipykernel + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # superqt + # vispy +pandas==2.2.1 + # via napari +parso==0.8.3 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.6 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pillow==10.2.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.9.5 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.14 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.2 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.15.2.1 +pyside6==6.6.2 +pyside6-addons==6.6.2 + # via pyside6 +pyside6-essentials==6.6.2 + # via + # pyside6 + # pyside6-addons +pytest==8.0.2 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.2.0 +python-dateutil==2.8.2 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==25.1.2 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.0 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.33.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via npe2 +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.22.0 + # via napari +scipy==1.12.0 + # via + # napari + # scikit-image +sentry-sdk==1.40.6 +setuptools==69.1.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shiboken2==5.15.2.1 + # via pyside2 +shiboken6==6.6.2 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.2.6 + # via numpydoc +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.1 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli==2.0.1 + # via + # build + # npe2 + # numpydoc + # pyproject-hooks + # pytest +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.1 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.9.0 + # via npe2 +typing-extensions==4.10.0 + # via + # app-model + # magicgui + # napari + # pint + # psygnal + # pydantic + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.1 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 +zipp==3.17.0 + # via importlib-metadata diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 3e3fe275f..4cc8c75a1 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -4,6 +4,8 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller +annotated-types==0.6.0 + # via pydantic app-model==0.2.4 # via napari appdirs==1.4.4 @@ -233,7 +235,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==2.6.3 # via # app-model # napari @@ -241,6 +243,8 @@ pydantic==1.10.14 # pydantic-compat pydantic-compat==0.1.2 # via app-model +pydantic-core==2.16.3 + # via pydantic pygments==2.17.2 # via # ipython @@ -410,6 +414,7 @@ typing-extensions==4.10.0 # pint # psygnal # pydantic + # pydantic-core # superqt # typer tzdata==2024.1 diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index 19c60e811..54869a1b0 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -2,6 +2,8 @@ # uv pip compile --python-version 3.11 --output-file requirements/constraints_py3.11_docs.txt pyproject.toml requirements/version_denylist.txt --extra docs --extra pyqt6 alabaster==0.7.16 # via sphinx +annotated-types==0.6.0 + # via pydantic app-model==0.2.4 # via napari appdirs==1.4.4 @@ -14,7 +16,7 @@ attrs==23.2.0 # via # jsonschema # referencing -autodoc-pydantic==1.9.0 +autodoc-pydantic==2.0.1 babel==2.14.0 # via sphinx build==1.0.3 @@ -223,15 +225,20 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==2.6.3 # via # app-model # autodoc-pydantic # napari # npe2 # pydantic-compat + # pydantic-settings pydantic-compat==0.1.2 # via app-model +pydantic-core==2.16.3 + # via pydantic +pydantic-settings==2.2.1 + # via autodoc-pydantic pygments==2.17.2 # via # ipython @@ -266,6 +273,8 @@ python-dateutil==2.8.2 # via # jupyter-client # pandas +python-dotenv==1.0.1 + # via pydantic-settings pytz==2024.1 # via pandas pyyaml==6.0.1 @@ -393,6 +402,7 @@ typing-extensions==4.10.0 # pint # psygnal # pydantic + # pydantic-core # superqt # typer tzdata==2024.1 diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt new file mode 100644 index 000000000..e1a1df295 --- /dev/null +++ b/requirements/constraints_py3.11_pydantic_1.txt @@ -0,0 +1,432 @@ +# 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 pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller --constraint requirements/pydantic_1.txt +alabaster==0.7.16 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +app-model==0.2.4 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +build==1.0.3 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.1 + # via ipykernel +coverage==7.4.3 +czifile==2019.7.2 +dask==2024.2.1 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.15 + # via magicgui +docutils==0.20.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.2.0 + # via dask +h5py==3.10.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.6 + # via requests +imagecodecs==2024.1.1 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +importlib-metadata==7.0.1 + # via dask +in-n-out==0.1.9 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.3 + # via + # napari-console + # qtconsole +ipython==8.22.1 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via + # numpydoc + # sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.1 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.3 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.1.0 +magicgui==0.8.1 + # via napari +mahotas==1.4.13 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +mypy-extensions==1.0.0 + # via psygnal +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.2.1 + # via scikit-image +nme==0.1.8 +npe2==0.7.4 + # via napari +numpy==1.26.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.6.0 + # via napari +oiffile==2023.8.30 +openpyxl==3.1.2 +packaging==23.2 + # via + # build + # dask + # ipykernel + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # superqt + # vispy +pandas==2.2.1 + # via napari +parso==0.8.3 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.6 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pillow==10.2.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.9.5 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.14 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.2 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.13.2 +pyside6==6.6.2 +pyside6-addons==6.6.2 + # via pyside6 +pyside6-essentials==6.6.2 + # via + # pyside6 + # pyside6-addons +pytest==8.0.2 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.2.0 +python-dateutil==2.8.2 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==25.1.2 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.0 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.33.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via npe2 +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.22.0 + # via napari +scipy==1.12.0 + # via + # napari + # scikit-image +sentry-sdk==1.40.6 +setuptools==69.1.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shiboken2==5.13.2 + # via pyside2 +shiboken6==6.6.2 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.2.6 + # via numpydoc +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.1 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.1 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.9.0 + # via npe2 +typing-extensions==4.10.0 + # via + # app-model + # magicgui + # napari + # pint + # psygnal + # pydantic + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.1 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 +zipp==3.17.0 + # via importlib-metadata diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index b0413d7a4..d5d105bac 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -4,6 +4,8 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller +annotated-types==0.6.0 + # via pydantic app-model==0.2.4 # via napari appdirs==1.4.4 @@ -252,7 +254,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==2.6.3 # via # app-model # napari @@ -260,6 +262,8 @@ pydantic==1.10.14 # pydantic-compat pydantic-compat==0.1.2 # via app-model +pydantic-core==2.16.3 + # via pydantic pygments==2.17.2 # via # ipython @@ -434,12 +438,14 @@ typer==0.9.0 # via npe2 typing-extensions==4.10.0 # via + # annotated-types # app-model # ipython # magicgui # napari # psygnal # pydantic + # pydantic-core # rich # superqt # typer diff --git a/requirements/constraints_py3.8_pydantic_1.txt b/requirements/constraints_py3.8_pydantic_1.txt new file mode 100644 index 000000000..639bff760 --- /dev/null +++ b/requirements/constraints_py3.8_pydantic_1.txt @@ -0,0 +1,465 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.8 --output-file requirements/constraints_py3.8_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller --constraint requirements/pydantic_1.txt +alabaster==0.7.13 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +app-model==0.2.4 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +backcall==0.2.0 + # via ipython +build==1.0.3 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.1 + # via ipykernel +coverage==7.4.3 +czifile==2019.7.2 +dask==2023.5.0 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.15 + # via magicgui +docutils==0.20.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +exceptiongroup==1.2.0 + # via pytest +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.2.0 + # via dask +h5py==3.10.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.6 + # via requests +imagecodecs==2023.3.16 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +importlib-metadata==7.0.1 + # via + # build + # dask + # jupyter-client + # pyinstaller + # pyinstaller-hooks-contrib + # sphinx +importlib-resources==6.1.2 + # via + # jsonschema + # jsonschema-specifications +in-n-out==0.1.9 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.3 + # via + # napari-console + # qtconsole +ipython==8.12.3 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via + # numpydoc + # sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.1 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.3 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.1.0 +magicgui==0.8.1 + # via napari +mahotas==1.4.13 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +mypy-extensions==1.0.0 + # via psygnal +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.1 + # via scikit-image +nme==0.1.8 +npe2==0.7.4 + # via napari +numpy==1.24.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # pywavelets + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.6.0 + # via napari +oiffile==2022.9.29 +openpyxl==3.1.2 +packaging==23.2 + # via + # build + # dask + # ipykernel + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # superqt + # vispy +pandas==2.0.3 + # via napari +parso==0.8.3 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.1 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pickleshare==0.7.5 + # via ipython +pillow==10.2.0 + # via + # imageio + # napari + # scikit-image +pint==0.21.1 + # via napari +pkgutil-resolve-name==1.3.10 + # via jsonschema +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.9.5 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.14 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.2 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.15.2.1 +pyside6==6.3.1 +pyside6-addons==6.3.1 + # via pyside6 +pyside6-essentials==6.3.1 + # via + # pyside6 + # pyside6-addons +pytest==8.0.2 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.2.0 +python-dateutil==2.8.2 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via + # babel + # pandas +pywavelets==1.4.1 + # via scikit-image +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==25.1.2 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.0 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.33.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via npe2 +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.21.0 + # via napari +scipy==1.10.1 + # via + # napari + # scikit-image +sentry-sdk==1.40.6 +setuptools==69.1.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shiboken2==5.15.2.1 + # via pyside2 +shiboken6==6.3.1 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.1.2 + # via numpydoc +sphinxcontrib-applehelp==1.0.4 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.1 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.1 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2023.7.10 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli==2.0.1 + # via + # build + # npe2 + # numpydoc + # pyproject-hooks + # pytest +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.1 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.9.0 + # via npe2 +typing-extensions==4.10.0 + # via + # app-model + # ipython + # magicgui + # napari + # psygnal + # pydantic + # rich + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.1 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 +zipp==3.17.0 + # via + # importlib-metadata + # importlib-resources diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index fcf3785ff..c58fa855f 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -4,6 +4,8 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller +annotated-types==0.6.0 + # via pydantic app-model==0.2.4 # via napari appdirs==1.4.4 @@ -243,7 +245,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==2.6.3 # via # app-model # napari @@ -251,6 +253,8 @@ pydantic==1.10.14 # pydantic-compat pydantic-compat==0.1.2 # via app-model +pydantic-core==2.16.3 + # via pydantic pygments==2.17.2 # via # ipython @@ -428,6 +432,7 @@ typing-extensions==4.10.0 # pint # psygnal # pydantic + # pydantic-core # superqt # typer tzdata==2024.1 diff --git a/requirements/constraints_py3.9_pydantic_1.txt b/requirements/constraints_py3.9_pydantic_1.txt new file mode 100644 index 000000000..94f4eafc3 --- /dev/null +++ b/requirements/constraints_py3.9_pydantic_1.txt @@ -0,0 +1,450 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.9 --output-file requirements/constraints_py3.9_pydantic_1.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller --constraint requirements/pydantic_1.txt +alabaster==0.7.16 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +app-model==0.2.4 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +build==1.0.3 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.1 + # via ipykernel +coverage==7.4.3 +czifile==2019.7.2 +dask==2024.2.1 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.15 + # via magicgui +docutils==0.20.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +exceptiongroup==1.2.0 + # via + # ipython + # pytest +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.2.0 + # via dask +h5py==3.10.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.6 + # via requests +imagecodecs==2024.1.1 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +importlib-metadata==7.0.1 + # via + # build + # dask + # jupyter-client + # pyinstaller + # pyinstaller-hooks-contrib + # sphinx +in-n-out==0.1.9 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.3 + # via + # napari-console + # qtconsole +ipython==8.18.1 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via + # numpydoc + # sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.0 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.1 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.3 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.1.0 +magicgui==0.8.1 + # via napari +mahotas==1.4.13 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.6 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +mypy-extensions==1.0.0 + # via psygnal +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.2.1 + # via scikit-image +nme==0.1.8 +npe2==0.7.4 + # via napari +numpy==1.26.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.6.0 + # via napari +oiffile==2023.8.30 +openpyxl==3.1.2 +packaging==23.2 + # via + # build + # dask + # ipykernel + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # superqt + # vispy +pandas==2.2.1 + # via napari +parso==0.8.3 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.6 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pillow==10.2.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.9.5 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.14 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.4.0 +pyinstaller-hooks-contrib==2024.1 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.2 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.15.2.1 +pyside6==6.3.1 +pyside6-addons==6.3.1 + # via pyside6 +pyside6-essentials==6.3.1 + # via + # pyside6 + # pyside6-addons +pytest==8.0.2 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.2.0 +python-dateutil==2.8.2 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==25.1.2 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.0 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.33.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via npe2 +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.22.0 + # via napari +scipy==1.12.0 + # via + # napari + # scikit-image +sentry-sdk==1.40.6 +setuptools==69.1.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shiboken2==5.15.2.1 + # via pyside2 +shiboken6==6.3.1 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.2.6 + # via numpydoc +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.1 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli==2.0.1 + # via + # build + # npe2 + # numpydoc + # pyproject-hooks + # pytest +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.1 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.9.0 + # via npe2 +typing-extensions==4.10.0 + # via + # app-model + # ipython + # magicgui + # napari + # pint + # psygnal + # pydantic + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.1 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 +zipp==3.17.0 + # via importlib-metadata diff --git a/requirements/pydantic_1.txt b/requirements/pydantic_1.txt new file mode 100644 index 000000000..fd72c6577 --- /dev/null +++ b/requirements/pydantic_1.txt @@ -0,0 +1 @@ +pydantic<2 diff --git a/requirements/version_denylist.txt b/requirements/version_denylist.txt index 7033d4cb9..8e462ec6f 100644 --- a/requirements/version_denylist.txt +++ b/requirements/version_denylist.txt @@ -6,5 +6,4 @@ PySide6 < 6.3.2 ; python_version < '3.10' PySide6 != 6.4.3, !=6.5.0, !=6.5.1, !=6.5.1.1, !=6.5.2; python_version >= '3.10' npe2!=0.2.2 imageio != 2.22.1 -pydantic<2.0 sentry-sdk!=1.29.0 diff --git a/tox.ini b/tox.ini index 801ff1463..3a74d7333 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{414,415,416,417,repo} +envlist = py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo} toxworkdir=/tmp/tox [gh-actions] @@ -18,10 +18,9 @@ fail_on_no_env = True [gh-actions:env] NAPARI = latest: all - napari414: napari_414 - napari415: napari_415 - napari416: napari_416 napari417: napari_417 + napari418: napari_417 + napari419: napari_417 repo: napari_repo BACKEND = pyqt: PyQt5 @@ -42,7 +41,6 @@ deps = PySide6: PySide6<6.3.2 PySide2: npe2!=0.2.2 imageio != 2.22.1 - pydantic<2.0 pytest-json-report [testenv] @@ -71,13 +69,14 @@ deps= pytest pytest-json-report -[testenv:py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{414,415,416,417,repo}] +[testenv:py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo}] deps = {[testenv]deps} - 414: napari==0.4.14 - 415: napari==0.4.15 - 416: napari==0.4.16 417: napari==0.4.17 + 417: pydantic<2 + 418: napari==0.4.18 + 418: pydantic<2 + 419: napari==0.4.19.post1 repo: git+https://github.com/napari/napari.git commands = !repo: python -m pytest -v package/tests/test_PartSeg/test_napari_widgets.py --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json From 91ce8c6e428b7e8a55c02f613297d5f600a9b854 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 11 Mar 2024 10:51:34 +0100 Subject: [PATCH 40/51] test: [Automatic] Constraints upgrades: `magicgui`, `packaging`, `psygnal`, `pyinstaller`, `sentry-sdk`, `superqt` (#1086) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * build * importlib-metadata * magicgui * packaging * psygnal * pyinstaller * pyinstaller-hooks-contrib * pytest * pytest-timeout * python-dateutil * sentry-sdk * superqt ## Summary by CodeRabbit - **Documentation** - Updated software dependencies to enhance performance and compatibility. - Notable updates include improvements to the build system, error tracking, and user interface components. Co-authored-by: Czaki <3826210+Czaki@users.noreply.github.com> --- requirements/constraints_py3.10.txt | 34 +++++++++---------- .../constraints_py3.10_pydantic_1.txt | 34 +++++++++---------- requirements/constraints_py3.11.txt | 30 +++++++--------- requirements/constraints_py3.11_docs.txt | 22 +++++------- .../constraints_py3.11_pydantic_1.txt | 30 +++++++--------- requirements/constraints_py3.8.txt | 30 +++++++--------- requirements/constraints_py3.8_pydantic_1.txt | 30 +++++++--------- requirements/constraints_py3.9.txt | 28 +++++++-------- requirements/constraints_py3.9_pydantic_1.txt | 28 +++++++-------- 9 files changed, 117 insertions(+), 149 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 68143e03f..9ab743224 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -80,8 +80,10 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 - # via dask +importlib-metadata==7.0.2 + # via + # build + # dask in-n-out==0.1.9 # via app-model iniconfig==2.0.0 @@ -90,7 +92,7 @@ ipykernel==6.29.3 # via # napari-console # qtconsole -ipython==8.22.1 +ipython==8.22.2 # via # ipykernel # napari-console @@ -124,7 +126,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -139,8 +141,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -178,7 +178,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -192,7 +192,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -227,7 +226,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -257,8 +256,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -283,13 +282,13 @@ pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -337,7 +336,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -372,7 +371,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -423,7 +422,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # pydantic-core # superqt diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt index b236e430c..1abc3d52d 100644 --- a/requirements/constraints_py3.10_pydantic_1.txt +++ b/requirements/constraints_py3.10_pydantic_1.txt @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -78,8 +78,10 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 - # via dask +importlib-metadata==7.0.2 + # via + # build + # dask in-n-out==0.1.9 # via app-model iniconfig==2.0.0 @@ -88,7 +90,7 @@ ipykernel==6.29.3 # via # napari-console # qtconsole -ipython==8.22.1 +ipython==8.22.2 # via # ipykernel # napari-console @@ -122,7 +124,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -137,8 +139,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -176,7 +176,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -190,7 +190,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -225,7 +224,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -253,8 +252,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -279,13 +278,13 @@ pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -333,7 +332,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -368,7 +367,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -419,7 +418,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # superqt # typer diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 4cc8c75a1..c87fcc1c7 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -76,7 +76,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via dask in-n-out==0.1.9 # via app-model @@ -86,7 +86,7 @@ ipykernel==6.29.3 # via # napari-console # qtconsole -ipython==8.22.1 +ipython==8.22.2 # via # ipykernel # napari-console @@ -120,7 +120,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -135,8 +135,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -174,7 +172,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -188,7 +186,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -223,7 +220,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -253,8 +250,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -279,13 +276,13 @@ pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -333,7 +330,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -368,7 +365,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -412,7 +409,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # pydantic-core # superqt diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index 54869a1b0..7a2706a63 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -19,7 +19,7 @@ attrs==23.2.0 autodoc-pydantic==2.0.1 babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -76,7 +76,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via dask in-n-out==0.1.9 # via app-model @@ -84,7 +84,7 @@ ipykernel==6.29.3 # via # napari-console # qtconsole -ipython==8.22.1 +ipython==8.22.2 # via # ipykernel # napari-console @@ -117,7 +117,7 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -132,8 +132,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -171,7 +169,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -182,7 +180,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -213,7 +210,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -269,7 +266,7 @@ pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -python-dateutil==2.8.2 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -319,7 +316,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 shiboken2==5.13.2 # via pyside2 shiboken6==6.6.2 @@ -356,7 +353,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -400,7 +397,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # pydantic-core # superqt diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt index e1a1df295..da5098666 100644 --- a/requirements/constraints_py3.11_pydantic_1.txt +++ b/requirements/constraints_py3.11_pydantic_1.txt @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -74,7 +74,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via dask in-n-out==0.1.9 # via app-model @@ -84,7 +84,7 @@ ipykernel==6.29.3 # via # napari-console # qtconsole -ipython==8.22.1 +ipython==8.22.2 # via # ipykernel # napari-console @@ -118,7 +118,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -133,8 +133,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -172,7 +170,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -186,7 +184,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -221,7 +218,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -249,8 +246,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -275,13 +272,13 @@ pyside6-essentials==6.6.2 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -329,7 +326,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -364,7 +361,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -408,7 +405,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # superqt # typer diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index d5d105bac..5a9155117 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -22,7 +22,7 @@ babel==2.14.0 # via sphinx backcall==0.2.0 # via ipython -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -80,7 +80,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via # build # dask @@ -88,7 +88,7 @@ importlib-metadata==7.0.1 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.1.2 +importlib-resources==6.1.3 # via # jsonschema # jsonschema-specifications @@ -134,7 +134,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -149,8 +149,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -189,7 +187,7 @@ numpydoc==1.6.0 # via napari oiffile==2022.9.29 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -203,7 +201,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.0.3 # via napari @@ -242,7 +239,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -272,8 +269,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -298,13 +295,13 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -356,7 +353,7 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -391,7 +388,7 @@ sphinxcontrib-serializinghtml==1.1.5 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -443,7 +440,6 @@ typing-extensions==4.10.0 # ipython # magicgui # napari - # psygnal # pydantic # pydantic-core # rich diff --git a/requirements/constraints_py3.8_pydantic_1.txt b/requirements/constraints_py3.8_pydantic_1.txt index 639bff760..255b99782 100644 --- a/requirements/constraints_py3.8_pydantic_1.txt +++ b/requirements/constraints_py3.8_pydantic_1.txt @@ -20,7 +20,7 @@ babel==2.14.0 # via sphinx backcall==0.2.0 # via ipython -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -78,7 +78,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via # build # dask @@ -86,7 +86,7 @@ importlib-metadata==7.0.1 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.1.2 +importlib-resources==6.1.3 # via # jsonschema # jsonschema-specifications @@ -132,7 +132,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -147,8 +147,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -187,7 +185,7 @@ numpydoc==1.6.0 # via napari oiffile==2022.9.29 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -201,7 +199,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.0.3 # via napari @@ -240,7 +237,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -268,8 +265,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -294,13 +291,13 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -352,7 +349,7 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -387,7 +384,7 @@ sphinxcontrib-serializinghtml==1.1.5 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -438,7 +435,6 @@ typing-extensions==4.10.0 # ipython # magicgui # napari - # psygnal # pydantic # rich # superqt diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index c58fa855f..b8228722e 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -80,7 +80,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via # build # dask @@ -130,7 +130,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -145,8 +145,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -184,7 +182,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -198,7 +196,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -233,7 +230,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -263,8 +260,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -289,13 +286,13 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -343,7 +340,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -378,7 +375,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -430,7 +427,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # pydantic-core # superqt diff --git a/requirements/constraints_py3.9_pydantic_1.txt b/requirements/constraints_py3.9_pydantic_1.txt index 94f4eafc3..6713abd26 100644 --- a/requirements/constraints_py3.9_pydantic_1.txt +++ b/requirements/constraints_py3.9_pydantic_1.txt @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.0.3 +build==1.1.1 # via npe2 cachey==0.2.1 # via napari @@ -78,7 +78,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.1 +importlib-metadata==7.0.2 # via # build # dask @@ -128,7 +128,7 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.1.0 -magicgui==0.8.1 +magicgui==0.8.2 # via napari mahotas==1.4.13 markdown-it-py==3.0.0 @@ -143,8 +143,6 @@ mdurl==0.1.2 # via markdown-it-py mpmath==1.3.0 # via sympy -mypy-extensions==1.0.0 - # via psygnal napari==0.4.19.post1 napari-console==0.0.9 # via napari @@ -182,7 +180,7 @@ numpydoc==1.6.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 -packaging==23.2 +packaging==24.0 # via # build # dask @@ -196,7 +194,6 @@ packaging==23.2 # qtpy # scikit-image # sphinx - # superqt # vispy pandas==2.2.1 # via napari @@ -231,7 +228,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.9.5 +psygnal==0.10.0 # via # app-model # magicgui @@ -259,8 +256,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.4.0 -pyinstaller-hooks-contrib==2024.1 +pyinstaller==6.5.0 +pyinstaller-hooks-contrib==2024.3 # via pyinstaller pyopengl==3.1.7 # via napari @@ -285,13 +282,13 @@ pyside6-essentials==6.3.1 # via # pyside6 # pyside6-addons -pytest==8.0.2 +pytest==8.1.1 # via # pytest-qt # pytest-timeout pytest-qt==4.4.0 -pytest-timeout==2.2.0 -python-dateutil==2.8.2 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 # via # jupyter-client # pandas @@ -339,7 +336,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.40.6 +sentry-sdk==1.41.0 setuptools==69.1.1 # via # pyinstaller @@ -374,7 +371,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.1 +superqt==0.6.2 # via # magicgui # napari @@ -426,7 +423,6 @@ typing-extensions==4.10.0 # magicgui # napari # pint - # psygnal # pydantic # superqt # typer From 488fd5e7b5c1a431da9aad2ad8c4d1f6255e0b77 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:53:47 +0100 Subject: [PATCH 41/51] ci: [pre-commit.ci] pre-commit autoupdate (#1089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.2.2 → v0.3.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.2...v0.3.2) - [github.com/pre-commit/mirrors-mypy: v1.8.0 → v1.9.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.8.0...v1.9.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a27346095..488c305f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: debug-statements - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.2 + rev: v0.3.2 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade @@ -44,7 +44,7 @@ repos: - mdformat-toc - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.8.0' # Use the sha / tag you want to point at + rev: 'v1.9.0' # Use the sha / tag you want to point at hooks: - id: mypy files: ^package/PartSegImage/.+\.py From 293be196664baa4900a6cad642d0e52cf3d6aa28 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 18 Mar 2024 11:48:00 +0100 Subject: [PATCH 42/51] test: [Automatic] Constraints upgrades: `psygnal`, `pydantic`, `sentry-sdk`, `vispy` (#1090) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * comm * coverage * dask * docstring-parser * fsspec * jupyter-client * jupyter-core * psygnal * pydantic * referencing * sentry-sdk * setuptools * traitlets * vispy * zipp ## Summary by CodeRabbit - **Chores** - Updated dependencies across various Python versions to enhance performance and security. Co-authored-by: Czaki <3826210+Czaki@users.noreply.github.com> --- requirements/constraints_py3.10.txt | 30 +++++++++--------- .../constraints_py3.10_pydantic_1.txt | 28 ++++++++--------- requirements/constraints_py3.11.txt | 30 +++++++++--------- requirements/constraints_py3.11_docs.txt | 26 ++++++++-------- .../constraints_py3.11_pydantic_1.txt | 28 ++++++++--------- requirements/constraints_py3.8.txt | 31 ++++++++++--------- requirements/constraints_py3.8_pydantic_1.txt | 29 ++++++++--------- requirements/constraints_py3.9.txt | 30 +++++++++--------- requirements/constraints_py3.9_pydantic_1.txt | 28 ++++++++--------- 9 files changed, 131 insertions(+), 129 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 9ab743224..45f1c8942 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -37,18 +37,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -63,7 +63,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -106,11 +106,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -226,7 +226,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -238,7 +238,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.3 +pydantic==2.6.4 # via # app-model # napari @@ -315,7 +315,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -336,8 +336,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -405,7 +405,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -432,7 +432,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -442,5 +442,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt index 1abc3d52d..44bfb6371 100644 --- a/requirements/constraints_py3.10_pydantic_1.txt +++ b/requirements/constraints_py3.10_pydantic_1.txt @@ -35,18 +35,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -61,7 +61,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -104,11 +104,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -224,7 +224,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -311,7 +311,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -332,8 +332,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -401,7 +401,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -427,7 +427,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -437,5 +437,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index c87fcc1c7..82ca5aad5 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -37,18 +37,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -59,7 +59,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -100,11 +100,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -220,7 +220,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -232,7 +232,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.3 +pydantic==2.6.4 # via # app-model # napari @@ -309,7 +309,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -330,8 +330,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -392,7 +392,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -419,7 +419,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -429,5 +429,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index 7a2706a63..ebceb824e 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -36,17 +36,17 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via @@ -59,7 +59,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -98,11 +98,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -210,7 +210,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -222,7 +222,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.3 +pydantic==2.6.4 # via # app-model # autodoc-pydantic @@ -295,7 +295,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -316,7 +316,7 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 +sentry-sdk==1.42.0 shiboken2==5.13.2 # via pyside2 shiboken6==6.6.2 @@ -380,7 +380,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -407,7 +407,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -417,5 +417,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt index da5098666..ef274b557 100644 --- a/requirements/constraints_py3.11_pydantic_1.txt +++ b/requirements/constraints_py3.11_pydantic_1.txt @@ -35,18 +35,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -57,7 +57,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -98,11 +98,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -218,7 +218,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -305,7 +305,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -326,8 +326,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -388,7 +388,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -414,7 +414,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -424,5 +424,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index 5a9155117..f3e9be546 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -39,9 +39,9 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 dask==2023.5.0 # via napari @@ -50,7 +50,7 @@ debugpy==1.8.1 decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -63,7 +63,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -88,10 +88,11 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.1.3 +importlib-resources==6.3.1 # via # jsonschema # jsonschema-specifications + # vispy in-n-out==0.1.9 # via app-model iniconfig==2.0.0 @@ -114,11 +115,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -239,7 +240,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -251,7 +252,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.3 +pydantic==2.6.4 # via # app-model # napari @@ -332,7 +333,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -353,8 +354,8 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -422,7 +423,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -451,7 +452,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -461,7 +462,7 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via # importlib-metadata # importlib-resources diff --git a/requirements/constraints_py3.8_pydantic_1.txt b/requirements/constraints_py3.8_pydantic_1.txt index 255b99782..70de7b4d8 100644 --- a/requirements/constraints_py3.8_pydantic_1.txt +++ b/requirements/constraints_py3.8_pydantic_1.txt @@ -37,9 +37,9 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 dask==2023.5.0 # via napari @@ -48,7 +48,7 @@ debugpy==1.8.1 decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -61,7 +61,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -86,10 +86,11 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.1.3 +importlib-resources==6.3.1 # via # jsonschema # jsonschema-specifications + # vispy in-n-out==0.1.9 # via app-model iniconfig==2.0.0 @@ -112,11 +113,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -237,7 +238,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -328,7 +329,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -349,8 +350,8 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -418,7 +419,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -445,7 +446,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -455,7 +456,7 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via # importlib-metadata # importlib-resources diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index b8228722e..12e2ba91b 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -37,18 +37,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -63,7 +63,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -110,11 +110,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -230,7 +230,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -242,7 +242,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.3 +pydantic==2.6.4 # via # app-model # napari @@ -319,7 +319,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -340,8 +340,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -409,7 +409,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -437,7 +437,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -447,5 +447,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata diff --git a/requirements/constraints_py3.9_pydantic_1.txt b/requirements/constraints_py3.9_pydantic_1.txt index 6713abd26..75247d8ab 100644 --- a/requirements/constraints_py3.9_pydantic_1.txt +++ b/requirements/constraints_py3.9_pydantic_1.txt @@ -35,18 +35,18 @@ click==8.1.7 # typer cloudpickle==3.0.0 # via dask -comm==0.2.1 +comm==0.2.2 # via ipykernel -coverage==7.4.3 +coverage==7.4.4 czifile==2019.7.2 -dask==2024.2.1 +dask==2024.3.1 # via napari debugpy==1.8.1 # via ipykernel decorator==5.1.1 # via ipython defusedxml==0.7.1 -docstring-parser==0.15 +docstring-parser==0.16 # via magicgui docutils==0.20.1 # via sphinx @@ -61,7 +61,7 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.2.0 +fsspec==2024.3.0 # via dask h5py==3.10.0 heapdict==1.0.1 @@ -108,11 +108,11 @@ jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 # via jsonschema -jupyter-client==8.6.0 +jupyter-client==8.6.1 # via # ipykernel # qtconsole -jupyter-core==5.7.1 +jupyter-core==5.7.2 # via # ipykernel # jupyter-client @@ -228,7 +228,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.0 +psygnal==0.10.2 # via # app-model # magicgui @@ -315,7 +315,7 @@ qtpy==2.4.1 # qtawesome # qtconsole # superqt -referencing==0.33.0 +referencing==0.34.0 # via # jsonschema # jsonschema-specifications @@ -336,8 +336,8 @@ scipy==1.12.0 # via # napari # scikit-image -sentry-sdk==1.41.0 -setuptools==69.1.1 +sentry-sdk==1.42.0 +setuptools==69.2.0 # via # pyinstaller # pyinstaller-hooks-contrib @@ -405,7 +405,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.1 +traitlets==5.14.2 # via # comm # ipykernel @@ -432,7 +432,7 @@ urllib3==2.2.1 # via # requests # sentry-sdk -vispy==0.14.1 +vispy==0.14.2 # via # napari # napari-svg @@ -442,5 +442,5 @@ wrapt==1.16.0 # via napari xlrd==2.0.1 xlsxwriter==3.2.0 -zipp==3.17.0 +zipp==3.18.1 # via importlib-metadata From a42ed797073df850e977e0053ec0edcf438e755a Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 12 Apr 2024 12:33:02 +0200 Subject: [PATCH 43/51] chore: Fix jupyter failing test by using constraints (#1093) ## Summary by CodeRabbit - **Chores** - Updated the Python version to 3.11 in the CI/CD pipeline. - Modified the path for the pip constraints file. - Introduced a new environment variable `PIP_CONSTRAINT` for specifying pip constraints. - Added Python 3.11 support to the test environment configurations in `tox.ini`. - Updated the `jupyter` dependency in the `jupyter` test environment configuration. - Removed an unnecessary line related to constraints for Python 3.9 in `tox.ini`. - Updated the `pygments` dependency version in the project configuration file. --- .azure-pipelines/tests.yaml | 6 +++--- azure-pipelines.yml | 8 +++++--- pyproject.toml | 4 ++-- tox.ini | 8 ++++---- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.azure-pipelines/tests.yaml b/.azure-pipelines/tests.yaml index 7023c3e6d..f88322184 100644 --- a/.azure-pipelines/tests.yaml +++ b/.azure-pipelines/tests.yaml @@ -3,10 +3,10 @@ parameters: type: string steps: - - {task: UsePythonVersion@0, inputs: {versionSpec: '3.9'}} + - {task: UsePythonVersion@0, inputs: {versionSpec: '3.11'}} - template: pip_cache.yaml parameters: - key: test | requirements/constraints_py3.9.txt | "$(Agent.OS)" | "$(PY)" + key: test | requirements/constraints_py3.11.txt | "$(Agent.OS)" | "$(PY)" path: ${{ parameters.cache_dir }} - task: DownloadPipelineArtifact@2 inputs: @@ -16,7 +16,7 @@ steps: pip install -U pip wheel setuptools virtualenv pip install -r requirements/requirements_dev.txt displayName: "Install deps" - - script: tox -e py39-PyQt5-azure + - script: tox -e py311-PyQt5-azure displayName: "Run Tox" env: CODECOV_TOKEN: $(codecov_token_secret) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eb9d61640..e2e359526 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -97,16 +97,18 @@ stages: DATA_PATH: typy_neuronow2 pip_cache_dir: $(Pipeline.Workspace)/.pip steps: - - {task: UsePythonVersion@0, inputs: {versionSpec: '3.9', architecture: x64}} + - {task: UsePythonVersion@0, inputs: {versionSpec: '3.11', architecture: x64}} - template: .azure-pipelines/pip_cache.yaml parameters: - key: notebook | requirements/constraints_py3.9.txt | "$(PY)" + key: notebook | requirements/constraints_py3.11.txt | "$(PY)" path: $(pip_cache_dir) - bash: | python -m pip install tox - displayName: Test notebook + displayName: "Install tox" - bash: tox -e jupyter displayName: "Run Notebook" + env: + PIP_CONSTRAINT: requirements/constraints_py3.11.txt - stage: Tests_linux dependsOn: [GetTestData, formatting_check] diff --git a/pyproject.toml b/pyproject.toml index 7407e7399..05a57c78f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ dependencies = [ "pandas>=1.1.0", "psygnal>=0.3.1", "pydantic>=1.9.1", - "pygments>=2.4.0", + "pygments>=2.12.0", "qtconsole>=4.7.7", "requests>=2.18.0", "scipy>=1.4.1", @@ -134,7 +134,7 @@ pyside6 = [ ] test = [ "coverage", - "lxml", + "lxml[html_clean]", "pytest>=7.0.0", "pytest-qt", "pytest-timeout", diff --git a/tox.ini b/tox.ini index 3a74d7333..551d4e2f2 100644 --- a/tox.ini +++ b/tox.ini @@ -68,6 +68,7 @@ conda_env=environment.yml deps= pytest pytest-json-report + lxml_html_clean [testenv:py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo}] deps = @@ -98,10 +99,11 @@ setenv = deps = {[base]deps} setuptools_scm[toml]>=3.4 + lxml_html_clean commands = coverage run -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json -[testenv:py{38,39,310}-{PyQt5, PySide2,PyQt6,PySide6}-azure] +[testenv:py{38,39,310,311}-{PyQt5, PySide2,PyQt6,PySide6}-azure] deps = pytest-azurepipelines {[testenv]deps} @@ -110,10 +112,8 @@ deps = [testenv:jupyter] deps = {[testenv]deps} - jupyter[all] - jupyter[all] + jupyter matplotlib - -crequirements/constraints_py3.9.txt setenv = DATA_PATH = {toxinidir}/typy_neuronow2 commands = From 2c45552b22c3155141e251702d2f591df792f7c4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 17:39:40 +0200 Subject: [PATCH 44/51] ci: [pre-commit.ci] pre-commit autoupdate (#1091) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.2.0 → 24.3.0](https://github.com/psf/black-pre-commit-mirror/compare/24.2.0...24.3.0) - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) - [github.com/astral-sh/ruff-pre-commit: v0.3.2 → v0.3.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.2...v0.3.5) - [github.com/asottile/pyupgrade: v3.15.1 → v3.15.2](https://github.com/asottile/pyupgrade/compare/v3.15.1...v3.15.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 488c305f0..b310a9164 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,12 +3,12 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.2.0 + rev: 24.3.0 hooks: - id: black pass_filenames: true - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-json - id: check-yaml @@ -20,11 +20,11 @@ repos: - id: debug-statements - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.2 + rev: v0.3.5 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade - rev: v3.15.1 + rev: v3.15.2 hooks: - id: pyupgrade args: ["--py38-plus"] From 03953e853ffcf9ec58d085116b48611a5a016896 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 17 Apr 2024 18:44:27 +0200 Subject: [PATCH 45/51] test: [Automatic] Constraints upgrades: `h5py`, `ipykernel`, `mahotas`, `pandas`, `psygnal`, `pydantic`, `pyinstaller`, `qtawesome`, `scipy`, `sentry-sdk`, `superqt` (#1092) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * app-model * build * dask * docutils * fsspec * h5py * idna * importlib-metadata * in-n-out * ipykernel * lazy-loader * lxml * lxml-html-clean * mahotas * matplotlib-inline * npe2 * numpydoc * pandas * parso * pillow * psygnal * pydantic * pydantic-core * pyinstaller * pyinstaller-hooks-contrib * pyqt6-qt6 * pyzmq * qtawesome * scipy * sentry-sdk * setuptools * shellingham * sphinx * superqt * typer * typing-extensions ## Summary by CodeRabbit - **Updated Dependencies** - Updated `fsspec` to version `2024.3.1`. - Updated `dask` to version `2024.4.1`. - Updated `scipy` to version `1.13.0`. - Updated `sphinx` to version `7.3.5`. - Updated `pydantic` to version `1.10.15`. Co-authored-by: Czaki <3826210+Czaki@users.noreply.github.com> --- requirements/constraints_py3.10.txt | 98 ++++++++++--------- .../constraints_py3.10_pydantic_1.txt | 96 +++++++++--------- requirements/constraints_py3.11.txt | 97 +++++++++--------- requirements/constraints_py3.11_docs.txt | 90 +++++++++-------- .../constraints_py3.11_pydantic_1.txt | 95 +++++++++--------- requirements/constraints_py3.8.txt | 74 +++++++------- requirements/constraints_py3.8_pydantic_1.txt | 72 +++++++------- requirements/constraints_py3.9.txt | 83 +++++++++------- requirements/constraints_py3.9_pydantic_1.txt | 81 ++++++++------- 9 files changed, 423 insertions(+), 363 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 45f1c8942..4c04abe4e 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -6,7 +6,7 @@ altgraph==0.17.4 # via pyinstaller annotated-types==0.6.0 # via pydantic -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -50,7 +50,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -63,14 +63,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -80,28 +80,26 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole -ipython==8.22.2 +ipython==8.23.0 # via # ipykernel # napari-console jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -117,7 +115,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -125,15 +123,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -152,10 +153,10 @@ napari-svg==0.1.10 # via napari nest-asyncio==1.6.0 # via ipykernel -networkx==3.2.1 +networkx==3.3 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -174,7 +175,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -183,6 +184,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -193,9 +195,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -203,7 +205,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -226,7 +228,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -238,7 +240,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.4 +pydantic==2.7.0 # via # app-model # napari @@ -246,7 +248,7 @@ pydantic==2.6.4 # pydantic-compat pydantic-compat==0.1.2 # via app-model -pydantic-core==2.16.3 +pydantic-core==2.18.1 # via pydantic pygments==2.17.2 # via @@ -256,8 +258,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -270,15 +272,15 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.15.2.1 -pyside6==6.6.2 -pyside6-addons==6.6.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 # via pyside6 -pyside6-essentials==6.6.2 +pyside6-essentials==6.7.0 # via # pyside6 # pyside6-addons @@ -299,12 +301,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -325,25 +327,29 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.22.0 +scikit-image==0.23.1 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 -shiboken6==6.6.2 +shiboken6==6.7.0 # via # pyside6 # pyside6-addons @@ -355,7 +361,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -371,7 +377,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -391,6 +397,7 @@ tomli==2.0.1 # numpydoc # pyproject-hooks # pytest + # sphinx tomli-w==1.0.0 # via npe2 toolz==0.12.1 @@ -414,11 +421,12 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model + # ipython # magicgui # napari # pint diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt index 44bfb6371..f166d9c4c 100644 --- a/requirements/constraints_py3.10_pydantic_1.txt +++ b/requirements/constraints_py3.10_pydantic_1.txt @@ -4,7 +4,7 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -48,7 +48,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -61,14 +61,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -78,28 +78,26 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole -ipython==8.22.2 +ipython==8.23.0 # via # ipykernel # napari-console jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -115,7 +113,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -123,15 +121,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -150,10 +151,10 @@ napari-svg==0.1.10 # via napari nest-asyncio==1.6.0 # via ipykernel -networkx==3.2.1 +networkx==3.3 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -172,7 +173,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -181,6 +182,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -191,9 +193,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -201,7 +203,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -224,7 +226,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -236,7 +238,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==1.10.15 # via # app-model # napari @@ -252,8 +254,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -266,15 +268,15 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.15.2.1 -pyside6==6.6.2 -pyside6-addons==6.6.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 # via pyside6 -pyside6-essentials==6.6.2 +pyside6-essentials==6.7.0 # via # pyside6 # pyside6-addons @@ -295,12 +297,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -321,25 +323,29 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.22.0 +scikit-image==0.23.1 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 -shiboken6==6.6.2 +shiboken6==6.7.0 # via # pyside6 # pyside6-addons @@ -351,7 +357,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -367,7 +373,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -387,6 +393,7 @@ tomli==2.0.1 # numpydoc # pyproject-hooks # pytest + # sphinx tomli-w==1.0.0 # via npe2 toolz==0.12.1 @@ -410,11 +417,12 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model + # ipython # magicgui # napari # pint diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 82ca5aad5..87c409491 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -6,7 +6,7 @@ altgraph==0.17.4 # via pyinstaller annotated-types==0.6.0 # via pydantic -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -50,7 +50,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -59,14 +59,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -76,26 +76,24 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via dask -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole -ipython==8.22.2 +ipython==8.23.0 # via # ipykernel # napari-console jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -111,7 +109,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -119,15 +117,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -146,10 +147,10 @@ napari-svg==0.1.10 # via napari nest-asyncio==1.6.0 # via ipykernel -networkx==3.2.1 +networkx==3.3 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -168,7 +169,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -177,6 +178,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -187,9 +189,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -197,7 +199,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -220,7 +222,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -232,7 +234,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.4 +pydantic==2.7.0 # via # app-model # napari @@ -240,7 +242,7 @@ pydantic==2.6.4 # pydantic-compat pydantic-compat==0.1.2 # via app-model -pydantic-core==2.16.3 +pydantic-core==2.18.1 # via pydantic pygments==2.17.2 # via @@ -250,8 +252,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -264,15 +266,15 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.13.2 -pyside6==6.6.2 -pyside6-addons==6.6.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 # via pyside6 -pyside6-essentials==6.6.2 +pyside6-essentials==6.7.0 # via # pyside6 # pyside6-addons @@ -293,12 +295,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -319,25 +321,29 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.22.0 +scikit-image==0.23.1 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.2 +shiboken6==6.7.0 # via # pyside6 # pyside6-addons @@ -349,7 +355,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -365,7 +371,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -401,11 +407,12 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model + # ipython # magicgui # napari # pint diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index ebceb824e..1d57556f3 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -4,7 +4,7 @@ alabaster==0.7.16 # via sphinx annotated-types==0.6.0 # via pydantic -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -16,10 +16,10 @@ attrs==23.2.0 # via # jsonschema # referencing -autodoc-pydantic==2.0.1 +autodoc-pydantic==2.1.0 babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -39,7 +39,7 @@ cloudpickle==3.0.0 comm==0.2.2 # via ipykernel czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -48,7 +48,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via # sphinx # sphinx-qt-documentation @@ -59,14 +59,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -76,24 +76,22 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via dask -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole -ipython==8.22.2 +ipython==8.23.0 # via # ipykernel # napari-console jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -109,7 +107,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -119,12 +117,12 @@ locket==1.0.0 # via partd magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -143,10 +141,10 @@ napari-svg==0.1.10 # via napari nest-asyncio==1.6.0 # via ipykernel -networkx==3.2.1 +networkx==3.3 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -165,7 +163,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -174,6 +172,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # qtconsole @@ -181,9 +180,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -191,7 +190,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -210,7 +209,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -222,7 +221,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.4 +pydantic==2.7.0 # via # app-model # autodoc-pydantic @@ -232,7 +231,7 @@ pydantic==2.6.4 # pydantic-settings pydantic-compat==0.1.2 # via app-model -pydantic-core==2.16.3 +pydantic-core==2.18.1 # via pydantic pydantic-settings==2.2.1 # via autodoc-pydantic @@ -254,15 +253,15 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.13.2 -pyside6==6.6.2 -pyside6-addons==6.6.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 # via pyside6 -pyside6-essentials==6.6.2 +pyside6-essentials==6.7.0 # via # pyside6 # pyside6-addons @@ -279,12 +278,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -305,21 +304,25 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.22.0 +scikit-image==0.23.1 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 +sentry-sdk==1.45.0 +shellingham==1.5.4 + # via typer shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.2 +shiboken6==6.7.0 # via # pyside6 # pyside6-addons @@ -331,13 +334,13 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via # autodoc-pydantic # numpydoc # sphinx-autodoc-typehints # sphinx-qt-documentation -sphinx-autodoc-typehints==2.0.0 +sphinx-autodoc-typehints==2.0.1 sphinx-qt-documentation==0.4.1 sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -353,7 +356,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -389,11 +392,12 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model + # ipython # magicgui # napari # pint diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt index ef274b557..abb03dfca 100644 --- a/requirements/constraints_py3.11_pydantic_1.txt +++ b/requirements/constraints_py3.11_pydantic_1.txt @@ -4,7 +4,7 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -48,7 +48,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -57,14 +57,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -74,26 +74,24 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via dask -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole -ipython==8.22.2 +ipython==8.23.0 # via # ipykernel # napari-console jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -109,7 +107,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -117,15 +115,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -144,10 +145,10 @@ napari-svg==0.1.10 # via napari nest-asyncio==1.6.0 # via ipykernel -networkx==3.2.1 +networkx==3.3 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -166,7 +167,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -175,6 +176,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -185,9 +187,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -195,7 +197,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -218,7 +220,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -230,7 +232,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==1.10.15 # via # app-model # napari @@ -246,8 +248,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -260,15 +262,15 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 pyside2==5.13.2 -pyside6==6.6.2 -pyside6-addons==6.6.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 # via pyside6 -pyside6-essentials==6.6.2 +pyside6-essentials==6.7.0 # via # pyside6 # pyside6-addons @@ -289,12 +291,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -315,25 +317,29 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.22.0 +scikit-image==0.23.1 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.13.2 # via pyside2 -shiboken6==6.6.2 +shiboken6==6.7.0 # via # pyside6 # pyside6-addons @@ -345,7 +351,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -361,7 +367,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -397,11 +403,12 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model + # ipython # magicgui # napari # pint diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index f3e9be546..e2247db30 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -6,7 +6,7 @@ altgraph==0.17.4 # via pyinstaller annotated-types==0.6.0 # via pydantic -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -22,7 +22,7 @@ babel==2.14.0 # via sphinx backcall==0.2.0 # via ipython -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -63,14 +63,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2023.3.16 imageio==2.34.0 @@ -80,7 +80,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask @@ -88,16 +88,16 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.3.1 +importlib-resources==6.4.0 # via # jsonschema # jsonschema-specifications # vispy -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole @@ -108,9 +108,7 @@ ipython==8.12.3 jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -126,7 +124,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -134,15 +132,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -164,7 +165,7 @@ nest-asyncio==1.6.0 networkx==3.1 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.24.4 # via @@ -184,7 +185,7 @@ numpy==1.24.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2022.9.29 openpyxl==3.1.2 @@ -193,6 +194,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -205,7 +207,7 @@ packaging==24.0 # vispy pandas==2.0.3 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -215,7 +217,7 @@ pexpect==4.9.0 # via ipython pickleshare==0.7.5 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -240,7 +242,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -252,7 +254,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.4 +pydantic==2.7.0 # via # app-model # napari @@ -260,7 +262,7 @@ pydantic==2.6.4 # pydantic-compat pydantic-compat==0.1.2 # via app-model -pydantic-core==2.16.3 +pydantic-core==2.18.1 # via pydantic pygments==2.17.2 # via @@ -270,8 +272,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -284,7 +286,7 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 @@ -317,12 +319,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -343,7 +345,9 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema @@ -354,11 +358,13 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -389,7 +395,7 @@ sphinxcontrib-serializinghtml==1.1.5 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -432,9 +438,9 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # annotated-types # app-model diff --git a/requirements/constraints_py3.8_pydantic_1.txt b/requirements/constraints_py3.8_pydantic_1.txt index 70de7b4d8..050f9f170 100644 --- a/requirements/constraints_py3.8_pydantic_1.txt +++ b/requirements/constraints_py3.8_pydantic_1.txt @@ -4,7 +4,7 @@ alabaster==0.7.13 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -20,7 +20,7 @@ babel==2.14.0 # via sphinx backcall==0.2.0 # via ipython -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -61,14 +61,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2023.3.16 imageio==2.34.0 @@ -78,7 +78,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask @@ -86,16 +86,16 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -importlib-resources==6.3.1 +importlib-resources==6.4.0 # via # jsonschema # jsonschema-specifications # vispy -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole @@ -106,9 +106,7 @@ ipython==8.12.3 jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -124,7 +122,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -132,15 +130,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -162,7 +163,7 @@ nest-asyncio==1.6.0 networkx==3.1 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.24.4 # via @@ -182,7 +183,7 @@ numpy==1.24.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2022.9.29 openpyxl==3.1.2 @@ -191,6 +192,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -203,7 +205,7 @@ packaging==24.0 # vispy pandas==2.0.3 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -213,7 +215,7 @@ pexpect==4.9.0 # via ipython pickleshare==0.7.5 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -238,7 +240,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -250,7 +252,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==1.10.15 # via # app-model # napari @@ -266,8 +268,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -280,7 +282,7 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 @@ -313,12 +315,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -339,7 +341,9 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema @@ -350,11 +354,13 @@ scipy==1.10.1 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -385,7 +391,7 @@ sphinxcontrib-serializinghtml==1.1.5 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -428,9 +434,9 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model # ipython diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index 12e2ba91b..c9d4a066f 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -6,7 +6,7 @@ altgraph==0.17.4 # via pyinstaller annotated-types==0.6.0 # via pydantic -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -20,7 +20,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -50,7 +50,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -63,14 +63,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -80,7 +80,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask @@ -88,11 +88,11 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole @@ -103,9 +103,7 @@ ipython==8.18.1 jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -121,7 +119,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -129,15 +127,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -159,7 +160,7 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -178,7 +179,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -187,6 +188,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -197,9 +199,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -207,7 +209,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -230,7 +232,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -242,7 +244,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==2.6.4 +pydantic==2.7.0 # via # app-model # napari @@ -250,7 +252,7 @@ pydantic==2.6.4 # pydantic-compat pydantic-compat==0.1.2 # via app-model -pydantic-core==2.16.3 +pydantic-core==2.18.1 # via pydantic pygments==2.17.2 # via @@ -260,8 +262,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -274,7 +276,7 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 @@ -303,12 +305,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -329,22 +331,26 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -359,7 +365,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -375,7 +381,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -395,6 +401,7 @@ tomli==2.0.1 # numpydoc # pyproject-hooks # pytest + # sphinx tomli-w==1.0.0 # via npe2 toolz==0.12.1 @@ -418,9 +425,9 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model # ipython diff --git a/requirements/constraints_py3.9_pydantic_1.txt b/requirements/constraints_py3.9_pydantic_1.txt index 75247d8ab..ab5957e03 100644 --- a/requirements/constraints_py3.9_pydantic_1.txt +++ b/requirements/constraints_py3.9_pydantic_1.txt @@ -4,7 +4,7 @@ alabaster==0.7.16 # via sphinx altgraph==0.17.4 # via pyinstaller -app-model==0.2.4 +app-model==0.2.6 # via napari appdirs==1.4.4 # via @@ -18,7 +18,7 @@ attrs==23.2.0 # referencing babel==2.14.0 # via sphinx -build==1.1.1 +build==1.2.1 # via npe2 cachey==0.2.1 # via napari @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.3.1 +dask==2024.4.1 # via napari debugpy==1.8.1 # via ipykernel @@ -48,7 +48,7 @@ decorator==5.1.1 defusedxml==0.7.1 docstring-parser==0.16 # via magicgui -docutils==0.20.1 +docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl @@ -61,14 +61,14 @@ executing==2.0.1 fonticon-fontawesome6==6.4.0 freetype-py==2.4.0 # via vispy -fsspec==2024.3.0 +fsspec==2024.3.1 # via dask -h5py==3.10.0 +h5py==3.11.0 heapdict==1.0.1 # via cachey hsluv==5.0.4 # via vispy -idna==3.6 +idna==3.7 # via requests imagecodecs==2024.1.1 imageio==2.34.0 @@ -78,7 +78,7 @@ imageio==2.34.0 # scikit-image imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.2 +importlib-metadata==7.1.0 # via # build # dask @@ -86,11 +86,11 @@ importlib-metadata==7.0.2 # pyinstaller # pyinstaller-hooks-contrib # sphinx -in-n-out==0.1.9 +in-n-out==0.2.0 # via app-model iniconfig==2.0.0 # via pytest -ipykernel==6.29.3 +ipykernel==6.29.4 # via # napari-console # qtconsole @@ -101,9 +101,7 @@ ipython==8.18.1 jedi==0.19.1 # via ipython jinja2==3.1.3 - # via - # numpydoc - # sphinx + # via sphinx jsonschema==4.21.1 # via napari jsonschema-specifications==2023.12.1 @@ -119,7 +117,7 @@ jupyter-core==5.7.2 # qtconsole kiwisolver==1.4.5 # via vispy -lazy-loader==0.3 +lazy-loader==0.4 # via # napari # scikit-image @@ -127,15 +125,18 @@ local-migrator==0.1.10 # via nme locket==1.0.0 # via partd -lxml==5.1.0 +lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari -mahotas==1.4.13 +mahotas==1.4.15 markdown-it-py==3.0.0 # via rich markupsafe==2.1.5 # via jinja2 -matplotlib-inline==0.1.6 +matplotlib-inline==0.1.7 # via # ipykernel # ipython @@ -157,7 +158,7 @@ nest-asyncio==1.6.0 networkx==3.2.1 # via scikit-image nme==0.1.8 -npe2==0.7.4 +npe2==0.7.5 # via napari numpy==1.26.4 # via @@ -176,7 +177,7 @@ numpy==1.26.4 # scipy # tifffile # vispy -numpydoc==1.6.0 +numpydoc==1.7.0 # via napari oiffile==2023.8.30 openpyxl==3.1.2 @@ -185,6 +186,7 @@ packaging==24.0 # build # dask # ipykernel + # lazy-loader # local-migrator # pooch # pyinstaller @@ -195,9 +197,9 @@ packaging==24.0 # scikit-image # sphinx # vispy -pandas==2.2.1 +pandas==2.2.2 # via napari -parso==0.8.3 +parso==0.8.4 # via jedi partd==1.4.1 # via dask @@ -205,7 +207,7 @@ partsegcore-compiled-backend==0.15.6 partsegdata==0.10.0 pexpect==4.9.0 # via ipython -pillow==10.2.0 +pillow==10.3.0 # via # imageio # napari @@ -228,7 +230,7 @@ psutil==5.9.8 # via # ipykernel # napari -psygnal==0.10.2 +psygnal==0.11.0 # via # app-model # magicgui @@ -240,7 +242,7 @@ pure-eval==0.2.2 # via stack-data pyconify==0.1.6 # via superqt -pydantic==1.10.14 +pydantic==1.10.15 # via # app-model # napari @@ -256,8 +258,8 @@ pygments==2.17.2 # rich # sphinx # superqt -pyinstaller==6.5.0 -pyinstaller-hooks-contrib==2024.3 +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 # via pyinstaller pyopengl==3.1.7 # via napari @@ -270,7 +272,7 @@ pyqt5-qt5==5.15.2 pyqt5-sip==12.13.0 # via pyqt5 pyqt6==6.6.1 -pyqt6-qt6==6.6.2 +pyqt6-qt6==6.6.3 # via pyqt6 pyqt6-sip==13.6.0 # via pyqt6 @@ -299,12 +301,12 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==25.1.2 +pyzmq==26.0.0 # via # ipykernel # jupyter-client # qtconsole -qtawesome==1.3.0 +qtawesome==1.3.1 qtconsole==5.5.1 # via napari-console qtpy==2.4.1 @@ -325,22 +327,26 @@ requests==2.31.0 # pyconify # sphinx rich==13.7.1 - # via npe2 + # via + # npe2 + # typer rpds-py==0.18.0 # via # jsonschema # referencing scikit-image==0.22.0 # via napari -scipy==1.12.0 +scipy==1.13.0 # via # napari # scikit-image -sentry-sdk==1.42.0 -setuptools==69.2.0 +sentry-sdk==1.45.0 +setuptools==69.5.1 # via # pyinstaller # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer shiboken2==5.15.2.1 # via pyside2 shiboken6==6.3.1 @@ -355,7 +361,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.2.6 +sphinx==7.3.5 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -371,7 +377,7 @@ sphinxcontrib-serializinghtml==1.1.10 # via sphinx stack-data==0.6.3 # via ipython -superqt==0.6.2 +superqt==0.6.3 # via # magicgui # napari @@ -391,6 +397,7 @@ tomli==2.0.1 # numpydoc # pyproject-hooks # pytest + # sphinx tomli-w==1.0.0 # via npe2 toolz==0.12.1 @@ -414,9 +421,9 @@ traitlets==5.14.2 # jupyter-core # matplotlib-inline # qtconsole -typer==0.9.0 +typer==0.12.3 # via npe2 -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # app-model # ipython From 4f335ac967acb8d701b95cdff898103e0039925e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:35:02 +0200 Subject: [PATCH 46/51] ci: [pre-commit.ci] pre-commit autoupdate (#1096) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black-pre-commit-mirror: 24.3.0 → 24.4.0](https://github.com/psf/black-pre-commit-mirror/compare/24.3.0...24.4.0) - [github.com/astral-sh/ruff-pre-commit: v0.3.5 → v0.3.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.5...v0.3.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Grzegorz Bokota --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b310a9164..c717ef167 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ default_language_version: repos: - repo: https://github.com/psf/black-pre-commit-mirror - rev: 24.3.0 + rev: 24.4.0 hooks: - id: black pass_filenames: true @@ -20,7 +20,7 @@ repos: - id: debug-statements - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.5 + rev: v0.3.7 hooks: - id: ruff - repo: https://github.com/asottile/pyupgrade From d643adf8cdb8231e1d22b5a2c7d966e60677e645 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 18 Apr 2024 13:50:10 +0200 Subject: [PATCH 47/51] fix: fix test for validation length of message for sentry-sdk 2.0 release (#1098) ## Summary by CodeRabbit - **Tests** - Enhanced Sentry integration tests with a new function to verify envelope contents, ensuring more robust error tracking and reporting. - Added a function `check_envelope(envelope)` to validate event contents within the envelope, improving test coverage and reliability. - Utilized `monkeypatch` for seamless integration of the new function within the test cases, specifically for handling `sentry-sdk 2`. --- package/tests/test_PartSeg/test_sentry.py | 11 +++++++++++ requirements/pre_test_problematic_version.txt | 1 - 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package/tests/test_PartSeg/test_sentry.py b/package/tests/test_PartSeg/test_sentry.py index a468eb815..b61399507 100644 --- a/package/tests/test_PartSeg/test_sentry.py +++ b/package/tests/test_PartSeg/test_sentry.py @@ -78,6 +78,9 @@ def check_event(event): assert len(event["message"]) == DEFAULT_ERROR_REPORT assert len(event["extra"]["lorem"]) == DEFAULT_ERROR_REPORT + def check_envelope(envelope): + check_event(envelope.get_event()) + try: raise ValueError("eeee") except ValueError as e: @@ -86,6 +89,9 @@ def check_event(event): client = Client("https://aaa@test.pl/77") Hub.current.bind_client(client) monkeypatch.setattr(client.transport, "capture_event", check_event) + # handle sentry-sdk 2 + monkeypatch.setattr(client.transport, "capture_envelope", check_envelope, raising=False) + with sentry_sdk.push_scope() as scope: scope.set_extra("lorem", message) sentry_sdk.capture_event(event, hint=hint) @@ -102,6 +108,9 @@ def check_event(event): assert len(event["message"]) == 5000 assert len(event["extra"]["lorem"]) == 5000 + def check_envelope(envelope): + check_event(envelope.get_event()) + try: raise ValueError("eeee") except ValueError as e: @@ -113,6 +122,8 @@ def check_event(event): client = Client("https://aaa@test.pl/77") Hub.current.bind_client(client) monkeypatch.setattr(client.transport, "capture_event", check_event) + # handle sentry-sdk 2 + monkeypatch.setattr(client.transport, "capture_envelope", check_envelope, raising=False) with sentry_sdk.push_scope() as scope: scope.set_extra("lorem", message) event_id = sentry_sdk.capture_event(event, hint=hint) diff --git a/requirements/pre_test_problematic_version.txt b/requirements/pre_test_problematic_version.txt index 3803d1cb6..c33ee87e0 100644 --- a/requirements/pre_test_problematic_version.txt +++ b/requirements/pre_test_problematic_version.txt @@ -1,2 +1 @@ mpmath!=1.4.0a0 -sentry-sdk!=2.0.0a1,!=2.0.0a2 From c245c3e67aecf5151da781173c83babc01979ffc Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 18 Apr 2024 13:50:26 +0200 Subject: [PATCH 48/51] fix: When fix reader check lowercase extension for validate compatybility (#1097) ## Summary by CodeRabbit - **Bug Fixes** - Enhanced file extension checking to be case-insensitive, improving file compatibility in image loading. --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- package/PartSegCore/napari_plugins/load_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/PartSegCore/napari_plugins/load_image.py b/package/PartSegCore/napari_plugins/load_image.py index 5b3d8b0aa..19f9a6d61 100644 --- a/package/PartSegCore/napari_plugins/load_image.py +++ b/package/PartSegCore/napari_plugins/load_image.py @@ -9,7 +9,7 @@ def napari_get_reader(path: str): ( functools.partial(partseg_loader, LoadStackImage) for extension in LoadStackImage.get_extensions() - if path.endswith(extension) + if path.lower().endswith(extension.lower()) ), None, ) From 75a220b722c722fb232e08d9871f3d8ce3e2d3a8 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 19 Apr 2024 23:07:59 +0200 Subject: [PATCH 49/51] ci: Add python 3.12 testing (#1087) ## Summary by CodeRabbit - **New Features** - Added support for Python 3.12 in the classifiers section, enhancing compatibility with newer Python environments. - **Bug Fixes** - Improved error handling in batch processing and plugin registration for stability and robustness. - **Chores** - Updated various package dependencies to newer versions, ensuring improved performance and security. - **Documentation** - Updated environment configurations to include Python 3.12, aligning with the latest development practices. --- .github/workflows/tests.yml | 4 +- .github/workflows/upgrade-dependencies.yml | 2 +- package/PartSeg/plugins/__init__.py | 7 +- .../batch_processing/batch_backend.py | 5 + .../batch_processing/parallel_backend.py | 17 +- package/PartSegCore/plugins/__init__.py | 19 +- .../test_PartSegCore/test_analysis_batch.py | 4 +- pyproject.toml | 1 + requirements/constraints_py3.12.txt | 432 ++++++++++++++++++ .../constraints_py3.12_pydantic_1.txt | 427 +++++++++++++++++ tox.ini | 15 +- 11 files changed, 905 insertions(+), 28 deletions(-) create mode 100644 requirements/constraints_py3.12.txt create mode 100644 requirements/constraints_py3.12_pydantic_1.txt diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index caef4ff85..af5af7d79 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,7 +39,7 @@ jobs: strategy: fail-fast: false matrix: - python_version: ["3.8", "3.9", "3.10", "3.11"] + python_version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: ["ubuntu-20.04"] qt_backend: ["PyQt5"] tox_args: [ "" ] @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - python_version: ["3.8", "3.9", "3.10"] + python_version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: ["ubuntu-20.04", "macos-11", "windows-2019"] qt_backend: ["PySide2", "PyQt5"] include: diff --git a/.github/workflows/upgrade-dependencies.yml b/.github/workflows/upgrade-dependencies.yml index fff2e32ab..b0012abb7 100644 --- a/.github/workflows/upgrade-dependencies.yml +++ b/.github/workflows/upgrade-dependencies.yml @@ -35,7 +35,7 @@ jobs: pip install -U uv flags=(--extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller) - for pyv in 3.8 3.9 3.10 3.11; do + for pyv in 3.8 3.9 3.10 3.11 3.12; 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 diff --git a/package/PartSeg/plugins/__init__.py b/package/PartSeg/plugins/__init__.py index 196fd0472..4b8ba0459 100644 --- a/package/PartSeg/plugins/__init__.py +++ b/package/PartSeg/plugins/__init__.py @@ -1,11 +1,9 @@ import contextlib import importlib -import itertools import os import pkgutil import sys import typing -from importlib.metadata import entry_points import PartSegCore.plugins @@ -30,10 +28,7 @@ def get_plugins(): else: sys.path.append(os.path.dirname(__file__)) packages = list(pkgutil.iter_modules(__path__)) - packages2 = itertools.chain( - entry_points().get("PartSeg.plugins", []), - entry_points().get("partseg.plugins", []), - ) + packages2 = PartSegCore.plugins.iter_entrypoints("PartSeg.plugins") return [importlib.import_module(el.name) for el in packages] + [el.load() for el in packages2] diff --git a/package/PartSegCore/analysis/batch_processing/batch_backend.py b/package/PartSegCore/analysis/batch_processing/batch_backend.py index 1a614d855..90e15c3b7 100644 --- a/package/PartSegCore/analysis/batch_processing/batch_backend.py +++ b/package/PartSegCore/analysis/batch_processing/batch_backend.py @@ -531,6 +531,11 @@ def get_results(self) -> BatchResultDescription: responses: list[tuple[uuid.UUID, WrappedResult]] = self.batch_manager.get_result() new_errors: list[tuple[str, ErrorInfo]] = [] for uuid_id, (ind, result_list) in responses: + if uuid_id == "-1": # pragma: no cover + self.errors_list.append((f"Unknown file {ind}", result_list)) + new_errors.append((f"Unknown file {ind}", result_list)) + continue + self.calculation_done += 1 self.counter_dict[uuid_id] += 1 calculation = self.calculation_dict[uuid_id] diff --git a/package/PartSegCore/analysis/batch_processing/parallel_backend.py b/package/PartSegCore/analysis/batch_processing/parallel_backend.py index 068fb7fc2..37dd1c0ee 100644 --- a/package/PartSegCore/analysis/batch_processing/parallel_backend.py +++ b/package/PartSegCore/analysis/batch_processing/parallel_backend.py @@ -268,10 +268,13 @@ def spawn_worker(task_queue: Queue, order_queue: Queue, result_queue: Queue, cal :param result_queue: Queue for calculation result :param calculation_dict: dict with global parameters """ - register_if_need() - with suppress(ImportError): - from PartSeg.plugins import register_if_need as register - - register() - worker = BatchWorker(task_queue, order_queue, result_queue, calculation_dict) - worker.run() + try: + register_if_need() + with suppress(ImportError): + from PartSeg.plugins import register_if_need as register + + register() + worker = BatchWorker(task_queue, order_queue, result_queue, calculation_dict) + worker.run() + except Exception as e: # pragma: no cover # pylint: disable=broad-except + result_queue.put(("-1", (-1, [(e, traceback.extract_tb(e.__traceback__))]))) diff --git a/package/PartSegCore/plugins/__init__.py b/package/PartSegCore/plugins/__init__.py index 6f75e2915..0f669eb72 100644 --- a/package/PartSegCore/plugins/__init__.py +++ b/package/PartSegCore/plugins/__init__.py @@ -1,16 +1,27 @@ import importlib import itertools import pkgutil +import sys import typing from importlib.metadata import entry_points +def iter_entrypoints(group: str): + if sys.version_info < (3, 10): + return itertools.chain( + entry_points().get(group, []), + entry_points().get(group.lower(), []), + ) + + return itertools.chain( + entry_points().select(group=group), + entry_points().select(group=group.lower()), + ) + + def get_plugins(): packages = pkgutil.iter_modules(__path__, f"{__name__}.") - packages2 = itertools.chain( - entry_points().get("PartSegCore.plugins", []), - entry_points().get("partsegcore.plugins", []), - ) + packages2 = iter_entrypoints("PartSegCore.plugins") return [importlib.import_module(el.name) for el in packages] + [el.load() for el in packages2] diff --git a/package/tests/test_PartSegCore/test_analysis_batch.py b/package/tests/test_PartSegCore/test_analysis_batch.py index a3ccce1e7..af183165e 100644 --- a/package/tests/test_PartSegCore/test_analysis_batch.py +++ b/package/tests/test_PartSegCore/test_analysis_batch.py @@ -442,7 +442,9 @@ def mask_operation_plan(request, simple_measurement_list): def wait_for_calculation(manager): for _ in range(int(120 / 0.1)): - manager.get_results() + res = manager.get_results() + if res.errors and res.errors[0][0].startswith("Unknown file"): + pytest.fail(str(res.errors)) # pragma: no cover if manager.has_work: time.sleep(0.1) else: diff --git a/pyproject.toml b/pyproject.toml index 05a57c78f..512bbca89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: Bio-Informatics", "Topic :: Scientific/Engineering :: Image Processing", diff --git a/requirements/constraints_py3.12.txt b/requirements/constraints_py3.12.txt new file mode 100644 index 000000000..65413423c --- /dev/null +++ b/requirements/constraints_py3.12.txt @@ -0,0 +1,432 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --python-version 3.12 --output-file requirements/constraints_py3.12.txt pyproject.toml requirements/version_denylist.txt --extra pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller +alabaster==0.7.16 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +annotated-types==0.6.0 + # via pydantic +app-model==0.2.6 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +build==1.2.1 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.2 + # via ipykernel +coverage==7.4.4 +czifile==2019.7.2 +dask==2024.4.1 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.16 + # via magicgui +docutils==0.21.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.3.1 + # via dask +h5py==3.11.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.7 + # via requests +imagecodecs==2024.1.1 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +in-n-out==0.2.0 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.4 + # via + # napari-console + # qtconsole +ipython==8.23.0 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.1 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.2 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.4 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.2.1 +magicgui==0.8.2 + # via napari +mahotas==1.4.15 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.7 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.3 + # via scikit-image +nme==0.1.8 +npe2==0.7.5 + # via napari +numpy==1.26.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.7.0 + # via napari +oiffile==2023.8.30 +openpyxl==3.1.2 +packaging==24.0 + # via + # build + # dask + # ipykernel + # lazy-loader + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # vispy +pandas==2.2.2 + # via napari +parso==0.8.4 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.6 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pillow==10.3.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.11.0 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==2.7.0 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pydantic-core==2.18.1 + # via pydantic +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.3 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.13.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 + # via pyside6 +pyside6-essentials==6.7.0 + # via + # pyside6 + # pyside6-addons +pytest==8.1.1 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==26.0.0 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.1 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.34.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via + # npe2 + # typer +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.23.1 + # via napari +scipy==1.13.0 + # via + # napari + # scikit-image +sentry-sdk==1.45.0 +setuptools==69.5.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer +shiboken2==5.13.2 + # via pyside2 +shiboken6==6.7.0 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.3.5 + # via numpydoc +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.3 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.2 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.12.3 + # via npe2 +typing-extensions==4.11.0 + # via + # app-model + # magicgui + # napari + # pint + # pydantic + # pydantic-core + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.2 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 diff --git a/requirements/constraints_py3.12_pydantic_1.txt b/requirements/constraints_py3.12_pydantic_1.txt new file mode 100644 index 000000000..479415659 --- /dev/null +++ b/requirements/constraints_py3.12_pydantic_1.txt @@ -0,0 +1,427 @@ +# 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 pyqt5 --extra pyqt6 --extra pyside2 --extra pyside6 --extra test --extra pyinstaller --constraint requirements/pydantic_1.txt +alabaster==0.7.16 + # via sphinx +altgraph==0.17.4 + # via pyinstaller +app-model==0.2.6 + # via napari +appdirs==1.4.4 + # via + # napari + # npe2 +asttokens==2.4.1 + # via stack-data +attrs==23.2.0 + # via + # jsonschema + # referencing +babel==2.14.0 + # via sphinx +build==1.2.1 + # via npe2 +cachey==0.2.1 + # via napari +certifi==2024.2.2 + # via + # napari + # requests + # sentry-sdk +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via + # dask + # typer +cloudpickle==3.0.0 + # via dask +comm==0.2.2 + # via ipykernel +coverage==7.4.4 +czifile==2019.7.2 +dask==2024.4.1 + # via napari +debugpy==1.8.1 + # via ipykernel +decorator==5.1.1 + # via ipython +defusedxml==0.7.1 +docstring-parser==0.16 + # via magicgui +docutils==0.21.1 + # via sphinx +et-xmlfile==1.1.0 + # via openpyxl +executing==2.0.1 + # via stack-data +fonticon-fontawesome6==6.4.0 +freetype-py==2.4.0 + # via vispy +fsspec==2024.3.1 + # via dask +h5py==3.11.0 +heapdict==1.0.1 + # via cachey +hsluv==5.0.4 + # via vispy +idna==3.7 + # via requests +imagecodecs==2024.1.1 +imageio==2.34.0 + # via + # napari + # napari-svg + # scikit-image +imagesize==1.4.1 + # via sphinx +in-n-out==0.2.0 + # via app-model +iniconfig==2.0.0 + # via pytest +ipykernel==6.29.4 + # via + # napari-console + # qtconsole +ipython==8.23.0 + # via + # ipykernel + # napari-console +jedi==0.19.1 + # via ipython +jinja2==3.1.3 + # via sphinx +jsonschema==4.21.1 + # via napari +jsonschema-specifications==2023.12.1 + # via jsonschema +jupyter-client==8.6.1 + # via + # ipykernel + # qtconsole +jupyter-core==5.7.2 + # via + # ipykernel + # jupyter-client + # qtconsole +kiwisolver==1.4.5 + # via vispy +lazy-loader==0.4 + # via + # napari + # scikit-image +local-migrator==0.1.10 + # via nme +locket==1.0.0 + # via partd +lxml==5.2.1 +magicgui==0.8.2 + # via napari +mahotas==1.4.15 +markdown-it-py==3.0.0 + # via rich +markupsafe==2.1.5 + # via jinja2 +matplotlib-inline==0.1.7 + # via + # ipykernel + # ipython +mdurl==0.1.2 + # via markdown-it-py +mpmath==1.3.0 + # via sympy +napari==0.4.19.post1 +napari-console==0.0.9 + # via napari +napari-plugin-engine==0.2.0 + # via + # napari + # napari-svg +napari-svg==0.1.10 + # via napari +nest-asyncio==1.6.0 + # via ipykernel +networkx==3.3 + # via scikit-image +nme==0.1.8 +npe2==0.7.5 + # via napari +numpy==1.26.4 + # via + # czifile + # dask + # h5py + # imagecodecs + # imageio + # mahotas + # napari + # napari-svg + # oiffile + # pandas + # partsegcore-compiled-backend + # scikit-image + # scipy + # tifffile + # vispy +numpydoc==1.7.0 + # via napari +oiffile==2023.8.30 +openpyxl==3.1.2 +packaging==24.0 + # via + # build + # dask + # ipykernel + # lazy-loader + # local-migrator + # pooch + # pyinstaller + # pyinstaller-hooks-contrib + # pytest + # qtconsole + # qtpy + # scikit-image + # sphinx + # vispy +pandas==2.2.2 + # via napari +parso==0.8.4 + # via jedi +partd==1.4.1 + # via dask +partsegcore-compiled-backend==0.15.6 +partsegdata==0.10.0 +pexpect==4.9.0 + # via ipython +pillow==10.3.0 + # via + # imageio + # napari + # scikit-image +pint==0.23 + # via napari +platformdirs==4.2.0 + # via + # jupyter-core + # pooch +pluggy==1.4.0 + # via + # pytest + # pytest-qt +pooch==1.8.1 + # via scikit-image +prompt-toolkit==3.0.43 + # via ipython +psutil==5.9.8 + # via + # ipykernel + # napari +psygnal==0.11.0 + # via + # app-model + # magicgui + # napari + # npe2 +ptyprocess==0.7.0 + # via pexpect +pure-eval==0.2.2 + # via stack-data +pyconify==0.1.6 + # via superqt +pydantic==1.10.15 + # via + # app-model + # napari + # npe2 + # pydantic-compat +pydantic-compat==0.1.2 + # via app-model +pygments==2.17.2 + # via + # ipython + # napari + # qtconsole + # rich + # sphinx + # superqt +pyinstaller==6.6.0 +pyinstaller-hooks-contrib==2024.4 + # via pyinstaller +pyopengl==3.1.7 + # via napari +pyopengl-accelerate==3.1.7 +pyproject-hooks==1.0.0 + # via build +pyqt5==5.15.10 +pyqt5-qt5==5.15.2 + # via pyqt5 +pyqt5-sip==12.13.0 + # via pyqt5 +pyqt6==6.6.1 +pyqt6-qt6==6.6.3 + # via pyqt6 +pyqt6-sip==13.6.0 + # via pyqt6 +pyside2==5.13.2 +pyside6==6.7.0 +pyside6-addons==6.7.0 + # via pyside6 +pyside6-essentials==6.7.0 + # via + # pyside6 + # pyside6-addons +pytest==8.1.1 + # via + # pytest-qt + # pytest-timeout +pytest-qt==4.4.0 +pytest-timeout==2.3.1 +python-dateutil==2.9.0.post0 + # via + # jupyter-client + # pandas +pytz==2024.1 + # via pandas +pyyaml==6.0.1 + # via + # dask + # napari + # npe2 +pyzmq==26.0.0 + # via + # ipykernel + # jupyter-client + # qtconsole +qtawesome==1.3.1 +qtconsole==5.5.1 + # via napari-console +qtpy==2.4.1 + # via + # magicgui + # napari + # napari-console + # qtawesome + # qtconsole + # superqt +referencing==0.34.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # pooch + # pyconify + # sphinx +rich==13.7.1 + # via + # npe2 + # typer +rpds-py==0.18.0 + # via + # jsonschema + # referencing +scikit-image==0.23.1 + # via napari +scipy==1.13.0 + # via + # napari + # scikit-image +sentry-sdk==1.45.0 +setuptools==69.5.1 + # via + # pyinstaller + # pyinstaller-hooks-contrib +shellingham==1.5.4 + # via typer +shiboken2==5.13.2 + # via pyside2 +shiboken6==6.7.0 + # via + # pyside6 + # pyside6-addons + # pyside6-essentials +simpleitk==2.3.1 +six==1.16.0 + # via + # asttokens + # python-dateutil +snowballstemmer==2.2.0 + # via sphinx +sphinx==7.3.5 + # via numpydoc +sphinxcontrib-applehelp==1.0.8 + # via sphinx +sphinxcontrib-devhelp==1.0.6 + # via sphinx +sphinxcontrib-htmlhelp==2.0.5 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.7 + # via sphinx +sphinxcontrib-serializinghtml==1.1.10 + # via sphinx +stack-data==0.6.3 + # via ipython +superqt==0.6.3 + # via + # magicgui + # napari +sympy==1.12 +tabulate==0.9.0 + # via numpydoc +tifffile==2024.2.12 + # via + # czifile + # napari + # oiffile + # scikit-image +tomli-w==1.0.0 + # via npe2 +toolz==0.12.1 + # via + # dask + # napari + # partd +tornado==6.4 + # via + # ipykernel + # jupyter-client +tqdm==4.66.2 + # via napari +traceback-with-variables==2.0.4 +traitlets==5.14.2 + # via + # comm + # ipykernel + # ipython + # jupyter-client + # jupyter-core + # matplotlib-inline + # qtconsole +typer==0.12.3 + # via npe2 +typing-extensions==4.11.0 + # via + # app-model + # magicgui + # napari + # pint + # pydantic + # superqt + # typer +tzdata==2024.1 + # via pandas +urllib3==2.2.1 + # via + # requests + # sentry-sdk +vispy==0.14.2 + # via + # napari + # napari-svg +wcwidth==0.2.13 + # via prompt-toolkit +wrapt==1.16.0 + # via napari +xlrd==2.0.1 +xlsxwriter==3.2.0 diff --git a/tox.ini b/tox.ini index 551d4e2f2..e9249bf6c 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ # and then run "tox" from this directory. [tox] -envlist = py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo} +envlist = py{38,39,310,311,312}-{PyQt5,PySide2,PyQt6,PySide6}-all, py{38,39,310,311,312}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo} toxworkdir=/tmp/tox [gh-actions] @@ -13,14 +13,15 @@ python = 3.9: py39 3.10: py310 3.11: py311 + 3.12: py312 fail_on_no_env = True [gh-actions:env] NAPARI = latest: all napari417: napari_417 - napari418: napari_417 - napari419: napari_417 + napari418: napari_418 + napari419: napari_419 repo: napari_repo BACKEND = pyqt: PyQt5 @@ -70,7 +71,7 @@ deps= pytest-json-report lxml_html_clean -[testenv:py{38,39,310,311}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo}] +[testenv:py{38,39,310,311,312}-{PyQt5,PySide2,PyQt6,PySide6}-napari_{417,418,419,repo}] deps = {[testenv]deps} 417: napari==0.4.17 @@ -83,11 +84,11 @@ commands = !repo: python -m pytest -v package/tests/test_PartSeg/test_napari_widgets.py --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json repo: python -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json -[testenv:py{38,39,310,311}-PyQt5-coverage] +[testenv:py{38,39,310,311,312}-PyQt5-coverage] deps = {[testenv]deps} commands = - coverage run -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json + coverage run --concurrency=multiprocessing -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json [testenv:py38-PyQt5-minimal] min_req = 1 @@ -103,7 +104,7 @@ deps = commands = coverage run -m pytest --json-report --json-report-file={toxinidir}/report-{envname}-{sys_platform}.json -[testenv:py{38,39,310,311}-{PyQt5, PySide2,PyQt6,PySide6}-azure] +[testenv:py{38,39,310,311,312}-{PyQt5, PySide2,PyQt6,PySide6}-azure] deps = pytest-azurepipelines {[testenv]deps} From 7e7389cf407ca4d4032365890041cff3b1cb0892 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Sun, 21 Apr 2024 19:30:00 +0200 Subject: [PATCH 50/51] ci: Exclude pyside2 on python 3.11 and 3.12 from testing (#1099) ## Summary by CodeRabbit - **Tests** - Modified CI workflow to exclude specific Python versions with Qt backend PySide2, enhancing compatibility testing. --- .github/workflows/tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index af5af7d79..c85f82fd6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -91,6 +91,11 @@ jobs: - python_version: "3.9" os: "ubuntu-22.04" qt_backend: "PyQt6" + exclude: + - python_version: "3.11" + qt_backend: "PySide2" + - python_version: "3.12" + qt_backend: "PySide2" with: test_data: True python_version: ${{ matrix.python_version }} From f014ed4e04ad7ecf87c98543d36f0113ac5659ee Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Mon, 22 Apr 2024 11:10:37 +0200 Subject: [PATCH 51/51] test: [Automatic] Constraints upgrades: `imageio`, `tifffile` (#1100) This PR is automatically created and updated by PartSeg GitHub action cron to keep bundle dependencies modules up to date. The updated packages are: * dask * exceptiongroup * imageio * pluggy * pyzmq * sphinx * tifffile * traitlets ## Summary by CodeRabbit - **New Features** - Updated various software packages across different system versions to enhance functionality and compatibility. - **Bug Fixes** - Addressed minor issues and improved stability with the latest software package updates. Co-authored-by: Czaki <3826210+Czaki@users.noreply.github.com> --- requirements/constraints_py3.10.txt | 18 +++++++++--------- .../constraints_py3.10_pydantic_1.txt | 18 +++++++++--------- requirements/constraints_py3.11.txt | 16 ++++++++-------- requirements/constraints_py3.11_docs.txt | 16 ++++++++-------- .../constraints_py3.11_pydantic_1.txt | 16 ++++++++-------- requirements/constraints_py3.12.txt | 19 +++++++++++-------- .../constraints_py3.12_pydantic_1.txt | 19 +++++++++++-------- requirements/constraints_py3.8.txt | 10 +++++----- requirements/constraints_py3.8_pydantic_1.txt | 10 +++++----- requirements/constraints_py3.9.txt | 16 ++++++++-------- requirements/constraints_py3.9_pydantic_1.txt | 16 ++++++++-------- 11 files changed, 90 insertions(+), 84 deletions(-) diff --git a/requirements/constraints_py3.10.txt b/requirements/constraints_py3.10.txt index 4c04abe4e..8f4701ce4 100644 --- a/requirements/constraints_py3.10.txt +++ b/requirements/constraints_py3.10.txt @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -54,7 +54,7 @@ docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via # ipython # pytest @@ -73,7 +73,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -216,7 +216,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -301,7 +301,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -334,7 +334,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -361,7 +361,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -384,7 +384,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -412,7 +412,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.10_pydantic_1.txt b/requirements/constraints_py3.10_pydantic_1.txt index f166d9c4c..090ba7f31 100644 --- a/requirements/constraints_py3.10_pydantic_1.txt +++ b/requirements/constraints_py3.10_pydantic_1.txt @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -52,7 +52,7 @@ docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via # ipython # pytest @@ -71,7 +71,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -214,7 +214,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -297,7 +297,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -330,7 +330,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -357,7 +357,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -380,7 +380,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -408,7 +408,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.11.txt b/requirements/constraints_py3.11.txt index 87c409491..4eb27068c 100644 --- a/requirements/constraints_py3.11.txt +++ b/requirements/constraints_py3.11.txt @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -69,7 +69,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -210,7 +210,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -295,7 +295,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -328,7 +328,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -355,7 +355,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -378,7 +378,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -398,7 +398,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.11_docs.txt b/requirements/constraints_py3.11_docs.txt index 1d57556f3..49fafc60e 100644 --- a/requirements/constraints_py3.11_docs.txt +++ b/requirements/constraints_py3.11_docs.txt @@ -39,7 +39,7 @@ cloudpickle==3.0.0 comm==0.2.2 # via ipykernel czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -69,7 +69,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -278,7 +278,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -311,7 +311,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -334,13 +334,13 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via # autodoc-pydantic # numpydoc # sphinx-autodoc-typehints # sphinx-qt-documentation -sphinx-autodoc-typehints==2.0.1 +sphinx-autodoc-typehints==2.1.0 sphinx-qt-documentation==0.4.1 sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -363,7 +363,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -383,7 +383,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.11_pydantic_1.txt b/requirements/constraints_py3.11_pydantic_1.txt index abb03dfca..595a416f6 100644 --- a/requirements/constraints_py3.11_pydantic_1.txt +++ b/requirements/constraints_py3.11_pydantic_1.txt @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -67,7 +67,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -208,7 +208,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -291,7 +291,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -324,7 +324,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -351,7 +351,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -374,7 +374,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -394,7 +394,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.12.txt b/requirements/constraints_py3.12.txt index 65413423c..5508fc8d8 100644 --- a/requirements/constraints_py3.12.txt +++ b/requirements/constraints_py3.12.txt @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -69,7 +69,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -116,6 +116,9 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari mahotas==1.4.15 @@ -205,7 +208,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -290,7 +293,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -323,7 +326,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -350,7 +353,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -373,7 +376,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -393,7 +396,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.12_pydantic_1.txt b/requirements/constraints_py3.12_pydantic_1.txt index 479415659..935e1fb96 100644 --- a/requirements/constraints_py3.12_pydantic_1.txt +++ b/requirements/constraints_py3.12_pydantic_1.txt @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -67,7 +67,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -114,6 +114,9 @@ local-migrator==0.1.10 locket==1.0.0 # via partd lxml==5.2.1 + # via lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml magicgui==0.8.2 # via napari mahotas==1.4.15 @@ -203,7 +206,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -286,7 +289,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -319,7 +322,7 @@ rpds-py==0.18.0 # via # jsonschema # referencing -scikit-image==0.23.1 +scikit-image==0.23.2 # via napari scipy==1.13.0 # via @@ -346,7 +349,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -369,7 +372,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -389,7 +392,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.8.txt b/requirements/constraints_py3.8.txt index e2247db30..860f9446c 100644 --- a/requirements/constraints_py3.8.txt +++ b/requirements/constraints_py3.8.txt @@ -56,7 +56,7 @@ docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via pytest executing==2.0.1 # via stack-data @@ -73,7 +73,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2023.3.16 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -230,7 +230,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -319,7 +319,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -429,7 +429,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.8_pydantic_1.txt b/requirements/constraints_py3.8_pydantic_1.txt index 050f9f170..b2a4b6655 100644 --- a/requirements/constraints_py3.8_pydantic_1.txt +++ b/requirements/constraints_py3.8_pydantic_1.txt @@ -54,7 +54,7 @@ docutils==0.20.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via pytest executing==2.0.1 # via stack-data @@ -71,7 +71,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2023.3.16 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -228,7 +228,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -315,7 +315,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -425,7 +425,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.9.txt b/requirements/constraints_py3.9.txt index c9d4a066f..d331cc6ad 100644 --- a/requirements/constraints_py3.9.txt +++ b/requirements/constraints_py3.9.txt @@ -41,7 +41,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -54,7 +54,7 @@ docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via # ipython # pytest @@ -73,7 +73,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -220,7 +220,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -305,7 +305,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -365,7 +365,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -388,7 +388,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -416,7 +416,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel diff --git a/requirements/constraints_py3.9_pydantic_1.txt b/requirements/constraints_py3.9_pydantic_1.txt index ab5957e03..06487621c 100644 --- a/requirements/constraints_py3.9_pydantic_1.txt +++ b/requirements/constraints_py3.9_pydantic_1.txt @@ -39,7 +39,7 @@ comm==0.2.2 # via ipykernel coverage==7.4.4 czifile==2019.7.2 -dask==2024.4.1 +dask==2024.4.2 # via napari debugpy==1.8.1 # via ipykernel @@ -52,7 +52,7 @@ docutils==0.21.1 # via sphinx et-xmlfile==1.1.0 # via openpyxl -exceptiongroup==1.2.0 +exceptiongroup==1.2.1 # via # ipython # pytest @@ -71,7 +71,7 @@ hsluv==5.0.4 idna==3.7 # via requests imagecodecs==2024.1.1 -imageio==2.34.0 +imageio==2.34.1 # via # napari # napari-svg @@ -218,7 +218,7 @@ platformdirs==4.2.0 # via # jupyter-core # pooch -pluggy==1.4.0 +pluggy==1.5.0 # via # pytest # pytest-qt @@ -301,7 +301,7 @@ pyyaml==6.0.1 # dask # napari # npe2 -pyzmq==26.0.0 +pyzmq==26.0.2 # via # ipykernel # jupyter-client @@ -361,7 +361,7 @@ six==1.16.0 # python-dateutil snowballstemmer==2.2.0 # via sphinx -sphinx==7.3.5 +sphinx==7.3.7 # via numpydoc sphinxcontrib-applehelp==1.0.8 # via sphinx @@ -384,7 +384,7 @@ superqt==0.6.3 sympy==1.12 tabulate==0.9.0 # via numpydoc -tifffile==2024.2.12 +tifffile==2024.4.18 # via # czifile # napari @@ -412,7 +412,7 @@ tornado==6.4 tqdm==4.66.2 # via napari traceback-with-variables==2.0.4 -traitlets==5.14.2 +traitlets==5.14.3 # via # comm # ipykernel