From 3b838deb4d800a0e702d2cd9de64918a90e30afa Mon Sep 17 00:00:00 2001 From: matei jordache Date: Sat, 28 Mar 2026 14:10:17 -0700 Subject: [PATCH] rework output type socket to be more flexible --- backend/execution.py | 6 ++--- backend/node_registry.py | 29 ++++++++++++++++++++-- backend/nodes/acf.py | 5 ++-- backend/nodes/angle_measure.py | 6 +++-- backend/nodes/annotations.py | 5 ++-- backend/nodes/color_map.py | 5 ++-- backend/nodes/colormap_adjust.py | 5 ++-- backend/nodes/coordinate.py | 5 ++-- backend/nodes/coordinate_pair.py | 5 ++-- backend/nodes/crop_resize_field.py | 5 ++-- backend/nodes/cross_section.py | 6 +++-- backend/nodes/cursors.py | 6 +++-- backend/nodes/curvature.py | 8 ++++-- backend/nodes/draw_mask.py | 5 ++-- backend/nodes/edge_detect.py | 5 ++-- backend/nodes/facet_level_field.py | 5 ++-- backend/nodes/fft_2d.py | 8 ++++-- backend/nodes/fft_filter_1d.py | 5 ++-- backend/nodes/fft_filter_2d.py | 5 ++-- backend/nodes/fix_zero.py | 5 ++-- backend/nodes/flip_field.py | 5 ++-- backend/nodes/folder.py | 5 ++-- backend/nodes/font_node.py | 5 ++-- backend/nodes/fractal_dimension.py | 7 ++++-- backend/nodes/gaussian_filter.py | 5 ++-- backend/nodes/grain_analysis.py | 5 ++-- backend/nodes/grain_distance_transform.py | 5 ++-- backend/nodes/histogram.py | 6 +++-- backend/nodes/image.py | 5 ++-- backend/nodes/image_demo.py | 5 ++-- backend/nodes/inverse_fft_2d.py | 5 ++-- backend/nodes/line_correction.py | 7 ++++-- backend/nodes/markup.py | 5 ++-- backend/nodes/mask_invert.py | 5 ++-- backend/nodes/mask_morphology.py | 5 ++-- backend/nodes/mask_operations.py | 5 ++-- backend/nodes/median_filter.py | 5 ++-- backend/nodes/number.py | 5 ++-- backend/nodes/plane_level_field.py | 5 ++-- backend/nodes/poly_level_field.py | 6 +++-- backend/nodes/preview_image.py | 2 +- backend/nodes/print_table.py | 2 +- backend/nodes/psdf.py | 5 ++-- backend/nodes/range_slider.py | 5 ++-- backend/nodes/rotate_field.py | 5 ++-- backend/nodes/save.py | 2 +- backend/nodes/save_image.py | 2 +- backend/nodes/scar_removal.py | 6 +++-- backend/nodes/statistics_node.py | 5 ++-- backend/nodes/stats.py | 5 ++-- backend/nodes/threshold_mask.py | 5 ++-- backend/nodes/value_display.py | 5 ++-- backend/nodes/view_3d.py | 6 +++-- backend/nodes/watershed_segmentation.py | 5 ++-- tests/test_nodes.py | 30 ++++++++++++++--------- 55 files changed, 213 insertions(+), 117 deletions(-) diff --git a/backend/execution.py b/backend/execution.py index c7f74c0..3c50a5f 100644 --- a/backend/execution.py +++ b/backend/execution.py @@ -31,7 +31,7 @@ from threading import RLock from time import perf_counter from typing import Any, Callable -from backend.node_registry import NODE_CLASS_MAPPINGS +from backend.node_registry import NODE_CLASS_MAPPINGS, get_node_output_types from backend.execution_context import active_node, execution_callbacks @@ -455,7 +455,7 @@ class ExecutionEngine: on_preview(node_id, preview) return - return_types = getattr(cls, "RETURN_TYPES", ()) + return_types = get_node_output_types(cls) for slot, type_name in enumerate(return_types): if slot >= len(result): @@ -536,7 +536,7 @@ class ExecutionEngine: import numpy as np from backend.data_types import LineData - return_types = getattr(cls, "RETURN_TYPES", ()) + return_types = get_node_output_types(cls) # Find the y-values (current slot) and try to find an x-axis y = result[slot] diff --git a/backend/node_registry.py b/backend/node_registry.py index c1b99da..41841af 100644 --- a/backend/node_registry.py +++ b/backend/node_registry.py @@ -15,6 +15,30 @@ NODE_CLASS_MAPPINGS: dict[str, type] = {} NODE_DISPLAY_NAME_MAPPINGS: dict[str, str] = {} +def get_node_output_specs(cls: type) -> tuple[tuple[str, str], ...]: + raw_outputs = getattr(cls, "OUTPUTS", None) + if raw_outputs is None: + raise AttributeError(f"{cls.__name__} must define OUTPUTS.") + + specs: list[tuple[str, str]] = [] + for index, output in enumerate(raw_outputs): + if not isinstance(output, (list, tuple)) or len(output) != 2: + raise TypeError( + f"{cls.__name__}.OUTPUTS[{index}] must be a 2-item tuple of (type, name)." + ) + type_name, name = output + specs.append((str(type_name), str(name))) + return tuple(specs) + + +def get_node_output_types(cls: type) -> tuple[str, ...]: + return tuple(type_name for type_name, _ in get_node_output_specs(cls)) + + +def get_node_output_names(cls: type) -> tuple[str, ...]: + return tuple(name for _, name in get_node_output_specs(cls)) + + def register_node(display_name: str | None = None): """ Class decorator that registers a node class into NODE_CLASS_MAPPINGS. @@ -25,6 +49,7 @@ def register_node(display_name: str | None = None): ... """ def decorator(cls: type) -> type: + get_node_output_specs(cls) name = cls.__name__ NODE_CLASS_MAPPINGS[name] = cls NODE_DISPLAY_NAME_MAPPINGS[name] = display_name or name @@ -50,8 +75,8 @@ def get_node_info(class_name: str) -> dict[str, Any]: "menu_categories": list(menu_metadata.get("menu_categories", [])), "input": input_types, "input_order": {k: list(v.keys()) for k, v in input_types.items()}, - "output": list(cls.RETURN_TYPES), - "output_name": list(getattr(cls, "RETURN_NAMES", cls.RETURN_TYPES)), + "output": list(get_node_output_types(cls)), + "output_name": list(get_node_output_names(cls)), "output_node": bool(getattr(cls, "OUTPUT_NODE", False)), "manual_trigger": bool(getattr(cls, "MANUAL_TRIGGER", False)), "description": getattr(cls, "DESCRIPTION", ""), diff --git a/backend/nodes/acf.py b/backend/nodes/acf.py index d447dcb..f031f16 100644 --- a/backend/nodes/acf.py +++ b/backend/nodes/acf.py @@ -16,8 +16,9 @@ class ACF: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("acf",) + OUTPUTS = ( + ('DATA_FIELD', 'acf'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/angle_measure.py b/backend/nodes/angle_measure.py index 1cccad4..1f01ff7 100644 --- a/backend/nodes/angle_measure.py +++ b/backend/nodes/angle_measure.py @@ -112,8 +112,10 @@ class AngleMeasure: }, } - RETURN_TYPES = ("ANNOTATION_SOURCE", "MEASURE_TABLE") - RETURN_NAMES = ("output", "measurements") + OUTPUTS = ( + ('ANNOTATION_SOURCE', 'output'), + ('MEASURE_TABLE', 'measurements'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/annotations.py b/backend/nodes/annotations.py index 6930c23..d9b2af4 100644 --- a/backend/nodes/annotations.py +++ b/backend/nodes/annotations.py @@ -43,8 +43,9 @@ class Annotations: }, } - RETURN_TYPES = ("ANNOTATION_SOURCE",) - RETURN_NAMES = ("Output",) + OUTPUTS = ( + ('ANNOTATION_SOURCE', 'output'), + ) FUNCTION = "render" DESCRIPTION = ( diff --git a/backend/nodes/color_map.py b/backend/nodes/color_map.py index dad6e53..f2ae45a 100644 --- a/backend/nodes/color_map.py +++ b/backend/nodes/color_map.py @@ -23,8 +23,9 @@ class ColorMap: } } - RETURN_TYPES = ("COLORMAP",) - RETURN_NAMES = ("colormap",) + OUTPUTS = ( + ('COLORMAP', 'colormap'), + ) FUNCTION = "build" DESCRIPTION = ( diff --git a/backend/nodes/colormap_adjust.py b/backend/nodes/colormap_adjust.py index 77b5762..da08f25 100644 --- a/backend/nodes/colormap_adjust.py +++ b/backend/nodes/colormap_adjust.py @@ -17,8 +17,9 @@ class ColormapAdjust: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/coordinate.py b/backend/nodes/coordinate.py index c0e7b02..0e3d322 100644 --- a/backend/nodes/coordinate.py +++ b/backend/nodes/coordinate.py @@ -15,8 +15,9 @@ class Coordinate: } } - RETURN_TYPES = ("COORD",) - RETURN_NAMES = ("point",) + OUTPUTS = ( + ('COORD', 'point'), + ) FUNCTION = "process" DESCRIPTION = "Output a fractional (x, y) coordinate pair in [0, 1]." diff --git a/backend/nodes/coordinate_pair.py b/backend/nodes/coordinate_pair.py index 6bfeb6c..cf32b8c 100644 --- a/backend/nodes/coordinate_pair.py +++ b/backend/nodes/coordinate_pair.py @@ -15,8 +15,9 @@ class CoordinatePair: } } - RETURN_TYPES = ("COORDPAIR",) - RETURN_NAMES = ("coord pair",) + OUTPUTS = ( + ('COORDPAIR', 'coord_pair'), + ) FUNCTION = "process" DESCRIPTION = "Output a pair of coordinates." diff --git a/backend/nodes/crop_resize_field.py b/backend/nodes/crop_resize_field.py index d9d85b8..32e7b33 100644 --- a/backend/nodes/crop_resize_field.py +++ b/backend/nodes/crop_resize_field.py @@ -26,8 +26,9 @@ class CropResizeField: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/cross_section.py b/backend/nodes/cross_section.py index b3f28cd..8ab7d05 100644 --- a/backend/nodes/cross_section.py +++ b/backend/nodes/cross_section.py @@ -27,8 +27,10 @@ class CrossSection: }, } - RETURN_TYPES = ("LINE", "COORDPAIR",) - RETURN_NAMES = ("profile", "marker pair",) + OUTPUTS = ( + ('LINE', 'profile'), + ('COORDPAIR', 'marker_pair'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/cursors.py b/backend/nodes/cursors.py index aaf52dd..661432c 100644 --- a/backend/nodes/cursors.py +++ b/backend/nodes/cursors.py @@ -27,8 +27,10 @@ class Cursors: }, } - RETURN_TYPES = ("MEASURE_TABLE", "COORDPAIR",) - RETURN_NAMES = ("measurement", "coord pair",) + OUTPUTS = ( + ('MEASURE_TABLE', 'measurement'), + ('COORDPAIR', 'coord_pair'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/curvature.py b/backend/nodes/curvature.py index 3c5aecf..3bc8e8e 100644 --- a/backend/nodes/curvature.py +++ b/backend/nodes/curvature.py @@ -287,8 +287,12 @@ class Curvature: }, } - RETURN_TYPES = ("ANNOTATION_SOURCE", "MEASURE_TABLE", "LINE", "LINE") - RETURN_NAMES = ("output", "measurements", "profile 1", "profile 2") + OUTPUTS = ( + ('ANNOTATION_SOURCE', 'output'), + ('MEASURE_TABLE', 'measurements'), + ('LINE', 'profile_1'), + ('LINE', 'profile_2'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/draw_mask.py b/backend/nodes/draw_mask.py index 0a8a9d9..e88c11f 100644 --- a/backend/nodes/draw_mask.py +++ b/backend/nodes/draw_mask.py @@ -22,8 +22,9 @@ class DrawMask: } } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/edge_detect.py b/backend/nodes/edge_detect.py index 902deb3..e0fd3aa 100644 --- a/backend/nodes/edge_detect.py +++ b/backend/nodes/edge_detect.py @@ -16,8 +16,9 @@ class EdgeDetect: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("edges",) + OUTPUTS = ( + ('DATA_FIELD', 'edges'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/facet_level_field.py b/backend/nodes/facet_level_field.py index 421bc56..1680eda 100644 --- a/backend/nodes/facet_level_field.py +++ b/backend/nodes/facet_level_field.py @@ -123,8 +123,9 @@ class FacetLevelField: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("leveled",) + OUTPUTS = ( + ('DATA_FIELD', 'leveled'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/fft_2d.py b/backend/nodes/fft_2d.py index e87668f..7df03bc 100644 --- a/backend/nodes/fft_2d.py +++ b/backend/nodes/fft_2d.py @@ -21,8 +21,12 @@ class FFT2D: } } - RETURN_TYPES = ("DATA_FIELD", "DATA_FIELD", "DATA_FIELD", "DATA_FIELD") - RETURN_NAMES = ("log_magnitude", "magnitude", "phase", "psdf") + OUTPUTS = ( + ('DATA_FIELD', 'log_magnitude'), + ('DATA_FIELD', 'magnitude'), + ('DATA_FIELD', 'phase'), + ('DATA_FIELD', 'psdf'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/fft_filter_1d.py b/backend/nodes/fft_filter_1d.py index 0817c9e..202afbf 100644 --- a/backend/nodes/fft_filter_1d.py +++ b/backend/nodes/fft_filter_1d.py @@ -29,8 +29,9 @@ class FFTFilter1D: } } - RETURN_TYPES = ("LINE",) - RETURN_NAMES = ("filtered",) + OUTPUTS = ( + ('LINE', 'filtered'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/fft_filter_2d.py b/backend/nodes/fft_filter_2d.py index da80d3d..509c182 100644 --- a/backend/nodes/fft_filter_2d.py +++ b/backend/nodes/fft_filter_2d.py @@ -30,8 +30,9 @@ class FFTFilter2D: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("filtered",) + OUTPUTS = ( + ('DATA_FIELD', 'filtered'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/fix_zero.py b/backend/nodes/fix_zero.py index f556147..be6943b 100644 --- a/backend/nodes/fix_zero.py +++ b/backend/nodes/fix_zero.py @@ -15,8 +15,9 @@ class FixZero: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("zeroed",) + OUTPUTS = ( + ('DATA_FIELD', 'zeroed'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/flip_field.py b/backend/nodes/flip_field.py index cefbf3e..6657bac 100644 --- a/backend/nodes/flip_field.py +++ b/backend/nodes/flip_field.py @@ -19,8 +19,9 @@ class FlipField: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/folder.py b/backend/nodes/folder.py index cd45137..61687fe 100644 --- a/backend/nodes/folder.py +++ b/backend/nodes/folder.py @@ -13,8 +13,9 @@ class Folder: } } - RETURN_TYPES = ("DIRECTORY",) - RETURN_NAMES = ("directory",) + OUTPUTS = ( + ('DIRECTORY', 'directory'), + ) FUNCTION = "list_files" DESCRIPTION = ( diff --git a/backend/nodes/font_node.py b/backend/nodes/font_node.py index ae96f1f..b653dba 100644 --- a/backend/nodes/font_node.py +++ b/backend/nodes/font_node.py @@ -19,8 +19,9 @@ class Font: } } - RETURN_TYPES = ("FONT",) - RETURN_NAMES = ("font",) + OUTPUTS = ( + ('FONT', 'font'), + ) FUNCTION = "build" DESCRIPTION = ( diff --git a/backend/nodes/fractal_dimension.py b/backend/nodes/fractal_dimension.py index 7090238..4a0bef7 100644 --- a/backend/nodes/fractal_dimension.py +++ b/backend/nodes/fractal_dimension.py @@ -304,8 +304,11 @@ class FractalDimension: } } - RETURN_TYPES = ("FLOAT", "LINE", "MEASURE_TABLE") - RETURN_NAMES = ("dimension", "curve", "measurements") + OUTPUTS = ( + ('FLOAT', 'dimension'), + ('LINE', 'curve'), + ('MEASURE_TABLE', 'measurements'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/gaussian_filter.py b/backend/nodes/gaussian_filter.py index b6d0be5..cc243f1 100644 --- a/backend/nodes/gaussian_filter.py +++ b/backend/nodes/gaussian_filter.py @@ -14,8 +14,9 @@ class GaussianFilter: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("filtered",) + OUTPUTS = ( + ('DATA_FIELD', 'filtered'), + ) FUNCTION = "process" DESCRIPTION = "Apply a Gaussian blur. Equivalent to gwy_data_field_filter_gaussian." diff --git a/backend/nodes/grain_analysis.py b/backend/nodes/grain_analysis.py index f2d2b7c..39b5361 100644 --- a/backend/nodes/grain_analysis.py +++ b/backend/nodes/grain_analysis.py @@ -17,8 +17,9 @@ class GrainAnalysis: } } - RETURN_TYPES = ("RECORD_TABLE",) - RETURN_NAMES = ("grain_stats",) + OUTPUTS = ( + ('RECORD_TABLE', 'grain_stats'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/grain_distance_transform.py b/backend/nodes/grain_distance_transform.py index f4780c8..cb2b355 100644 --- a/backend/nodes/grain_distance_transform.py +++ b/backend/nodes/grain_distance_transform.py @@ -103,8 +103,9 @@ class GrainDistanceTransform: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("distance",) + OUTPUTS = ( + ('DATA_FIELD', 'distance'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/histogram.py b/backend/nodes/histogram.py index dba4ca5..c8ee79e 100644 --- a/backend/nodes/histogram.py +++ b/backend/nodes/histogram.py @@ -21,8 +21,10 @@ class Histogram: } } - RETURN_TYPES = ("MEASURE_TABLE", "COORDPAIR",) - RETURN_NAMES = ("measurements", "marker pair",) + OUTPUTS = ( + ('MEASURE_TABLE', 'measurements'), + ('COORDPAIR', 'marker_pair'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/image.py b/backend/nodes/image.py index 8aa068e..6bd38ad 100644 --- a/backend/nodes/image.py +++ b/backend/nodes/image.py @@ -24,8 +24,9 @@ class Image: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "load" DESCRIPTION = ( diff --git a/backend/nodes/image_demo.py b/backend/nodes/image_demo.py index be7d1d3..7137773 100644 --- a/backend/nodes/image_demo.py +++ b/backend/nodes/image_demo.py @@ -19,8 +19,9 @@ class ImageDemo: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "load" DESCRIPTION = "Load a bundled demo file so you can try the app without providing your own data." diff --git a/backend/nodes/inverse_fft_2d.py b/backend/nodes/inverse_fft_2d.py index 2764d95..0811995 100644 --- a/backend/nodes/inverse_fft_2d.py +++ b/backend/nodes/inverse_fft_2d.py @@ -18,8 +18,9 @@ class InverseFFT2D: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("image",) + OUTPUTS = ( + ('DATA_FIELD', 'image'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/line_correction.py b/backend/nodes/line_correction.py index 041de89..d47b5db 100644 --- a/backend/nodes/line_correction.py +++ b/backend/nodes/line_correction.py @@ -307,8 +307,11 @@ class LineCorrection: }, } - RETURN_TYPES = ("DATA_FIELD", "DATA_FIELD", "LINE") - RETURN_NAMES = ("corrected", "background", "row shifts") + OUTPUTS = ( + ('DATA_FIELD', 'corrected'), + ('DATA_FIELD', 'background'), + ('LINE', 'row_shifts'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/markup.py b/backend/nodes/markup.py index 5cf8a69..f14b0aa 100644 --- a/backend/nodes/markup.py +++ b/backend/nodes/markup.py @@ -33,8 +33,9 @@ class Markup: } } - RETURN_TYPES = ("ANNOTATION_SOURCE",) - RETURN_NAMES = ("Output",) + OUTPUTS = ( + ('ANNOTATION_SOURCE', 'output'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/mask_invert.py b/backend/nodes/mask_invert.py index 4b90e0b..474797f 100644 --- a/backend/nodes/mask_invert.py +++ b/backend/nodes/mask_invert.py @@ -21,8 +21,9 @@ class MaskInvert: } } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = "Invert a binary mask — swap masked and unmasked regions." diff --git a/backend/nodes/mask_morphology.py b/backend/nodes/mask_morphology.py index 351cb34..2c7c363 100644 --- a/backend/nodes/mask_morphology.py +++ b/backend/nodes/mask_morphology.py @@ -28,8 +28,9 @@ class MaskMorphology: } } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/mask_operations.py b/backend/nodes/mask_operations.py index 1e7ed01..a9d535c 100644 --- a/backend/nodes/mask_operations.py +++ b/backend/nodes/mask_operations.py @@ -37,8 +37,9 @@ class MaskOperations: }, } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/median_filter.py b/backend/nodes/median_filter.py index 8ae7b3c..1a8e5d8 100644 --- a/backend/nodes/median_filter.py +++ b/backend/nodes/median_filter.py @@ -14,8 +14,9 @@ class MedianFilter: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("filtered",) + OUTPUTS = ( + ('DATA_FIELD', 'filtered'), + ) FUNCTION = "process" DESCRIPTION = "Apply a median filter. Equivalent to gwy_data_field_filter_median." diff --git a/backend/nodes/number.py b/backend/nodes/number.py index 9f028f4..ec2d88b 100644 --- a/backend/nodes/number.py +++ b/backend/nodes/number.py @@ -14,8 +14,9 @@ class Number: } } - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/plane_level_field.py b/backend/nodes/plane_level_field.py index bb8c15f..99dd763 100644 --- a/backend/nodes/plane_level_field.py +++ b/backend/nodes/plane_level_field.py @@ -61,8 +61,9 @@ class PlaneLevelField: }, } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("leveled",) + OUTPUTS = ( + ('DATA_FIELD', 'leveled'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/poly_level_field.py b/backend/nodes/poly_level_field.py index 09ad5b8..ba420dc 100644 --- a/backend/nodes/poly_level_field.py +++ b/backend/nodes/poly_level_field.py @@ -16,8 +16,10 @@ class PolyLevelField: } } - RETURN_TYPES = ("DATA_FIELD", "DATA_FIELD") - RETURN_NAMES = ("leveled", "background") + OUTPUTS = ( + ('DATA_FIELD', 'leveled'), + ('DATA_FIELD', 'background'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/preview_image.py b/backend/nodes/preview_image.py index d39f207..1ab5c0c 100644 --- a/backend/nodes/preview_image.py +++ b/backend/nodes/preview_image.py @@ -30,7 +30,7 @@ class PreviewImage: } } - RETURN_TYPES = () + OUTPUTS = () FUNCTION = "preview" OUTPUT_NODE = True diff --git a/backend/nodes/print_table.py b/backend/nodes/print_table.py index 30cc5ce..15ebfa2 100644 --- a/backend/nodes/print_table.py +++ b/backend/nodes/print_table.py @@ -15,7 +15,7 @@ class PrintTable: } } - RETURN_TYPES = () + OUTPUTS = () FUNCTION = "print_table" OUTPUT_NODE = True diff --git a/backend/nodes/psdf.py b/backend/nodes/psdf.py index 0fb7f4c..29a4d37 100644 --- a/backend/nodes/psdf.py +++ b/backend/nodes/psdf.py @@ -17,8 +17,9 @@ class PSDF: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("psdf",) + OUTPUTS = ( + ('DATA_FIELD', 'psdf'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/range_slider.py b/backend/nodes/range_slider.py index 11dcd01..6309305 100644 --- a/backend/nodes/range_slider.py +++ b/backend/nodes/range_slider.py @@ -23,8 +23,9 @@ class RangeSlider: } } - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/rotate_field.py b/backend/nodes/rotate_field.py index 6fd4309..866255c 100644 --- a/backend/nodes/rotate_field.py +++ b/backend/nodes/rotate_field.py @@ -18,8 +18,9 @@ class RotateField: } } - RETURN_TYPES = ("DATA_FIELD",) - RETURN_NAMES = ("field",) + OUTPUTS = ( + ('DATA_FIELD', 'field'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/save.py b/backend/nodes/save.py index ae01f32..4257ce7 100644 --- a/backend/nodes/save.py +++ b/backend/nodes/save.py @@ -61,7 +61,7 @@ class Save: }, } - RETURN_TYPES = () + OUTPUTS = () FUNCTION = "save" OUTPUT_NODE = True diff --git a/backend/nodes/save_image.py b/backend/nodes/save_image.py index 072f198..14c832c 100644 --- a/backend/nodes/save_image.py +++ b/backend/nodes/save_image.py @@ -47,7 +47,7 @@ class SaveImage: "optional": optional, } - RETURN_TYPES = () + OUTPUTS = () FUNCTION = "save" OUTPUT_NODE = True diff --git a/backend/nodes/scar_removal.py b/backend/nodes/scar_removal.py index 0011dfe..0939111 100644 --- a/backend/nodes/scar_removal.py +++ b/backend/nodes/scar_removal.py @@ -185,8 +185,10 @@ class ScarRemoval: } } - RETURN_TYPES = ("DATA_FIELD", "IMAGE") - RETURN_NAMES = ("corrected", "scar mask") + OUTPUTS = ( + ('DATA_FIELD', 'corrected'), + ('IMAGE', 'scar_mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/statistics_node.py b/backend/nodes/statistics_node.py index f508b64..c89e18d 100644 --- a/backend/nodes/statistics_node.py +++ b/backend/nodes/statistics_node.py @@ -14,8 +14,9 @@ class Statistics: } } - RETURN_TYPES = ("MEASURE_TABLE",) - RETURN_NAMES = ("stats",) + OUTPUTS = ( + ('MEASURE_TABLE', 'stats'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/stats.py b/backend/nodes/stats.py index f11fba0..77e5850 100644 --- a/backend/nodes/stats.py +++ b/backend/nodes/stats.py @@ -49,8 +49,9 @@ class Stats: } } - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/threshold_mask.py b/backend/nodes/threshold_mask.py index 108cc97..8b407fa 100644 --- a/backend/nodes/threshold_mask.py +++ b/backend/nodes/threshold_mask.py @@ -21,8 +21,9 @@ class ThresholdMask: } } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/backend/nodes/value_display.py b/backend/nodes/value_display.py index eb6cdca..e8fccee 100644 --- a/backend/nodes/value_display.py +++ b/backend/nodes/value_display.py @@ -24,8 +24,9 @@ class ValueDisplay: } } - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "display_value" DESCRIPTION = "Display a FLOAT, or a selected numeric row from a measurement table, and pass the value through unchanged." diff --git a/backend/nodes/view_3d.py b/backend/nodes/view_3d.py index bec4eb5..6731a97 100644 --- a/backend/nodes/view_3d.py +++ b/backend/nodes/view_3d.py @@ -135,8 +135,10 @@ class View3D: }, } - RETURN_TYPES = ("MESH_MODEL", "IMAGE") - RETURN_NAMES = ("mesh", "viewport") + OUTPUTS = ( + ('MESH_MODEL', 'mesh'), + ('IMAGE', 'viewport'), + ) FUNCTION = "render" OUTPUT_NODE = True diff --git a/backend/nodes/watershed_segmentation.py b/backend/nodes/watershed_segmentation.py index ecd301a..b9fcbee 100644 --- a/backend/nodes/watershed_segmentation.py +++ b/backend/nodes/watershed_segmentation.py @@ -221,8 +221,9 @@ class WatershedSegmentation: }, } - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("mask",) + OUTPUTS = ( + ('IMAGE', 'mask'), + ) FUNCTION = "process" DESCRIPTION = ( diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 9366785..b7fa58c 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -2425,8 +2425,9 @@ def test_execution_engine_numeric_socket_coercion(): def INPUT_TYPES(cls): return {"required": {"value": ("INT",)}} - RETURN_TYPES = ("INT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('INT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests" @@ -2439,8 +2440,9 @@ def test_execution_engine_numeric_socket_coercion(): def INPUT_TYPES(cls): return {"required": {"value": ("FLOAT",)}} - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests" @@ -2483,8 +2485,9 @@ def test_execution_engine_caches_unchanged_nodes(): def INPUT_TYPES(cls): return {"required": {"value": ("FLOAT",)}} - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests" @@ -2500,8 +2503,9 @@ def test_execution_engine_caches_unchanged_nodes(): def INPUT_TYPES(cls): return {"required": {"value": ("FLOAT",)}} - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests" @@ -2552,8 +2556,9 @@ def test_execution_engine_only_propagates_real_output_changes(): def INPUT_TYPES(cls): return {"required": {"value": ("FLOAT",)}} - RETURN_TYPES = ("INT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('INT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests" @@ -2569,8 +2574,9 @@ def test_execution_engine_only_propagates_real_output_changes(): def INPUT_TYPES(cls): return {"required": {"value": ("INT",)}} - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("value",) + OUTPUTS = ( + ('FLOAT', 'value'), + ) FUNCTION = "process" CATEGORY = "tests"