You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For remembering states of combo boxes where we choose features we tend to use contexts. We frequently use DomainContext, which works well most of the time.
It works so well that I did not notice, until now, that it is not appropriate if combo boxes within the widget are limited to a different subset of (attributes, class_vars, metas).
Here is an example:
fromOrange.dataimportTable, DomainfromOrange.widgets.tests.baseimportWidgetTestfromOrange.widgets.widgetimportOWWidgetfromOrange.widgets.guiimportcomboBoxfromOrange.widgets.settingsimport \
ContextSetting, DomainContextHandler, PerfectDomainContextHandlerfromOrange.widgets.utils.itemmodelsimportDomainModelfromorangewidget.utils.signalsimportInputclassOWProblem(OWWidget):
name="Context Problem"v1=ContextSetting(None)
v2=ContextSetting(None)
settingsHandler=DomainContextHandler()
classInputs:
data=Input("Data", Table, default=True)
def__init__(self):
super().__init__()
m1=DomainModel(DomainModel.SEPARATED,
valid_types=DomainModel.PRIMITIVE)
comboBox(self.controlArea, self, "v1", model=m1, label="All")
m2=DomainModel(DomainModel.METAS|DomainModel.CLASSES,
valid_types=DomainModel.PRIMITIVE)
comboBox(self.controlArea, self, "v2", model=m2, label="Metas + Classes")
self.contextAboutToBeOpened.connect(lambdax: self.init_interface(x[0]))
definit_interface(self, data):
domain=data.domainifdataisnotNoneelseNoneself.controls.v1.model().set_domain(domain)
self.controls.v2.model().set_domain(domain)
@Inputs.datadefset_data(self, data):
self.closeContext()
self.openContext(data)
classTestOWProblem(WidgetTest):
defsetUp(self):
self.widget=self.create_widget(OWProblem)
deftest_v2_invalid_after_reloading(self):
iris=Table("iris")
petals_in_metas=Domain(iris.domain.attributes[:2],
iris.domain.class_var,
metas=iris.domain.attributes[2:])
self.send_signal(self.widget.Inputs.data,
iris.transform(petals_in_metas))
self.widget.v1=iris.domain["sepal width"]
# v2 can have only metas and classes thus this will be invalid# context for original irisself.widget.v2=iris.domain["petal width"]
self.send_signal(self.widget.Inputs.data, iris) # crashes
Running the test gives:
File "/home/marko/dev/orange-spectroscopy/orangecontrib/spectroscopy/widgets/owproblem.py", line 42, in set_data
self.openContext(data)
File "/home/marko/dev/orange-widget-base/orangewidget/widget.py", line 1350, in openContext
self.settingsHandler.open_context(self, *a)
File "/home/marko/dev/orange3/Orange/widgets/settings.py", line 125, in open_context
super().open_context(widget, domain, *self.encode_domain(domain))
File "/home/marko/dev/orange-widget-base/orangewidget/settings.py", line 833, in open_context
self.settings_to_widget(widget, *args)
File "/home/marko/dev/orange-widget-base/orangewidget/settings.py", line 946, in settings_to_widget
_apply_setting(setting, instance, value)
File "/home/marko/dev/orange-widget-base/orangewidget/settings.py", line 204, in _apply_setting
setattr(instance, setting.name, value)
File "/home/marko/dev/orange-widget-base/orangewidget/gui.py", line 194, in __setattr__
callback(value)
File "/home/marko/dev/orange-widget-base/orangewidget/gui.py", line 2320, in __call__
self.action(*args)
File "/home/marko/dev/orange-widget-base/orangewidget/gui.py", line 2407, in action
raise ValueError("Combo box does not contain item " + repr(value))
ValueError: Combo box does not contain item ContinuousVariable(name='petal width', number_of_decimals=1)
Is this a bug in DomainContextHandler? No, it is how it was designed; it is just that I was using it wrongly. For this kind of situations, I'll need a new type of context. PerfectDomainContextHandler does not exhibit the same issue but is too restrictive. I'll need something in between.
It is a bug that contexts that match and could not be opened effectively (for any reason) block you from using the widget with that data? Probably. :) When this happens, the only solutions is to clear the settings.
The text was updated successfully, but these errors were encountered:
The only remaining problem is that exclude_attributes effectively means exclude_attributes_or_classes. Therefore, if a class var is set as v2, then the resulting context will never be matched.
However, because exclude_* is never checked for PERFECT_MATCH, the solution with exclude_attributes=True still allows the user to properly save and load the workflow even if v2 was a class variable. It is just that that particular context will match nowhere.
For remembering states of combo boxes where we choose features we tend to use contexts. We frequently use
DomainContext
, which works well most of the time.It works so well that I did not notice, until now, that it is not appropriate if combo boxes within the widget are limited to a different subset of (attributes, class_vars, metas).
Here is an example:
Running the test gives:
Is this a bug in DomainContextHandler? No, it is how it was designed; it is just that I was using it wrongly. For this kind of situations, I'll need a new type of context.
PerfectDomainContextHandler
does not exhibit the same issue but is too restrictive. I'll need something in between.It is a bug that contexts that match and could not be opened effectively (for any reason) block you from using the widget with that data? Probably. :) When this happens, the only solutions is to clear the settings.
The text was updated successfully, but these errors were encountered: