internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: biolab/orange3

Issue:
Scatter Plot no longer allows labelling by strings
##### Orange version
3.3.9

##### Expected behavior
Scatter Plot offers string attributes in Label dropdown.

##### Actual behavior
Cannot label by string attributes (discrete and continuous metas work).

##### Steps to reproduce the behavior
File (zoo.tab) -- Scatter Plot. Try to label dots by animal name.



Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owscatterplot.py b/Orange/widgets/visualize/owscatterplot.py
--- a/Orange/widgets/visualize/owscatterplot.py
+++ b/Orange/widgets/visualize/owscatterplot.py
@@ -198,7 +198,7 @@ def __init__(self):
             callback=self.update_colors,
             model=self.color_model, **common_options)
         self.label_model = DomainModel(
-            placeholder="(No labels)", valid_types=dmod.PRIMITIVE)
+            placeholder="(No labels)")
         self.cb_attr_label = gui.comboBox(
             box, self, "graph.attr_label", label="Label:",
             callback=self.graph.update_labels,


Test patch:
Repository: biolab/orange3

Issue:
Wrong error message for multitarget prediction
##### Expected behavior

Error when having two or more target variables should be "Too many target variables."

##### Actual behavior

Error says "Data has no target variable."

##### Steps to reproduce the behavior

Set two attributes in File widget to be target variable and connect Classification Tree or Test&Score to it.



Discussion:

Resolving patch:
diff --git a/Orange/widgets/evaluate/owtestlearners.py b/Orange/widgets/evaluate/owtestlearners.py
--- a/Orange/widgets/evaluate/owtestlearners.py
+++ b/Orange/widgets/evaluate/owtestlearners.py
@@ -165,17 +165,18 @@ class OWTestLearners(OWWidget):
     class_selection = settings.ContextSetting(TARGET_AVERAGE)
 
     class Error(OWWidget.Error):
-        class_required = Msg("Train data input requires a class variable")
-        class_required_test = Msg("Test data input requires a class variable")
+        class_required = Msg("Train data input requires a target variable.")
+        too_many_classes = Msg("Too many target variables.")
+        class_required_test = Msg("Test data input requires a target variable.")
         too_many_folds = Msg("Number of folds exceeds the data size")
         class_inconsistent = Msg("Test and train data sets "
-                                 "have different classes")
+                                 "have different target variables.")
 
     class Warning(OWWidget.Warning):
         missing_data = \
-            Msg("Instances with unknown target values were removed from{}data")
-        test_data_missing = Msg("Missing separate test data input")
-        scores_not_computed = Msg("Some scores could not be computed")
+            Msg("Instances with unknown target values were removed from{}data.")
+        test_data_missing = Msg("Missing separate test data input.")
+        scores_not_computed = Msg("Some scores could not be computed.")
         test_data_unused = Msg("Test data is present but unused. "
                                "Select 'Test on test data' to use it.")
 
@@ -273,11 +274,15 @@ def set_train_data(self, data):
         Set the input training dataset.
         """
         self.Information.data_sampled.clear()
-        if data and not data.domain.class_var:
+        if data and not data.domain.class_vars:
             self.Error.class_required()
             data = None
+        elif data and len(data.domain.class_vars) > 1:
+            self.Error.too_many_classes()
+            data = None
         else:
             self.Error.class_required.clear()
+            self.Error.too_many_classes.clear()
 
         if isinstance(data, SqlTable):
             if data.approx_len() < AUTO_DL_LIMIT:


Test patch:
Repository: biolab/orange3

Issue:
Scatter plot: Report crashes when the widget has no data
https://sentry.io/biolab/orange3/issues/197554235/

```
AttributeError:  'NoneType' object has no attribute 'is_discrete'
  Module "Orange.canvas.report.report", line 32, in show_report

    self.create_report_html()
  Module "Orange.canvas.report.report", line 54, in create_report_html

    self.send_report()
  Module "Orange.widgets.visualize.owscatterplot", line 504, in send_report

    ("Jittering", (self.attr_x.is_discrete or
```


Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owscatterplot.py b/Orange/widgets/visualize/owscatterplot.py
--- a/Orange/widgets/visualize/owscatterplot.py
+++ b/Orange/widgets/visualize/owscatterplot.py
@@ -494,6 +494,8 @@ def get_widget_name_extension(self):
             return "{} vs {}".format(self.attr_x.name, self.attr_y.name)
 
     def send_report(self):
+        if self.data is None:
+            return
         def name(var):
             return var and var.name
         caption = report.render_items_vert((


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_owscatterplot.py b/Orange/widgets/visualize/tests/test_owscatterplot.py
--- a/Orange/widgets/visualize/tests/test_owscatterplot.py
+++ b/Orange/widgets/visualize/tests/test_owscatterplot.py
@@ -1,5 +1,7 @@
 # Test methods with long descriptive names can omit docstrings
 # pylint: disable=missing-docstring
+from unittest.mock import MagicMock
+
 import numpy as np
 
 from AnyQt.QtCore import QRectF
@@ -91,3 +93,12 @@ def test_error_message(self):
         self.assertTrue(self.widget.Warning.missing_coords.is_shown())
         self.send_signal("Data", None)
         self.assertFalse(self.widget.Warning.missing_coords.is_shown())
+
+    def test_report_on_empty(self):
+        self.widget.report_plot = MagicMock()
+        self.widget.report_caption = MagicMock()
+        self.widget.report_items = MagicMock()
+        self.widget.send_report()  # Essentially, don't crash
+        self.widget.report_plot.assert_not_called()
+        self.widget.report_caption.assert_not_called()
+        self.widget.report_items.assert_not_called()
Repository: biolab/orange3

Issue:
OWHeatmap: extend check to all non-continuous attributes.
##### Expected behavior
Display an error if dataset contains no continuous attributes.

##### Actual behavior
Widget crashes if presented only with string attributes.

Annoying when Heatmap is placed after e.g. Select Columns.


Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owheatmap.py b/Orange/widgets/visualize/owheatmap.py
--- a/Orange/widgets/visualize/owheatmap.py
+++ b/Orange/widgets/visualize/owheatmap.py
@@ -478,6 +478,9 @@ class Error(widget.OWWidget.Error):
         no_continuous = Msg("No continuous feature columns")
         not_enough_memory = Msg("Not enough memory to show this data")
 
+    class Warning(widget.OWWidget.Warning):
+        threshold_error = Msg("Low slider should be less than High")
+
     def __init__(self):
         super().__init__()
 
@@ -692,6 +695,7 @@ def set_dataset(self, data=None):
                 data_sample.download_data(2000, partial=True)
                 data = Table(data_sample)
 
+
         if data is not None and sp.issparse(data.X):
             try:
                 data = data.copy()
@@ -703,6 +707,13 @@ def set_dataset(self, data=None):
                 self.Information.sparse_densified()
 
         input_data = data
+
+        # Data contains no attributes or meta attributes only
+        if data is not None and len(data.domain.attributes) == 0:
+            self.Error.no_continuous()
+            input_data = data = None
+
+        # Data contains some discrete attributes which must be filtered
         if data is not None and \
                 any(var.is_discrete for var in data.domain.attributes):
             ndisc = sum(var.is_discrete for var in data.domain.attributes)
@@ -1393,7 +1404,15 @@ def update_grid_spacing(self):
             layout.setSpacing(self.SpaceX)
             self.__fixup_grid_layout()
 
+    def check_threshold_consistency(self):
+        return self.threshold_low < self.threshold_high
+
     def update_color_schema(self):
+        if not self.check_threshold_consistency():
+            self.Warning.threshold_error()
+            return
+        else:
+            self.Warning.clear()
         palette = self.color_palette()
         for heatmap in self.heatmap_widgets():
             heatmap.set_color_table(palette)


Test patch:
Repository: biolab/orange3

Issue:
IndexError:  list index out of range
https://sentry.io/biolab/orange3/issues/198897981/

```
IndexError:  list index out of range
  Module "Orange.canvas.report.report", line 32, in show_report

    self.create_report_html()
  Module "Orange.canvas.report.report", line 54, in create_report_html

    self.send_report()
  Module "Orange.widgets.evaluate.owpredictions", line 508, in send_report

    for i in self.selected_classes])
  Module "Orange.widgets.evaluate.owpredictions", line 508, in <listcomp>

    for i in self.selected_classes])
```


Discussion:

Resolving patch:
diff --git a/Orange/widgets/evaluate/owpredictions.py b/Orange/widgets/evaluate/owpredictions.py
--- a/Orange/widgets/evaluate/owpredictions.py
+++ b/Orange/widgets/evaluate/owpredictions.py
@@ -504,7 +504,7 @@ def merge_data_with_predictions():
             text = self.infolabel.text().replace('\n', '<br>')
             if self.show_probabilities and self.selected_classes:
                 text += '<br>Showing probabilities for: '
-                text += ', '. join([self.data.domain.class_var.values[i]
+                text += ', '. join([self.class_values[i]
                                     for i in self.selected_classes])
             self.report_paragraph('Info', text)
             self.report_table("Data & Predictions", merge_data_with_predictions(),


Test patch:
Repository: biolab/orange3

Issue:
AttributeError:  'NoneType' object has no attribute 'name'
https://sentry.io/biolab/orange3/issues/200714524/

```
AttributeError:  'NoneType' object has no attribute 'name'
  Module "Orange.widgets.gui", line 2237, in __call__

    self.func(**kwds)
  Module "Orange.widgets.visualize.owdistributions", line 361, in _on_relative_freq_changed

    self.display_contingency()
  Module "Orange.widgets.visualize.owdistributions", line 384, in display_contingency

    bottomaxis.setLabel(var.name)
```


Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owdistributions.py b/Orange/widgets/visualize/owdistributions.py
--- a/Orange/widgets/visualize/owdistributions.py
+++ b/Orange/widgets/visualize/owdistributions.py
@@ -26,7 +26,7 @@
 from Orange.widgets.visualize.owlinearprojection import LegendItem, ScatterPlotItem
 from Orange.widgets.io import FileFormat
 
-from .owscatterplotgraph import HelpEventDelegate
+from Orange.widgets.visualize.owscatterplotgraph import HelpEventDelegate
 
 def selected_index(view):
     """Return the selected integer `index` (row) in the view.
@@ -250,6 +250,8 @@ def clear(self):
         self.groupvar_idx = 0
         self._legend.clear()
         self._legend.hide()
+        self.groupvarview.clear()
+        self.cb_prob.clear()
 
     def _setup_smoothing(self):
         if not self.disc_cont and self.var and self.var.is_continuous:


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_owdistributions.py b/Orange/widgets/visualize/tests/test_owdistributions.py
--- a/Orange/widgets/visualize/tests/test_owdistributions.py
+++ b/Orange/widgets/visualize/tests/test_owdistributions.py
@@ -14,6 +14,7 @@ def setUpClass(cls):
         super().setUpClass()
         dataset_dirs.append(test_dirname())
         cls.data = Table("test9.tab")
+        cls.iris = Table("iris")
 
     def setUp(self):
         self.widget = self.create_widget(OWDistributions)
@@ -33,3 +34,12 @@ def test_metas(self):
         self.widget.cb_disc_cont.setChecked(True)
         self.widget.variable_idx = 2
         self.widget._setup()
+
+    def test_remove_data(self):
+        """Check widget when data is removed"""
+        self.send_signal("Data", self.iris)
+        self.assertEqual(self.widget.cb_prob.count(), 5)
+        self.assertEqual(self.widget.groupvarview.count(), 2)
+        self.send_signal("Data", None)
+        self.assertEqual(self.widget.cb_prob.count(), 0)
+        self.assertEqual(self.widget.groupvarview.count(), 0)
Repository: biolab/orange3

Issue:
AttributeError:  'ContinuousVariable' object has no attribute 'values'
https://sentry.io/biolab/orange3/issues/196782791/

```
AttributeError:  'ContinuousVariable' object has no attribute 'values'
  Module "Orange.widgets.gui", line 2237, in __call__

    self.func(**kwds)
  Module "Orange.widgets.visualize.owmosaic", line 458, in reset_graph

    self.update_graph()
  Module "Orange.widgets.visualize.owmosaic", line 943, in update_graph

    get_conditional_distribution(data, attr_list)
  Module "Orange.widgets.visualize.owmosaic", line 981, in get_conditional_distribution

    for indices in product(*(range(len(a.values)) for a in attr)):
  Module "Orange.widgets.visualize.owmosaic", line 981, in <genexpr>

    for indices in product(*(range(len(a.values)) for a in attr)):
```


Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owmosaic.py b/Orange/widgets/visualize/owmosaic.py
--- a/Orange/widgets/visualize/owmosaic.py
+++ b/Orange/widgets/visualize/owmosaic.py
@@ -404,7 +404,8 @@ def set_data(self, data):
             self.discrete_data = None
         elif any(attr.is_continuous for attr in data.domain):
             self.discrete_data = Discretize(
-                method=EqualFreq(n=4), discretize_classes=True)(data)
+                method=EqualFreq(n=4), discretize_classes=True,
+                discretize_metas=True)(data)
         else:
             self.discrete_data = self.data
 


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_owmosaic.py b/Orange/widgets/visualize/tests/test_owmosaic.py
--- a/Orange/widgets/visualize/tests/test_owmosaic.py
+++ b/Orange/widgets/visualize/tests/test_owmosaic.py
@@ -1,9 +1,11 @@
 # Test methods with long descriptive names can omit docstrings
 # pylint: disable=missing-docstring
+import numpy as np
+
 from AnyQt.QtCore import QEvent, QPoint, Qt
 from AnyQt.QtGui import QMouseEvent
 
-from Orange.data import Table, DiscreteVariable, Domain
+from Orange.data import Table, DiscreteVariable, Domain, ContinuousVariable
 from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin
 from Orange.widgets.visualize.owmosaic import OWMosaicDisplay, MosaicVizRank
 
@@ -26,6 +28,14 @@ def _select_data(self):
             Qt.LeftButton, Qt.KeyboardModifiers()))
         return [2, 3, 9, 23, 29, 30, 34, 35, 37, 42, 47, 49]
 
+    def test_continuous_metas(self):
+        """Check widget for dataset with continuous metas"""
+        domain = Domain([ContinuousVariable("c1")],
+                        metas=[ContinuousVariable("m")])
+        data = Table(domain, np.arange(6).reshape(6, 1),
+                     metas=np.arange(6).reshape(6, 1))
+        self.send_signal("Data", data)
+
 
 # Derive from WidgetTest to simplify creation of the Mosaic widget, although
 # we are actually testing the MosaicVizRank dialog and not the widget
Repository: biolab/orange3

Issue:
File widget: slow loading of large files
##### Orange version
master

##### Expected behavior
A file with ~1000 continuous attributes and ~10000 samples is loaded in less than a second.

##### Actual behavior
It is way to slow.

##### Additional info (worksheets, data, screenshots, ...)
Currently the changes to the domain in the bottom part of the file widget are always applied (even if there are none). Perhaps speed up loading by giving the modified domain info to the file reader (suggestion by @astaric ).




Discussion:

Resolving patch:
diff --git a/Orange/widgets/utils/domaineditor.py b/Orange/widgets/utils/domaineditor.py
--- a/Orange/widgets/utils/domaineditor.py
+++ b/Orange/widgets/utils/domaineditor.py
@@ -217,13 +217,20 @@ def is_missing(x):
             if place == Place.skip:
                 continue
             if orig_plc == Place.meta:
-                col_data = list(chain(*data[:, orig_var].metas))
+                col_data = data[:, orig_var].metas
+            elif orig_plc == Place.class_var:
+                col_data = data[:, orig_var].Y
             else:
-                col_data = list(chain(*data[:, orig_var]))
+                col_data = data[:, orig_var].X
+            col_data = col_data.ravel()
             if name == orig_var.name and tpe == type(orig_var):
                 var = orig_var
+            elif tpe == type(orig_var):
+                # change the name so that all_vars will get the correct name
+                orig_var.name = name
+                var = orig_var
             elif tpe == DiscreteVariable:
-                values = list(str(i) for i in set(col_data) if not is_missing(i))
+                values = list(str(i) for i in np.unique(col_data) if not is_missing(i))
                 var = tpe(name, values)
                 col_data = [np.nan if is_missing(x) else values.index(str(x))
                             for x in col_data]


Test patch:
Repository: biolab/orange3

Issue:
IndexError:  index out of bounds: 0 <= 0 <= 0, 0 <= 5 <= 0, 0 <= 5
`Table.__repr__` dies on sparse matrices with less than 5 rows since scipy does not support indexing [:5] for matrices with less than 5 row.

https://sentry.io/biolab/orange3/issues/196743325/

