Comments (13)
Woah this is really cool. We're thinking of moving core Orange to a task graph system (using dask arrays), so this is right up our alley. Would you be willing to share your code with us? :)
Regarding adding class attributes dynamically, I suggest a metaclass. Make sure the metaclass extends WidgetMetaClass
.
from orange-widget-base.
See #144. You can derive from any class, for as long as the ancestor (that is, your class containing the boiler code) is marked with openclass=True
.
Meta classes are of course an option, too, but I'd strongly encourage going with normal subclassing.
While I was writing this, @irgolic suggested meta classes. If all your widgets have the same inputs and outputs, you don't need meta classes. If they are different, this would be parametrized meta class. Go for it, if you really must. :)
from orange-widget-base.
Judging only by the code snippet you posted here, I think I may've solved this exact problem for orange3-pandas, wherein widget UIs are generated from pandas docstrings/signatures.
It's not quite ready/released yet, but if you say hi on Discord, I can share.
from orange-widget-base.
@irgolic We don't even have proper projects yet but you could already have a look at this:
https://gitlab.esrf.fr/denolf/workflow_concepts
It's an attempt at finding the optimal ECO system of projects suitable for workflows at the ESRF. Orange3 would be part of that.
We will probably have one core project for representing task graphs (persistent and at runtime):
https://gitlab.esrf.fr/denolf/workflow_concepts/-/tree/master/esrftaskgraph
And then bindings for task schedulers and graph design GUIs. This is what we have so far for Orange:
https://gitlab.esrf.fr/denolf/workflow_concepts/-/tree/master/esrf2orange3
And this is the binding for dask:
https://gitlab.esrf.fr/denolf/workflow_concepts/-/tree/master/esrf2dask
from orange-widget-base.
I don't think I can access your internal gitlab.
from orange-widget-base.
Ah sorry, it was not even a public project yet, that's how recent this is ;-). Try again.
from orange-widget-base.
I tried with a metaclass and a subclass but I need to do this
class WidgetMetaClass(type(QDialog)):
def __new__(mcs, name, bases, namespace, openclass=False, **kwargs):
cls = super().__new__(mcs, name, bases, namespace, **kwargs)
if not cls.name: # not a widget
return cls
# >>> HERE I NEED TO ADD inputs, outputs and settings
cls.convert_signals()
cls.settingsHandler = \
SettingsHandler.create(cls, template=cls.settingsHandler)
return cls
Any suggestions? Of course I could do something dodgy with convert_signals
but that might break in the future.
from orange-widget-base.
No in fact I cannot even do that because I have no way of passing new arguments.
class ESRFWidgetMetaClass(WidgetMetaClass):
def __new__(
metacls,
name,
bases,
attr,
esrftaskclass=None,
input_names=None,
output_names=None,
**kw
):
if input_names is None:
input_names = dict()
if output_names is None:
output_names = dict()
prepare_kw = {
"esrftaskclass": esrftaskclass,
"inputnamemap": input_names,
"outputnamemap": output_names,
}
# _prepare_owesrfwidgetclass need to access prepare_kw
return super().__new__(metacls, name, bases, attr, **kw)
@classmethod
def convert_signals(cls):
cls._prepare_owesrfwidgetclass()
super().convert_signals()
@classmethod
def _prepare_owesrfwidgetclass(cls):
...
from orange-widget-base.
You might need to do something funky if you wanted to use the signals syntactic sugar, but if you add to attr
(namespace) a list named inputs
of (name, type, method_name, flags)
tuples, it should be fine.
from orange-widget-base.
Ok perfect, I can do what I want now by using WidgetMetaClass
and subclassing with openclass=True
. Thanks!
from orange-widget-base.
I have foreseen that. I wrote that you'll need parametrized meta classes. :)
If all your subclasses have the same inputs and outputs, then add them to your base class, not the meta class. You have an example here: https://github.com/biolab/orange3/blob/master/Orange/widgets/utils/owlearnerwidget.py#L54. This is an open widget class that defines signals, and errors and a part of GUI... Derived classes can add to that. For instance, Logistic regression (https://github.com/biolab/orange3/blob/master/Orange/widgets/model/owlogisticregression.py#L15) adds an additional output and warning, by deriving its output from the inherited class with outputs.
I still don't see why would you need meta classes.
But if you do, you can do two things.
You can add arguments to new, just differently. You can define your meta class exactly as you did above, and then use it like this
class MyWidget(OWBaseWidget, metaclass=ESRFWidgetMetaClass, esrftaskclass=..., input_names=...):
...
The arguments to the meta class are given as the arguments to the widget class definition. Incidentally, this is how openclass
is implemented in Orange. See https://github.com/biolab/orange-widget-base/blob/master/orangewidget/widget.py#L96: openclass
is an extra argument to __new__
and it's value (which is False
be default) is overridden in, for example, the code I linked to above. https://github.com/biolab/orange3/blob/master/Orange/widgets/utils/owlearnerwidget.py#L54.
The other way is totally fancy. Parametrizing meta classes via closures.
def my_metaclass(esrftaskclass=None, input_names=None, output_names=None):
class ESRFWidgetMetaClass(WidgetMetaClass):
def __new__(metacls, name, bases):
...
return ESRFWidgetMetaClass
class MyWidget(OWBaseWidget, metaclass=my_metaclass(my_specific_task_class, my_input_names)):
....
In this way, every widget will have his specific meta class.
from orange-widget-base.
Ok perfect, I can do what I want now by using
WidgetMetaClass
and subclassing withopenclass=True
. Thanks!
No, no, don't. Just pass openclass=True
to the widget from which you plan to derive other widgets. Check this: https://github.com/biolab/orange3/blob/master/Orange/widgets/data/owpreprocess.py#L1066. This is the widget that preprocessing widgets are derived from.
class OWPreprocess(widget.OWWidget, openclass=True):
...
class Inputs:
data = Input("Data", Orange.data.Table)
class Outputs:
preprocessor = Output("Preprocessor", preprocess.preprocess.Preprocess, dynamic=False)
preprocessed_data = Output("Preprocessed Data", Orange.data.Table)
storedsettings = Setting({})
autocommit = Setting(True)
PREPROCESSORS = PREPROCESS_ACTIONS
CONTROLLER = Controller
...
from orange-widget-base.
Yes I got that. I have one common base widget from which I will be deriving my normal widgets
class OWESRFWidget(OWWidget, metaclass=ESRFWidgetMetaClass, openclass=True):
...
class MyWidget1(OWESRFWidget, esrftaskclass=MyClass1):
...
class MyWidget2(OWESRFWidget, esrftaskclass=MyClass2):
...
ESRFWidgetMetaClass
adds inputs, outputs and settings based on the esrftaskclass
argument. The classes MyClass1
, MyClass2
, ... do the actual computations (they also know what the inputs and outputs are). This is how we want to decouple GUI from computation so we can execute task graphs without needing the canvas (or Orange for that matter) by different task schedulers (luigi, dask, ... depending on what kind of distribution we need).
from orange-widget-base.
Related Issues (20)
- Override cursor handling in spinbox and autocommit is buggy ... HOT 2
- gui.TabWidget renders poorly HOT 9
- Widget geometry should be saved together with other Settings
- Line Edits don't select entire text on double click HOT 11
- ControlAreaVisible is not applied if save_position=False
- Explicit Orange3 import
- Add no shadow option?
- Opening a workflow results in many crashes HOT 3
- No module named PyQtWebEngineCore HOT 1
- ColoredBarItemDelegate: Crashes on data with missing values
- ARIMA Model Widget AttributeError: 'NoneType' object has no attribute 'control' HOT 1
- ListViewSearch: Does not filter on changed data HOT 1
- Visual settings need to be documented HOT 1
- Indicate uncommitted changes at the widget and canvas levels HOT 4
- Images in reports are too large HOT 1
- LDAvis: error on report (blank ldavis)
- ErrorReporting.handle_exception: causes segfault HOT 2
- Retain column width in QTableView HOT 1
- Show Help in widget does not work (on macOS?) HOT 3
- Error caused by `_bind_messages` when widget class includes a DataFrame-type attribute HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from orange-widget-base.