{
    "file_diffs": [
        {
            "old_file_content": "from itertools import chain\n\nimport numpy as np\n\nfrom AnyQt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex, QTimer\nfrom AnyQt.QtGui import QColor, QFont, QBrush\nfrom AnyQt.QtWidgets import QHeaderView, QColorDialog, QTableView, QComboBox\n\nimport Orange\nfrom Orange.util import color_to_hex\nfrom Orange.widgets import widget, settings, gui\nfrom Orange.widgets.gui import HorizontalGridDelegate\nfrom Orange.widgets.utils import itemmodels, colorpalettes\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.widget import Input, Output\nfrom orangewidget.settings import IncompatibleContext\n\nColorRole = next(gui.OrangeUserRole)\nStripRole = next(gui.OrangeUserRole)\n\n\nclass AttrDesc:\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (Variable): an instance of variable\n        new_name (str or `None`): a changed name or `None`\n    \"\"\"\n    def __init__(self, var):\n        self.var = var\n        self.new_name = None\n\n    @property\n    def name(self):\n        return self.new_name or self.var.name\n\n    @name.setter\n    def name(self, name):\n        self.new_name = name\n\n\nclass DiscAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (DiscreteVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        new_colors (list of tuple or None): new colors as tuples (R, G, B)\n        new_values (list of str or None): new names for values, if changed\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        self.new_colors = None\n        self.new_values = None\n\n    @property\n    def colors(self):\n        if self.new_colors is None:\n            return self.var.colors\n        else:\n            return self.new_colors\n\n    def set_color(self, i, color):\n        if self.new_colors is None:\n            self.new_colors = list(self.var.colors)\n        self.new_colors[i] = color\n\n    @property\n    def values(self):\n        return tuple(self.new_values or self.var.values)\n\n    def set_value(self, i, value):\n        if not self.new_values:\n            self.new_values = list(self.var.values)\n        self.new_values[i] = value\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name, values=self.values)\n        new_var.colors = np.asarray(self.colors)\n        return new_var\n\n\nclass ContAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (ContinuousVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        palette_name (str or None): name of palette or None if unmodified\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        if var.palette.name not in colorpalettes.ContinuousPalettes:\n            self.new_palette_name = colorpalettes.DefaultContinuousPaletteName\n        else:\n            self.new_palette_name = None\n\n    @property\n    def palette_name(self):\n        return self.new_palette_name or self.var.palette.name\n\n    @palette_name.setter\n    def palette_name(self, palette_name):\n        self.new_palette_name = palette_name\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name)\n        new_var.attributes[\"palette\"] = self.palette_name\n        return new_var\n\n\nclass ColorTableModel(QAbstractTableModel):\n    \"\"\"\n    Base color model for discrete and continuous variables. The model handles:\n    - the first column - variable name (including setData)\n    - flags\n    - row count, computed as len(attrdescs)\n\n    Attribute:\n        attrdescs (list of AttrDesc): attrdescs with user-defined changes\n    \"\"\"\n    def __init__(self):\n        QAbstractTableModel.__init__(self)\n        self.attrdescs = []\n\n    @staticmethod\n    def flags(_):  # pragma: no cover\n        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable\n\n    def set_data(self, attrdescs):\n        self.modelAboutToBeReset.emit()\n        self.attrdescs = attrdescs\n        self.modelReset.emit()\n\n    def rowCount(self, parent=QModelIndex()):\n        return 0 if parent.isValid() else len(self.attrdescs)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # Only valid for the first column; derived classes implement the rest\n        row = index.row()\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return self.attrdescs[row].name\n        if role == Qt.FontRole:\n            font = QFont()\n            font.setBold(True)\n            return font\n        if role == Qt.TextAlignmentRole:\n            return Qt.AlignRight | Qt.AlignVCenter\n        return None\n\n    def setData(self, index, value, role):\n        # Only valid for the first column; derived classes implement the rest\n        if role == Qt.EditRole:\n            self.attrdescs[index.row()].name = value\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass DiscColorTableModel(ColorTableModel):\n    \"\"\"\n    A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n    \"\"\"\n    def columnCount(self, parent=QModelIndex()):\n        if parent.isValid():\n            return 0\n        return 1 + max((len(row.var.values) for row in self.attrdescs),\n                       default=0)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # pylint: disable=too-many-return-statements\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().data(index, role)\n\n        desc = self.attrdescs[row]\n        if col > len(desc.var.values):\n            return None\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return desc.values[col - 1]\n\n        color = desc.colors[col - 1]\n        if role == Qt.DecorationRole:\n            return QColor(*color)\n        if role == Qt.ToolTipRole:\n            return color_to_hex(color)\n        if role == ColorRole:\n            return color\n        return None\n\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n\n        desc = self.attrdescs[row]\n        if role == ColorRole:\n            desc.set_color(col - 1, value[:3])\n        elif role == Qt.EditRole:\n            desc.set_value(col - 1, value)\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass ContColorTableModel(ColorTableModel):\n    \"\"\"A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n\n    Attributes:\n        mouse_row (int): the row over which the mouse is hovering\n    \"\"\"\n    def __init__(self):\n        super().__init__()\n        self.mouse_row = None\n\n    def set_mouse_row(self, row):\n        self.mouse_row = row\n\n    @staticmethod\n    def columnCount(parent=QModelIndex()):\n        return 0 if parent.isValid() else 3\n\n    def data(self, index, role=Qt.DisplayRole):\n        def _column0():\n            return ColorTableModel.data(self, index, role)\n\n        def _column1():\n            palette = colorpalettes.ContinuousPalettes[desc.palette_name]\n            if role == Qt.ToolTipRole:\n                return palette.friendly_name\n            if role == ColorRole:\n                return palette\n            if role == StripRole:\n                return palette.color_strip(128, 16)\n            if role == Qt.SizeHintRole:\n                return QSize(150, 16)\n            return None\n\n        def _column2():\n            if role == Qt.SizeHintRole:\n                return QSize(100, 1)\n            if role == Qt.ForegroundRole:\n                return QBrush(Qt.blue)\n            if row == self.mouse_row and role == Qt.DisplayRole:\n                return \"Copy to all\"\n            return None\n\n        row, col = index.row(), index.column()\n        desc = self.attrdescs[row]\n        if 0 <= col <= 2:\n            return [_column0, _column1, _column2][col]()\n\n    # noinspection PyMethodOverriding\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n        if role == ColorRole:\n            self.attrdescs[row].palette_name = value.name\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n    def copy_to_all(self, index):\n        palette_name = self.attrdescs[index.row()].palette_name\n        for desc in self.attrdescs:\n            desc.palette_name = palette_name\n        self.dataChanged.emit(self.index(0, 1), self.index(self.rowCount(), 1))\n\n\nclass ColorStripDelegate(HorizontalGridDelegate):\n    def __init__(self, view):\n        super().__init__()\n        self.view = view\n\n    def createEditor(self, parent, option, index):\n        class Combo(QComboBox):\n            def __init__(self, parent, initial_data):\n                super().__init__(parent)\n                model = itemmodels.ContinuousPalettesModel(icon_width=128)\n                self.setModel(model)\n                self.setCurrentIndex(model.indexOf(initial_data))\n                self.setIconSize(QSize(128, 16))\n                QTimer.singleShot(0, self.showPopup)\n\n            def hidePopup(self):\n                super().hidePopup()\n                view.closeEditor(self, ColorStripDelegate.NoHint)\n\n        def select(i):\n            self.view.model().setData(\n                index,\n                combo.model().index(i, 0).data(Qt.UserRole),\n                ColorRole)\n\n        view = self.view\n        combo = Combo(parent, index.data(ColorRole))\n        combo.currentIndexChanged[int].connect(select)\n        return combo\n\n    def paint(self, painter, option, index):\n        strip = index.data(StripRole)\n        rect = option.rect\n        painter.drawPixmap(\n            rect.x() + 13, rect.y() + (rect.height() - strip.height()) / 2,\n            strip)\n        super().paint(painter, option, index)\n\n\nclass ColorTable(QTableView):\n    \"\"\"\n    The base table view for discrete and continuous attributes.\n\n    Sets the basic properties of the table and implementes mouseRelease that\n    calls handle_click with appropriate index. It also prepares a grid_deleagte\n    that is used in derived classes.\n    \"\"\"\n    def __init__(self, model):\n        QTableView.__init__(self)\n        self.horizontalHeader().hide()\n        self.verticalHeader().hide()\n        self.setShowGrid(False)\n        self.setSelectionMode(QTableView.NoSelection)\n        self.setModel(model)\n        # View doesn't take ownership of delegates, so we store it here\n        self.grid_delegate = HorizontalGridDelegate()\n\n    def mouseReleaseEvent(self, event):\n        index = self.indexAt(event.pos())\n        if not index.isValid():\n            return\n        rect = self.visualRect(index)\n        self.handle_click(index, event.pos().x() - rect.x())\n\n\nclass DiscreteTable(ColorTable):\n    \"\"\"Table view for discrete variables\"\"\"\n    def __init__(self, model):\n        super().__init__(model)\n        self.horizontalHeader().setSectionResizeMode(\n            QHeaderView.ResizeToContents)\n        self.setItemDelegate(self.grid_delegate)\n        self.setEditTriggers(QTableView.NoEditTriggers)\n\n    def handle_click(self, index, x_offset):\n        \"\"\"\n        Handle click events for the first column (call the edit method)\n        and the second (call method for changing the palette)\n        \"\"\"\n        if self.model().data(index, Qt.EditRole) is None:\n            return\n        if index.column() == 0 or x_offset > 24:\n            self.edit(index)\n        else:\n            self.change_color(index)\n\n    def change_color(self, index):\n        \"\"\"Invoke palette editor and set the color\"\"\"\n        color = self.model().data(index, ColorRole)\n        if color is None:\n            return\n        dlg = QColorDialog(QColor(*color))\n        if dlg.exec():\n            color = dlg.selectedColor()\n            self.model().setData(index, color.getRgb(), ColorRole)\n\n\nclass ContinuousTable(ColorTable):\n    \"\"\"Table view for continuous variables\"\"\"\n\n    def __init__(self, model):\n        super().__init__(model)\n        self.viewport().setMouseTracking(True)\n        # View doesn't take ownership of delegates, so we must store it\n        self.color_delegate = ColorStripDelegate(self)\n        self.setItemDelegateForColumn(0, self.grid_delegate)\n        self.setItemDelegateForColumn(1, self.color_delegate)\n        self.setColumnWidth(1, 256)\n        self.setEditTriggers(\n            QTableView.SelectedClicked | QTableView.DoubleClicked)\n\n    def mouseMoveEvent(self, event):\n        \"\"\"Store the hovered row index in the model, trigger viewport update\"\"\"\n        pos = event.pos()\n        ind = self.indexAt(pos)\n        self.model().set_mouse_row(ind.row())\n        super().mouseMoveEvent(event)\n        self.viewport().update()\n\n    def leaveEvent(self, _):\n        \"\"\"Remove the stored the hovered row index, trigger viewport update\"\"\"\n        self.model().set_mouse_row(None)\n        self.viewport().update()\n\n    def handle_click(self, index, _):\n        \"\"\"Call the specific methods for handling clicks for each column\"\"\"\n        if index.column() < 2:\n            self.edit(index)\n        elif index.column() == 2:\n            self.model().copy_to_all(index)\n\n\nclass OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n        else:\n            self.data = data\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    WidgetPreview(OWColor).run(Orange.data.Table(\"heart_disease.tab\"))\n",
            "new_file_content": "from itertools import chain\n\nimport numpy as np\n\nfrom AnyQt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex, QTimer\nfrom AnyQt.QtGui import QColor, QFont, QBrush\nfrom AnyQt.QtWidgets import QHeaderView, QColorDialog, QTableView, QComboBox\n\nimport Orange\nfrom Orange.util import color_to_hex\nfrom Orange.widgets import widget, settings, gui\nfrom Orange.widgets.gui import HorizontalGridDelegate\nfrom Orange.widgets.utils import itemmodels, colorpalettes\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.widget import Input, Output\nfrom orangewidget.settings import IncompatibleContext\n\nColorRole = next(gui.OrangeUserRole)\nStripRole = next(gui.OrangeUserRole)\n\n\nclass AttrDesc:\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (Variable): an instance of variable\n        new_name (str or `None`): a changed name or `None`\n    \"\"\"\n    def __init__(self, var):\n        self.var = var\n        self.new_name = None\n\n    @property\n    def name(self):\n        return self.new_name or self.var.name\n\n    @name.setter\n    def name(self, name):\n        self.new_name = name\n\n\nclass DiscAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (DiscreteVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        new_colors (list of tuple or None): new colors as tuples (R, G, B)\n        new_values (list of str or None): new names for values, if changed\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        self.new_colors = None\n        self.new_values = None\n\n    @property\n    def colors(self):\n        if self.new_colors is None:\n            return self.var.colors\n        else:\n            return self.new_colors\n\n    def set_color(self, i, color):\n        if self.new_colors is None:\n            self.new_colors = list(self.var.colors)\n        self.new_colors[i] = color\n\n    @property\n    def values(self):\n        return tuple(self.new_values or self.var.values)\n\n    def set_value(self, i, value):\n        if not self.new_values:\n            self.new_values = list(self.var.values)\n        self.new_values[i] = value\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name, values=self.values)\n        new_var.colors = np.asarray(self.colors)\n        return new_var\n\n\nclass ContAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (ContinuousVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        palette_name (str or None): name of palette or None if unmodified\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        if var.palette.name not in colorpalettes.ContinuousPalettes:\n            self.new_palette_name = colorpalettes.DefaultContinuousPaletteName\n        else:\n            self.new_palette_name = None\n\n    @property\n    def palette_name(self):\n        return self.new_palette_name or self.var.palette.name\n\n    @palette_name.setter\n    def palette_name(self, palette_name):\n        self.new_palette_name = palette_name\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name)\n        new_var.attributes[\"palette\"] = self.palette_name\n        return new_var\n\n\nclass ColorTableModel(QAbstractTableModel):\n    \"\"\"\n    Base color model for discrete and continuous variables. The model handles:\n    - the first column - variable name (including setData)\n    - flags\n    - row count, computed as len(attrdescs)\n\n    Attribute:\n        attrdescs (list of AttrDesc): attrdescs with user-defined changes\n    \"\"\"\n    def __init__(self):\n        QAbstractTableModel.__init__(self)\n        self.attrdescs = []\n\n    @staticmethod\n    def flags(_):  # pragma: no cover\n        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable\n\n    def set_data(self, attrdescs):\n        self.modelAboutToBeReset.emit()\n        self.attrdescs = attrdescs\n        self.modelReset.emit()\n\n    def rowCount(self, parent=QModelIndex()):\n        return 0 if parent.isValid() else len(self.attrdescs)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # Only valid for the first column; derived classes implement the rest\n        row = index.row()\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return self.attrdescs[row].name\n        if role == Qt.FontRole:\n            font = QFont()\n            font.setBold(True)\n            return font\n        if role == Qt.TextAlignmentRole:\n            return Qt.AlignRight | Qt.AlignVCenter\n        return None\n\n    def setData(self, index, value, role):\n        # Only valid for the first column; derived classes implement the rest\n        if role == Qt.EditRole:\n            self.attrdescs[index.row()].name = value\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass DiscColorTableModel(ColorTableModel):\n    \"\"\"\n    A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n    \"\"\"\n    def columnCount(self, parent=QModelIndex()):\n        if parent.isValid():\n            return 0\n        return 1 + max((len(row.var.values) for row in self.attrdescs),\n                       default=0)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # pylint: disable=too-many-return-statements\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().data(index, role)\n\n        desc = self.attrdescs[row]\n        if col > len(desc.var.values):\n            return None\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return desc.values[col - 1]\n\n        color = desc.colors[col - 1]\n        if role == Qt.DecorationRole:\n            return QColor(*color)\n        if role == Qt.ToolTipRole:\n            return color_to_hex(color)\n        if role == ColorRole:\n            return color\n        return None\n\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n\n        desc = self.attrdescs[row]\n        if role == ColorRole:\n            desc.set_color(col - 1, value[:3])\n        elif role == Qt.EditRole:\n            desc.set_value(col - 1, value)\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass ContColorTableModel(ColorTableModel):\n    \"\"\"A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n\n    Attributes:\n        mouse_row (int): the row over which the mouse is hovering\n    \"\"\"\n    def __init__(self):\n        super().__init__()\n        self.mouse_row = None\n\n    def set_mouse_row(self, row):\n        self.mouse_row = row\n\n    @staticmethod\n    def columnCount(parent=QModelIndex()):\n        return 0 if parent.isValid() else 3\n\n    def data(self, index, role=Qt.DisplayRole):\n        def _column0():\n            return ColorTableModel.data(self, index, role)\n\n        def _column1():\n            palette = colorpalettes.ContinuousPalettes[desc.palette_name]\n            if role == Qt.ToolTipRole:\n                return palette.friendly_name\n            if role == ColorRole:\n                return palette\n            if role == StripRole:\n                return palette.color_strip(128, 16)\n            if role == Qt.SizeHintRole:\n                return QSize(150, 16)\n            return None\n\n        def _column2():\n            if role == Qt.SizeHintRole:\n                return QSize(100, 1)\n            if role == Qt.ForegroundRole:\n                return QBrush(Qt.blue)\n            if row == self.mouse_row and role == Qt.DisplayRole:\n                return \"Copy to all\"\n            return None\n\n        row, col = index.row(), index.column()\n        desc = self.attrdescs[row]\n        if 0 <= col <= 2:\n            return [_column0, _column1, _column2][col]()\n\n    # noinspection PyMethodOverriding\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n        if role == ColorRole:\n            self.attrdescs[row].palette_name = value.name\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n    def copy_to_all(self, index):\n        palette_name = self.attrdescs[index.row()].palette_name\n        for desc in self.attrdescs:\n            desc.palette_name = palette_name\n        self.dataChanged.emit(self.index(0, 1), self.index(self.rowCount(), 1))\n\n\nclass ColorStripDelegate(HorizontalGridDelegate):\n    def __init__(self, view):\n        super().__init__()\n        self.view = view\n\n    def createEditor(self, parent, option, index):\n        class Combo(QComboBox):\n            def __init__(self, parent, initial_data):\n                super().__init__(parent)\n                model = itemmodels.ContinuousPalettesModel(icon_width=128)\n                self.setModel(model)\n                self.setCurrentIndex(model.indexOf(initial_data))\n                self.setIconSize(QSize(128, 16))\n                QTimer.singleShot(0, self.showPopup)\n\n            def hidePopup(self):\n                super().hidePopup()\n                view.closeEditor(self, ColorStripDelegate.NoHint)\n\n        def select(i):\n            self.view.model().setData(\n                index,\n                combo.model().index(i, 0).data(Qt.UserRole),\n                ColorRole)\n\n        view = self.view\n        combo = Combo(parent, index.data(ColorRole))\n        combo.currentIndexChanged[int].connect(select)\n        return combo\n\n    def paint(self, painter, option, index):\n        strip = index.data(StripRole)\n        rect = option.rect\n        painter.drawPixmap(\n            rect.x() + 13, rect.y() + (rect.height() - strip.height()) / 2,\n            strip)\n        super().paint(painter, option, index)\n\n\nclass ColorTable(QTableView):\n    \"\"\"\n    The base table view for discrete and continuous attributes.\n\n    Sets the basic properties of the table and implementes mouseRelease that\n    calls handle_click with appropriate index. It also prepares a grid_deleagte\n    that is used in derived classes.\n    \"\"\"\n    def __init__(self, model):\n        QTableView.__init__(self)\n        self.horizontalHeader().hide()\n        self.verticalHeader().hide()\n        self.setShowGrid(False)\n        self.setSelectionMode(QTableView.NoSelection)\n        self.setModel(model)\n        # View doesn't take ownership of delegates, so we store it here\n        self.grid_delegate = HorizontalGridDelegate()\n\n    def mouseReleaseEvent(self, event):\n        index = self.indexAt(event.pos())\n        if not index.isValid():\n            return\n        rect = self.visualRect(index)\n        self.handle_click(index, event.pos().x() - rect.x())\n\n\nclass DiscreteTable(ColorTable):\n    \"\"\"Table view for discrete variables\"\"\"\n    def __init__(self, model):\n        super().__init__(model)\n        self.horizontalHeader().setSectionResizeMode(\n            QHeaderView.ResizeToContents)\n        self.setItemDelegate(self.grid_delegate)\n        self.setEditTriggers(QTableView.NoEditTriggers)\n\n    def handle_click(self, index, x_offset):\n        \"\"\"\n        Handle click events for the first column (call the edit method)\n        and the second (call method for changing the palette)\n        \"\"\"\n        if self.model().data(index, Qt.EditRole) is None:\n            return\n        if index.column() == 0 or x_offset > 24:\n            self.edit(index)\n        else:\n            self.change_color(index)\n\n    def change_color(self, index):\n        \"\"\"Invoke palette editor and set the color\"\"\"\n        color = self.model().data(index, ColorRole)\n        if color is None:\n            return\n        dlg = QColorDialog(QColor(*color))\n        if dlg.exec():\n            color = dlg.selectedColor()\n            self.model().setData(index, color.getRgb(), ColorRole)\n\n\nclass ContinuousTable(ColorTable):\n    \"\"\"Table view for continuous variables\"\"\"\n\n    def __init__(self, model):\n        super().__init__(model)\n        self.viewport().setMouseTracking(True)\n        # View doesn't take ownership of delegates, so we must store it\n        self.color_delegate = ColorStripDelegate(self)\n        self.setItemDelegateForColumn(0, self.grid_delegate)\n        self.setItemDelegateForColumn(1, self.color_delegate)\n        self.setColumnWidth(1, 256)\n        self.setEditTriggers(\n            QTableView.SelectedClicked | QTableView.DoubleClicked)\n\n    def mouseMoveEvent(self, event):\n        \"\"\"Store the hovered row index in the model, trigger viewport update\"\"\"\n        pos = event.pos()\n        ind = self.indexAt(pos)\n        self.model().set_mouse_row(ind.row())\n        super().mouseMoveEvent(event)\n        self.viewport().update()\n\n    def leaveEvent(self, _):\n        \"\"\"Remove the stored the hovered row index, trigger viewport update\"\"\"\n        self.model().set_mouse_row(None)\n        self.viewport().update()\n\n    def handle_click(self, index, _):\n        \"\"\"Call the specific methods for handling clicks for each column\"\"\"\n        if index.column() < 2:\n            self.edit(index)\n        elif index.column() == 2:\n            self.model().copy_to_all(index)\n\n\nclass OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    WidgetPreview(OWColor).run(Orange.data.Table(\"heart_disease.tab\"))\n",
            "header": {
                "file": {
                    "path": "Orange/widgets/data/owcolor.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "02b0c2c35",
                "new_commit_hash": "0381cf128",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/data/owcolor.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/data/owcolor.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 12,
                            "length": 6
                        },
                        "new_range": {
                            "start": 12,
                            "length": 7
                        },
                        "section": "from Orange.widgets import widget, settings, gui"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from Orange.widgets.gui import HorizontalGridDelegate",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils import itemmodels, colorpalettes",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils.widgetpreview import WidgetPreview",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                                "type": "added"
                            },
                            {
                                "content": "from Orange.widgets.widget import Input, Output",
                                "type": "context"
                            },
                            {
                                "content": "from orangewidget.settings import IncompatibleContext",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 15,
                            "end_lineno": 15,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 458,
                            "length": 6
                        },
                        "new_range": {
                            "start": 459,
                            "length": 9
                        },
                        "section": "class OWColor(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        box.button.setFixedWidth(180)",
                                "type": "context"
                            },
                            {
                                "content": "        box.layout().insertStretch(0)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        self.info.set_input_summary(self.info.NoInput)",
                                "type": "added"
                            },
                            {
                                "content": "        self.info.set_output_summary(self.info.NoOutput)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @staticmethod",
                                "type": "context"
                            },
                            {
                                "content": "    def sizeHint():  # pragma: no cover",
                                "type": "context"
                            },
                            {
                                "content": "        return QSize(500, 570)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "method",
                            "name": "OWColor.__init__",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 441,
                            "end_lineno": 463,
                            "parent": {
                                "file_name": "Orange/widgets/data/owcolor.py",
                                "type": "class",
                                "name": "OWColor",
                                "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 418,
                                "end_lineno": 574,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "class",
                            "name": "OWColor",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 418,
                            "end_lineno": 574,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 469,
                            "length": 8
                        },
                        "new_range": {
                            "start": 473,
                            "length": 10
                        },
                        "section": "class OWColor(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.cont_descs = []",
                                "type": "context"
                            },
                            {
                                "content": "        if data is None:",
                                "type": "context"
                            },
                            {
                                "content": "            self.data = self.domain = None",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_input_summary(self.info.NoInput)",
                                "type": "added"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            self.data = data",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_input_summary(len(data), format_summary_details(data))",
                                "type": "added"
                            },
                            {
                                "content": "            for var in chain(data.domain.variables, data.domain.metas):",
                                "type": "context"
                            },
                            {
                                "content": "                if var.is_discrete:",
                                "type": "context"
                            },
                            {
                                "content": "                    self.disc_descs.append(DiscAttrDesc(var))",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "class",
                            "name": "OWColor",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 418,
                            "end_lineno": 574,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "method",
                            "name": "OWColor.set_data",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 470,
                            "end_lineno": 491,
                            "parent": {
                                "file_name": "Orange/widgets/data/owcolor.py",
                                "type": "class",
                                "name": "OWColor",
                                "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 418,
                                "end_lineno": 574,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 498,
                            "length": 6
                        },
                        "new_range": {
                            "start": 504,
                            "length": 7
                        },
                        "section": "class OWColor(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        if self.data is None:",
                                "type": "context"
                            },
                            {
                                "content": "            self.Outputs.data.send(None)",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_output_summary(self.info.NoOutput)",
                                "type": "added"
                            },
                            {
                                "content": "            return",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "        disc_dict = {desc.var.name: desc for desc in self.disc_descs}",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "class",
                            "name": "OWColor",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 418,
                            "end_lineno": 574,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "method",
                            "name": "OWColor.commit",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 496,
                            "end_lineno": 519,
                            "parent": {
                                "file_name": "Orange/widgets/data/owcolor.py",
                                "type": "class",
                                "name": "OWColor",
                                "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 418,
                                "end_lineno": 574,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 507,
                            "length": 6
                        },
                        "new_range": {
                            "start": 514,
                            "length": 8
                        },
                        "section": "class OWColor(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        new_domain = Orange.data.Domain(",
                                "type": "context"
                            },
                            {
                                "content": "            make(dom.attributes), make(dom.class_vars), make(dom.metas))",
                                "type": "context"
                            },
                            {
                                "content": "        new_data = self.data.transform(new_domain)",
                                "type": "context"
                            },
                            {
                                "content": "        self.info.set_output_summary(len(new_data),",
                                "type": "added"
                            },
                            {
                                "content": "                                     format_summary_details(new_data))",
                                "type": "added"
                            },
                            {
                                "content": "        self.Outputs.data.send(new_data)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def send_report(self):",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "class",
                            "name": "OWColor",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 418,
                            "end_lineno": 574,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/owcolor.py",
                            "type": "method",
                            "name": "OWColor.commit",
                            "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 496,
                            "end_lineno": 519,
                            "parent": {
                                "file_name": "Orange/widgets/data/owcolor.py",
                                "type": "class",
                                "name": "OWColor",
                                "content": "class OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n            self.info.set_input_summary(self.info.NoInput)\n        else:\n            self.data = data\n            self.info.set_input_summary(len(data), format_summary_details(data))\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.info.set_output_summary(len(new_data),\n                                     format_summary_details(new_data))\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 418,
                                "end_lineno": 574,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring, protected-access\nimport unittest\nfrom unittest.mock import patch, Mock\n\nimport numpy as np\nfrom AnyQt.QtCore import Qt, QSize, QRect\nfrom AnyQt.QtGui import QBrush\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.util import color_to_hex\nfrom Orange.widgets.utils import colorpalettes\nfrom Orange.widgets.data import owcolor\nfrom Orange.widgets.data.owcolor import ColorRole\nfrom Orange.widgets.tests.base import WidgetTest\nfrom orangewidget.tests.base import GuiTest\n\n\nclass AttrDescTest(unittest.TestCase):\n    def test_name(self):\n        x = ContinuousVariable(\"x\")\n        desc = owcolor.AttrDesc(x)\n        self.assertEqual(desc.name, \"x\")\n        desc.name = \"y\"\n        self.assertEqual(desc.name, \"y\")\n        desc.name = None\n        self.assertEqual(desc.name, \"x\")\n\n\nclass DiscAttrTest(unittest.TestCase):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", [\"a\", \"b\", \"c\"])\n        self.desc = owcolor.DiscAttrDesc(x)\n\n    def test_colors(self):\n        desc = self.desc\n        colors = desc.colors.copy()\n        desc.set_color(2, (0, 0, 0))\n        colors[2] = 0\n        np.testing.assert_equal(desc.colors, colors)\n\n    def test_values(self):\n        desc = self.desc\n        self.assertEqual(desc.values, (\"a\", \"b\", \"c\"))\n        desc.set_value(1, \"d\")\n        self.assertEqual(desc.values, (\"a\", \"d\", \"c\"))\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.set_color(0, [1, 2, 3])\n        desc.set_color(1, [4, 5, 6])\n        desc.set_color(2, [7, 8, 9])\n        desc.name = \"z\"\n        desc.set_value(1, \"d\")\n        var = desc.create_variable()\n        self.assertIsInstance(var, DiscreteVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.values, (\"a\", \"d\", \"c\"))\n        np.testing.assert_equal(var.colors, [[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n\n        palette = desc.var.attributes[\"palette\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"palette\"], palette)\n        self.assertFalse(hasattr(var.attributes, \"palette\"))\n\n\nclass ContAttrDesc(unittest.TestCase):\n    def setUp(self):\n        x = ContinuousVariable(\"x\")\n        self.desc = owcolor.ContAttrDesc(x)\n\n    def test_palette(self):\n        desc = self.desc\n        palette = desc.palette_name\n        self.assertIsInstance(palette, str)\n        desc.palette_name = \"foo\"\n        self.assertEqual(desc.palette_name, \"foo\")\n        desc.palette_name = None\n        self.assertEqual(desc.palette_name, palette)\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.name = \"z\"\n        palette_name = _find_other_palette(\n            colorpalettes.ContinuousPalettes[desc.palette_name]).name\n        desc.palette_name = palette_name\n        var = desc.create_variable()\n        self.assertIsInstance(var, ContinuousVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.palette.name, palette_name)\n\n        colors = desc.var.attributes[\"colors\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"colors\"], colors)\n        self.assertFalse(hasattr(var.attributes, \"colors\"))\n\n\nclass BaseTestColorTableModel:\n    def test_row_count(self):\n        model = self.model\n\n        self.assertEqual(model.rowCount(), 0)\n        model.set_data(self.descs)\n        self.assertEqual(model.rowCount(), len(self.descs))\n        self.assertEqual(model.rowCount(self.model.index(0, 0)), 0)\n\n    def test_data(self):\n        self.model.set_data(self.descs)\n        data = self.model.data\n\n        index = self.model.index(1, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n        self.assertEqual(data(index, Qt.EditRole), self.descs[1].name)\n        self.assertTrue(data(index, Qt.FontRole).bold())\n        self.assertTrue(data(index, Qt.TextAlignmentRole) & Qt.AlignRight)\n\n        self.descs[1].name = \"bar\"\n        self.assertEqual(data(index), \"bar\")\n\n        index = self.model.index(2, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[2].name)\n\n\n    def test_set_data(self):\n        emit = Mock()\n        try:\n            self.model.dataChanged.connect(emit)\n            self.model.set_data(self.descs)\n            data = self.model.data\n            setData = self.model.setData\n\n            index = self.model.index(1, 0)\n            assert self.descs[1].name != \"foo\"\n            self.assertFalse(setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n            self.assertTrue(setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            self.assertEqual(data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[1].name, \"foo\")\n        finally:\n            self.model.dataChanged.disconnect(emit)\n\n\nclass TestDiscColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", list(\"abc\"))\n        y = DiscreteVariable(\"y\", list(\"def\"))\n        z = DiscreteVariable(\"z\", list(\"ghijk\"))\n        self.descs = [owcolor.DiscAttrDesc(v) for v in (x, y, z)]\n        self.model = owcolor.DiscColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        self.assertEqual(model.columnCount(), 1)\n        model.set_data(self.descs[:2])\n        self.assertEqual(model.columnCount(), 4)\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 6)\n\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(1, 2)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"e\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"e\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[1].var.colors[1]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(2, 5)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[2].var.colors[4]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.descs[2].set_value(4, \"foo\")\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            index = model.index(2, 5)\n\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n            self.assertFalse(model.setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertTrue(model.setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            emit.reset_mock()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[2].values, (\"g\", \"h\", \"i\", \"j\", \"foo\"))\n\n            new_color = [0, 1, 2]\n            self.assertTrue(model.setData(index, new_color + [255], ColorRole))\n            emit.assert_called()\n            emit.reset_mock()\n            color = model.data(index, Qt.DecorationRole)\n            rgb = [color.red(), color.green(), color.blue()]\n            self.assertEqual(rgb, new_color)\n\n            color = model.data(index, owcolor.ColorRole)\n            self.assertEqual(list(color), new_color)\n\n            self.assertEqual(\n                model.data(index, Qt.ToolTipRole), color_to_hex(new_color))\n\n            np.testing.assert_equal(self.descs[2].colors[4], rgb)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\ndef _find_other_palette(initial):\n    for palette in colorpalettes.ContinuousPalettes.values():\n        if palette.name != initial.name:\n            return palette\n    return None  # pragma: no cover\n\n\nclass TestContColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 3)\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        palette = colorpalettes.ContinuousPalettes[self.descs[1].palette_name]\n        self.assertEqual(model.data(index, Qt.ToolTipRole),\n                         palette.friendly_name)\n        self.assertEqual(model.data(index, ColorRole), palette)\n        with patch.object(palette, \"color_strip\") as color_strip:\n            strip = model.data(index, owcolor.StripRole)\n            self.assertIs(strip, color_strip.return_value)\n            color_strip.assert_called_with(128, 16)\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsNone(model.data(index, Qt.FontRole))\n\n        palette = _find_other_palette(self.descs[1])\n        self.descs[1].palette_name = palette.name\n        self.assertIs(model.data(index, ColorRole), palette)\n\n        index = self.model.index(1, 2)\n        self.assertIsNone(model.data(index, Qt.ToolTipRole))\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsInstance(model.data(index, Qt.ForegroundRole), QBrush)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(0)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(1)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"Copy to all\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        index2 = model.index(2, 1)\n        initial = model.data(index, ColorRole)\n        initial2 = model.data(index, ColorRole)\n        assert initial.name == initial2.name\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            self.assertFalse(model.setData(index, None, Qt.DisplayRole))\n            emit.assert_not_called()\n\n            self.assertTrue(model.setData(index, palette, ColorRole))\n            emit.assert_called()\n            self.assertIs(model.data(index2, ColorRole), initial2)\n\n            self.assertEqual(model.data(index, Qt.ToolTipRole),\n                             palette.friendly_name)\n            self.assertEqual(model.data(index, ColorRole), palette)\n            self.assertEqual(self.descs[1].palette_name, palette.name)\n            with patch.object(palette, \"color_strip\") as color_strip:\n                strip = model.data(index, owcolor.StripRole)\n                self.assertIs(strip, color_strip.return_value)\n                color_strip.assert_called_with(128, 16)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n    def test_copy_to_all(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n            model.setData(index, palette, ColorRole)\n            emit.assert_called()\n            emit.reset_mock()\n\n            model.copy_to_all(index)\n            emit.assert_called_once()\n            for row, desc in enumerate(self.descs):\n                self.assertEqual(\n                    model.data(model.index(row, 1), ColorRole).name,\n                    palette.name)\n                self.assertEqual(desc.palette_name, palette.name)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\nclass TestColorStripDelegate(GuiTest):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n        self.model.set_data(self.descs)\n        self.table = owcolor.ContinuousTable(self.model)\n\n    def test_color_combo(self):\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n        model.setData(index, palette, ColorRole)\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        combo = self.table.color_delegate.createEditor(None, Mock(), index)\n        self.assertEqual(combo.currentText(), palette.friendly_name)\n        palette = _find_other_palette(palette)\n        combo.setCurrentIndex(combo.findText(palette.friendly_name))\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        with patch.object(self.table, \"closeEditor\") as closeEditor:\n            combo.hidePopup()\n            closeEditor.assert_called()\n\n    @patch.object(owcolor.HorizontalGridDelegate, \"paint\")\n    def test_paint(self, _):\n        model = self.model\n        index = model.index(1, 1)\n        painter = Mock()\n        option = Mock()\n        option.rect = QRect(10, 20, 30, 40)\n        index.data = Mock()\n        index.data.return_value = Mock()\n        index.data.return_value.height = Mock(return_value=42)\n        self.table.color_delegate.paint(painter, option, index)\n        self.assertIs(painter.drawPixmap.call_args[0][2],\n                      index.data.return_value)\n\n\nclass TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n",
            "new_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring, protected-access,unsubscriptable-object\nimport unittest\nfrom unittest.mock import patch, Mock\n\nimport numpy as np\nfrom AnyQt.QtCore import Qt, QSize, QRect\nfrom AnyQt.QtGui import QBrush\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.util import color_to_hex\nfrom Orange.widgets.utils import colorpalettes\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.data import owcolor\nfrom Orange.widgets.data.owcolor import ColorRole\nfrom Orange.widgets.tests.base import WidgetTest\nfrom orangewidget.tests.base import GuiTest\n\n\nclass AttrDescTest(unittest.TestCase):\n    def test_name(self):\n        x = ContinuousVariable(\"x\")\n        desc = owcolor.AttrDesc(x)\n        self.assertEqual(desc.name, \"x\")\n        desc.name = \"y\"\n        self.assertEqual(desc.name, \"y\")\n        desc.name = None\n        self.assertEqual(desc.name, \"x\")\n\n\nclass DiscAttrTest(unittest.TestCase):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", [\"a\", \"b\", \"c\"])\n        self.desc = owcolor.DiscAttrDesc(x)\n\n    def test_colors(self):\n        desc = self.desc\n        colors = desc.colors.copy()\n        desc.set_color(2, (0, 0, 0))\n        colors[2] = 0\n        np.testing.assert_equal(desc.colors, colors)\n\n    def test_values(self):\n        desc = self.desc\n        self.assertEqual(desc.values, (\"a\", \"b\", \"c\"))\n        desc.set_value(1, \"d\")\n        self.assertEqual(desc.values, (\"a\", \"d\", \"c\"))\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.set_color(0, [1, 2, 3])\n        desc.set_color(1, [4, 5, 6])\n        desc.set_color(2, [7, 8, 9])\n        desc.name = \"z\"\n        desc.set_value(1, \"d\")\n        var = desc.create_variable()\n        self.assertIsInstance(var, DiscreteVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.values, (\"a\", \"d\", \"c\"))\n        np.testing.assert_equal(var.colors, [[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n\n        palette = desc.var.attributes[\"palette\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"palette\"], palette)\n        self.assertFalse(hasattr(var.attributes, \"palette\"))\n\n\nclass ContAttrDesc(unittest.TestCase):\n    def setUp(self):\n        x = ContinuousVariable(\"x\")\n        self.desc = owcolor.ContAttrDesc(x)\n\n    def test_palette(self):\n        desc = self.desc\n        palette = desc.palette_name\n        self.assertIsInstance(palette, str)\n        desc.palette_name = \"foo\"\n        self.assertEqual(desc.palette_name, \"foo\")\n        desc.palette_name = None\n        self.assertEqual(desc.palette_name, palette)\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.name = \"z\"\n        palette_name = _find_other_palette(\n            colorpalettes.ContinuousPalettes[desc.palette_name]).name\n        desc.palette_name = palette_name\n        var = desc.create_variable()\n        self.assertIsInstance(var, ContinuousVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.palette.name, palette_name)\n\n        colors = desc.var.attributes[\"colors\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"colors\"], colors)\n        self.assertFalse(hasattr(var.attributes, \"colors\"))\n\n\nclass BaseTestColorTableModel:\n    def test_row_count(self):\n        model = self.model\n\n        self.assertEqual(model.rowCount(), 0)\n        model.set_data(self.descs)\n        self.assertEqual(model.rowCount(), len(self.descs))\n        self.assertEqual(model.rowCount(self.model.index(0, 0)), 0)\n\n    def test_data(self):\n        self.model.set_data(self.descs)\n        data = self.model.data\n\n        index = self.model.index(1, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n        self.assertEqual(data(index, Qt.EditRole), self.descs[1].name)\n        self.assertTrue(data(index, Qt.FontRole).bold())\n        self.assertTrue(data(index, Qt.TextAlignmentRole) & Qt.AlignRight)\n\n        self.descs[1].name = \"bar\"\n        self.assertEqual(data(index), \"bar\")\n\n        index = self.model.index(2, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[2].name)\n\n\n    def test_set_data(self):\n        emit = Mock()\n        try:\n            self.model.dataChanged.connect(emit)\n            self.model.set_data(self.descs)\n            data = self.model.data\n            setData = self.model.setData\n\n            index = self.model.index(1, 0)\n            assert self.descs[1].name != \"foo\"\n            self.assertFalse(setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n            self.assertTrue(setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            self.assertEqual(data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[1].name, \"foo\")\n        finally:\n            self.model.dataChanged.disconnect(emit)\n\n\nclass TestDiscColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", list(\"abc\"))\n        y = DiscreteVariable(\"y\", list(\"def\"))\n        z = DiscreteVariable(\"z\", list(\"ghijk\"))\n        self.descs = [owcolor.DiscAttrDesc(v) for v in (x, y, z)]\n        self.model = owcolor.DiscColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        self.assertEqual(model.columnCount(), 1)\n        model.set_data(self.descs[:2])\n        self.assertEqual(model.columnCount(), 4)\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 6)\n\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(1, 2)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"e\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"e\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[1].var.colors[1]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(2, 5)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[2].var.colors[4]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.descs[2].set_value(4, \"foo\")\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            index = model.index(2, 5)\n\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n            self.assertFalse(model.setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertTrue(model.setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            emit.reset_mock()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[2].values, (\"g\", \"h\", \"i\", \"j\", \"foo\"))\n\n            new_color = [0, 1, 2]\n            self.assertTrue(model.setData(index, new_color + [255], ColorRole))\n            emit.assert_called()\n            emit.reset_mock()\n            color = model.data(index, Qt.DecorationRole)\n            rgb = [color.red(), color.green(), color.blue()]\n            self.assertEqual(rgb, new_color)\n\n            color = model.data(index, owcolor.ColorRole)\n            self.assertEqual(list(color), new_color)\n\n            self.assertEqual(\n                model.data(index, Qt.ToolTipRole), color_to_hex(new_color))\n\n            np.testing.assert_equal(self.descs[2].colors[4], rgb)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\ndef _find_other_palette(initial):\n    for palette in colorpalettes.ContinuousPalettes.values():\n        if palette.name != initial.name:\n            return palette\n    return None  # pragma: no cover\n\n\nclass TestContColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 3)\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        palette = colorpalettes.ContinuousPalettes[self.descs[1].palette_name]\n        self.assertEqual(model.data(index, Qt.ToolTipRole),\n                         palette.friendly_name)\n        self.assertEqual(model.data(index, ColorRole), palette)\n        with patch.object(palette, \"color_strip\") as color_strip:\n            strip = model.data(index, owcolor.StripRole)\n            self.assertIs(strip, color_strip.return_value)\n            color_strip.assert_called_with(128, 16)\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsNone(model.data(index, Qt.FontRole))\n\n        palette = _find_other_palette(self.descs[1])\n        self.descs[1].palette_name = palette.name\n        self.assertIs(model.data(index, ColorRole), palette)\n\n        index = self.model.index(1, 2)\n        self.assertIsNone(model.data(index, Qt.ToolTipRole))\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsInstance(model.data(index, Qt.ForegroundRole), QBrush)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(0)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(1)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"Copy to all\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        index2 = model.index(2, 1)\n        initial = model.data(index, ColorRole)\n        initial2 = model.data(index, ColorRole)\n        assert initial.name == initial2.name\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            self.assertFalse(model.setData(index, None, Qt.DisplayRole))\n            emit.assert_not_called()\n\n            self.assertTrue(model.setData(index, palette, ColorRole))\n            emit.assert_called()\n            self.assertIs(model.data(index2, ColorRole), initial2)\n\n            self.assertEqual(model.data(index, Qt.ToolTipRole),\n                             palette.friendly_name)\n            self.assertEqual(model.data(index, ColorRole), palette)\n            self.assertEqual(self.descs[1].palette_name, palette.name)\n            with patch.object(palette, \"color_strip\") as color_strip:\n                strip = model.data(index, owcolor.StripRole)\n                self.assertIs(strip, color_strip.return_value)\n                color_strip.assert_called_with(128, 16)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n    def test_copy_to_all(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n            model.setData(index, palette, ColorRole)\n            emit.assert_called()\n            emit.reset_mock()\n\n            model.copy_to_all(index)\n            emit.assert_called_once()\n            for row, desc in enumerate(self.descs):\n                self.assertEqual(\n                    model.data(model.index(row, 1), ColorRole).name,\n                    palette.name)\n                self.assertEqual(desc.palette_name, palette.name)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\nclass TestColorStripDelegate(GuiTest):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n        self.model.set_data(self.descs)\n        self.table = owcolor.ContinuousTable(self.model)\n\n    def test_color_combo(self):\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n        model.setData(index, palette, ColorRole)\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        combo = self.table.color_delegate.createEditor(None, Mock(), index)\n        self.assertEqual(combo.currentText(), palette.friendly_name)\n        palette = _find_other_palette(palette)\n        combo.setCurrentIndex(combo.findText(palette.friendly_name))\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        with patch.object(self.table, \"closeEditor\") as closeEditor:\n            combo.hidePopup()\n            closeEditor.assert_called()\n\n    @patch.object(owcolor.HorizontalGridDelegate, \"paint\")\n    def test_paint(self, _):\n        model = self.model\n        index = model.index(1, 1)\n        painter = Mock()\n        option = Mock()\n        option.rect = QRect(10, 20, 30, 40)\n        index.data = Mock()\n        index.data.return_value = Mock()\n        index.data.return_value.height = Mock(return_value=42)\n        self.table.color_delegate.paint(painter, option, index)\n        self.assertIs(painter.drawPixmap.call_args[0][2],\n                      index.data.return_value)\n\n\nclass TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        self.send_signal(self.widget.Inputs.data, data)\n        input_sum.assert_called_with(len(data), format_summary_details(data))\n        output = self.get_output(self.widget.Outputs.data)\n        output_sum.assert_called_with(len(output),\n                                      format_summary_details(output))\n        input_sum.reset_mock()\n        output_sum.reset_mock()\n        self.send_signal(self.widget.Inputs.data, None)\n        input_sum.assert_called_once()\n        self.assertEqual(input_sum.call_args[0][0].brief, \"\")\n        output_sum.assert_called_once()\n        self.assertEqual(output_sum.call_args[0][0].brief, \"\")\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n",
            "header": {
                "file": {
                    "path": "Orange/widgets/data/tests/test_owcolor.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "6f4dbf359",
                "new_commit_hash": "8f133ff75",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/data/tests/test_owcolor.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/data/tests/test_owcolor.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1,
                            "length": 5
                        },
                        "new_range": {
                            "start": 1,
                            "length": 5
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "# Test methods with long descriptive names can omit docstrings",
                                "type": "context"
                            },
                            {
                                "content": "# pylint: disable=missing-docstring, protected-access",
                                "type": "deleted"
                            },
                            {
                                "content": "# pylint: disable=missing-docstring, protected-access,unsubscriptable-object",
                                "type": "added"
                            },
                            {
                                "content": "import unittest",
                                "type": "context"
                            },
                            {
                                "content": "from unittest.mock import patch, Mock",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 10,
                            "length": 6
                        },
                        "new_range": {
                            "start": 10,
                            "length": 7
                        },
                        "section": "from AnyQt.QtGui import QBrush"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.util import color_to_hex",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils import colorpalettes",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                                "type": "added"
                            },
                            {
                                "content": "from Orange.widgets.data import owcolor",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.data.owcolor import ColorRole",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.tests.base import WidgetTest",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owcolor.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 13,
                            "end_lineno": 13,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 483,
                            "length": 6
                        },
                        "new_range": {
                            "start": 484,
                            "length": 25
                        },
                        "section": "class TestOWColor(WidgetTest):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    def test_string_variables(self):",
                                "type": "context"
                            },
                            {
                                "content": "        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_summary(self):",
                                "type": "added"
                            },
                            {
                                "content": "        \"\"\"Check if the status bar is updated when data is received\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "        data = self.iris",
                                "type": "added"
                            },
                            {
                                "content": "        input_sum = self.widget.info.set_input_summary = Mock()",
                                "type": "added"
                            },
                            {
                                "content": "        output_sum = self.widget.info.set_output_summary = Mock()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        self.send_signal(self.widget.Inputs.data, data)",
                                "type": "added"
                            },
                            {
                                "content": "        input_sum.assert_called_with(len(data), format_summary_details(data))",
                                "type": "added"
                            },
                            {
                                "content": "        output = self.get_output(self.widget.Outputs.data)",
                                "type": "added"
                            },
                            {
                                "content": "        output_sum.assert_called_with(len(output),",
                                "type": "added"
                            },
                            {
                                "content": "                                      format_summary_details(output))",
                                "type": "added"
                            },
                            {
                                "content": "        input_sum.reset_mock()",
                                "type": "added"
                            },
                            {
                                "content": "        output_sum.reset_mock()",
                                "type": "added"
                            },
                            {
                                "content": "        self.send_signal(self.widget.Inputs.data, None)",
                                "type": "added"
                            },
                            {
                                "content": "        input_sum.assert_called_once()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(input_sum.call_args[0][0].brief, \"\")",
                                "type": "added"
                            },
                            {
                                "content": "        output_sum.assert_called_once()",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(output_sum.call_args[0][0].brief, \"\")",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "if __name__ == \"__main__\":",
                                "type": "context"
                            },
                            {
                                "content": "    unittest.main()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owcolor.py",
                            "type": "class",
                            "name": "TestOWColor",
                            "content": "class TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        self.send_signal(self.widget.Inputs.data, data)\n        input_sum.assert_called_with(len(data), format_summary_details(data))\n        output = self.get_output(self.widget.Outputs.data)\n        output_sum.assert_called_with(len(output),\n                                      format_summary_details(output))\n        input_sum.reset_mock()\n        output_sum.reset_mock()\n        self.send_signal(self.widget.Inputs.data, None)\n        input_sum.assert_called_once()\n        self.assertEqual(input_sum.call_args[0][0].brief, \"\")\n        output_sum.assert_called_once()\n        self.assertEqual(output_sum.call_args[0][0].brief, \"\")",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 403,
                            "end_lineno": 504,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owcolor.py",
                            "type": "method",
                            "name": "TestOWColor.test_summary",
                            "content": "class TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        self.send_signal(self.widget.Inputs.data, data)\n        input_sum.assert_called_with(len(data), format_summary_details(data))\n        output = self.get_output(self.widget.Outputs.data)\n        output_sum.assert_called_with(len(output),\n                                      format_summary_details(output))\n        input_sum.reset_mock()\n        output_sum.reset_mock()\n        self.send_signal(self.widget.Inputs.data, None)\n        input_sum.assert_called_once()\n        self.assertEqual(input_sum.call_args[0][0].brief, \"\")\n        output_sum.assert_called_once()\n        self.assertEqual(output_sum.call_args[0][0].brief, \"\")",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 487,
                            "end_lineno": 504,
                            "parent": {
                                "file_name": "Orange/widgets/data/tests/test_owcolor.py",
                                "type": "class",
                                "name": "TestOWColor",
                                "content": "class TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        self.send_signal(self.widget.Inputs.data, data)\n        input_sum.assert_called_with(len(data), format_summary_details(data))\n        output = self.get_output(self.widget.Outputs.data)\n        output_sum.assert_called_with(len(output),\n                                      format_summary_details(output))\n        input_sum.reset_mock()\n        output_sum.reset_mock()\n        self.send_signal(self.widget.Inputs.data, None)\n        input_sum.assert_called_once()\n        self.assertEqual(input_sum.call_args[0][0].brief, \"\")\n        output_sum.assert_called_once()\n        self.assertEqual(output_sum.call_args[0][0].brief, \"\")",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 403,
                                "end_lineno": 504,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "17e9691cee9100e6fd2c4798d06e71aa97ecbbfa^",
    "new_commit_hash": "17e9691cee9100e6fd2c4798d06e71aa97ecbbfa",
    "commit_message": "Merge pull request #4501 from aturanjanin/owcolor\n\n[ENH] OWColor: Data info displayed in the status bar",
    "commit_date": "2020-03-13T10:16:04+01:00",
    "metadata": {}
}
{
    "repo_name": "orange3",
    "new_commit_hash": "17e9691cee9100e6fd2c4798d06e71aa97ecbbfa",
    "test_file_codes": [
        "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring, protected-access,unsubscriptable-object\nimport unittest\nfrom unittest.mock import patch, Mock\n\nimport numpy as np\nfrom AnyQt.QtCore import Qt, QSize, QRect\nfrom AnyQt.QtGui import QBrush\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.util import color_to_hex\nfrom Orange.widgets.utils import colorpalettes\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.data import owcolor\nfrom Orange.widgets.data.owcolor import ColorRole\nfrom Orange.widgets.tests.base import WidgetTest\nfrom orangewidget.tests.base import GuiTest\n\n\nclass AttrDescTest(unittest.TestCase):\n    def test_name(self):\n        x = ContinuousVariable(\"x\")\n        desc = owcolor.AttrDesc(x)\n        self.assertEqual(desc.name, \"x\")\n        desc.name = \"y\"\n        self.assertEqual(desc.name, \"y\")\n        desc.name = None\n        self.assertEqual(desc.name, \"x\")\n\n\nclass DiscAttrTest(unittest.TestCase):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", [\"a\", \"b\", \"c\"])\n        self.desc = owcolor.DiscAttrDesc(x)\n\n    def test_colors(self):\n        desc = self.desc\n        colors = desc.colors.copy()\n        desc.set_color(2, (0, 0, 0))\n        colors[2] = 0\n        np.testing.assert_equal(desc.colors, colors)\n\n    def test_values(self):\n        desc = self.desc\n        self.assertEqual(desc.values, (\"a\", \"b\", \"c\"))\n        desc.set_value(1, \"d\")\n        self.assertEqual(desc.values, (\"a\", \"d\", \"c\"))\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.set_color(0, [1, 2, 3])\n        desc.set_color(1, [4, 5, 6])\n        desc.set_color(2, [7, 8, 9])\n        desc.name = \"z\"\n        desc.set_value(1, \"d\")\n        var = desc.create_variable()\n        self.assertIsInstance(var, DiscreteVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.values, (\"a\", \"d\", \"c\"))\n        np.testing.assert_equal(var.colors, [[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n\n        palette = desc.var.attributes[\"palette\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"palette\"], palette)\n        self.assertFalse(hasattr(var.attributes, \"palette\"))\n\n\nclass ContAttrDesc(unittest.TestCase):\n    def setUp(self):\n        x = ContinuousVariable(\"x\")\n        self.desc = owcolor.ContAttrDesc(x)\n\n    def test_palette(self):\n        desc = self.desc\n        palette = desc.palette_name\n        self.assertIsInstance(palette, str)\n        desc.palette_name = \"foo\"\n        self.assertEqual(desc.palette_name, \"foo\")\n        desc.palette_name = None\n        self.assertEqual(desc.palette_name, palette)\n\n    def test_create_variable(self):\n        desc = self.desc\n        desc.name = \"z\"\n        palette_name = _find_other_palette(\n            colorpalettes.ContinuousPalettes[desc.palette_name]).name\n        desc.palette_name = palette_name\n        var = desc.create_variable()\n        self.assertIsInstance(var, ContinuousVariable)\n        self.assertEqual(var.name, \"z\")\n        self.assertEqual(var.palette.name, palette_name)\n\n        colors = desc.var.attributes[\"colors\"] = object()\n        var = desc.create_variable()\n        self.assertIs(desc.var.attributes[\"colors\"], colors)\n        self.assertFalse(hasattr(var.attributes, \"colors\"))\n\n\nclass BaseTestColorTableModel:\n    def test_row_count(self):\n        model = self.model\n\n        self.assertEqual(model.rowCount(), 0)\n        model.set_data(self.descs)\n        self.assertEqual(model.rowCount(), len(self.descs))\n        self.assertEqual(model.rowCount(self.model.index(0, 0)), 0)\n\n    def test_data(self):\n        self.model.set_data(self.descs)\n        data = self.model.data\n\n        index = self.model.index(1, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n        self.assertEqual(data(index, Qt.EditRole), self.descs[1].name)\n        self.assertTrue(data(index, Qt.FontRole).bold())\n        self.assertTrue(data(index, Qt.TextAlignmentRole) & Qt.AlignRight)\n\n        self.descs[1].name = \"bar\"\n        self.assertEqual(data(index), \"bar\")\n\n        index = self.model.index(2, 0)\n        self.assertEqual(data(index, Qt.DisplayRole), self.descs[2].name)\n\n\n    def test_set_data(self):\n        emit = Mock()\n        try:\n            self.model.dataChanged.connect(emit)\n            self.model.set_data(self.descs)\n            data = self.model.data\n            setData = self.model.setData\n\n            index = self.model.index(1, 0)\n            assert self.descs[1].name != \"foo\"\n            self.assertFalse(setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(data(index, Qt.DisplayRole), self.descs[1].name)\n            self.assertTrue(setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            self.assertEqual(data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[1].name, \"foo\")\n        finally:\n            self.model.dataChanged.disconnect(emit)\n\n\nclass TestDiscColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        x = DiscreteVariable(\"x\", list(\"abc\"))\n        y = DiscreteVariable(\"y\", list(\"def\"))\n        z = DiscreteVariable(\"z\", list(\"ghijk\"))\n        self.descs = [owcolor.DiscAttrDesc(v) for v in (x, y, z)]\n        self.model = owcolor.DiscColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        self.assertEqual(model.columnCount(), 1)\n        model.set_data(self.descs[:2])\n        self.assertEqual(model.columnCount(), 4)\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 6)\n\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(1, 2)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"e\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"e\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[1].var.colors[1]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.assertIsNone(model.data(model.index(0, 4)))\n\n        index = model.index(2, 5)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n        self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n        font = model.data(index, Qt.FontRole)\n        self.assertTrue(font is None or not font.bold())\n\n        var_colors = self.descs[2].var.colors[4]\n        color = model.data(index, Qt.DecorationRole)\n        np.testing.assert_equal(color.getRgb()[:3], var_colors)\n\n        color = model.data(index, owcolor.ColorRole)\n        np.testing.assert_equal(color, var_colors)\n\n        self.assertEqual(\n            model.data(index, Qt.ToolTipRole), color_to_hex(var_colors))\n\n        self.descs[2].set_value(4, \"foo\")\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            index = model.index(2, 5)\n\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertEqual(model.data(index, Qt.EditRole), \"k\")\n            self.assertFalse(model.setData(index, \"foo\", Qt.DisplayRole))\n            emit.assert_not_called()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"k\")\n            self.assertTrue(model.setData(index, \"foo\", Qt.EditRole))\n            emit.assert_called()\n            emit.reset_mock()\n            self.assertEqual(model.data(index, Qt.DisplayRole), \"foo\")\n            self.assertEqual(self.descs[2].values, (\"g\", \"h\", \"i\", \"j\", \"foo\"))\n\n            new_color = [0, 1, 2]\n            self.assertTrue(model.setData(index, new_color + [255], ColorRole))\n            emit.assert_called()\n            emit.reset_mock()\n            color = model.data(index, Qt.DecorationRole)\n            rgb = [color.red(), color.green(), color.blue()]\n            self.assertEqual(rgb, new_color)\n\n            color = model.data(index, owcolor.ColorRole)\n            self.assertEqual(list(color), new_color)\n\n            self.assertEqual(\n                model.data(index, Qt.ToolTipRole), color_to_hex(new_color))\n\n            np.testing.assert_equal(self.descs[2].colors[4], rgb)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\ndef _find_other_palette(initial):\n    for palette in colorpalettes.ContinuousPalettes.values():\n        if palette.name != initial.name:\n            return palette\n    return None  # pragma: no cover\n\n\nclass TestContColorTableModel(GuiTest, BaseTestColorTableModel):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n\n    def test_column_count(self):\n        model = self.model\n\n        model.set_data(self.descs)\n        self.assertEqual(model.columnCount(), 3)\n        self.assertEqual(model.columnCount(model.index(0, 0)), 0)\n\n    def test_data(self):\n        super().test_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        palette = colorpalettes.ContinuousPalettes[self.descs[1].palette_name]\n        self.assertEqual(model.data(index, Qt.ToolTipRole),\n                         palette.friendly_name)\n        self.assertEqual(model.data(index, ColorRole), palette)\n        with patch.object(palette, \"color_strip\") as color_strip:\n            strip = model.data(index, owcolor.StripRole)\n            self.assertIs(strip, color_strip.return_value)\n            color_strip.assert_called_with(128, 16)\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsNone(model.data(index, Qt.FontRole))\n\n        palette = _find_other_palette(self.descs[1])\n        self.descs[1].palette_name = palette.name\n        self.assertIs(model.data(index, ColorRole), palette)\n\n        index = self.model.index(1, 2)\n        self.assertIsNone(model.data(index, Qt.ToolTipRole))\n        self.assertIsInstance(model.data(index, Qt.SizeHintRole), QSize)\n        self.assertIsInstance(model.data(index, Qt.ForegroundRole), QBrush)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(0)\n        self.assertIsNone(model.data(index, Qt.DisplayRole))\n        model.set_mouse_row(1)\n        self.assertEqual(model.data(index, Qt.DisplayRole), \"Copy to all\")\n\n    def test_set_data(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        index2 = model.index(2, 1)\n        initial = model.data(index, ColorRole)\n        initial2 = model.data(index, ColorRole)\n        assert initial.name == initial2.name\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n\n            self.assertFalse(model.setData(index, None, Qt.DisplayRole))\n            emit.assert_not_called()\n\n            self.assertTrue(model.setData(index, palette, ColorRole))\n            emit.assert_called()\n            self.assertIs(model.data(index2, ColorRole), initial2)\n\n            self.assertEqual(model.data(index, Qt.ToolTipRole),\n                             palette.friendly_name)\n            self.assertEqual(model.data(index, ColorRole), palette)\n            self.assertEqual(self.descs[1].palette_name, palette.name)\n            with patch.object(palette, \"color_strip\") as color_strip:\n                strip = model.data(index, owcolor.StripRole)\n                self.assertIs(strip, color_strip.return_value)\n                color_strip.assert_called_with(128, 16)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n    def test_copy_to_all(self):\n        super().test_set_data()\n\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n\n        emit = Mock()\n        try:\n            model.dataChanged.connect(emit)\n            model.setData(index, palette, ColorRole)\n            emit.assert_called()\n            emit.reset_mock()\n\n            model.copy_to_all(index)\n            emit.assert_called_once()\n            for row, desc in enumerate(self.descs):\n                self.assertEqual(\n                    model.data(model.index(row, 1), ColorRole).name,\n                    palette.name)\n                self.assertEqual(desc.palette_name, palette.name)\n        finally:\n            model.dataChanged.disconnect(emit)\n\n\nclass TestColorStripDelegate(GuiTest):\n    def setUp(self):\n        z = ContinuousVariable(\"z\")\n        w = ContinuousVariable(\"w\")\n        u = ContinuousVariable(\"u\")\n        self.descs = [owcolor.ContAttrDesc(v) for v in (z, w, u)]\n        self.model = owcolor.ContColorTableModel()\n        self.model.set_data(self.descs)\n        self.table = owcolor.ContinuousTable(self.model)\n\n    def test_color_combo(self):\n        model = self.model\n        index = model.index(1, 1)\n        initial = model.data(index, ColorRole)\n        palette = _find_other_palette(initial)\n        model.setData(index, palette, ColorRole)\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        combo = self.table.color_delegate.createEditor(None, Mock(), index)\n        self.assertEqual(combo.currentText(), palette.friendly_name)\n        palette = _find_other_palette(palette)\n        combo.setCurrentIndex(combo.findText(palette.friendly_name))\n        self.assertEqual(self.descs[1].palette_name, palette.name)\n\n        with patch.object(self.table, \"closeEditor\") as closeEditor:\n            combo.hidePopup()\n            closeEditor.assert_called()\n\n    @patch.object(owcolor.HorizontalGridDelegate, \"paint\")\n    def test_paint(self, _):\n        model = self.model\n        index = model.index(1, 1)\n        painter = Mock()\n        option = Mock()\n        option.rect = QRect(10, 20, 30, 40)\n        index.data = Mock()\n        index.data.return_value = Mock()\n        index.data.return_value.height = Mock(return_value=42)\n        self.table.color_delegate.paint(painter, option, index)\n        self.assertIs(painter.drawPixmap.call_args[0][2],\n                      index.data.return_value)\n\n\nclass TestOWColor(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(owcolor.OWColor)\n        self.iris = Table(\"iris\")\n\n    def test_reuse_old_settings(self):\n        self.send_signal(self.widget.Inputs.data, self.iris)\n\n        assert isinstance(self.widget, owcolor.OWColor)\n        self.widget.saveSettings()\n\n        w = self.create_widget(owcolor.OWColor, reset_default_settings=False)\n        self.send_signal(self.widget.Inputs.data, self.iris, widget=w)\n\n    def test_invalid_input_colors(self):\n        a = ContinuousVariable(\"a\")\n        a.attributes[\"colors\"] = \"invalid\"\n        t = Table.from_domain(Domain([a]))\n\n        self.send_signal(self.widget.Inputs.data, t)\n\n    def test_unconditional_commit_on_new_signal(self):\n        with patch.object(self.widget, 'unconditional_commit') as commit:\n            self.widget.auto_apply = False\n            commit.reset_mock()\n            self.send_signal(self.widget.Inputs.data, self.iris)\n            commit.assert_called()\n\n    def test_commit_on_data_changed(self):\n        widget = self.widget\n        model = widget.cont_model\n        self.send_signal(widget.Inputs.data, self.iris)\n        with patch.object(widget, 'commit') as commit:\n            commit.reset_mock()\n            model.setData(model.index(0, 0), \"y\", Qt.EditRole)\n            commit.assert_called()\n\n    def test_lose_data(self):\n        widget = self.widget\n        send = widget.Outputs.data.send = Mock()\n\n        self.send_signal(widget.Inputs.data, self.iris)\n        send.assert_called_once()\n        self.assertEqual(widget.disc_model.rowCount(), 1)\n        self.assertEqual(widget.cont_model.rowCount(), 4)\n\n        send.reset_mock()\n        self.send_signal(widget.Inputs.data, None)\n        send.assert_called_with(None)\n        self.assertEqual(widget.disc_model.rowCount(), 0)\n        self.assertEqual(widget.cont_model.rowCount(), 0)\n\n    def test_model_content(self):\n        widget = self.widget\n        data = Table(\"heart_disease\")\n        self.send_signal(widget.Inputs.data, data)\n\n        dm = widget.disc_model\n        self.assertEqual(\n            [dm.data(dm.index(i, 0)) for i in range(dm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n        cm = widget.disc_model\n        self.assertEqual(\n            [dm.data(cm.index(i, 0)) for i in range(cm.rowCount())],\n            [var.name for var in data.domain.variables if var.is_discrete]\n        )\n\n    def test_report(self):\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n        self.widget.send_report()\n\n        self.send_signal(self.widget.Inputs.data, None)\n        self.widget.send_report()\n\n    def test_string_variables(self):\n        self.send_signal(self.widget.Inputs.data, Table(\"zoo\"))\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        self.send_signal(self.widget.Inputs.data, data)\n        input_sum.assert_called_with(len(data), format_summary_details(data))\n        output = self.get_output(self.widget.Outputs.data)\n        output_sum.assert_called_with(len(output),\n                                      format_summary_details(output))\n        input_sum.reset_mock()\n        output_sum.reset_mock()\n        self.send_signal(self.widget.Inputs.data, None)\n        input_sum.assert_called_once()\n        self.assertEqual(input_sum.call_args[0][0].brief, \"\")\n        output_sum.assert_called_once()\n        self.assertEqual(output_sum.call_args[0][0].brief, \"\")\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
    ],
    "test_file_names": [
        "test_1.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Orange installation attempts...\nAttempting installation with Python 3.7...\nrunning build_ext\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.projection._som\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpzsxcoet5/tmp\ncreating /tmp/tmpzsxcoet5/tmp/tmpzsxcoet5\ncompile options: '-MMD -MF /tmp/tmpzsxcoet5/file.c.d -c'\ncc: /tmp/tmpzsxcoet5/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpsawd6p_5/tmp\ncreating /tmp/tmpsawd6p_5/tmp/tmpsawd6p_5\ncompile options: '-MMD -MF /tmp/tmpsawd6p_5/file.c.d -c'\ncc: /tmp/tmpsawd6p_5/file.c\ncustomize UnixCCompiler using build_ext\nbuilding 'Orange.classification._simple_tree' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange\ncreating build/temp.linux-x86_64-3.7/Orange/classification\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_simple_tree.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_simple_tree.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_simple_tree.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.classification._tree_scorers' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/classification/_tree_scorers.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/classification/_tree_scorers.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/classification/_tree_scorers.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._valuecount' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/data\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_valuecount.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_valuecount.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_valuecount.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._contingency' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_contingency.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_contingency.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_contingency.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._io' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_io.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_io.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_io.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.data._variable' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/data/_variable.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/data/_variable.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/data/_variable.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.distance._distance' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/distance\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/distance/_distance.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/distance/_distance.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/distance/_distance.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._discretize' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/preprocess\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/preprocess/_discretize.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_discretize.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_discretize.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.preprocess._relieff' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/preprocess/_relieff.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/preprocess/_relieff.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/preprocess/_relieff.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.projection._som' extension\ncompiling C sources\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/projection\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\ncc: Orange/projection/_som.c\ncc -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/projection/_som.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/projection/_som.cpython-37m-x86_64-linux-gnu.so\nbuilding 'Orange.widgets.utils._grid_density' extension\ncompiling C++ sources\nC compiler: c++ -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating build/temp.linux-x86_64-3.7/Orange/widgets\ncreating build/temp.linux-x86_64-3.7/Orange/widgets/utils\ncompile options: '-I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/include -I/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/include/python3.7m -c'\nc++: Orange/widgets/utils/_grid_density.cpp\nc++ -pthread -shared -L/tools/deps/lib build/temp.linux-x86_64-3.7/Orange/widgets/utils/_grid_density.o -L/home/gcpuser/.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib -lm -lpython3.7m -o Orange/widgets/utils/_grid_density.cpython-37m-x86_64-linux-gnu.so\nrunning develop\nrunning build_scripts\nrunning egg_info\nrunning build_src\nbuild_src\nbuilding extension \"Orange.classification._simple_tree\" sources\nbuilding extension \"Orange.classification._tree_scorers\" sources\nbuilding extension \"Orange.data._valuecount\" sources\nbuilding extension \"Orange.data._contingency\" sources\nbuilding extension \"Orange.data._io\" sources\nbuilding extension \"Orange.data._variable\" sources\nbuilding extension \"Orange.distance._distance\" sources\nbuilding extension \"Orange.preprocess._discretize\" sources\nbuilding extension \"Orange.preprocess._relieff\" sources\nbuilding extension \"Orange.projection._som\" sources\nbuilding extension \"Orange.widgets.utils._grid_density\" sources\nbuild_src: building npy-pkg config files\ncreating Orange3.egg-info\nwriting Orange3.egg-info/PKG-INFO\nwriting dependency_links to Orange3.egg-info/dependency_links.txt\nwriting entry points to Orange3.egg-info/entry_points.txt\nwriting requirements to Orange3.egg-info/requires.txt\nwriting top-level names to Orange3.egg-info/top_level.txt\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest file 'Orange3.egg-info/SOURCES.txt'\nreading manifest template 'MANIFEST.in'\nwarning: no files found matching 'README*' under directory 'Orange'\nwarning: no files found matching 'LICENSE' under directory 'Orange'\nwarning: no files found matching '*.basket' under directory 'Orange/datasets'\nwarning: no files found matching '*.js' under directory 'Orange/widgets'\nwarning: no files found matching '*.css' under directory 'Orange/widgets'\nwarning: no files found matching '*.html' under directory 'Orange/widgets'\nwarning: no files found matching 'COPYING'\nadding license file 'LICENSE'\nwriting manifest file 'Orange3.egg-info/SOURCES.txt'\nrunning build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmp5l6r_zd7/tmp\ncreating /tmp/tmp5l6r_zd7/tmp/tmp5l6r_zd7\ncompile options: '-MMD -MF /tmp/tmp5l6r_zd7/file.c.d -c'\ncc: /tmp/tmp5l6r_zd7/file.c\ncustomize UnixCCompiler using build_ext\ncustomize UnixCCompiler\nC compiler: cc -pthread -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/tools/deps/include -I/tools/deps/include/ncursesw -fPIC\n\ncreating /tmp/tmpqb2ciign/tmp\ncreating /tmp/tmpqb2ciign/tmp/tmpqb2ciign\ncompile options: '-MMD -MF /tmp/tmpqb2ciign/file.c.d -c'\ncc: /tmp/tmpqb2ciign/file.c\ncustomize UnixCCompiler using build_ext\nCreating /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/Orange3.egg-link (link to .)\nAdding Orange3 3.25.0.dev0+17e9691 to easy-install.pth file\nInstalling orange-canvas script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nInstalled /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa\nProcessing dependencies for Orange3==3.25.0.dev0+17e9691\nSearching for XlsxWriter==3.2.0\nBest match: XlsxWriter 3.2.0\nAdding XlsxWriter 3.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for xlrd==2.0.1\nBest match: xlrd 2.0.1\nAdding xlrd 2.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for setuptools==59.8.0\nBest match: setuptools 59.8.0\nAdding setuptools 59.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for serverfiles==0.3.1\nBest match: serverfiles 0.3.1\nAdding serverfiles 0.3.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for scipy==1.7.3\nBest match: scipy 1.7.3\nAdding scipy 1.7.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for scikit-learn==1.0.2\nBest match: scikit-learn 1.0.2\nAdding scikit-learn 1.0.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for requests==2.31.0\nBest match: requests 2.31.0\nAdding requests 2.31.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for PyYAML==6.0.1\nBest match: PyYAML 6.0.1\nAdding PyYAML 6.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for python-louvain==0.16\nBest match: python-louvain 0.16\nAdding python-louvain 0.16 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pyqtgraph==0.10.0\nBest match: pyqtgraph 0.10.0\nAdding pyqtgraph 0.10.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pip==24.0\nBest match: pip 24.0\nAdding pip 24.0 to easy-install.pth file\nInstalling pip script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling pip3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling pip3.10 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pandas==1.3.5\nBest match: pandas 1.3.5\nAdding pandas 1.3.5 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for orange-widget-base==4.22.0\nBest match: orange-widget-base 4.22.0\nAdding orange-widget-base 4.22.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for orange-canvas-core==0.1.35\nBest match: orange-canvas-core 0.1.35\nAdding orange-canvas-core 0.1.35 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for openpyxl==3.1.3\nBest match: openpyxl 3.1.3\nAdding openpyxl 3.1.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for openTSNE==1.0.1\nBest match: openTSNE 1.0.1\nAdding openTSNE 1.0.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for numpy==1.17.5\nBest match: numpy 1.17.5\nAdding numpy 1.17.5 to easy-install.pth file\nInstalling f2py script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling f2py3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling f2py3.7 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for networkx==2.6.3\nBest match: networkx 2.6.3\nAdding networkx 2.6.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for matplotlib==3.5.3\nBest match: matplotlib 3.5.3\nAdding matplotlib 3.5.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for keyrings.alt==4.2.0\nBest match: keyrings.alt 4.2.0\nAdding keyrings.alt 4.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for keyring==24.1.1\nBest match: keyring 24.1.1\nAdding keyring 24.1.1 to easy-install.pth file\nInstalling keyring script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for joblib==1.3.2\nBest match: joblib 1.3.2\nAdding joblib 1.3.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for docutils==0.20.1\nBest match: docutils 0.20.1\nAdding docutils 0.20.1 to easy-install.pth file\nInstalling docutils script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for chardet==5.2.0\nBest match: chardet 5.2.0\nAdding chardet 5.2.0 to easy-install.pth file\nInstalling chardetect script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for Bottleneck==1.4.0\nBest match: Bottleneck 1.4.0\nAdding Bottleneck 1.4.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for baycomp==1.0.3\nBest match: baycomp 1.0.3\nAdding baycomp 1.0.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for AnyQt==0.2.0\nBest match: AnyQt 0.2.0\nAdding AnyQt 0.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for threadpoolctl==3.1.0\nBest match: threadpoolctl 3.1.0\nAdding threadpoolctl 3.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for certifi==2024.12.14\nBest match: certifi 2024.12.14\nAdding certifi 2024.12.14 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for idna==3.10\nBest match: idna 3.10\nAdding idna 3.10 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for charset-normalizer==3.4.1\nBest match: charset-normalizer 3.4.1\nAdding charset-normalizer 3.4.1 to easy-install.pth file\nInstalling normalizer script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for urllib3==2.0.7\nBest match: urllib3 2.0.7\nAdding urllib3 2.0.7 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pytz==2024.2\nBest match: pytz 2024.2\nAdding pytz 2024.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for python-dateutil==2.9.0.post0\nBest match: python-dateutil 2.9.0.post0\nAdding python-dateutil 2.9.0.post0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for typing-extensions==4.7.1\nBest match: typing-extensions 4.7.1\nAdding typing-extensions 4.7.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for commonmark==0.9.1\nBest match: commonmark 0.9.1\nAdding commonmark 0.9.1 to easy-install.pth file\nInstalling cmark script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for importlib-metadata==6.7.0\nBest match: importlib-metadata 6.7.0\nAdding importlib-metadata 6.7.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for packaging==24.0\nBest match: packaging 24.0\nAdding packaging 24.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for dictdiffer==0.9.0\nBest match: dictdiffer 0.9.0\nAdding dictdiffer 0.9.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for qasync==0.25.0\nBest match: qasync 0.25.0\nAdding qasync 0.25.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for requests-cache==1.1.1\nBest match: requests-cache 1.1.1\nAdding requests-cache 1.1.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for et-xmlfile==1.1.0\nBest match: et-xmlfile 1.1.0\nAdding et-xmlfile 1.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for kiwisolver==1.4.5\nBest match: kiwisolver 1.4.5\nAdding kiwisolver 1.4.5 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for cycler==0.11.0\nBest match: cycler 0.11.0\nAdding cycler 0.11.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pyparsing==3.1.4\nBest match: pyparsing 3.1.4\nAdding pyparsing 3.1.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for fonttools==4.38.0\nBest match: fonttools 4.38.0\nAdding fonttools 4.38.0 to easy-install.pth file\nInstalling fonttools script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling pyftmerge script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling pyftsubset script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\nInstalling ttx script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for Pillow==9.5.0\nBest match: Pillow 9.5.0\nAdding Pillow 9.5.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for jaraco.classes==3.2.3\nBest match: jaraco.classes 3.2.3\nAdding jaraco.classes 3.2.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for SecretStorage==3.3.3\nBest match: SecretStorage 3.3.3\nAdding SecretStorage 3.3.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for importlib-resources==5.12.0\nBest match: importlib-resources 5.12.0\nAdding importlib-resources 5.12.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for jeepney==0.8.0\nBest match: jeepney 0.8.0\nAdding jeepney 0.8.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for six==1.17.0\nBest match: six 1.17.0\nAdding six 1.17.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for zipp==3.15.0\nBest match: zipp 3.15.0\nAdding zipp 3.15.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for platformdirs==4.0.0\nBest match: platformdirs 4.0.0\nAdding platformdirs 4.0.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for attrs==24.2.0\nBest match: attrs 24.2.0\nAdding attrs 24.2.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for cattrs==23.1.2\nBest match: cattrs 23.1.2\nAdding cattrs 23.1.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for url-normalize==1.4.3\nBest match: url-normalize 1.4.3\nAdding url-normalize 1.4.3 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for more-itertools==9.1.0\nBest match: more-itertools 9.1.0\nAdding more-itertools 9.1.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for cryptography==44.0.0\nBest match: cryptography 44.0.0\nAdding cryptography 44.0.0 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for exceptiongroup==1.2.2\nBest match: exceptiongroup 1.2.2\nAdding exceptiongroup 1.2.2 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for cffi==1.15.1\nBest match: cffi 1.15.1\nAdding cffi 1.15.1 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nSearching for pycparser==2.21\nBest match: pycparser 2.21\nAdding pycparser 2.21 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages\nFinished processing dependencies for Orange3==3.25.0.dev0+17e9691\nVerifying Orange installation...\n✅ Orange installation successful!\nSuccessfully installed orange using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 18 packages in 145ms\nPrepared 18 packages in 1ms\nInstalled 18 packages in 73ms\n + cython==0.29.37\n + exceptiongroup==1.2.2\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + numpy==1.17.5\n + packaging==24.0\n + pluggy==1.2.0\n + pyqt5==5.15.10\n + pyqt5-qt5==5.15.16\n + pyqt5-sip==12.13.0\n + pyqtwebengine==5.15.6\n + pyqtwebengine-qt5==5.15.16\n + pytest==7.4.4\n + setuptools==59.8.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + wheel==0.42.0\n + zipp==3.15.0\nResolved 48 packages in 260ms\nInstalled 42 packages in 528ms\n + baycomp==1.0.3\n + bottleneck==1.4.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + chardet==5.2.0\n + charset-normalizer==3.4.1\n + cryptography==44.0.0\n + cycler==0.11.0\n + et-xmlfile==1.1.0\n + fonttools==4.38.0\n + idna==3.10\n + importlib-resources==5.12.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + joblib==1.3.2\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + kiwisolver==1.4.5\n + matplotlib==3.5.3\n + more-itertools==9.1.0\n + networkx==2.6.3\n + openpyxl==3.1.3\n + opentsne==1.0.1\n + pandas==1.3.5\n + pillow==9.5.0\n + pip==24.0\n + pycparser==2.21\n + pyparsing==3.1.4\n + python-dateutil==2.9.0.post0\n + python-louvain==0.16\n + pytz==2024.2\n + pyyaml==6.0.1\n + requests==2.31.0\n + scikit-learn==1.0.2\n + scipy==1.7.3\n + secretstorage==3.3.3\n + serverfiles==0.3.1\n + six==1.17.0\n + threadpoolctl==3.1.0\n + urllib3==2.0.7\n + xlrd==2.0.1\n + xlsxwriter==3.2.0\nResolved 34 packages in 106ms\nInstalled 13 packages in 199ms\n + anyqt==0.2.0\n + attrs==24.2.0\n + cattrs==23.1.2\n + commonmark==0.9.1\n + dictdiffer==0.9.0\n + docutils==0.20.1\n + orange-canvas-core==0.1.35\n + orange-widget-base==4.22.0\n + platformdirs==4.0.0\n + pyqtgraph==0.10.0\n + qasync==0.25.0\n + requests-cache==1.1.1\n + url-normalize==1.4.3\nResolved 2 packages in 4ms\nInstalled 2 packages in 21ms\n + psycopg2==2.9.9\n + pymssql==2.3.2\nAudited 1 package in 63ms\nAudited 2 packages in 1ms\nOrange/classification/_simple_tree.c: In function ‘gain_ratio_c’:\nOrange/classification/_simple_tree.c:63:9: warning: implicit declaration of function ‘qsort_r’; did you mean ‘qsort’? [-Wimplicit-function-declaration]\n   63 |         qsort_r(base, nel, size, compar, thunk)\n      |         ^~~~~~~\nOrange/classification/_simple_tree.c:147:9: note: in expansion of macro ‘QSORT_R_FUNC’\n  147 |         QSORT_R_FUNC(examples, size, sizeof(struct Example), (void*) &compar_attr, compar_examples);\n      |         ^~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/classification/_tree_scorers.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_2find_threshold_entropy’:\nOrange/classification/_tree_scorers.c:3115:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 3115 |   __pyx_t_7 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_6find_threshold_MSE’:\nOrange/classification/_tree_scorers.c:4619:27: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 4619 |   __pyx_t_1 = ((__pyx_v_N <= __pyx_v_min_leaf) != 0);\n      |                           ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_8find_binarization_MSE’:\nOrange/classification/_tree_scorers.c:5396:43: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5396 |           for (__pyx_t_22 = 0; __pyx_t_22 < __pyx_t_21; __pyx_t_22+=1) {\n      |                                           ^\nOrange/classification/_tree_scorers.c:5517:39: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5517 |           __pyx_t_27 = ((__pyx_v_left >= __pyx_v_min_leaf) != 0);\n      |                                       ^~\nOrange/classification/_tree_scorers.c:5523:53: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 5523 |           __pyx_t_27 = (((__pyx_v_N - __pyx_v_left) >= __pyx_v_min_leaf) != 0);\n      |                                                     ^~\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_14compute_predictions_csr’:\nOrange/classification/_tree_scorers.c:7051:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7051 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c: In function ‘__pyx_pf_6Orange_14classification_13_tree_scorers_16compute_predictions_csc’:\nOrange/classification/_tree_scorers.c:7741:41: warning: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’ [-Wsign-compare]\n 7741 |         for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {\n      |                                         ^\nOrange/classification/_tree_scorers.c:7801:143: warning: comparison of integer expressions of different signedness: ‘__pyx_t_5numpy_int32_t’ {aka ‘int’} and ‘unsigned int’ [-Wsign-compare]\n 7801 |               __pyx_t_17 = (((*((__pyx_t_5numpy_int32_t *) ( /* dim=0 */ (__pyx_v_indices.data + __pyx_t_18 * __pyx_v_indices.strides[0]) ))) != __pyx_v_i) != 0);\n      |                                                                                                                                               ^~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_valuecount.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_contingency.c:598:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/data/_io.c: In function ‘__pyx_pf_6Orange_4data_3_io_sparse_read_float.constprop’:\nOrange/data/_io.c:3881:24: warning: ‘__pyx_v_decs’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3881 |           __pyx_v_decs = (__pyx_v_decs / 10.0);\n      |           ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:4070:24: warning: ‘__pyx_v_value’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4070 |           __pyx_t_10 = PyFloat_FromDouble(__pyx_v_value); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 221, __pyx_L5_error)\n      |                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:480:40: warning: ‘__pyx_v_attr_index’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n  480 |   #define PyInt_FromLong               PyLong_FromLong\n      |                                        ^~~~~~~~~~~~~~~\nOrange/data/_io.c:1301:7: note: ‘__pyx_v_attr_index’ was declared here\n 1301 |   int __pyx_v_attr_index;\n      |       ^~~~~~~~~~~~~~~~~~\nOrange/data/_io.c:2935:25: warning: ‘__pyx_v_atomp’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2935 |           __pyx_v_atomp = (__pyx_v_atomp + 1);\n      |           ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/distance/_distance.c:598:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_discretize.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/preprocess/_relieff.cpp:581:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/projection/_som.c:598:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning \"Using deprecated NumPy API, disable it with \" \"#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-Wcpp]\n   17 | #warning \"Using deprecated NumPy API, disable it with \" \\\n      |  ^~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_5update_hex’:\nOrange/projection/_som.c:3655:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3655 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:3654:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3654 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_7get_winners_sparse’:\nOrange/projection/_som.c:4547:223: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4547 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_38, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_39, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_y;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:4114:7: note: ‘__pyx_v_win_y’ was declared here\n 4114 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:4536:223: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4536 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_36, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_37, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_x;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:4113:7: note: ‘__pyx_v_win_x’ was declared here\n 4113 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pf_6Orange_10projection_4_som_8update_sparse.constprop’:\nOrange/projection/_som.c:4746:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4746 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:4745:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 4745 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_3update’:\nOrange/projection/_som.c:3141:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 3141 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pw_6Orange_10projection_4_som_1get_winners’:\nOrange/projection/_som.c:2964:223: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2964 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_27, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_y;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:2665:7: note: ‘__pyx_v_win_y’ was declared here\n 2665 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:2953:223: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 2953 |           *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int16_t *, __pyx_pybuffernd_winners.rcbuffer->pybuffer.buf, __pyx_t_25, __pyx_pybuffernd_winners.diminfo[0].strides, __pyx_t_26, __pyx_pybuffernd_winners.diminfo[1].strides) = __pyx_v_win_x;\n      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~\nOrange/projection/_som.c:2664:7: note: ‘__pyx_v_win_x’ was declared here\n 2664 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c: In function ‘__pyx_pf_6Orange_10projection_4_som_10update_sparse_hex.constprop’:\nOrange/projection/_som.c:5515:7: warning: ‘__pyx_v_win_y’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 5515 |   int __pyx_v_win_y;\n      |       ^~~~~~~~~~~~~\nOrange/projection/_som.c:5514:7: warning: ‘__pyx_v_win_x’ may be used uninitialized in this function [-Wmaybe-uninitialized]\n 5514 |   int __pyx_v_win_x;\n      |       ^~~~~~~~~~~~~\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/setuptools/command/easy_install.py:159: EasyInstallDeprecationWarning: easy_install command is deprecated. Use build and pip and other standards-based tools.\n  EasyInstallDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/setuptools/command/install.py:37: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.\n  setuptools.SetuptoolsDeprecationWarning,\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa/.venv/lib/python3.7/site-packages/setuptools/command/egg_info.py:628: SetuptoolsDeprecationWarning: Custom 'build_py' does not implement 'get_data_files_without_manifest'.\nPlease extend command classes from setuptools instead of distutils.\n  SetuptoolsDeprecationWarning\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa\ncollected 32 items\n\nr2e_tests/test_1.py sss.............................                     [100%]\n\n==================================== PASSES ====================================\n___________________ TestColorStripDelegate.test_color_combo ____________________\n----------------------------- Captured stderr call -----------------------------\nThis plugin does not support raise()\nThis plugin does not support grabbing the keyboard\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::AttrDescTest::test_name\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_colors\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_create_variable\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_values\nPASSED r2e_tests/test_1.py::ContAttrDesc::test_create_variable\nPASSED r2e_tests/test_1.py::ContAttrDesc::test_palette\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_column_count\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_data\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_row_count\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_set_data\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_column_count\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_copy_to_all\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_data\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_row_count\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_set_data\nPASSED r2e_tests/test_1.py::TestColorStripDelegate::test_color_combo\nPASSED r2e_tests/test_1.py::TestColorStripDelegate::test_paint\nPASSED r2e_tests/test_1.py::TestOWColor::test_commit_on_data_changed\nPASSED r2e_tests/test_1.py::TestOWColor::test_image_export\nPASSED r2e_tests/test_1.py::TestOWColor::test_invalid_input_colors\nPASSED r2e_tests/test_1.py::TestOWColor::test_lose_data\nPASSED r2e_tests/test_1.py::TestOWColor::test_minimum_size\nPASSED r2e_tests/test_1.py::TestOWColor::test_model_content\nPASSED r2e_tests/test_1.py::TestOWColor::test_msg_base_class\nPASSED r2e_tests/test_1.py::TestOWColor::test_report\nPASSED r2e_tests/test_1.py::TestOWColor::test_reuse_old_settings\nPASSED r2e_tests/test_1.py::TestOWColor::test_string_variables\nPASSED r2e_tests/test_1.py::TestOWColor::test_summary\nPASSED r2e_tests/test_1.py::TestOWColor::test_unconditional_commit_on_new_signal\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:244: image exporting not tested as .widget was not set\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:238: minimum size not tested as .widget was not set\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:250: msg base class not tested as .widget was not set\n======================== 29 passed, 3 skipped in 3.70s =========================\nWidgets left: 0    Max widgets: 1053 \n\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_17e9691cee9100e6fd2c4798d06e71aa97ecbbfa\ncollected 32 items\n\nr2e_tests/test_1.py sss...........................F.                     [100%]\n\n=================================== FAILURES ===================================\n___________________________ TestOWColor.test_summary ___________________________\n\nself = <r2e_tests.test_1.TestOWColor testMethod=test_summary>\n\n    def test_summary(self):\n        \"\"\"Check if the status bar is updated when data is received\"\"\"\n        data = self.iris\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n    \n        self.send_signal(self.widget.Inputs.data, data)\n>       input_sum.assert_called_with(len(data), format_summary_details(data))\n\nr2e_tests/test_1.py:494: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\n_mock_self = <Mock id='136183635532944'>\nargs = (150, '150 instances, 5 variables\\nFeatures: 4 numeric\\nTarget: categorical\\nMetas: —')\nkwargs = {}\nexpected = \"mock(150, '150 instances, 5 variables\\\\nFeatures: 4 numeric\\\\nTarget: categorical\\\\nMetas: —')\"\n\n    def assert_called_with(_mock_self, *args, **kwargs):\n        \"\"\"assert that the mock was called with the specified arguments.\n    \n        Raises an AssertionError if the args and keyword args passed in are\n        different to the last call to the mock.\"\"\"\n        self = _mock_self\n        if self.call_args is None:\n            expected = self._format_mock_call_signature(args, kwargs)\n>           raise AssertionError('Expected call: %s\\nNot called' % (expected,))\nE           AssertionError: Expected call: mock(150, '150 instances, 5 variables\\nFeatures: 4 numeric\\nTarget: categorical\\nMetas: —')\nE           Not called\n\n../../../../.local/share/uv/python/cpython-3.7.9-linux-x86_64-gnu/lib/python3.7/unittest/mock.py:869: AssertionError\n==================================== PASSES ====================================\n___________________ TestColorStripDelegate.test_color_combo ____________________\n----------------------------- Captured stderr call -----------------------------\nThis plugin does not support raise()\nThis plugin does not support grabbing the keyboard\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::AttrDescTest::test_name\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_colors\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_create_variable\nPASSED r2e_tests/test_1.py::DiscAttrTest::test_values\nPASSED r2e_tests/test_1.py::ContAttrDesc::test_create_variable\nPASSED r2e_tests/test_1.py::ContAttrDesc::test_palette\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_column_count\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_data\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_row_count\nPASSED r2e_tests/test_1.py::TestDiscColorTableModel::test_set_data\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_column_count\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_copy_to_all\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_data\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_row_count\nPASSED r2e_tests/test_1.py::TestContColorTableModel::test_set_data\nPASSED r2e_tests/test_1.py::TestColorStripDelegate::test_color_combo\nPASSED r2e_tests/test_1.py::TestColorStripDelegate::test_paint\nPASSED r2e_tests/test_1.py::TestOWColor::test_commit_on_data_changed\nPASSED r2e_tests/test_1.py::TestOWColor::test_image_export\nPASSED r2e_tests/test_1.py::TestOWColor::test_invalid_input_colors\nPASSED r2e_tests/test_1.py::TestOWColor::test_lose_data\nPASSED r2e_tests/test_1.py::TestOWColor::test_minimum_size\nPASSED r2e_tests/test_1.py::TestOWColor::test_model_content\nPASSED r2e_tests/test_1.py::TestOWColor::test_msg_base_class\nPASSED r2e_tests/test_1.py::TestOWColor::test_report\nPASSED r2e_tests/test_1.py::TestOWColor::test_reuse_old_settings\nPASSED r2e_tests/test_1.py::TestOWColor::test_string_variables\nPASSED r2e_tests/test_1.py::TestOWColor::test_unconditional_commit_on_new_signal\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:244: image exporting not tested as .widget was not set\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:238: minimum size not tested as .widget was not set\nSKIPPED [1] .venv/lib/python3.7/site-packages/orangewidget/tests/base.py:250: msg base class not tested as .widget was not set\nFAILED r2e_tests/test_1.py::TestOWColor::test_summary - AssertionError: Expec...\n=================== 1 failed, 28 passed, 3 skipped in 2.52s ====================\nWidgets left: 0    Max widgets: 1053 \n\n",
    "old_commit_res_stderr": ""
}
Orange/widgets/data/owcolor.py Orange/widgets/data/tests/test_owcolor.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** OWColor Widget Fails to Update Data Information in Status Bar

**Description:**
When loading or clearing data in the OWColor widget, the status bar does not display the updated data information. This makes it difficult for users to see summaries of the input and output data, affecting usability and transparency.

**Example Code:**
```python
def test_summary(self):
    data = self.iris
    input_sum = self.widget.info.set_input_summary = Mock()
    output_sum = self.widget.info.set_output_summary = Mock()
    
    self.send_signal(self.widget.Inputs.data, data)
    input_sum.assert_called_with(len(data), format_summary_details(data))
```

**Expected Behavior:**
Upon receiving new data, the status bar should display summaries of the input data, and similarly update when data is cleared. This includes showing the number of instances, variables, and other relevant details.

**Actual Behavior:**
The `set_input_summary` and `set_output_summary` methods are not called, resulting in the status bar remaining empty or not reflecting the current state of the data.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/widgets/data/owcolor.py
from itertools import chain

import numpy as np

from AnyQt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex, QTimer
from AnyQt.QtGui import QColor, QFont, QBrush
from AnyQt.QtWidgets import QHeaderView, QColorDialog, QTableView, QComboBox

import Orange
from Orange.util import color_to_hex
from Orange.widgets import widget, settings, gui
from Orange.widgets.gui import HorizontalGridDelegate
from Orange.widgets.utils import itemmodels, colorpalettes
from Orange.widgets.utils.widgetpreview import WidgetPreview
from Orange.widgets.widget import Input, Output
from orangewidget.settings import IncompatibleContext

ColorRole = next(gui.OrangeUserRole)
StripRole = next(gui.OrangeUserRole)


class AttrDesc:
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (Variable): an instance of variable
        new_name (str or `None`): a changed name or `None`
    """
    def __init__(self, var):
        self.var = var
        self.new_name = None

    @property
    def name(self):
        return self.new_name or self.var.name

    @name.setter
    def name(self, name):
        self.new_name = name


class DiscAttrDesc(AttrDesc):
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (DiscreteVariable): an instance of variable
        name (str or `None`): a changed name or `None`
        new_colors (list of tuple or None): new colors as tuples (R, G, B)
        new_values (list of str or None): new names for values, if changed
    """
    def __init__(self, var):
        super().__init__(var)
        self.new_colors = None
        self.new_values = None

    @property
    def colors(self):
        if self.new_colors is None:
            return self.var.colors
        else:
            return self.new_colors

    def set_color(self, i, color):
        if self.new_colors is None:
            self.new_colors = list(self.var.colors)
        self.new_colors[i] = color

    @property
    def values(self):
        return tuple(self.new_values or self.var.values)

    def set_value(self, i, value):
        if not self.new_values:
            self.new_values = list(self.var.values)
        self.new_values[i] = value

    def create_variable(self):
        new_var = self.var.copy(name=self.name, values=self.values)
        new_var.colors = np.asarray(self.colors)
        return new_var


class ContAttrDesc(AttrDesc):
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (ContinuousVariable): an instance of variable
        name (str or `None`): a changed name or `None`
        palette_name (str or None): name of palette or None if unmodified
    """
    def __init__(self, var):
        super().__init__(var)
        if var.palette.name not in colorpalettes.ContinuousPalettes:
            self.new_palette_name = colorpalettes.DefaultContinuousPaletteName
        else:
            self.new_palette_name = None

    @property
    def palette_name(self):
        return self.new_palette_name or self.var.palette.name

    @palette_name.setter
    def palette_name(self, palette_name):
        self.new_palette_name = palette_name

    def create_variable(self):
        new_var = self.var.copy(name=self.name)
        new_var.attributes["palette"] = self.palette_name
        return new_var


class ColorTableModel(QAbstractTableModel):
    """
    Base color model for discrete and continuous variables. The model handles:
    - the first column - variable name (including setData)
    - flags
    - row count, computed as len(attrdescs)

    Attribute:
        attrdescs (list of AttrDesc): attrdescs with user-defined changes
    """
    def __init__(self):
        QAbstractTableModel.__init__(self)
        self.attrdescs = []

    @staticmethod
    def flags(_):  # pragma: no cover
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def set_data(self, attrdescs):
        self.modelAboutToBeReset.emit()
        self.attrdescs = attrdescs
        self.modelReset.emit()

    def rowCount(self, parent=QModelIndex()):
        return 0 if parent.isValid() else len(self.attrdescs)

    def data(self, index, role=Qt.DisplayRole):
        # Only valid for the first column; derived classes implement the rest
        row = index.row()
        if role in (Qt.DisplayRole, Qt.EditRole):
            return self.attrdescs[row].name
        if role == Qt.FontRole:
            font = QFont()
            font.setBold(True)
            return font
        if role == Qt.TextAlignmentRole:
            return Qt.AlignRight | Qt.AlignVCenter
        return None

    def setData(self, index, value, role):
        # Only valid for the first column; derived classes implement the rest
        if role == Qt.EditRole:
            self.attrdescs[index.row()].name = value
        else:
            return False
        self.dataChanged.emit(index, index)
        return True


class DiscColorTableModel(ColorTableModel):
    """
    A model that stores the colors corresponding to values of discrete
    variables. Colors are shown as decorations.
    """
    def columnCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return 1 + max((len(row.var.values) for row in self.attrdescs),
                       default=0)

    def data(self, index, role=Qt.DisplayRole):
        # pylint: disable=too-many-return-statements
        row, col = index.row(), index.column()
        if col == 0:
            return super().data(index, role)

        desc = self.attrdescs[row]
        if col > len(desc.var.values):
            return None
        if role in (Qt.DisplayRole, Qt.EditRole):
            return desc.values[col - 1]

        color = desc.colors[col - 1]
        if role == Qt.DecorationRole:
            return QColor(*color)
        if role == Qt.ToolTipRole:
            return color_to_hex(color)
        if role == ColorRole:
            return color
        return None

    def setData(self, index, value, role):
        row, col = index.row(), index.column()
        if col == 0:
            return super().setData(index, value, role)

        desc = self.attrdescs[row]
        if role == ColorRole:
            desc.set_color(col - 1, value[:3])
        elif role == Qt.EditRole:
            desc.set_value(col - 1, value)
        else:
            return False
        self.dataChanged.emit(index, index)
        return True


class ContColorTableModel(ColorTableModel):
    """A model that stores the colors corresponding to values of discrete
    variables. Colors are shown as decorations.

    Attributes:
        mouse_row (int): the row over which the mouse is hovering
    """
    def __init__(self):
        super().__init__()
        self.mouse_row = None

    def set_mouse_row(self, row):
        self.mouse_row = row

    @staticmethod
    def columnCount(parent=QModelIndex()):
        return 0 if parent.isValid() else 3

    def data(self, index, role=Qt.DisplayRole):
        def _column0():
            return ColorTableModel.data(self, index, role)

        def _column1():
            palette = colorpalettes.ContinuousPalettes[desc.palette_name]
            if role == Qt.ToolTipRole:
                return palette.friendly_name
            if role == ColorRole:
                return palette
            if role == StripRole:
                return palette.color_strip(128, 16)
            if role == Qt.SizeHintRole:
                return QSize(150, 16)
            return None

        def _column2():
            if role == Qt.SizeHintRole:
                return QSize(100, 1)
            if role == Qt.ForegroundRole:
                return QBrush(Qt.blue)
            if row == self.mouse_row and role == Qt.DisplayRole:
                return "Copy to all"
            return None

        row, col = index.row(), index.column()
        desc = self.attrdescs[row]
        if 0 <= col <= 2:
            return [_column0, _column1, _column2][col]()

    # noinspection PyMethodOverriding
    def setData(self, index, value, role):
        row, col = index.row(), index.column()
        if col == 0:
            return super().setData(index, value, role)
        if role == ColorRole:
            self.attrdescs[row].palette_name = value.name
        else:
            return False
        self.dataChanged.emit(index, index)
        return True

    def copy_to_all(self, index):
        palette_name = self.attrdescs[index.row()].palette_name
        for desc in self.attrdescs:
            desc.palette_name = palette_name
        self.dataChanged.emit(self.index(0, 1), self.index(self.rowCount(), 1))


class ColorStripDelegate(HorizontalGridDelegate):
    def __init__(self, view):
        super().__init__()
        self.view = view

    def createEditor(self, parent, option, index):
        class Combo(QComboBox):
            def __init__(self, parent, initial_data):
                super().__init__(parent)
                model = itemmodels.ContinuousPalettesModel(icon_width=128)
                self.setModel(model)
                self.setCurrentIndex(model.indexOf(initial_data))
                self.setIconSize(QSize(128, 16))
                QTimer.singleShot(0, self.showPopup)

            def hidePopup(self):
                super().hidePopup()
                view.closeEditor(self, ColorStripDelegate.NoHint)

        def select(i):
            self.view.model().setData(
                index,
                combo.model().index(i, 0).data(Qt.UserRole),
                ColorRole)

        view = self.view
        combo = Combo(parent, index.data(ColorRole))
        combo.currentIndexChanged[int].connect(select)
        return combo

    def paint(self, painter, option, index):
        strip = index.data(StripRole)
        rect = option.rect
        painter.drawPixmap(
            rect.x() + 13, rect.y() + (rect.height() - strip.height()) / 2,
            strip)
        super().paint(painter, option, index)


class ColorTable(QTableView):
    """
    The base table view for discrete and continuous attributes.

    Sets the basic properties of the table and implementes mouseRelease that
    calls handle_click with appropriate index. It also prepares a grid_deleagte
    that is used in derived classes.
    """
    def __init__(self, model):
        QTableView.__init__(self)
        self.horizontalHeader().hide()
        self.verticalHeader().hide()
        self.setShowGrid(False)
        self.setSelectionMode(QTableView.NoSelection)
        self.setModel(model)
        # View doesn't take ownership of delegates, so we store it here
        self.grid_delegate = HorizontalGridDelegate()

    def mouseReleaseEvent(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return
        rect = self.visualRect(index)
        self.handle_click(index, event.pos().x() - rect.x())


class DiscreteTable(ColorTable):
    """Table view for discrete variables"""
    def __init__(self, model):
        super().__init__(model)
        self.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.setItemDelegate(self.grid_delegate)
        self.setEditTriggers(QTableView.NoEditTriggers)

    def handle_click(self, index, x_offset):
        """
        Handle click events for the first column (call the edit method)
        and the second (call method for changing the palette)
        """
        if self.model().data(index, Qt.EditRole) is None:
            return
        if index.column() == 0 or x_offset > 24:
            self.edit(index)
        else:
            self.change_color(index)

    def change_color(self, index):
        """Invoke palette editor and set the color"""
        color = self.model().data(index, ColorRole)
        if color is None:
            return
        dlg = QColorDialog(QColor(*color))
        if dlg.exec():
            color = dlg.selectedColor()
            self.model().setData(index, color.getRgb(), ColorRole)


class ContinuousTable(ColorTable):
    """Table view for continuous variables"""

    def __init__(self, model):
        super().__init__(model)
        self.viewport().setMouseTracking(True)
        # View doesn't take ownership of delegates, so we must store it
        self.color_delegate = ColorStripDelegate(self)
        self.setItemDelegateForColumn(0, self.grid_delegate)
        self.setItemDelegateForColumn(1, self.color_delegate)
        self.setColumnWidth(1, 256)
        self.setEditTriggers(
            QTableView.SelectedClicked | QTableView.DoubleClicked)

    def mouseMoveEvent(self, event):
        """Store the hovered row index in the model, trigger viewport update"""
        pos = event.pos()
        ind = self.indexAt(pos)
        self.model().set_mouse_row(ind.row())
        super().mouseMoveEvent(event)
        self.viewport().update()

    def leaveEvent(self, _):
        """Remove the stored the hovered row index, trigger viewport update"""
        self.model().set_mouse_row(None)
        self.viewport().update()

    def handle_click(self, index, _):
        """Call the specific methods for handling clicks for each column"""
        if index.column() < 2:
            self.edit(index)
        elif index.column() == 2:
            self.model().copy_to_all(index)


class OWColor(widget.OWWidget):
    name = "Color"
    description = "Set color legend for variables."
    icon = "icons/Colors.svg"

    class Inputs:
        data = Input("Data", Orange.data.Table)

    class Outputs:
        data = Output("Data", Orange.data.Table)

    settingsHandler = settings.PerfectDomainContextHandler(
        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)
    disc_descs = settings.ContextSetting([])
    cont_descs = settings.ContextSetting([])
    color_settings = settings.Setting(None)
    selected_schema_index = settings.Setting(0)
    auto_apply = settings.Setting(True)

    settings_version = 2

    want_main_area = False

    def __init__(self):
        super().__init__()
        self.data = None
        self.orig_domain = self.domain = None

        box = gui.hBox(self.controlArea, "Discrete Variables")
        self.disc_model = DiscColorTableModel()
        self.disc_view = DiscreteTable(self.disc_model)
        self.disc_model.dataChanged.connect(self._on_data_changed)
        box.layout().addWidget(self.disc_view)

        box = gui.hBox(self.controlArea, "Numeric Variables")
        self.cont_model = ContColorTableModel()
        self.cont_view = ContinuousTable(self.cont_model)
        self.cont_model.dataChanged.connect(self._on_data_changed)
        box.layout().addWidget(self.cont_view)

        box = gui.auto_apply(self.controlArea, self, "auto_apply")
        box.button.setFixedWidth(180)
        box.layout().insertStretch(0)

    @staticmethod
    def sizeHint():  # pragma: no cover
        return QSize(500, 570)

    @Inputs.data
    def set_data(self, data):
        self.closeContext()
        self.disc_descs = []
        self.cont_descs = []
        if data is None:
            self.data = self.domain = None
        else:
            self.data = data
            for var in chain(data.domain.variables, data.domain.metas):
                if var.is_discrete:
                    self.disc_descs.append(DiscAttrDesc(var))
                elif var.is_continuous:
                    self.cont_descs.append(ContAttrDesc(var))

        self.disc_model.set_data(self.disc_descs)
        self.cont_model.set_data(self.cont_descs)
        self.openContext(data)
        self.disc_view.resizeColumnsToContents()
        self.cont_view.resizeColumnsToContents()
        self.unconditional_commit()

    def _on_data_changed(self):
        self.commit()

    def commit(self):
        def make(variables):
            new_vars = []
            for var in variables:
                source = disc_dict if var.is_discrete else cont_dict
                desc = source.get(var.name)
                new_vars.append(desc.create_variable() if desc else var)
            return new_vars

        if self.data is None:
            self.Outputs.data.send(None)
            return

        disc_dict = {desc.var.name: desc for desc in self.disc_descs}
        cont_dict = {desc.var.name: desc for desc in self.cont_descs}

        dom = self.data.domain
        new_domain = Orange.data.Domain(
            make(dom.attributes), make(dom.class_vars), make(dom.metas))
        new_data = self.data.transform(new_domain)
        self.Outputs.data.send(new_data)

    def send_report(self):
        """Send report"""
        def _report_variables(variables):
            from Orange.widgets.report import colored_square as square

            def was(n, o):
                return n if n == o else f"{n} (was: {o})"

            max_values = max(
                (len(var.values) for var in variables if var.is_discrete),
                default=1)

            rows = ""
            disc_dict = {k.var.name: k for k in self.disc_descs}
            cont_dict = {k.var.name: k for k in self.cont_descs}
            for var in variables:
                if var.is_discrete:
                    desc = disc_dict[var.name]
                    value_cols = "    \n".join(
                        f"<td>{square(*color)} {was(value, old_value)}</td>"
                        for color, value, old_value in
                        zip(desc.colors, desc.values, var.values))
                elif var.is_continuous:
                    desc = cont_dict[var.name]
                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]
                    value_cols = f'<td colspan="{max_values}">' \
                                 f'{pal.friendly_name}</td>'
                else:
                    continue
                names = was(desc.name, desc.var.name)
                rows += '<tr style="height: 2em">\n' \
                        f'  <th style="text-align: right">{names}</th>' \
                        f'  {value_cols}\n' \
                        '</tr>\n'
            return rows

        if not self.data:
            return
        dom = self.data.domain
        sections = (
            (name, _report_variables(variables))
            for name, variables in (
                ("Features", dom.attributes),
                ("Outcome" + "s" * (len(dom.class_vars) > 1), dom.class_vars),
                ("Meta attributes", dom.metas)))
        table = "".join(f"<tr><th>{name}</th></tr>{rows}"
                        for name, rows in sections if rows)
        if table:
            self.report_raw(r"<table>{table}</table>")

    @classmethod
    def migrate_context(cls, context, version):
        if not version or version < 2:
            raise IncompatibleContext


if __name__ == "__main__":  # pragma: no cover
    WidgetPreview(OWColor).run(Orange.data.Table("heart_disease.tab"))

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** OWColor Widget Fails to Update Data Information in Status Bar

**Description:**
When loading or clearing data in the OWColor widget, the status bar does not display the updated data information. This makes it difficult for users to see summaries of the input and output data, affecting usability and transparency.

**Example Code:**
```python
def test_summary(self):
    data = self.iris
    input_sum = self.widget.info.set_input_summary = Mock()
    output_sum = self.widget.info.set_output_summary = Mock()
    
    self.send_signal(self.widget.Inputs.data, data)
    input_sum.assert_called_with(len(data), format_summary_details(data))
```

**Expected Behavior:**
Upon receiving new data, the status bar should display summaries of the input data, and similarly update when data is cleared. This includes showing the number of instances, variables, and other relevant details.

**Actual Behavior:**
The `set_input_summary` and `set_output_summary` methods are not called, resulting in the status bar remaining empty or not reflecting the current state of the data.

[/ISSUE]
{
    "AttrDescTest.test_name": "PASSED",
    "DiscAttrTest.test_colors": "PASSED",
    "DiscAttrTest.test_create_variable": "PASSED",
    "DiscAttrTest.test_values": "PASSED",
    "ContAttrDesc.test_create_variable": "PASSED",
    "ContAttrDesc.test_palette": "PASSED",
    "TestDiscColorTableModel.test_column_count": "PASSED",
    "TestDiscColorTableModel.test_data": "PASSED",
    "TestDiscColorTableModel.test_row_count": "PASSED",
    "TestDiscColorTableModel.test_set_data": "PASSED",
    "TestContColorTableModel.test_column_count": "PASSED",
    "TestContColorTableModel.test_copy_to_all": "PASSED",
    "TestContColorTableModel.test_data": "PASSED",
    "TestContColorTableModel.test_row_count": "PASSED",
    "TestContColorTableModel.test_set_data": "PASSED",
    "TestColorStripDelegate.test_color_combo": "PASSED",
    "TestColorStripDelegate.test_paint": "PASSED",
    "TestOWColor.test_commit_on_data_changed": "PASSED",
    "TestOWColor.test_image_export": "PASSED",
    "TestOWColor.test_invalid_input_colors": "PASSED",
    "TestOWColor.test_lose_data": "PASSED",
    "TestOWColor.test_minimum_size": "PASSED",
    "TestOWColor.test_model_content": "PASSED",
    "TestOWColor.test_msg_base_class": "PASSED",
    "TestOWColor.test_report": "PASSED",
    "TestOWColor.test_reuse_old_settings": "PASSED",
    "TestOWColor.test_string_variables": "PASSED",
    "TestOWColor.test_summary": "PASSED",
    "TestOWColor.test_unconditional_commit_on_new_signal": "PASSED"
}
diff --git a/Orange/widgets/data/owcolor.py b/Orange/widgets/data/owcolor.py
index 02b0c2c35..0381cf128 100644
--- a/Orange/widgets/data/owcolor.py
+++ b/Orange/widgets/data/owcolor.py
@@ -12,6 +12,7 @@ from Orange.widgets import widget, settings, gui
 from Orange.widgets.gui import HorizontalGridDelegate
 from Orange.widgets.utils import itemmodels, colorpalettes
 from Orange.widgets.utils.widgetpreview import WidgetPreview
+from Orange.widgets.utils.state_summary import format_summary_details
 from Orange.widgets.widget import Input, Output
 from orangewidget.settings import IncompatibleContext
 
@@ -458,6 +459,9 @@ class OWColor(widget.OWWidget):
         box.button.setFixedWidth(180)
         box.layout().insertStretch(0)
 
+        self.info.set_input_summary(self.info.NoInput)
+        self.info.set_output_summary(self.info.NoOutput)
+
     @staticmethod
     def sizeHint():  # pragma: no cover
         return QSize(500, 570)
@@ -469,8 +473,10 @@ class OWColor(widget.OWWidget):
         self.cont_descs = []
         if data is None:
             self.data = self.domain = None
+            self.info.set_input_summary(self.info.NoInput)
         else:
             self.data = data
+            self.info.set_input_summary(len(data), format_summary_details(data))
             for var in chain(data.domain.variables, data.domain.metas):
                 if var.is_discrete:
                     self.disc_descs.append(DiscAttrDesc(var))
@@ -498,6 +504,7 @@ class OWColor(widget.OWWidget):
 
         if self.data is None:
             self.Outputs.data.send(None)
+            self.info.set_output_summary(self.info.NoOutput)
             return
 
         disc_dict = {desc.var.name: desc for desc in self.disc_descs}
@@ -507,6 +514,8 @@ class OWColor(widget.OWWidget):
         new_domain = Orange.data.Domain(
             make(dom.attributes), make(dom.class_vars), make(dom.metas))
         new_data = self.data.transform(new_domain)
+        self.info.set_output_summary(len(new_data),
+                                     format_summary_details(new_data))
         self.Outputs.data.send(new_data)
 
     def send_report(self):

{"Orange/widgets/data/owcolor.py": "from itertools import chain\n\nimport numpy as np\n\nfrom AnyQt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex, QTimer\nfrom AnyQt.QtGui import QColor, QFont, QBrush\nfrom AnyQt.QtWidgets import QHeaderView, QColorDialog, QTableView, QComboBox\n\nimport Orange\nfrom Orange.util import color_to_hex\nfrom Orange.widgets import widget, settings, gui\nfrom Orange.widgets.gui import HorizontalGridDelegate\nfrom Orange.widgets.utils import itemmodels, colorpalettes\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.widget import Input, Output\nfrom orangewidget.settings import IncompatibleContext\n\nColorRole = next(gui.OrangeUserRole)\nStripRole = next(gui.OrangeUserRole)\n\n\nclass AttrDesc:\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (Variable): an instance of variable\n        new_name (str or `None`): a changed name or `None`\n    \"\"\"\n    def __init__(self, var):\n        self.var = var\n        self.new_name = None\n\n    @property\n    def name(self):\n        return self.new_name or self.var.name\n\n    @name.setter\n    def name(self, name):\n        self.new_name = name\n\n\nclass DiscAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (DiscreteVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        new_colors (list of tuple or None): new colors as tuples (R, G, B)\n        new_values (list of str or None): new names for values, if changed\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        self.new_colors = None\n        self.new_values = None\n\n    @property\n    def colors(self):\n        if self.new_colors is None:\n            return self.var.colors\n        else:\n            return self.new_colors\n\n    def set_color(self, i, color):\n        if self.new_colors is None:\n            self.new_colors = list(self.var.colors)\n        self.new_colors[i] = color\n\n    @property\n    def values(self):\n        return tuple(self.new_values or self.var.values)\n\n    def set_value(self, i, value):\n        if not self.new_values:\n            self.new_values = list(self.var.values)\n        self.new_values[i] = value\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name, values=self.values)\n        new_var.colors = np.asarray(self.colors)\n        return new_var\n\n\nclass ContAttrDesc(AttrDesc):\n    \"\"\"\n    Describes modifications that will be applied to variable.\n\n    Provides methods that return either the modified value or the original\n\n    Attributes:\n        var (ContinuousVariable): an instance of variable\n        name (str or `None`): a changed name or `None`\n        palette_name (str or None): name of palette or None if unmodified\n    \"\"\"\n    def __init__(self, var):\n        super().__init__(var)\n        if var.palette.name not in colorpalettes.ContinuousPalettes:\n            self.new_palette_name = colorpalettes.DefaultContinuousPaletteName\n        else:\n            self.new_palette_name = None\n\n    @property\n    def palette_name(self):\n        return self.new_palette_name or self.var.palette.name\n\n    @palette_name.setter\n    def palette_name(self, palette_name):\n        self.new_palette_name = palette_name\n\n    def create_variable(self):\n        new_var = self.var.copy(name=self.name)\n        new_var.attributes[\"palette\"] = self.palette_name\n        return new_var\n\n\nclass ColorTableModel(QAbstractTableModel):\n    \"\"\"\n    Base color model for discrete and continuous variables. The model handles:\n    - the first column - variable name (including setData)\n    - flags\n    - row count, computed as len(attrdescs)\n\n    Attribute:\n        attrdescs (list of AttrDesc): attrdescs with user-defined changes\n    \"\"\"\n    def __init__(self):\n        QAbstractTableModel.__init__(self)\n        self.attrdescs = []\n\n    @staticmethod\n    def flags(_):  # pragma: no cover\n        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable\n\n    def set_data(self, attrdescs):\n        self.modelAboutToBeReset.emit()\n        self.attrdescs = attrdescs\n        self.modelReset.emit()\n\n    def rowCount(self, parent=QModelIndex()):\n        return 0 if parent.isValid() else len(self.attrdescs)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # Only valid for the first column; derived classes implement the rest\n        row = index.row()\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return self.attrdescs[row].name\n        if role == Qt.FontRole:\n            font = QFont()\n            font.setBold(True)\n            return font\n        if role == Qt.TextAlignmentRole:\n            return Qt.AlignRight | Qt.AlignVCenter\n        return None\n\n    def setData(self, index, value, role):\n        # Only valid for the first column; derived classes implement the rest\n        if role == Qt.EditRole:\n            self.attrdescs[index.row()].name = value\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass DiscColorTableModel(ColorTableModel):\n    \"\"\"\n    A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n    \"\"\"\n    def columnCount(self, parent=QModelIndex()):\n        if parent.isValid():\n            return 0\n        return 1 + max((len(row.var.values) for row in self.attrdescs),\n                       default=0)\n\n    def data(self, index, role=Qt.DisplayRole):\n        # pylint: disable=too-many-return-statements\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().data(index, role)\n\n        desc = self.attrdescs[row]\n        if col > len(desc.var.values):\n            return None\n        if role in (Qt.DisplayRole, Qt.EditRole):\n            return desc.values[col - 1]\n\n        color = desc.colors[col - 1]\n        if role == Qt.DecorationRole:\n            return QColor(*color)\n        if role == Qt.ToolTipRole:\n            return color_to_hex(color)\n        if role == ColorRole:\n            return color\n        return None\n\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n\n        desc = self.attrdescs[row]\n        if role == ColorRole:\n            desc.set_color(col - 1, value[:3])\n        elif role == Qt.EditRole:\n            desc.set_value(col - 1, value)\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n\nclass ContColorTableModel(ColorTableModel):\n    \"\"\"A model that stores the colors corresponding to values of discrete\n    variables. Colors are shown as decorations.\n\n    Attributes:\n        mouse_row (int): the row over which the mouse is hovering\n    \"\"\"\n    def __init__(self):\n        super().__init__()\n        self.mouse_row = None\n\n    def set_mouse_row(self, row):\n        self.mouse_row = row\n\n    @staticmethod\n    def columnCount(parent=QModelIndex()):\n        return 0 if parent.isValid() else 3\n\n    def data(self, index, role=Qt.DisplayRole):\n        def _column0():\n            return ColorTableModel.data(self, index, role)\n\n        def _column1():\n            palette = colorpalettes.ContinuousPalettes[desc.palette_name]\n            if role == Qt.ToolTipRole:\n                return palette.friendly_name\n            if role == ColorRole:\n                return palette\n            if role == StripRole:\n                return palette.color_strip(128, 16)\n            if role == Qt.SizeHintRole:\n                return QSize(150, 16)\n            return None\n\n        def _column2():\n            if role == Qt.SizeHintRole:\n                return QSize(100, 1)\n            if role == Qt.ForegroundRole:\n                return QBrush(Qt.blue)\n            if row == self.mouse_row and role == Qt.DisplayRole:\n                return \"Copy to all\"\n            return None\n\n        row, col = index.row(), index.column()\n        desc = self.attrdescs[row]\n        if 0 <= col <= 2:\n            return [_column0, _column1, _column2][col]()\n\n    # noinspection PyMethodOverriding\n    def setData(self, index, value, role):\n        row, col = index.row(), index.column()\n        if col == 0:\n            return super().setData(index, value, role)\n        if role == ColorRole:\n            self.attrdescs[row].palette_name = value.name\n        else:\n            return False\n        self.dataChanged.emit(index, index)\n        return True\n\n    def copy_to_all(self, index):\n        palette_name = self.attrdescs[index.row()].palette_name\n        for desc in self.attrdescs:\n            desc.palette_name = palette_name\n        self.dataChanged.emit(self.index(0, 1), self.index(self.rowCount(), 1))\n\n\nclass ColorStripDelegate(HorizontalGridDelegate):\n    def __init__(self, view):\n        super().__init__()\n        self.view = view\n\n    def createEditor(self, parent, option, index):\n        class Combo(QComboBox):\n            def __init__(self, parent, initial_data):\n                super().__init__(parent)\n                model = itemmodels.ContinuousPalettesModel(icon_width=128)\n                self.setModel(model)\n                self.setCurrentIndex(model.indexOf(initial_data))\n                self.setIconSize(QSize(128, 16))\n                QTimer.singleShot(0, self.showPopup)\n\n            def hidePopup(self):\n                super().hidePopup()\n                view.closeEditor(self, ColorStripDelegate.NoHint)\n\n        def select(i):\n            self.view.model().setData(\n                index,\n                combo.model().index(i, 0).data(Qt.UserRole),\n                ColorRole)\n\n        view = self.view\n        combo = Combo(parent, index.data(ColorRole))\n        combo.currentIndexChanged[int].connect(select)\n        return combo\n\n    def paint(self, painter, option, index):\n        strip = index.data(StripRole)\n        rect = option.rect\n        painter.drawPixmap(\n            rect.x() + 13, rect.y() + (rect.height() - strip.height()) / 2,\n            strip)\n        super().paint(painter, option, index)\n\n\nclass ColorTable(QTableView):\n    \"\"\"\n    The base table view for discrete and continuous attributes.\n\n    Sets the basic properties of the table and implementes mouseRelease that\n    calls handle_click with appropriate index. It also prepares a grid_deleagte\n    that is used in derived classes.\n    \"\"\"\n    def __init__(self, model):\n        QTableView.__init__(self)\n        self.horizontalHeader().hide()\n        self.verticalHeader().hide()\n        self.setShowGrid(False)\n        self.setSelectionMode(QTableView.NoSelection)\n        self.setModel(model)\n        # View doesn't take ownership of delegates, so we store it here\n        self.grid_delegate = HorizontalGridDelegate()\n\n    def mouseReleaseEvent(self, event):\n        index = self.indexAt(event.pos())\n        if not index.isValid():\n            return\n        rect = self.visualRect(index)\n        self.handle_click(index, event.pos().x() - rect.x())\n\n\nclass DiscreteTable(ColorTable):\n    \"\"\"Table view for discrete variables\"\"\"\n    def __init__(self, model):\n        super().__init__(model)\n        self.horizontalHeader().setSectionResizeMode(\n            QHeaderView.ResizeToContents)\n        self.setItemDelegate(self.grid_delegate)\n        self.setEditTriggers(QTableView.NoEditTriggers)\n\n    def handle_click(self, index, x_offset):\n        \"\"\"\n        Handle click events for the first column (call the edit method)\n        and the second (call method for changing the palette)\n        \"\"\"\n        if self.model().data(index, Qt.EditRole) is None:\n            return\n        if index.column() == 0 or x_offset > 24:\n            self.edit(index)\n        else:\n            self.change_color(index)\n\n    def change_color(self, index):\n        \"\"\"Invoke palette editor and set the color\"\"\"\n        color = self.model().data(index, ColorRole)\n        if color is None:\n            return\n        dlg = QColorDialog(QColor(*color))\n        if dlg.exec():\n            color = dlg.selectedColor()\n            self.model().setData(index, color.getRgb(), ColorRole)\n\n\nclass ContinuousTable(ColorTable):\n    \"\"\"Table view for continuous variables\"\"\"\n\n    def __init__(self, model):\n        super().__init__(model)\n        self.viewport().setMouseTracking(True)\n        # View doesn't take ownership of delegates, so we must store it\n        self.color_delegate = ColorStripDelegate(self)\n        self.setItemDelegateForColumn(0, self.grid_delegate)\n        self.setItemDelegateForColumn(1, self.color_delegate)\n        self.setColumnWidth(1, 256)\n        self.setEditTriggers(\n            QTableView.SelectedClicked | QTableView.DoubleClicked)\n\n    def mouseMoveEvent(self, event):\n        \"\"\"Store the hovered row index in the model, trigger viewport update\"\"\"\n        pos = event.pos()\n        ind = self.indexAt(pos)\n        self.model().set_mouse_row(ind.row())\n        super().mouseMoveEvent(event)\n        self.viewport().update()\n\n    def leaveEvent(self, _):\n        \"\"\"Remove the stored the hovered row index, trigger viewport update\"\"\"\n        self.model().set_mouse_row(None)\n        self.viewport().update()\n\n    def handle_click(self, index, _):\n        \"\"\"Call the specific methods for handling clicks for each column\"\"\"\n        if index.column() < 2:\n            self.edit(index)\n        elif index.column() == 2:\n            self.model().copy_to_all(index)\n\n\nclass OWColor(widget.OWWidget):\n    name = \"Color\"\n    description = \"Set color legend for variables.\"\n    icon = \"icons/Colors.svg\"\n\n    class Inputs:\n        data = Input(\"Data\", Orange.data.Table)\n\n    class Outputs:\n        data = Output(\"Data\", Orange.data.Table)\n\n    settingsHandler = settings.PerfectDomainContextHandler(\n        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)\n    disc_descs = settings.ContextSetting([])\n    cont_descs = settings.ContextSetting([])\n    color_settings = settings.Setting(None)\n    selected_schema_index = settings.Setting(0)\n    auto_apply = settings.Setting(True)\n\n    settings_version = 2\n\n    want_main_area = False\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.orig_domain = self.domain = None\n\n        box = gui.hBox(self.controlArea, \"Discrete Variables\")\n        self.disc_model = DiscColorTableModel()\n        self.disc_view = DiscreteTable(self.disc_model)\n        self.disc_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.disc_view)\n\n        box = gui.hBox(self.controlArea, \"Numeric Variables\")\n        self.cont_model = ContColorTableModel()\n        self.cont_view = ContinuousTable(self.cont_model)\n        self.cont_model.dataChanged.connect(self._on_data_changed)\n        box.layout().addWidget(self.cont_view)\n\n        box = gui.auto_apply(self.controlArea, self, \"auto_apply\")\n        box.button.setFixedWidth(180)\n        box.layout().insertStretch(0)\n\n    @staticmethod\n    def sizeHint():  # pragma: no cover\n        return QSize(500, 570)\n\n    @Inputs.data\n    def set_data(self, data):\n        self.closeContext()\n        self.disc_descs = []\n        self.cont_descs = []\n        if data is None:\n            self.data = self.domain = None\n        else:\n            self.data = data\n            for var in chain(data.domain.variables, data.domain.metas):\n                if var.is_discrete:\n                    self.disc_descs.append(DiscAttrDesc(var))\n                elif var.is_continuous:\n                    self.cont_descs.append(ContAttrDesc(var))\n\n        self.disc_model.set_data(self.disc_descs)\n        self.cont_model.set_data(self.cont_descs)\n        self.openContext(data)\n        self.disc_view.resizeColumnsToContents()\n        self.cont_view.resizeColumnsToContents()\n        self.unconditional_commit()\n\n    def _on_data_changed(self):\n        self.commit()\n\n    def commit(self):\n        def make(variables):\n            new_vars = []\n            for var in variables:\n                source = disc_dict if var.is_discrete else cont_dict\n                desc = source.get(var.name)\n                new_vars.append(desc.create_variable() if desc else var)\n            return new_vars\n\n        if self.data is None:\n            self.Outputs.data.send(None)\n            return\n\n        disc_dict = {desc.var.name: desc for desc in self.disc_descs}\n        cont_dict = {desc.var.name: desc for desc in self.cont_descs}\n\n        dom = self.data.domain\n        new_domain = Orange.data.Domain(\n            make(dom.attributes), make(dom.class_vars), make(dom.metas))\n        new_data = self.data.transform(new_domain)\n        self.Outputs.data.send(new_data)\n\n    def send_report(self):\n        \"\"\"Send report\"\"\"\n        def _report_variables(variables):\n            from Orange.widgets.report import colored_square as square\n\n            def was(n, o):\n                return n if n == o else f\"{n} (was: {o})\"\n\n            max_values = max(\n                (len(var.values) for var in variables if var.is_discrete),\n                default=1)\n\n            rows = \"\"\n            disc_dict = {k.var.name: k for k in self.disc_descs}\n            cont_dict = {k.var.name: k for k in self.cont_descs}\n            for var in variables:\n                if var.is_discrete:\n                    desc = disc_dict[var.name]\n                    value_cols = \"    \\n\".join(\n                        f\"<td>{square(*color)} {was(value, old_value)}</td>\"\n                        for color, value, old_value in\n                        zip(desc.colors, desc.values, var.values))\n                elif var.is_continuous:\n                    desc = cont_dict[var.name]\n                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]\n                    value_cols = f'<td colspan=\"{max_values}\">' \\\n                                 f'{pal.friendly_name}</td>'\n                else:\n                    continue\n                names = was(desc.name, desc.var.name)\n                rows += '<tr style=\"height: 2em\">\\n' \\\n                        f'  <th style=\"text-align: right\">{names}</th>' \\\n                        f'  {value_cols}\\n' \\\n                        '</tr>\\n'\n            return rows\n\n        if not self.data:\n            return\n        dom = self.data.domain\n        sections = (\n            (name, _report_variables(variables))\n            for name, variables in (\n                (\"Features\", dom.attributes),\n                (\"Outcome\" + \"s\" * (len(dom.class_vars) > 1), dom.class_vars),\n                (\"Meta attributes\", dom.metas)))\n        table = \"\".join(f\"<tr><th>{name}</th></tr>{rows}\"\n                        for name, rows in sections if rows)\n        if table:\n            self.report_raw(r\"<table>{table}</table>\")\n\n    @classmethod\n    def migrate_context(cls, context, version):\n        if not version or version < 2:\n            raise IncompatibleContext\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    WidgetPreview(OWColor).run(Orange.data.Table(\"heart_disease.tab\"))\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** OWColor Widget Fails to Update Data Information in Status Bar

**Description:**
When loading or clearing data in the OWColor widget, the status bar does not display the updated data information. This makes it difficult for users to see summaries of the input and output data, affecting usability and transparency.

**Example Code:**
```python
def test_summary(self):
    data = self.iris
    input_sum = self.widget.info.set_input_summary = Mock()
    output_sum = self.widget.info.set_output_summary = Mock()
    
    self.send_signal(self.widget.Inputs.data, data)
    input_sum.assert_called_with(len(data), format_summary_details(data))
```

**Expected Behavior:**
Upon receiving new data, the status bar should display summaries of the input data, and similarly update when data is cleared. This includes showing the number of instances, variables, and other relevant details.

**Actual Behavior:**
The `set_input_summary` and `set_output_summary` methods are not called, resulting in the status bar remaining empty or not reflecting the current state of the data.

[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### Orange/widgets/data/owcolor.py
from itertools import chain

import numpy as np

from AnyQt.QtCore import Qt, QSize, QAbstractTableModel, QModelIndex, QTimer
from AnyQt.QtGui import QColor, QFont, QBrush
from AnyQt.QtWidgets import QHeaderView, QColorDialog, QTableView, QComboBox

import Orange
from Orange.util import color_to_hex
from Orange.widgets import widget, settings, gui
from Orange.widgets.gui import HorizontalGridDelegate
from Orange.widgets.utils import itemmodels, colorpalettes
from Orange.widgets.utils.widgetpreview import WidgetPreview
from Orange.widgets.widget import Input, Output
from orangewidget.settings import IncompatibleContext

ColorRole = next(gui.OrangeUserRole)
StripRole = next(gui.OrangeUserRole)


class AttrDesc:
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (Variable): an instance of variable
        new_name (str or `None`): a changed name or `None`
    """
    def __init__(self, var):
        self.var = var
        self.new_name = None

    @property
    def name(self):
        return self.new_name or self.var.name

    @name.setter
    def name(self, name):
        self.new_name = name


class DiscAttrDesc(AttrDesc):
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (DiscreteVariable): an instance of variable
        name (str or `None`): a changed name or `None`
        new_colors (list of tuple or None): new colors as tuples (R, G, B)
        new_values (list of str or None): new names for values, if changed
    """
    def __init__(self, var):
        super().__init__(var)
        self.new_colors = None
        self.new_values = None

    @property
    def colors(self):
        if self.new_colors is None:
            return self.var.colors
        else:
            return self.new_colors

    def set_color(self, i, color):
        if self.new_colors is None:
            self.new_colors = list(self.var.colors)
        self.new_colors[i] = color

    @property
    def values(self):
        return tuple(self.new_values or self.var.values)

    def set_value(self, i, value):
        if not self.new_values:
            self.new_values = list(self.var.values)
        self.new_values[i] = value

    def create_variable(self):
        new_var = self.var.copy(name=self.name, values=self.values)
        new_var.colors = np.asarray(self.colors)
        return new_var


class ContAttrDesc(AttrDesc):
    """
    Describes modifications that will be applied to variable.

    Provides methods that return either the modified value or the original

    Attributes:
        var (ContinuousVariable): an instance of variable
        name (str or `None`): a changed name or `None`
        palette_name (str or None): name of palette or None if unmodified
    """
    def __init__(self, var):
        super().__init__(var)
        if var.palette.name not in colorpalettes.ContinuousPalettes:
            self.new_palette_name = colorpalettes.DefaultContinuousPaletteName
        else:
            self.new_palette_name = None

    @property
    def palette_name(self):
        return self.new_palette_name or self.var.palette.name

    @palette_name.setter
    def palette_name(self, palette_name):
        self.new_palette_name = palette_name

    def create_variable(self):
        new_var = self.var.copy(name=self.name)
        new_var.attributes["palette"] = self.palette_name
        return new_var


class ColorTableModel(QAbstractTableModel):
    """
    Base color model for discrete and continuous variables. The model handles:
    - the first column - variable name (including setData)
    - flags
    - row count, computed as len(attrdescs)

    Attribute:
        attrdescs (list of AttrDesc): attrdescs with user-defined changes
    """
    def __init__(self):
        QAbstractTableModel.__init__(self)
        self.attrdescs = []

    @staticmethod
    def flags(_):  # pragma: no cover
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def set_data(self, attrdescs):
        self.modelAboutToBeReset.emit()
        self.attrdescs = attrdescs
        self.modelReset.emit()

    def rowCount(self, parent=QModelIndex()):
        return 0 if parent.isValid() else len(self.attrdescs)

    def data(self, index, role=Qt.DisplayRole):
        # Only valid for the first column; derived classes implement the rest
        row = index.row()
        if role in (Qt.DisplayRole, Qt.EditRole):
            return self.attrdescs[row].name
        if role == Qt.FontRole:
            font = QFont()
            font.setBold(True)
            return font
        if role == Qt.TextAlignmentRole:
            return Qt.AlignRight | Qt.AlignVCenter
        return None

    def setData(self, index, value, role):
        # Only valid for the first column; derived classes implement the rest
        if role == Qt.EditRole:
            self.attrdescs[index.row()].name = value
        else:
            return False
        self.dataChanged.emit(index, index)
        return True


class DiscColorTableModel(ColorTableModel):
    """
    A model that stores the colors corresponding to values of discrete
    variables. Colors are shown as decorations.
    """
    def columnCount(self, parent=QModelIndex()):
        if parent.isValid():
            return 0
        return 1 + max((len(row.var.values) for row in self.attrdescs),
                       default=0)

    def data(self, index, role=Qt.DisplayRole):
        # pylint: disable=too-many-return-statements
        row, col = index.row(), index.column()
        if col == 0:
            return super().data(index, role)

        desc = self.attrdescs[row]
        if col > len(desc.var.values):
            return None
        if role in (Qt.DisplayRole, Qt.EditRole):
            return desc.values[col - 1]

        color = desc.colors[col - 1]
        if role == Qt.DecorationRole:
            return QColor(*color)
        if role == Qt.ToolTipRole:
            return color_to_hex(color)
        if role == ColorRole:
            return color
        return None

    def setData(self, index, value, role):
        row, col = index.row(), index.column()
        if col == 0:
            return super().setData(index, value, role)

        desc = self.attrdescs[row]
        if role == ColorRole:
            desc.set_color(col - 1, value[:3])
        elif role == Qt.EditRole:
            desc.set_value(col - 1, value)
        else:
            return False
        self.dataChanged.emit(index, index)
        return True


class ContColorTableModel(ColorTableModel):
    """A model that stores the colors corresponding to values of discrete
    variables. Colors are shown as decorations.

    Attributes:
        mouse_row (int): the row over which the mouse is hovering
    """
    def __init__(self):
        super().__init__()
        self.mouse_row = None

    def set_mouse_row(self, row):
        self.mouse_row = row

    @staticmethod
    def columnCount(parent=QModelIndex()):
        return 0 if parent.isValid() else 3

    def data(self, index, role=Qt.DisplayRole):
        def _column0():
            return ColorTableModel.data(self, index, role)

        def _column1():
            palette = colorpalettes.ContinuousPalettes[desc.palette_name]
            if role == Qt.ToolTipRole:
                return palette.friendly_name
            if role == ColorRole:
                return palette
            if role == StripRole:
                return palette.color_strip(128, 16)
            if role == Qt.SizeHintRole:
                return QSize(150, 16)
            return None

        def _column2():
            if role == Qt.SizeHintRole:
                return QSize(100, 1)
            if role == Qt.ForegroundRole:
                return QBrush(Qt.blue)
            if row == self.mouse_row and role == Qt.DisplayRole:
                return "Copy to all"
            return None

        row, col = index.row(), index.column()
        desc = self.attrdescs[row]
        if 0 <= col <= 2:
            return [_column0, _column1, _column2][col]()

    # noinspection PyMethodOverriding
    def setData(self, index, value, role):
        row, col = index.row(), index.column()
        if col == 0:
            return super().setData(index, value, role)
        if role == ColorRole:
            self.attrdescs[row].palette_name = value.name
        else:
            return False
        self.dataChanged.emit(index, index)
        return True

    def copy_to_all(self, index):
        palette_name = self.attrdescs[index.row()].palette_name
        for desc in self.attrdescs:
            desc.palette_name = palette_name
        self.dataChanged.emit(self.index(0, 1), self.index(self.rowCount(), 1))


class ColorStripDelegate(HorizontalGridDelegate):
    def __init__(self, view):
        super().__init__()
        self.view = view

    def createEditor(self, parent, option, index):
        class Combo(QComboBox):
            def __init__(self, parent, initial_data):
                super().__init__(parent)
                model = itemmodels.ContinuousPalettesModel(icon_width=128)
                self.setModel(model)
                self.setCurrentIndex(model.indexOf(initial_data))
                self.setIconSize(QSize(128, 16))
                QTimer.singleShot(0, self.showPopup)

            def hidePopup(self):
                super().hidePopup()
                view.closeEditor(self, ColorStripDelegate.NoHint)

        def select(i):
            self.view.model().setData(
                index,
                combo.model().index(i, 0).data(Qt.UserRole),
                ColorRole)

        view = self.view
        combo = Combo(parent, index.data(ColorRole))
        combo.currentIndexChanged[int].connect(select)
        return combo

    def paint(self, painter, option, index):
        strip = index.data(StripRole)
        rect = option.rect
        painter.drawPixmap(
            rect.x() + 13, rect.y() + (rect.height() - strip.height()) / 2,
            strip)
        super().paint(painter, option, index)


class ColorTable(QTableView):
    """
    The base table view for discrete and continuous attributes.

    Sets the basic properties of the table and implementes mouseRelease that
    calls handle_click with appropriate index. It also prepares a grid_deleagte
    that is used in derived classes.
    """
    def __init__(self, model):
        QTableView.__init__(self)
        self.horizontalHeader().hide()
        self.verticalHeader().hide()
        self.setShowGrid(False)
        self.setSelectionMode(QTableView.NoSelection)
        self.setModel(model)
        # View doesn't take ownership of delegates, so we store it here
        self.grid_delegate = HorizontalGridDelegate()

    def mouseReleaseEvent(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return
        rect = self.visualRect(index)
        self.handle_click(index, event.pos().x() - rect.x())


class DiscreteTable(ColorTable):
    """Table view for discrete variables"""
    def __init__(self, model):
        super().__init__(model)
        self.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.setItemDelegate(self.grid_delegate)
        self.setEditTriggers(QTableView.NoEditTriggers)

    def handle_click(self, index, x_offset):
        """
        Handle click events for the first column (call the edit method)
        and the second (call method for changing the palette)
        """
        if self.model().data(index, Qt.EditRole) is None:
            return
        if index.column() == 0 or x_offset > 24:
            self.edit(index)
        else:
            self.change_color(index)

    def change_color(self, index):
        """Invoke palette editor and set the color"""
        color = self.model().data(index, ColorRole)
        if color is None:
            return
        dlg = QColorDialog(QColor(*color))
        if dlg.exec():
            color = dlg.selectedColor()
            self.model().setData(index, color.getRgb(), ColorRole)


class ContinuousTable(ColorTable):
    """Table view for continuous variables"""

    def __init__(self, model):
        super().__init__(model)
        self.viewport().setMouseTracking(True)
        # View doesn't take ownership of delegates, so we must store it
        self.color_delegate = ColorStripDelegate(self)
        self.setItemDelegateForColumn(0, self.grid_delegate)
        self.setItemDelegateForColumn(1, self.color_delegate)
        self.setColumnWidth(1, 256)
        self.setEditTriggers(
            QTableView.SelectedClicked | QTableView.DoubleClicked)

    def mouseMoveEvent(self, event):
        """Store the hovered row index in the model, trigger viewport update"""
        pos = event.pos()
        ind = self.indexAt(pos)
        self.model().set_mouse_row(ind.row())
        super().mouseMoveEvent(event)
        self.viewport().update()

    def leaveEvent(self, _):
        """Remove the stored the hovered row index, trigger viewport update"""
        self.model().set_mouse_row(None)
        self.viewport().update()

    def handle_click(self, index, _):
        """Call the specific methods for handling clicks for each column"""
        if index.column() < 2:
            self.edit(index)
        elif index.column() == 2:
            self.model().copy_to_all(index)


class OWColor(widget.OWWidget):
    name = "Color"
    description = "Set color legend for variables."
    icon = "icons/Colors.svg"

    class Inputs:
        data = Input("Data", Orange.data.Table)

    class Outputs:
        data = Output("Data", Orange.data.Table)

    settingsHandler = settings.PerfectDomainContextHandler(
        match_values=settings.PerfectDomainContextHandler.MATCH_VALUES_ALL)
    disc_descs = settings.ContextSetting([])
    cont_descs = settings.ContextSetting([])
    color_settings = settings.Setting(None)
    selected_schema_index = settings.Setting(0)
    auto_apply = settings.Setting(True)

    settings_version = 2

    want_main_area = False

    def __init__(self):
        super().__init__()
        self.data = None
        self.orig_domain = self.domain = None

        box = gui.hBox(self.controlArea, "Discrete Variables")
        self.disc_model = DiscColorTableModel()
        self.disc_view = DiscreteTable(self.disc_model)
        self.disc_model.dataChanged.connect(self._on_data_changed)
        box.layout().addWidget(self.disc_view)

        box = gui.hBox(self.controlArea, "Numeric Variables")
        self.cont_model = ContColorTableModel()
        self.cont_view = ContinuousTable(self.cont_model)
        self.cont_model.dataChanged.connect(self._on_data_changed)
        box.layout().addWidget(self.cont_view)

        box = gui.auto_apply(self.controlArea, self, "auto_apply")
        box.button.setFixedWidth(180)
        box.layout().insertStretch(0)

    @staticmethod
    def sizeHint():  # pragma: no cover
        return QSize(500, 570)

    @Inputs.data
    def set_data(self, data):
        self.closeContext()
        self.disc_descs = []
        self.cont_descs = []
        if data is None:
            self.data = self.domain = None
        else:
            self.data = data
            for var in chain(data.domain.variables, data.domain.metas):
                if var.is_discrete:
                    self.disc_descs.append(DiscAttrDesc(var))
                elif var.is_continuous:
                    self.cont_descs.append(ContAttrDesc(var))

        self.disc_model.set_data(self.disc_descs)
        self.cont_model.set_data(self.cont_descs)
        self.openContext(data)
        self.disc_view.resizeColumnsToContents()
        self.cont_view.resizeColumnsToContents()
        self.unconditional_commit()

    def _on_data_changed(self):
        self.commit()

    def commit(self):
        def make(variables):
            new_vars = []
            for var in variables:
                source = disc_dict if var.is_discrete else cont_dict
                desc = source.get(var.name)
                new_vars.append(desc.create_variable() if desc else var)
            return new_vars

        if self.data is None:
            self.Outputs.data.send(None)
            return

        disc_dict = {desc.var.name: desc for desc in self.disc_descs}
        cont_dict = {desc.var.name: desc for desc in self.cont_descs}

        dom = self.data.domain
        new_domain = Orange.data.Domain(
            make(dom.attributes), make(dom.class_vars), make(dom.metas))
        new_data = self.data.transform(new_domain)
        self.Outputs.data.send(new_data)

    def send_report(self):
        """Send report"""
        def _report_variables(variables):
            from Orange.widgets.report import colored_square as square

            def was(n, o):
                return n if n == o else f"{n} (was: {o})"

            max_values = max(
                (len(var.values) for var in variables if var.is_discrete),
                default=1)

            rows = ""
            disc_dict = {k.var.name: k for k in self.disc_descs}
            cont_dict = {k.var.name: k for k in self.cont_descs}
            for var in variables:
                if var.is_discrete:
                    desc = disc_dict[var.name]
                    value_cols = "    \n".join(
                        f"<td>{square(*color)} {was(value, old_value)}</td>"
                        for color, value, old_value in
                        zip(desc.colors, desc.values, var.values))
                elif var.is_continuous:
                    desc = cont_dict[var.name]
                    pal = colorpalettes.ContinuousPalettes[desc.palette_name]
                    value_cols = f'<td colspan="{max_values}">' \
                                 f'{pal.friendly_name}</td>'
                else:
                    continue
                names = was(desc.name, desc.var.name)
                rows += '<tr style="height: 2em">\n' \
                        f'  <th style="text-align: right">{names}</th>' \
                        f'  {value_cols}\n' \
                        '</tr>\n'
            return rows

        if not self.data:
            return
        dom = self.data.domain
        sections = (
            (name, _report_variables(variables))
            for name, variables in (
                ("Features", dom.attributes),
                ("Outcome" + "s" * (len(dom.class_vars) > 1), dom.class_vars),
                ("Meta attributes", dom.metas)))
        table = "".join(f"<tr><th>{name}</th></tr>{rows}"
                        for name, rows in sections if rows)
        if table:
            self.report_raw(r"<table>{table}</table>")

    @classmethod
    def migrate_context(cls, context, version):
        if not version or version < 2:
            raise IncompatibleContext


if __name__ == "__main__":  # pragma: no cover
    WidgetPreview(OWColor).run(Orange.data.Table("heart_disease.tab"))

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user