From dc48d5c26afecf60f175dff5a1b0383ab3378ce6 Mon Sep 17 00:00:00 2001 From: astaric Date: Fri, 14 Jul 2017 15:18:31 +0200 Subject: [PATCH] signals: Support extending of Inputs/Outputs classes --- Orange/widgets/model/owlinearregression.py | 4 ++-- Orange/widgets/model/owlogisticregression.py | 6 +++--- Orange/widgets/utils/signals.py | 20 +++++++++++++------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Orange/widgets/model/owlinearregression.py b/Orange/widgets/model/owlinearregression.py index 62f2bca5f43..18742113273 100644 --- a/Orange/widgets/model/owlinearregression.py +++ b/Orange/widgets/model/owlinearregression.py @@ -25,8 +25,8 @@ class OWLinearRegression(OWBaseLearner): LEARNER = LinearRegressionLearner - class Outputs: - coefficients = Output("Coefficients", Table, explicit=True) + class Outputs(OWBaseLearner.Outputs): + coefficients = Output("Coefficients", Table) #: Types REGULARIZATION_TYPES = ["No regularization", "Ridge regression (L2)", diff --git a/Orange/widgets/model/owlogisticregression.py b/Orange/widgets/model/owlogisticregression.py index aee81486609..050b62cb9fd 100644 --- a/Orange/widgets/model/owlogisticregression.py +++ b/Orange/widgets/model/owlogisticregression.py @@ -7,7 +7,7 @@ from Orange.classification.logistic_regression import LogisticRegressionLearner from Orange.widgets import settings, gui from Orange.widgets.utils.owlearnerwidget import OWBaseLearner -from Orange.widgets.widget import Output +from Orange.widgets.utils.signals import Output class OWLogisticRegression(OWBaseLearner): @@ -22,8 +22,8 @@ class OWLogisticRegression(OWBaseLearner): LEARNER = LogisticRegressionLearner - class Outputs: - coefficients = Output("Coefficients", Table, explicit=True) + class Outputs(OWBaseLearner.Outputs): + coefficients = Output("Coefficients", Table) penalty_type = settings.Setting(1) C_index = settings.Setting(61) diff --git a/Orange/widgets/utils/signals.py b/Orange/widgets/utils/signals.py index 4511da4a37e..1f8a650ea78 100644 --- a/Orange/widgets/utils/signals.py +++ b/Orange/widgets/utils/signals.py @@ -1,4 +1,5 @@ import copy +import inspect import itertools from Orange.canvas.registry.description import InputSignal, OutputSignal @@ -145,6 +146,12 @@ def send(self, value, id=None): signal_manager.send(self.widget, self.name, value, id) +def _get_members(obj, member_type): + def is_member_type(member): + return isinstance(member, member_type) + return inspect.getmembers(obj, is_member_type) + + class WidgetSignalsMixin: """Mixin for managing widget's input and output signals""" class Inputs: @@ -158,9 +165,8 @@ def __init__(self): def _bind_outputs(self): bound_cls = self.Outputs() - for name, signal in self.Outputs.__dict__.items(): - if isinstance(signal, Output): - bound_cls.__dict__[name] = signal.bound_signal(self) + for name, signal in _get_members(bound_cls, Output): + setattr(bound_cls, name, signal.bound_signal(self)) setattr(self, "Outputs", bound_cls) def send(self, signalName, value, id=None): @@ -210,8 +216,9 @@ def signal_from_args(args, signal_type): @classmethod def _check_input_handlers(cls): - unbound = [signal.name for signal in cls.Inputs.__dict__.values() - if isinstance(signal, Input) and not signal.handler] + unbound = [signal.name + for _, signal in _get_members(cls.Inputs, Input) + if not signal.handler] if unbound: raise ValueError("unbound signal(s) in {}: {}". format(cls.__name__, ", ".join(unbound))) @@ -242,8 +249,7 @@ def get_signals(cls, direction): return old_style signal_class = getattr(cls, direction.title()) - signals = [signal for signal in signal_class.__dict__.values() - if isinstance(signal, _Signal)] + signals = [signal for _, signal in _get_members(signal_class, _Signal)] return list(sorted(signals, key=lambda s: s._seq_id))