```
IndexError:  index out of bounds: 0 <= 0 <= 0, 0 <= 5 <= 0, 0 <= 5
(13 additional frame(s) were not displayed)
...
  Module "Orange.data.table", line 659, in __getitem__

    return self.from_table_rows(self, key)
  Module "Orange.data.table", line 408, in from_table_rows

    self.X = source.X[row_indices]
  Module "scipy.sparse.csr", line 284, in __getitem__

    return self._get_submatrix(row, col)
  Module "scipy.sparse.csr", line 411, in _get_submatrix

    check_bounds(i0, i1, M)
  Module "scipy.sparse.csr", line 407, in check_bounds

    " %d <= %d" % (i0, num, i1, num, i0, i1))
```


Discussion:

Resolving patch:
diff --git a/Orange/data/table.py b/Orange/data/table.py
--- a/Orange/data/table.py
+++ b/Orange/data/table.py
@@ -803,8 +803,11 @@ def __str__(self):
         return "[" + ",\n ".join(str(ex) for ex in self)
 
     def __repr__(self):
-        s = "[" + ",\n ".join(repr(ex) for ex in self[:5])
-        if len(self) > 5:
+        head = 5
+        if self.is_sparse():
+            head = min(self.X.shape[0], head)
+        s = "[" + ",\n ".join(repr(ex) for ex in self[:head])
+        if len(self) > head:
             s += ",\n ..."
         s += "\n]"
         return s


Test patch:
diff --git a/Orange/tests/test_table.py b/Orange/tests/test_table.py
--- a/Orange/tests/test_table.py
+++ b/Orange/tests/test_table.py
@@ -1213,6 +1213,11 @@ def test_is_sparse(self):
         table.X = sp.csr_matrix(table.X)
         self.assertTrue(table.is_sparse())
 
+    def test_repr_sparse_with_one_row(self):
+        table = data.Table("iris")[:1]
+        table.X = sp.csr_matrix(table.X)
+        repr(table)     # make sure repr does not crash
+
 
 def column_sizes(table):
     return (len(table.domain.attributes),
Repository: biolab/orange3

Issue:
Manifold Learning result is recalculated on no parameter change
##### Orange version
3.3.10

The result of Manifold Learning is recalculated every single time a numeric input element loses focus in its settings. It should only happen if the value has been changed.



Discussion:

Resolving patch:
diff --git a/Orange/widgets/gui.py b/Orange/widgets/gui.py
--- a/Orange/widgets/gui.py
+++ b/Orange/widgets/gui.py
@@ -502,15 +502,23 @@ def __init__(self, minv, maxv, step, parent=None):
         super().__init__(parent)
         self.setRange(minv, maxv)
         self.setSingleStep(step)
+        self.changed = False
+
+    def onValueChanged(self):
+        """
+        Sets the flag to determine whether the value has been changed.
+        """
+        self.changed = True
 
     def onEnter(self):
         """
         Commits the change by calling the appropriate callbacks.
         """
-        if self.cback:
+        if self.cback and self.changed:
             self.cback(int(str(self.text())))
-        if self.cfunc:
+        if self.cfunc and self.changed:
             self.cfunc()
+        self.changed = False
 
 
 class DoubleSpinBoxWFocusOut(QtWidgets.QDoubleSpinBox):
@@ -522,12 +530,20 @@ def __init__(self, minv, maxv, step, parent):
         self.setDecimals(math.ceil(-math.log10(step)))
         self.setRange(minv, maxv)
         self.setSingleStep(step)
+        self.changed = False
+
+    def onValueChanged(self):
+        """
+        Sets the flag to determine whether the value has been changed.
+        """
+        self.changed = True
 
     def onEnter(self):
-        if self.cback:
+        if self.cback and self.changed:
             self.cback(float(str(self.text()).replace(",", ".")))
-        if self.cfunc:
+        if self.cfunc and self.changed:
             self.cfunc()
+        self.changed = False
 
 
 def spin(widget, master, value, minv, maxv, step=1, box=None, label=None,
@@ -650,6 +666,7 @@ def spin(widget, master, value, minv, maxv, step=1, box=None, label=None,
         cbox.disables = [sbox]
         cbox.makeConsistent()
     if callback and callbackOnReturn:
+        sbox.valueChanged.connect(sbox.onValueChanged)
         sbox.editingFinished.connect(sbox.onEnter)
         if hasattr(sbox, "upButton"):
             sbox.upButton().clicked.connect(


Test patch: