{
    "file_diffs": [
        {
            "old_file_content": "from functools import partial\nfrom typing import Optional\n\nfrom AnyQt.QtWidgets import QWidget, QGridLayout\nfrom AnyQt.QtWidgets import QListView\nfrom AnyQt.QtCore import (\n    Qt, QTimer, QSortFilterProxyModel, QItemSelection, QItemSelectionModel,\n    QMimeData, QAbstractItemModel\n)\n\nfrom Orange.widgets import gui, widget\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting, Setting\nfrom Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.widget import Input, Output, AttributeList, Msg\nfrom Orange.data.table import Table\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.utils.itemmodels import VariableListModel\nimport Orange\n\n\ndef source_model(view):\n    \"\"\" Return the source model for the Qt Item View if it uses\n    the QSortFilterProxyModel.\n    \"\"\"\n    if isinstance(view.model(), QSortFilterProxyModel):\n        return view.model().sourceModel()\n    else:\n        return view.model()\n\n\ndef source_indexes(indexes, view):\n    \"\"\" Map model indexes through a views QSortFilterProxyModel\n    \"\"\"\n    model = view.model()\n    if isinstance(model, QSortFilterProxyModel):\n        return list(map(model.mapToSource, indexes))\n    else:\n        return indexes\n\n\nclass VariablesListItemModel(VariableListModel):\n    \"\"\"\n    An Variable list item model specialized for Drag and Drop.\n    \"\"\"\n    MIME_TYPE = \"application/x-Orange-VariableListModelData\"\n\n    def flags(self, index):\n        flags = super().flags(index)\n        if index.isValid():\n            flags |= Qt.ItemIsDragEnabled\n        else:\n            flags |= Qt.ItemIsDropEnabled\n        return flags\n\n    @staticmethod\n    def supportedDropActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    @staticmethod\n    def supportedDragActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    def mimeTypes(self):\n        return [self.MIME_TYPE]\n\n    def mimeData(self, indexlist):\n        \"\"\"\n        Reimplemented.\n\n        For efficiency reasons only the variable instances are set on the\n        mime data (under `'_items'` property)\n        \"\"\"\n        items = [self[index.row()] for index in indexlist]\n        mime = QMimeData()\n        # the encoded 'data' is empty, variables are passed by properties\n        mime.setData(self.MIME_TYPE, b'')\n        mime.setProperty(\"_items\", items)\n        return mime\n\n    def dropMimeData(self, mime, action, row, column, parent):\n        \"\"\"\n        Reimplemented.\n        \"\"\"\n        if action == Qt.IgnoreAction:\n            return True  # pragma: no cover\n        if not mime.hasFormat(self.MIME_TYPE):\n            return False  # pragma: no cover\n        variables = mime.property(\"_items\")\n        if variables is None:\n            return False  # pragma: no cover\n        if row < 0:\n            row = self.rowCount()\n\n        self[row:row] = variables\n        return True\n\n\nclass OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    brown = Orange.data.Table(\"brown-selected\")\n    feats = AttributeList(brown.domain.attributes[:2])\n    WidgetPreview(OWSelectAttributes).run(set_data=brown, set_features=feats)\n",
            "new_file_content": "from functools import partial\nfrom typing import Optional\n\nfrom AnyQt.QtWidgets import QWidget, QGridLayout\nfrom AnyQt.QtWidgets import QListView\nfrom AnyQt.QtCore import (\n    Qt, QTimer, QSortFilterProxyModel, QItemSelection, QItemSelectionModel,\n    QMimeData, QAbstractItemModel\n)\n\nfrom Orange.widgets import gui, widget\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting, Setting\nfrom Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.widget import Input, Output, AttributeList, Msg\nfrom Orange.data.table import Table\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.utils.itemmodels import VariableListModel\nimport Orange\n\n\ndef source_model(view):\n    \"\"\" Return the source model for the Qt Item View if it uses\n    the QSortFilterProxyModel.\n    \"\"\"\n    if isinstance(view.model(), QSortFilterProxyModel):\n        return view.model().sourceModel()\n    else:\n        return view.model()\n\n\ndef source_indexes(indexes, view):\n    \"\"\" Map model indexes through a views QSortFilterProxyModel\n    \"\"\"\n    model = view.model()\n    if isinstance(model, QSortFilterProxyModel):\n        return list(map(model.mapToSource, indexes))\n    else:\n        return indexes\n\n\nclass VariablesListItemModel(VariableListModel):\n    \"\"\"\n    An Variable list item model specialized for Drag and Drop.\n    \"\"\"\n    MIME_TYPE = \"application/x-Orange-VariableListModelData\"\n\n    def flags(self, index):\n        flags = super().flags(index)\n        if index.isValid():\n            flags |= Qt.ItemIsDragEnabled\n        else:\n            flags |= Qt.ItemIsDropEnabled\n        return flags\n\n    @staticmethod\n    def supportedDropActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    @staticmethod\n    def supportedDragActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    def mimeTypes(self):\n        return [self.MIME_TYPE]\n\n    def mimeData(self, indexlist):\n        \"\"\"\n        Reimplemented.\n\n        For efficiency reasons only the variable instances are set on the\n        mime data (under `'_items'` property)\n        \"\"\"\n        items = [self[index.row()] for index in indexlist]\n        mime = QMimeData()\n        # the encoded 'data' is empty, variables are passed by properties\n        mime.setData(self.MIME_TYPE, b'')\n        mime.setProperty(\"_items\", items)\n        return mime\n\n    def dropMimeData(self, mime, action, row, column, parent):\n        \"\"\"\n        Reimplemented.\n        \"\"\"\n        if action == Qt.IgnoreAction:\n            return True  # pragma: no cover\n        if not mime.hasFormat(self.MIME_TYPE):\n            return False  # pragma: no cover\n        variables = mime.property(\"_items\")\n        if variables is None:\n            return False  # pragma: no cover\n        if row < 0:\n            row = self.rowCount()\n\n        self[row:row] = variables\n        return True\n\n\nclass OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    brown = Orange.data.Table(\"brown-selected\")\n    feats = AttributeList(brown.domain.attributes[:2])\n    WidgetPreview(OWSelectAttributes).run(set_data=brown, set_features=feats)\n",
            "header": {
                "file": {
                    "path": "Orange/widgets/data/owselectcolumns.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "3835127b7",
                "new_commit_hash": "c23161aaa",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/data/owselectcolumns.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/data/owselectcolumns.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 14,
                            "length": 6
                        },
                        "new_range": {
                            "start": 14,
                            "length": 7
                        },
                        "section": "from Orange.widgets.data.contexthandlers import \\"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from Orange.widgets.settings import ContextSetting, Setting",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter",
                                "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, AttributeList, Msg",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.data.table import Table",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils import vartype",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 17,
                            "end_lineno": 17,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 266,
                            "length": 6
                        },
                        "new_range": {
                            "start": 267,
                            "length": 9
                        },
                        "section": "class OWSelectAttributes(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.output_data = None",
                                "type": "context"
                            },
                            {
                                "content": "        self.original_completer_items = []",
                                "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": "        self.resize(600, 600)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    @property",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "class",
                            "name": "OWSelectAttributes",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 102,
                            "end_lineno": 564,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "method",
                            "name": "OWSelectAttributes.__init__",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 130,
                            "end_lineno": 273,
                            "parent": {
                                "file_name": "Orange/widgets/data/owselectcolumns.py",
                                "type": "class",
                                "name": "OWSelectAttributes",
                                "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 102,
                                "end_lineno": 564,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 343,
                            "length": 11
                        },
                        "new_range": {
                            "start": 347,
                            "length": 13
                        },
                        "section": "class OWSelectAttributes(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self.class_attrs[:] = classes",
                                "type": "context"
                            },
                            {
                                "content": "            self.meta_attrs[:] = metas",
                                "type": "context"
                            },
                            {
                                "content": "            self.available_attrs[:] = available",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_input_summary(len(data), format_summary_details(data))",
                                "type": "added"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            self.used_attrs[:] = []",
                                "type": "context"
                            },
                            {
                                "content": "            self.class_attrs[:] = []",
                                "type": "context"
                            },
                            {
                                "content": "            self.meta_attrs[:] = []",
                                "type": "context"
                            },
                            {
                                "content": "            self.available_attrs[:] = []",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_input_summary(self.info.NoInput)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def update_domain_role_hints(self):",
                                "type": "context"
                            },
                            {
                                "content": "        \"\"\" Update the domain hints to be stored in the widgets settings.",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "method",
                            "name": "OWSelectAttributes.set_data",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 305,
                            "end_lineno": 356,
                            "parent": {
                                "file_name": "Orange/widgets/data/owselectcolumns.py",
                                "type": "class",
                                "name": "OWSelectAttributes",
                                "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 102,
                                "end_lineno": 564,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "class",
                            "name": "OWSelectAttributes",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 102,
                            "end_lineno": 564,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 522,
                            "length": 10
                        },
                        "new_range": {
                            "start": 528,
                            "length": 13
                        },
                        "section": "class OWSelectAttributes(widget.OWWidget):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            self.output_data = newdata",
                                "type": "context"
                            },
                            {
                                "content": "            self.Outputs.data.send(newdata)",
                                "type": "context"
                            },
                            {
                                "content": "            self.Outputs.features.send(AttributeList(attributes))",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_output_summary(len(newdata),",
                                "type": "added"
                            },
                            {
                                "content": "                                         format_summary_details(newdata))",
                                "type": "added"
                            },
                            {
                                "content": "        else:",
                                "type": "context"
                            },
                            {
                                "content": "            self.output_data = None",
                                "type": "context"
                            },
                            {
                                "content": "            self.Outputs.data.send(None)",
                                "type": "context"
                            },
                            {
                                "content": "            self.Outputs.features.send(None)",
                                "type": "context"
                            },
                            {
                                "content": "            self.info.set_output_summary(self.info.NoOutput)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def reset(self):",
                                "type": "context"
                            },
                            {
                                "content": "        self.enable_used_attrs()",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "class",
                            "name": "OWSelectAttributes",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 102,
                            "end_lineno": 564,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/widgets/data/owselectcolumns.py",
                            "type": "method",
                            "name": "OWSelectAttributes.commit",
                            "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 519,
                            "end_lineno": 537,
                            "parent": {
                                "file_name": "Orange/widgets/data/owselectcolumns.py",
                                "type": "class",
                                "name": "OWSelectAttributes",
                                "content": "class OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.info.set_input_summary(self.info.NoInput)\n        self.info.set_output_summary(self.info.NoOutput)\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n            self.info.set_input_summary(len(data), format_summary_details(data))\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n            self.info.set_input_summary(self.info.NoInput)\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n            self.info.set_output_summary(len(newdata),\n                                         format_summary_details(newdata))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n            self.info.set_output_summary(self.info.NoOutput)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 102,
                                "end_lineno": 564,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from unittest import TestCase\nfrom unittest.mock import Mock\n\nfrom AnyQt.QtCore import QMimeData, QPoint, Qt\nfrom AnyQt.QtGui import QDragEnterEvent\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.tests.base import WidgetTest\nfrom Orange.widgets.data.owselectcolumns \\\n    import OWSelectAttributes, VariablesListItemModel\nfrom Orange.widgets.data.owrank import OWRank\nfrom Orange.widgets.widget import AttributeList\n\nContinuous = vartype(ContinuousVariable(\"c\"))\nDiscrete = vartype(DiscreteVariable(\"d\"))\n\n\nclass TestSelectAttributesDomainContextHandler(TestCase):\n    def setUp(self):\n        self.domain = Domain(\n            attributes=[ContinuousVariable('c1'),\n                        DiscreteVariable('d1', values='abc'),\n                        DiscreteVariable('d2', values='def')],\n            class_vars=[DiscreteVariable('d3', values='ghi')],\n            metas=[ContinuousVariable('c2'),\n                   DiscreteVariable('d4', values='jkl')]\n        )\n        self.args = (self.domain,\n                     {'c1': Continuous, 'd1': Discrete,\n                      'd2': Discrete, 'd3': Discrete},\n                     {'c2': Continuous, 'd4': Discrete, })\n\n        self.handler = SelectAttributesDomainContextHandler()\n        self.handler.read_defaults = lambda: None\n\n    def test_open_context(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(\n            attributes=self.args[1], metas=self.args[2], values=dict(\n                domain_role_hints=({('d1', Discrete): ('available', 0),\n                                    ('d2', Discrete): ('meta', 0),\n                                    ('c1', Continuous): ('attribute', 0),\n                                    ('d3', Discrete): ('attribute', 1),\n                                    ('d4', Discrete): ('attribute', 2),\n                                    ('c2', Continuous): ('class', 0)}, -2),\n                with_metas=[('d1', Discrete), ('d2', Discrete)]\n            ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('d3', Discrete): ('attribute', 1),\n                          ('d4', Discrete): ('attribute', 2),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_imperfect_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d6', Discrete): ('attribute', 1),\n                                ('d7', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2)\n        ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_no_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d3', Discrete): ('attribute', 1),\n                                ('d4', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2),\n            required=('g1', Continuous),\n        ))\n        self.handler.global_contexts = [context]\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints, {})\n\n\nclass TestModel(TestCase):\n    def test_drop_mime(self):\n        iris = Table(\"iris\")\n        m = VariablesListItemModel(iris.domain.variables)\n        mime = m.mimeData([m.index(1, 0)])\n        self.assertTrue(mime.hasFormat(VariablesListItemModel.MIME_TYPE))\n        assert m.dropMimeData(mime, Qt.MoveAction, 5, 0, m.index(-1, -1))\n        self.assertIs(m[5], m[1])\n        assert m.dropMimeData(mime, Qt.MoveAction, -1, -1, m.index(-1, -1))\n        self.assertIs(m[6], m[1])\n\n    def test_flags(self):\n        m = VariablesListItemModel([ContinuousVariable(\"X\")])\n        flags = m.flags(m.index(0))\n        self.assertTrue(flags & Qt.ItemIsDragEnabled)\n        self.assertFalse(flags & Qt.ItemIsDropEnabled)\n        # 'invalid' index is drop enabled -> indicates insertion capability\n        flags = m.flags(m.index(-1, -1))\n        self.assertTrue(flags & Qt.ItemIsDropEnabled)\n\n\nclass SimpleWidget:\n    domain_role_hints = ContextSetting({})\n    required = ContextSetting(\"\", required=ContextSetting.REQUIRED)\n\n    def retrieveSpecificSettings(self):\n        pass\n\n    def storeSpecificSettings(self):\n        pass\n\n\nclass TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n",
            "new_file_content": "# pylint: disable=unsubscriptable-object\nfrom unittest import TestCase\nfrom unittest.mock import Mock\n\nfrom AnyQt.QtCore import QMimeData, QPoint, Qt\nfrom AnyQt.QtGui import QDragEnterEvent\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.tests.base import WidgetTest\nfrom Orange.widgets.data.owselectcolumns \\\n    import OWSelectAttributes, VariablesListItemModel\nfrom Orange.widgets.data.owrank import OWRank\nfrom Orange.widgets.widget import AttributeList\n\nContinuous = vartype(ContinuousVariable(\"c\"))\nDiscrete = vartype(DiscreteVariable(\"d\"))\n\n\nclass TestSelectAttributesDomainContextHandler(TestCase):\n    def setUp(self):\n        self.domain = Domain(\n            attributes=[ContinuousVariable('c1'),\n                        DiscreteVariable('d1', values='abc'),\n                        DiscreteVariable('d2', values='def')],\n            class_vars=[DiscreteVariable('d3', values='ghi')],\n            metas=[ContinuousVariable('c2'),\n                   DiscreteVariable('d4', values='jkl')]\n        )\n        self.args = (self.domain,\n                     {'c1': Continuous, 'd1': Discrete,\n                      'd2': Discrete, 'd3': Discrete},\n                     {'c2': Continuous, 'd4': Discrete, })\n\n        self.handler = SelectAttributesDomainContextHandler()\n        self.handler.read_defaults = lambda: None\n\n    def test_open_context(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(\n            attributes=self.args[1], metas=self.args[2], values=dict(\n                domain_role_hints=({('d1', Discrete): ('available', 0),\n                                    ('d2', Discrete): ('meta', 0),\n                                    ('c1', Continuous): ('attribute', 0),\n                                    ('d3', Discrete): ('attribute', 1),\n                                    ('d4', Discrete): ('attribute', 2),\n                                    ('c2', Continuous): ('class', 0)}, -2),\n                with_metas=[('d1', Discrete), ('d2', Discrete)]\n            ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('d3', Discrete): ('attribute', 1),\n                          ('d4', Discrete): ('attribute', 2),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_imperfect_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d6', Discrete): ('attribute', 1),\n                                ('d7', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2)\n        ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_no_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d3', Discrete): ('attribute', 1),\n                                ('d4', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2),\n            required=('g1', Continuous),\n        ))\n        self.handler.global_contexts = [context]\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints, {})\n\n\nclass TestModel(TestCase):\n    def test_drop_mime(self):\n        iris = Table(\"iris\")\n        m = VariablesListItemModel(iris.domain.variables)\n        mime = m.mimeData([m.index(1, 0)])\n        self.assertTrue(mime.hasFormat(VariablesListItemModel.MIME_TYPE))\n        assert m.dropMimeData(mime, Qt.MoveAction, 5, 0, m.index(-1, -1))\n        self.assertIs(m[5], m[1])\n        assert m.dropMimeData(mime, Qt.MoveAction, -1, -1, m.index(-1, -1))\n        self.assertIs(m[6], m[1])\n\n    def test_flags(self):\n        m = VariablesListItemModel([ContinuousVariable(\"X\")])\n        flags = m.flags(m.index(0))\n        self.assertTrue(flags & Qt.ItemIsDragEnabled)\n        self.assertFalse(flags & Qt.ItemIsDropEnabled)\n        # 'invalid' index is drop enabled -> indicates insertion capability\n        flags = m.flags(m.index(-1, -1))\n        self.assertTrue(flags & Qt.ItemIsDropEnabled)\n\n\nclass SimpleWidget:\n    domain_role_hints = ContextSetting({})\n    required = ContextSetting(\"\", required=ContextSetting.REQUIRED)\n\n    def retrieveSpecificSettings(self):\n        pass\n\n    def storeSpecificSettings(self):\n        pass\n\n\nclass TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        data = Table(\"iris\")\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\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",
            "header": {
                "file": {
                    "path": "Orange/widgets/data/tests/test_owselectcolumns.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "d9d6aed27",
                "new_commit_hash": "8dff52c2b",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/data/tests/test_owselectcolumns.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/data/tests/test_owselectcolumns.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1,
                            "length": 3
                        },
                        "new_range": {
                            "start": 1,
                            "length": 4
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "# pylint: disable=unsubscriptable-object",
                                "type": "added"
                            },
                            {
                                "content": "from unittest import TestCase",
                                "type": "context"
                            },
                            {
                                "content": "from unittest.mock import Mock",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 9,
                            "length": 6
                        },
                        "new_range": {
                            "start": 10,
                            "length": 7
                        },
                        "section": "from Orange.widgets.data.contexthandlers import \\"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    SelectAttributesDomainContextHandler",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.settings import ContextSetting",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils import vartype",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.utils.state_summary import format_summary_details",
                                "type": "added"
                            },
                            {
                                "content": "from Orange.widgets.tests.base import WidgetTest",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.data.owselectcolumns \\",
                                "type": "context"
                            },
                            {
                                "content": "    import OWSelectAttributes, VariablesListItemModel",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owselectcolumns.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": 386,
                            "length": 3
                        },
                        "new_range": {
                            "start": 388,
                            "length": 23
                        },
                        "section": "class TestOWSelectAttributes(WidgetTest):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            d1.domain.attributes,",
                                "type": "context"
                            },
                            {
                                "content": "            data.domain.attributes",
                                "type": "context"
                            },
                            {
                                "content": "        )",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    def test_summary(self):",
                                "type": "added"
                            },
                            {
                                "content": "        \"\"\"Check if status bar is updated when data is received\"\"\"",
                                "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": "        data = Table(\"iris\")",
                                "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": "",
                                "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": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owselectcolumns.py",
                            "type": "class",
                            "name": "TestOWSelectAttributes",
                            "content": "class TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        data = Table(\"iris\")\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\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": 141,
                            "end_lineno": 410,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/data/tests/test_owselectcolumns.py",
                            "type": "method",
                            "name": "TestOWSelectAttributes.test_summary",
                            "content": "class TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        data = Table(\"iris\")\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\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": 392,
                            "end_lineno": 410,
                            "parent": {
                                "file_name": "Orange/widgets/data/tests/test_owselectcolumns.py",
                                "type": "class",
                                "name": "TestOWSelectAttributes",
                                "content": "class TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        data = Table(\"iris\")\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\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": 141,
                                "end_lineno": 410,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "34063e68e5a733e152f05e10ca762afe080e7ddd^",
    "new_commit_hash": "34063e68e5a733e152f05e10ca762afe080e7ddd",
    "commit_message": "Merge pull request #4454 from aturanjanin/owselectcolumns\n\n[ENH] OWSelectColumns: Data info displayed in the status bar",
    "commit_date": "2020-02-28T11:04:41+01:00",
    "metadata": {}
}
{
    "repo_name": "orange3",
    "new_commit_hash": "34063e68e5a733e152f05e10ca762afe080e7ddd",
    "test_file_codes": [
        "# pylint: disable=unsubscriptable-object\nfrom unittest import TestCase\nfrom unittest.mock import Mock\n\nfrom AnyQt.QtCore import QMimeData, QPoint, Qt\nfrom AnyQt.QtGui import QDragEnterEvent\n\nfrom Orange.data import Table, ContinuousVariable, DiscreteVariable, Domain\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.utils.state_summary import format_summary_details\nfrom Orange.widgets.tests.base import WidgetTest\nfrom Orange.widgets.data.owselectcolumns \\\n    import OWSelectAttributes, VariablesListItemModel\nfrom Orange.widgets.data.owrank import OWRank\nfrom Orange.widgets.widget import AttributeList\n\nContinuous = vartype(ContinuousVariable(\"c\"))\nDiscrete = vartype(DiscreteVariable(\"d\"))\n\n\nclass TestSelectAttributesDomainContextHandler(TestCase):\n    def setUp(self):\n        self.domain = Domain(\n            attributes=[ContinuousVariable('c1'),\n                        DiscreteVariable('d1', values='abc'),\n                        DiscreteVariable('d2', values='def')],\n            class_vars=[DiscreteVariable('d3', values='ghi')],\n            metas=[ContinuousVariable('c2'),\n                   DiscreteVariable('d4', values='jkl')]\n        )\n        self.args = (self.domain,\n                     {'c1': Continuous, 'd1': Discrete,\n                      'd2': Discrete, 'd3': Discrete},\n                     {'c2': Continuous, 'd4': Discrete, })\n\n        self.handler = SelectAttributesDomainContextHandler()\n        self.handler.read_defaults = lambda: None\n\n    def test_open_context(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(\n            attributes=self.args[1], metas=self.args[2], values=dict(\n                domain_role_hints=({('d1', Discrete): ('available', 0),\n                                    ('d2', Discrete): ('meta', 0),\n                                    ('c1', Continuous): ('attribute', 0),\n                                    ('d3', Discrete): ('attribute', 1),\n                                    ('d4', Discrete): ('attribute', 2),\n                                    ('c2', Continuous): ('class', 0)}, -2),\n                with_metas=[('d1', Discrete), ('d2', Discrete)]\n            ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('d3', Discrete): ('attribute', 1),\n                          ('d4', Discrete): ('attribute', 2),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_imperfect_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d6', Discrete): ('attribute', 1),\n                                ('d7', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2)\n        ))\n        self.handler.global_contexts = \\\n            [Mock(values={}), context, Mock(values={})]\n\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n\n        self.assertEqual(widget.domain_role_hints,\n                         {('d1', Discrete): ('available', 0),\n                          ('d2', Discrete): ('meta', 0),\n                          ('c1', Continuous): ('attribute', 0),\n                          ('c2', Continuous): ('class', 0)})\n\n    def test_open_context_with_no_match(self):\n        self.handler.bind(SimpleWidget)\n        context = Mock(values=dict(\n            domain_role_hints=({('d1', Discrete): ('available', 0),\n                                ('d2', Discrete): ('meta', 0),\n                                ('c1', Continuous): ('attribute', 0),\n                                ('d3', Discrete): ('attribute', 1),\n                                ('d4', Discrete): ('attribute', 2),\n                                ('c2', Continuous): ('class', 0)}, -2),\n            required=('g1', Continuous),\n        ))\n        self.handler.global_contexts = [context]\n        widget = SimpleWidget()\n        self.handler.initialize(widget)\n        self.handler.open_context(widget, self.args[0])\n        self.assertEqual(widget.domain_role_hints, {})\n\n\nclass TestModel(TestCase):\n    def test_drop_mime(self):\n        iris = Table(\"iris\")\n        m = VariablesListItemModel(iris.domain.variables)\n        mime = m.mimeData([m.index(1, 0)])\n        self.assertTrue(mime.hasFormat(VariablesListItemModel.MIME_TYPE))\n        assert m.dropMimeData(mime, Qt.MoveAction, 5, 0, m.index(-1, -1))\n        self.assertIs(m[5], m[1])\n        assert m.dropMimeData(mime, Qt.MoveAction, -1, -1, m.index(-1, -1))\n        self.assertIs(m[6], m[1])\n\n    def test_flags(self):\n        m = VariablesListItemModel([ContinuousVariable(\"X\")])\n        flags = m.flags(m.index(0))\n        self.assertTrue(flags & Qt.ItemIsDragEnabled)\n        self.assertFalse(flags & Qt.ItemIsDropEnabled)\n        # 'invalid' index is drop enabled -> indicates insertion capability\n        flags = m.flags(m.index(-1, -1))\n        self.assertTrue(flags & Qt.ItemIsDropEnabled)\n\n\nclass SimpleWidget:\n    domain_role_hints = ContextSetting({})\n    required = ContextSetting(\"\", required=ContextSetting.REQUIRED)\n\n    def retrieveSpecificSettings(self):\n        pass\n\n    def storeSpecificSettings(self):\n        pass\n\n\nclass TestOWSelectAttributes(WidgetTest):\n    def setUp(self):\n        self.widget = self.create_widget(OWSelectAttributes)\n\n    def assertVariableCountsEqual(self, available, used, classattrs, metas=0):\n        self.assertEqual(len(self.widget.available_attrs), available)\n        self.assertEqual(len(self.widget.used_attrs), used)\n        self.assertEqual(len(self.widget.class_attrs), classattrs)\n        self.assertEqual(len(self.widget.meta_attrs), metas)\n\n    def assertControlsEnabled(self, _list, button, box, widget=None):\n        if widget is None:\n            widget = self.widget\n        control = widget.use_features_box\n        self.assertEqual(control.button.isEnabled(), button)\n        self.assertEqual(control.isVisibleTo(widget), box)\n        self.assertEqual(widget.used_attrs_view.isEnabled(), _list)\n        self.assertEqual(widget.up_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.move_attr_button.isEnabled(), _list)\n        self.assertEqual(widget.down_attr_button.isEnabled(), _list)\n        if button:\n            control.button.click()\n            self.assertEqual(control.button.isEnabled(), False)\n\n    def test_multiple_target_variable(self):\n        \"\"\"\n        More than one target variable can be moved to a box for target variables\n        at the same time and moved back as well.\n        GH-2100\n        GH-2086\n        \"\"\"\n        iris = Table(\"iris\")\n        self.send_signal(self.widget.Inputs.data, iris)\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.move_class_button.click()\n        self.assertVariableCountsEqual(available=0, used=4, classattrs=1)\n\n        self.widget.used_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.used_attrs_view)\n        self.assertVariableCountsEqual(available=4, used=0, classattrs=1)\n\n        self.widget.available_attrs_view.selectAll()\n        self.widget.move_selected(self.widget.class_attrs_view)\n        self.assertVariableCountsEqual(0, 0, 5)\n\n    def test_input_features(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_by_name(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_same_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes))\n\n    def test_input_features_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.attributes[::3])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(10, 6, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             in_features)\n\n    def test_input_features_by_name_sub_domain(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList([DiscreteVariable(attr.name, attr.values)\n                                     for attr in data.domain.attributes[:5]])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(11, 5, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(data.domain.attributes[:5]))\n\n    def test_input_features_diff_domain(self):\n        zoo = Table(\"zoo\")\n        in_features = AttributeList(Table(\"iris\").domain.attributes)\n        self.send_signal(self.widget.Inputs.data, zoo)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 16, 1, 1)\n        self.assertListEqual(self.get_output(self.widget.Outputs.features),\n                             list(zoo.domain.attributes))\n        self.assertTrue(self.widget.Warning.mismatching_domain.is_shown())\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertFalse(self.widget.Warning.mismatching_domain.is_shown())\n\n    def test_input_features_no_data(self):\n        data = Table(\"zoo\")\n        in_features = AttributeList(data.domain.variables + data.domain.metas)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n    def test_input_combinations(self):\n        data = Table(\"iris\")\n        in_features = AttributeList(data.domain.attributes[:2])\n\n        # check initial state\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 4, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 4)\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, True, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove data\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send features\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(0, 0, 0, 0)\n        self.assertIsNone(self.get_output(self.widget.Outputs.features))\n\n        # send data\n        self.send_signal(self.widget.Inputs.data, data)\n        self.assertControlsEnabled(True, False, True)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n        # remove features\n        self.send_signal(self.widget.Inputs.features, None)\n        self.assertControlsEnabled(True, False, False)\n        self.assertVariableCountsEqual(2, 2, 1, 0)\n        self.assertEqual(len(self.get_output(self.widget.Outputs.features)), 2)\n\n    def test_input_features_from_rank(self):\n        data = Table(\"iris\")\n        owrank = self.create_widget(OWRank)\n        self.send_signal(owrank.Inputs.data, data, widget=owrank)\n        rank_features = self.get_output(owrank.Outputs.features, widget=owrank)\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, rank_features)\n        self.assertControlsEnabled(True, True, True)\n        features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(rank_features, features)\n\n    def test_use_features_checked(self):\n        data = Table(\"iris\")\n        attrs = data.domain.attributes\n\n        # prepare stored settings (check \"Use input features\")\n        in_features = AttributeList(attrs[:2])\n        self.send_signal(self.widget.Inputs.data, data)\n        self.send_signal(self.widget.Inputs.features, in_features)\n        self.widget.use_features_box.checkbox.setChecked(True)\n        self.assertControlsEnabled(False, False, True)\n        out_features = self.get_output(self.widget.Outputs.features)\n        self.assertListEqual(out_features, in_features)\n        settings = self.widget.settingsHandler.pack_data(self.widget)\n\n        # \"Use input features\" is checked by default\n        widget = self.create_widget(OWSelectAttributes, settings)\n        in_features = AttributeList(attrs[:3])\n        self.send_signal(widget.Inputs.data, data, widget=widget)\n        self.send_signal(widget.Inputs.features, in_features, widget=widget)\n        self.assertControlsEnabled(False, False, True, widget)\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertListEqual(out_features, in_features)\n\n        # reset \"Features\"\n        widget.reset()\n        out_features = self.get_output(widget.Outputs.features, widget=widget)\n        self.assertFalse(widget.use_features_box.checkbox.isChecked())\n        self.assertListEqual(out_features, AttributeList(attrs))\n        self.assertControlsEnabled(True, True, True, widget)\n\n    def test_used_attrs_supported_types(self):\n        data = Table(\"zoo\")\n        event = self._drag_enter_event(data.domain[:1])\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertTrue(event.isAccepted())\n\n        event = self._drag_enter_event(data.domain.metas)\n        self.widget.used_attrs_view.dragEnterEvent(event)\n        self.assertFalse(event.isAccepted())\n\n    def _drag_enter_event(self, variables):\n        # pylint: disable=attribute-defined-outside-init\n        self.event_data = mime = QMimeData()\n        mime.setProperty(\"_items\", variables)\n        return QDragEnterEvent(QPoint(0, 0), Qt.MoveAction, mime,\n                               Qt.NoButton, Qt.NoModifier)\n\n    def test_move_rows(self):\n        data = Table(\"iris\")[:5]\n        w = self.widget\n        self.send_signal(w.Inputs.data, data)\n        view = w.used_attrs_view\n        model = view.model()\n        selmodel = view.selectionModel()\n        midx = model.index(1, 0)\n        selmodel.select(midx, selmodel.ClearAndSelect)\n\n        w.move_up(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes[:2][::-1] + data.domain.attributes[2:]\n        )\n        w.move_down(view)\n        d1 = self.get_output(w.Outputs.data, w)\n        self.assertEqual(\n            d1.domain.attributes,\n            data.domain.attributes\n        )\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n\n        data = Table(\"iris\")\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\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"
    ],
    "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/tmp6mydzvci/tmp\ncreating /tmp/tmp6mydzvci/tmp/tmp6mydzvci\ncompile options: '-MMD -MF /tmp/tmp6mydzvci/file.c.d -c'\ncc: /tmp/tmp6mydzvci/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/tmp4pyjbi2i/tmp\ncreating /tmp/tmp4pyjbi2i/tmp/tmp4pyjbi2i\ncompile options: '-MMD -MF /tmp/tmp4pyjbi2i/file.c.d -c'\ncc: /tmp/tmp4pyjbi2i/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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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/tmp3rihcnqa/tmp\ncreating /tmp/tmp3rihcnqa/tmp/tmp3rihcnqa\ncompile options: '-MMD -MF /tmp/tmp3rihcnqa/file.c.d -c'\ncc: /tmp/tmp3rihcnqa/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/tmplimo3fss/tmp\ncreating /tmp/tmplimo3fss/tmp/tmplimo3fss\ncompile options: '-MMD -MF /tmp/tmplimo3fss/file.c.d -c'\ncc: /tmp/tmplimo3fss/file.c\ncustomize UnixCCompiler using build_ext\nCreating /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/Orange3.egg-link (link to .)\nAdding Orange3 3.25.0.dev0+34063e6 to easy-install.pth file\nInstalling orange-canvas script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nInstalled /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd\nProcessing dependencies for Orange3==3.25.0.dev0+34063e6\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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling pip3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling pip3.10 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling f2py3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling f2py3.7 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling pyftmerge script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling pyftsubset script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\nInstalling ttx script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages\nFinished processing dependencies for Orange3==3.25.0.dev0+34063e6\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 144ms\nPrepared 18 packages in 19ms\nInstalled 18 packages in 115ms\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 360ms\nInstalled 42 packages in 234ms\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 254ms\nInstalled 13 packages in 239ms\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 3ms\nInstalled 2 packages in 15ms\n + psycopg2==2.9.9\n + pymssql==2.3.2\nAudited 1 package in 23ms\nAudited 2 packages in 23ms\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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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_34063e68e5a733e152f05e10ca762afe080e7ddd/.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": 1,
    "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_34063e68e5a733e152f05e10ca762afe080e7ddd\ncollected 25 items\n\nr2e_tests/test_1.py sss...............F......                            [100%]\n\n=================================== FAILURES ===================================\n___________________ TestOWSelectAttributes.test_minimum_size ___________________\n\nself = <r2e_tests.test_1.TestOWSelectAttributes testMethod=test_minimum_size>\n\n    def test_minimum_size(self):\n        widget = getattr(self, \"widget\", None)\n        if widget is None:\n            self.skipTest(\"minimum size not tested as .widget was not set\")\n>       self.check_minimum_size(widget)\n\n.venv/lib/python3.7/site-packages/orangewidget/tests/base.py:242: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.venv/lib/python3.7/site-packages/orangewidget/tests/base.py:615: in check_minimum_size\n    self.assertLess(min_size.width(), 800)\nE   AssertionError: 804 not less than 800\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context_with_imperfect_match\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context_with_no_match\nPASSED r2e_tests/test_1.py::TestModel::test_drop_mime\nPASSED r2e_tests/test_1.py::TestModel::test_flags\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_image_export\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_combinations\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_by_name\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_by_name_sub_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_diff_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_from_rank\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_no_data\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_same_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_sub_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_move_rows\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_msg_base_class\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_multiple_target_variable\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_summary\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_use_features_checked\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_used_attrs_supported_types\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::TestOWSelectAttributes::test_minimum_size - Asser...\n=================== 1 failed, 21 passed, 3 skipped in 4.51s ====================\nWidgets left: 0    Max widgets: 1690 \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_34063e68e5a733e152f05e10ca762afe080e7ddd\ncollected 25 items\n\nr2e_tests/test_1.py sss...............F...F..                            [100%]\n\n=================================== FAILURES ===================================\n___________________ TestOWSelectAttributes.test_minimum_size ___________________\n\nself = <r2e_tests.test_1.TestOWSelectAttributes testMethod=test_minimum_size>\n\n    def test_minimum_size(self):\n        widget = getattr(self, \"widget\", None)\n        if widget is None:\n            self.skipTest(\"minimum size not tested as .widget was not set\")\n>       self.check_minimum_size(widget)\n\n.venv/lib/python3.7/site-packages/orangewidget/tests/base.py:242: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n.venv/lib/python3.7/site-packages/orangewidget/tests/base.py:615: in check_minimum_size\n    self.assertLess(min_size.width(), 800)\nE   AssertionError: 804 not less than 800\n_____________________ TestOWSelectAttributes.test_summary ______________________\n\nself = <r2e_tests.test_1.TestOWSelectAttributes testMethod=test_summary>\n\n    def test_summary(self):\n        \"\"\"Check if status bar is updated when data is received\"\"\"\n        input_sum = self.widget.info.set_input_summary = Mock()\n        output_sum = self.widget.info.set_output_summary = Mock()\n    \n        data = Table(\"iris\")\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:399: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\n_mock_self = <Mock id='125851539280464'>\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=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context_with_imperfect_match\nPASSED r2e_tests/test_1.py::TestSelectAttributesDomainContextHandler::test_open_context_with_no_match\nPASSED r2e_tests/test_1.py::TestModel::test_drop_mime\nPASSED r2e_tests/test_1.py::TestModel::test_flags\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_image_export\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_combinations\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_by_name\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_by_name_sub_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_diff_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_from_rank\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_no_data\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_same_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_input_features_sub_domain\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_move_rows\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_msg_base_class\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_multiple_target_variable\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_use_features_checked\nPASSED r2e_tests/test_1.py::TestOWSelectAttributes::test_used_attrs_supported_types\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::TestOWSelectAttributes::test_minimum_size - Asser...\nFAILED r2e_tests/test_1.py::TestOWSelectAttributes::test_summary - AssertionE...\n=================== 2 failed, 20 passed, 3 skipped in 2.83s ====================\nWidgets left: 0    Max widgets: 1690 \n\n",
    "old_commit_res_stderr": ""
}
Orange/widgets/data/owselectcolumns.py Orange/widgets/data/tests/test_owselectcolumns.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** OWSelectColumns Fails to Update Status Bar with Data Information

**Description:**
When data is provided to the `OWSelectColumns` widget, the status bar is expected to display detailed information about the input and output data. However, the status bar does not update accordingly, leading to confusion about the data being processed.

**Example Buggy Code:**
```python
def test_status_bar_update():
    widget = OWSelectAttributes()
    data = Table("iris")
    widget.send_signal(widget.Inputs.data, data)
    # Expected: Status bar displays "150 instances, 5 variables"
    # Actual: Status bar remains empty or shows default message
```

**Expected Behavior:**
Upon receiving data, the `OWSelectColumns` widget should update the status bar with comprehensive details about the input and output datasets, such as the number of instances and variables.

**Actual Behavior:**
The status bar does not reflect the received data information, causing the summary to remain empty or display incorrect details. This leads to failing tests that check for proper status bar updates when data is received or cleared.
[/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/owselectcolumns.py
from functools import partial
from typing import Optional

from AnyQt.QtWidgets import QWidget, QGridLayout
from AnyQt.QtWidgets import QListView
from AnyQt.QtCore import (
    Qt, QTimer, QSortFilterProxyModel, QItemSelection, QItemSelectionModel,
    QMimeData, QAbstractItemModel
)

from Orange.widgets import gui, widget
from Orange.widgets.data.contexthandlers import \
    SelectAttributesDomainContextHandler
from Orange.widgets.settings import ContextSetting, Setting
from Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter
from Orange.widgets.utils.widgetpreview import WidgetPreview
from Orange.widgets.widget import Input, Output, AttributeList, Msg
from Orange.data.table import Table
from Orange.widgets.utils import vartype
from Orange.widgets.utils.itemmodels import VariableListModel
import Orange


def source_model(view):
    """ Return the source model for the Qt Item View if it uses
    the QSortFilterProxyModel.
    """
    if isinstance(view.model(), QSortFilterProxyModel):
        return view.model().sourceModel()
    else:
        return view.model()


def source_indexes(indexes, view):
    """ Map model indexes through a views QSortFilterProxyModel
    """
    model = view.model()
    if isinstance(model, QSortFilterProxyModel):
        return list(map(model.mapToSource, indexes))
    else:
        return indexes


class VariablesListItemModel(VariableListModel):
    """
    An Variable list item model specialized for Drag and Drop.
    """
    MIME_TYPE = "application/x-Orange-VariableListModelData"

    def flags(self, index):
        flags = super().flags(index)
        if index.isValid():
            flags |= Qt.ItemIsDragEnabled
        else:
            flags |= Qt.ItemIsDropEnabled
        return flags

    @staticmethod
    def supportedDropActions():
        return Qt.MoveAction  # pragma: no cover

    @staticmethod
    def supportedDragActions():
        return Qt.MoveAction  # pragma: no cover

    def mimeTypes(self):
        return [self.MIME_TYPE]

    def mimeData(self, indexlist):
        """
        Reimplemented.

        For efficiency reasons only the variable instances are set on the
        mime data (under `'_items'` property)
        """
        items = [self[index.row()] for index in indexlist]
        mime = QMimeData()
        # the encoded 'data' is empty, variables are passed by properties
        mime.setData(self.MIME_TYPE, b'')
        mime.setProperty("_items", items)
        return mime

    def dropMimeData(self, mime, action, row, column, parent):
        """
        Reimplemented.
        """
        if action == Qt.IgnoreAction:
            return True  # pragma: no cover
        if not mime.hasFormat(self.MIME_TYPE):
            return False  # pragma: no cover
        variables = mime.property("_items")
        if variables is None:
            return False  # pragma: no cover
        if row < 0:
            row = self.rowCount()

        self[row:row] = variables
        return True


class OWSelectAttributes(widget.OWWidget):
    # pylint: disable=too-many-instance-attributes
    name = "Select Columns"
    description = "Select columns from the data table and assign them to " \
                  "data features, classes or meta variables."
    icon = "icons/SelectColumns.svg"
    priority = 100
    keywords = ["filter", "attributes", "target", "variable"]

    class Inputs:
        data = Input("Data", Table, default=True)
        features = Input("Features", AttributeList)

    class Outputs:
        data = Output("Data", Table)
        features = Output("Features", AttributeList, dynamic=False)

    want_main_area = False
    want_control_area = True

    settingsHandler = SelectAttributesDomainContextHandler()
    domain_role_hints = ContextSetting({})
    use_input_features = Setting(False)
    auto_commit = Setting(True)

    class Warning(widget.OWWidget.Warning):
        mismatching_domain = Msg("Features and data domain do not match")

    def __init__(self):
        super().__init__()
        self.data = None
        self.features = None

        # Schedule interface updates (enabled buttons) using a coalescing
        # single shot timer (complex interactions on selection and filtering
        # updates in the 'available_attrs_view')
        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)
        self.__interface_update_timer.timeout.connect(
            self.__update_interface_state)
        # The last view that has the selection for move operation's source
        self.__last_active_view = None  # type: Optional[QListView]

        def update_on_change(view):
            # Schedule interface state update on selection change in `view`
            self.__last_active_view = view
            self.__interface_update_timer.start()

        self.controlArea = QWidget(self.controlArea)
        self.layout().addWidget(self.controlArea)
        layout = QGridLayout()
        self.controlArea.setLayout(layout)
        layout.setContentsMargins(4, 4, 4, 4)
        box = gui.vBox(self.controlArea, "Available Variables",
                       addToLayout=False)

        self.available_attrs = VariablesListItemModel()
        filter_edit, self.available_attrs_view = variables_filter(
            parent=self, model=self.available_attrs)
        box.layout().addWidget(filter_edit)

        def dropcompleted(action):
            if action == Qt.MoveAction:
                self.commit()

        self.available_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.available_attrs_view))
        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)

        box.layout().addWidget(self.available_attrs_view)
        layout.addWidget(box, 0, 0, 3, 1)

        box = gui.vBox(self.controlArea, "Features", addToLayout=False)
        self.used_attrs = VariablesListItemModel()
        filter_edit, self.used_attrs_view = variables_filter(
            parent=self, model=self.used_attrs,
            accepted_type=(Orange.data.DiscreteVariable,
                           Orange.data.ContinuousVariable))
        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)
        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)
        self.used_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.used_attrs_view))
        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        self.use_features_box = gui.auto_commit(
            self.controlArea, self, "use_input_features",
            "Use input features", "Always use input features",
            box=False, commit=self.__use_features_clicked,
            callback=self.__use_features_changed, addToLayout=False
        )
        self.enable_use_features_box()
        box.layout().addWidget(self.use_features_box)
        box.layout().addWidget(filter_edit)
        box.layout().addWidget(self.used_attrs_view)
        layout.addWidget(box, 0, 2, 1, 1)

        box = gui.vBox(self.controlArea, "Target Variable", addToLayout=False)
        self.class_attrs = VariablesListItemModel()
        self.class_attrs_view = VariablesListItemView(
            acceptedType=(Orange.data.DiscreteVariable,
                          Orange.data.ContinuousVariable))
        self.class_attrs_view.setModel(self.class_attrs)
        self.class_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.class_attrs_view))
        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        self.class_attrs_view.setMaximumHeight(72)
        box.layout().addWidget(self.class_attrs_view)
        layout.addWidget(box, 1, 2, 1, 1)

        box = gui.vBox(self.controlArea, "Meta Attributes", addToLayout=False)
        self.meta_attrs = VariablesListItemModel()
        self.meta_attrs_view = VariablesListItemView(
            acceptedType=Orange.data.Variable)
        self.meta_attrs_view.setModel(self.meta_attrs)
        self.meta_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.meta_attrs_view))
        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        box.layout().addWidget(self.meta_attrs_view)
        layout.addWidget(box, 2, 2, 1, 1)

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 0, 1, 1, 1)

        self.up_attr_button = gui.button(bbox, self, "Up",
                                         callback=partial(self.move_up, self.used_attrs_view))
        self.move_attr_button = gui.button(bbox, self, ">",
                                           callback=partial(self.move_selected,
                                                            self.used_attrs_view)
                                          )
        self.down_attr_button = gui.button(bbox, self, "Down",
                                           callback=partial(self.move_down, self.used_attrs_view))

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 1, 1, 1, 1)

        self.up_class_button = gui.button(bbox, self, "Up",
                                          callback=partial(self.move_up, self.class_attrs_view))
        self.move_class_button = gui.button(bbox, self, ">",
                                            callback=partial(self.move_selected,
                                                             self.class_attrs_view)
                                           )
        self.down_class_button = gui.button(bbox, self, "Down",
                                            callback=partial(self.move_down, self.class_attrs_view))

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 2, 1, 1, 1)
        self.up_meta_button = gui.button(bbox, self, "Up",
                                         callback=partial(self.move_up, self.meta_attrs_view))
        self.move_meta_button = gui.button(bbox, self, ">",
                                           callback=partial(self.move_selected,
                                                            self.meta_attrs_view)
                                          )
        self.down_meta_button = gui.button(bbox, self, "Down",
                                           callback=partial(self.move_down, self.meta_attrs_view))

        autobox = gui.auto_send(None, self, "auto_commit")
        layout.addWidget(autobox, 3, 0, 1, 3)
        reset = gui.button(None, self, "Reset", callback=self.reset, width=120)
        autobox.layout().insertWidget(0, reset)
        autobox.layout().insertStretch(1, 20)

        layout.setRowStretch(0, 4)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 2)
        layout.setHorizontalSpacing(0)
        self.controlArea.setLayout(layout)

        self.output_data = None
        self.original_completer_items = []

        self.resize(600, 600)

    @property
    def features_from_data_attributes(self):
        if self.data is None or self.features is None:
            return []
        domain = self.data.domain
        return [domain[feature.name] for feature in self.features
                if feature.name in domain and domain[feature.name]
                in domain.attributes]

    def can_use_features(self):
        return bool(self.features_from_data_attributes) and \
               self.features_from_data_attributes != self.used_attrs[:]

    def __use_features_changed(self):  # Use input features check box
        # Needs a check since callback is invoked before object is created
        if not hasattr(self, "use_features_box"):
            return
        self.enable_used_attrs(not self.use_input_features)
        if self.use_input_features and self.can_use_features():
            self.use_features()
        if not self.use_input_features:
            self.enable_use_features_box()

    def __use_features_clicked(self):  # Use input features button
        self.use_features()

    def __used_attrs_changed(self):
        self.enable_use_features_box()

    @Inputs.data
    def set_data(self, data=None):
        self.update_domain_role_hints()
        self.closeContext()
        self.data = data
        if data is not None:
            self.openContext(data)
            all_vars = data.domain.variables + data.domain.metas

            var_sig = lambda attr: (attr.name, vartype(attr))

            domain_hints = {var_sig(attr): ("attribute", i)
                            for i, attr in enumerate(data.domain.attributes)}

            domain_hints.update({var_sig(attr): ("meta", i)
                                 for i, attr in enumerate(data.domain.metas)})

            if data.domain.class_vars:
                domain_hints.update(
                    {var_sig(attr): ("class", i)
                     for i, attr in enumerate(data.domain.class_vars)})

            # update the hints from context settings
            domain_hints.update(self.domain_role_hints)

            attrs_for_role = lambda role: [
                (domain_hints[var_sig(attr)][1], attr)
                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]

            attributes = [
                attr for place, attr in sorted(attrs_for_role("attribute"),
                                               key=lambda a: a[0])]
            classes = [
                attr for place, attr in sorted(attrs_for_role("class"),
                                               key=lambda a: a[0])]
            metas = [
                attr for place, attr in sorted(attrs_for_role("meta"),
                                               key=lambda a: a[0])]
            available = [
                attr for place, attr in sorted(attrs_for_role("available"),
                                               key=lambda a: a[0])]

            self.used_attrs[:] = attributes
            self.class_attrs[:] = classes
            self.meta_attrs[:] = metas
            self.available_attrs[:] = available
        else:
            self.used_attrs[:] = []
            self.class_attrs[:] = []
            self.meta_attrs[:] = []
            self.available_attrs[:] = []

    def update_domain_role_hints(self):
        """ Update the domain hints to be stored in the widgets settings.
        """
        hints_from_model = lambda role, model: [
            ((attr.name, vartype(attr)), (role, i))
            for i, attr in enumerate(model)]
        hints = dict(hints_from_model("available", self.available_attrs))
        hints.update(hints_from_model("attribute", self.used_attrs))
        hints.update(hints_from_model("class", self.class_attrs))
        hints.update(hints_from_model("meta", self.meta_attrs))
        self.domain_role_hints = hints

    @Inputs.features
    def set_features(self, features):
        self.features = features

    def handleNewSignals(self):
        self.check_data()
        self.enable_used_attrs()
        self.enable_use_features_box()
        if self.use_input_features and self.features_from_data_attributes:
            self.enable_used_attrs(False)
            self.use_features()
        self.unconditional_commit()

    def check_data(self):
        self.Warning.mismatching_domain.clear()
        if self.data is not None and self.features is not None and \
                not self.features_from_data_attributes:
            self.Warning.mismatching_domain()

    def enable_used_attrs(self, enable=True):
        self.up_attr_button.setEnabled(enable)
        self.move_attr_button.setEnabled(enable)
        self.down_attr_button.setEnabled(enable)
        self.used_attrs_view.setEnabled(enable)
        self.used_attrs_view.repaint()

    def enable_use_features_box(self):
        self.use_features_box.button.setEnabled(self.can_use_features())
        enable_checkbox = bool(self.features_from_data_attributes)
        self.use_features_box.setHidden(not enable_checkbox)
        self.use_features_box.repaint()

    def use_features(self):
        attributes = self.features_from_data_attributes
        available, used = self.available_attrs[:], self.used_attrs[:]
        self.available_attrs[:] = [attr for attr in used + available
                                   if attr not in attributes]
        self.used_attrs[:] = attributes
        self.commit()

    @staticmethod
    def selected_rows(view):
        """ Return the selected rows in the view.
        """
        rows = view.selectionModel().selectedRows()
        model = view.model()
        if isinstance(model, QSortFilterProxyModel):
            rows = [model.mapToSource(r) for r in rows]
        return [r.row() for r in rows]

    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):
        rows = [idx.row() for idx in view.selectionModel().selectedRows()]
        model = view.model()  # type: QAbstractItemModel
        rowcount = model.rowCount()
        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]

        def itemData(index):
            return {role: model.data(index, role) for role in roles}

        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):
            d1 = itemData(model.index(row, 0))
            d2 = itemData(model.index(newrow, 0))
            model.setItemData(model.index(row, 0), d2)
            model.setItemData(model.index(newrow, 0), d1)

        selection = QItemSelection()
        for nrow in newrows:
            index = model.index(nrow, 0)
            selection.select(index, index)
        view.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

        self.commit()

    def move_up(self, view: QListView):
        self.move_rows(view, -1)

    def move_down(self, view: QListView):
        self.move_rows(view, 1)

    def move_selected(self, view):
        if self.selected_rows(view):
            self.move_selected_from_to(view, self.available_attrs_view)
        elif self.selected_rows(self.available_attrs_view):
            self.move_selected_from_to(self.available_attrs_view, view)

    def move_selected_from_to(self, src, dst):
        self.move_from_to(src, dst, self.selected_rows(src))

    def move_from_to(self, src, dst, rows):
        src_model = source_model(src)
        attrs = [src_model[r] for r in rows]

        for s1, s2 in reversed(list(slices(rows))):
            del src_model[s1:s2]

        dst_model = source_model(dst)

        dst_model.extend(attrs)

        self.commit()

    def __update_interface_state(self):
        last_view = self.__last_active_view
        if last_view is not None:
            self.update_interface_state(last_view)

    def update_interface_state(self, focus=None):
        for view in [self.available_attrs_view, self.used_attrs_view,
                     self.class_attrs_view, self.meta_attrs_view]:
            if view is not focus and not view.hasFocus() \
                    and view.selectionModel().hasSelection():
                view.selectionModel().clear()

        def selected_vars(view):
            model = source_model(view)
            return [model[i] for i in self.selected_rows(view)]

        available_selected = selected_vars(self.available_attrs_view)
        attrs_selected = selected_vars(self.used_attrs_view)
        class_selected = selected_vars(self.class_attrs_view)
        meta_selected = selected_vars(self.meta_attrs_view)

        available_types = set(map(type, available_selected))
        all_primitive = all(var.is_primitive()
                            for var in available_types)

        move_attr_enabled = \
            ((available_selected and all_primitive) or attrs_selected) and \
            self.used_attrs_view.isEnabled()

        self.move_attr_button.setEnabled(bool(move_attr_enabled))
        if move_attr_enabled:
            self.move_attr_button.setText(">" if available_selected else "<")

        move_class_enabled = bool(all_primitive and available_selected) or class_selected

        self.move_class_button.setEnabled(bool(move_class_enabled))
        if move_class_enabled:
            self.move_class_button.setText(">" if available_selected else "<")
        move_meta_enabled = available_selected or meta_selected

        self.move_meta_button.setEnabled(bool(move_meta_enabled))
        if move_meta_enabled:
            self.move_meta_button.setText(">" if available_selected else "<")

        self.__last_active_view = None
        self.__interface_update_timer.stop()

    def commit(self):
        self.update_domain_role_hints()
        if self.data is not None:
            attributes = list(self.used_attrs)
            class_var = list(self.class_attrs)
            metas = list(self.meta_attrs)

            domain = Orange.data.Domain(attributes, class_var, metas)
            newdata = self.data.transform(domain)
            self.output_data = newdata
            self.Outputs.data.send(newdata)
            self.Outputs.features.send(AttributeList(attributes))
        else:
            self.output_data = None
            self.Outputs.data.send(None)
            self.Outputs.features.send(None)

    def reset(self):
        self.enable_used_attrs()
        self.use_features_box.checkbox.setChecked(False)
        if self.data is not None:
            self.available_attrs[:] = []
            self.used_attrs[:] = self.data.domain.attributes
            self.class_attrs[:] = self.data.domain.class_vars
            self.meta_attrs[:] = self.data.domain.metas
            self.update_domain_role_hints()
            self.commit()

    def send_report(self):
        if not self.data or not self.output_data:
            return
        in_domain, out_domain = self.data.domain, self.output_data.domain
        self.report_domain("Input data", self.data.domain)
        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (
                out_domain.attributes, out_domain.class_vars, out_domain.metas):
            self.report_paragraph("Output data", "No changes.")
        else:
            self.report_domain("Output data", self.output_data.domain)
            diff = list(set(in_domain.variables + in_domain.metas) -
                        set(out_domain.variables + out_domain.metas))
            if diff:
                text = "%i (%s)" % (len(diff), ", ".join(x.name for x in diff))
                self.report_items((("Removed", text),))


if __name__ == "__main__":  # pragma: no cover
    brown = Orange.data.Table("brown-selected")
    feats = AttributeList(brown.domain.attributes[:2])
    WidgetPreview(OWSelectAttributes).run(set_data=brown, set_features=feats)

```
--- 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:** OWSelectColumns Fails to Update Status Bar with Data Information

**Description:**
When data is provided to the `OWSelectColumns` widget, the status bar is expected to display detailed information about the input and output data. However, the status bar does not update accordingly, leading to confusion about the data being processed.

**Example Buggy Code:**
```python
def test_status_bar_update():
    widget = OWSelectAttributes()
    data = Table("iris")
    widget.send_signal(widget.Inputs.data, data)
    # Expected: Status bar displays "150 instances, 5 variables"
    # Actual: Status bar remains empty or shows default message
```

**Expected Behavior:**
Upon receiving data, the `OWSelectColumns` widget should update the status bar with comprehensive details about the input and output datasets, such as the number of instances and variables.

**Actual Behavior:**
The status bar does not reflect the received data information, causing the summary to remain empty or display incorrect details. This leads to failing tests that check for proper status bar updates when data is received or cleared.
[/ISSUE]
{
    "TestSelectAttributesDomainContextHandler.test_open_context": "PASSED",
    "TestSelectAttributesDomainContextHandler.test_open_context_with_imperfect_match": "PASSED",
    "TestSelectAttributesDomainContextHandler.test_open_context_with_no_match": "PASSED",
    "TestModel.test_drop_mime": "PASSED",
    "TestModel.test_flags": "PASSED",
    "TestOWSelectAttributes.test_image_export": "PASSED",
    "TestOWSelectAttributes.test_input_combinations": "PASSED",
    "TestOWSelectAttributes.test_input_features": "PASSED",
    "TestOWSelectAttributes.test_input_features_by_name": "PASSED",
    "TestOWSelectAttributes.test_input_features_by_name_sub_domain": "PASSED",
    "TestOWSelectAttributes.test_input_features_diff_domain": "PASSED",
    "TestOWSelectAttributes.test_input_features_from_rank": "PASSED",
    "TestOWSelectAttributes.test_input_features_no_data": "PASSED",
    "TestOWSelectAttributes.test_input_features_same_domain": "PASSED",
    "TestOWSelectAttributes.test_input_features_sub_domain": "PASSED",
    "TestOWSelectAttributes.test_move_rows": "PASSED",
    "TestOWSelectAttributes.test_msg_base_class": "PASSED",
    "TestOWSelectAttributes.test_multiple_target_variable": "PASSED",
    "TestOWSelectAttributes.test_summary": "PASSED",
    "TestOWSelectAttributes.test_use_features_checked": "PASSED",
    "TestOWSelectAttributes.test_used_attrs_supported_types": "PASSED",
    "TestOWSelectAttributes.test_minimum_size": "FAILED"
}
diff --git a/Orange/widgets/data/owselectcolumns.py b/Orange/widgets/data/owselectcolumns.py
index 3835127b7..c23161aaa 100644
--- a/Orange/widgets/data/owselectcolumns.py
+++ b/Orange/widgets/data/owselectcolumns.py
@@ -14,6 +14,7 @@ from Orange.widgets.data.contexthandlers import \
 from Orange.widgets.settings import ContextSetting, Setting
 from Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter
 from Orange.widgets.utils.widgetpreview import WidgetPreview
+from Orange.widgets.utils.state_summary import format_summary_details
 from Orange.widgets.widget import Input, Output, AttributeList, Msg
 from Orange.data.table import Table
 from Orange.widgets.utils import vartype
@@ -266,6 +267,9 @@ class OWSelectAttributes(widget.OWWidget):
         self.output_data = None
         self.original_completer_items = []
 
+        self.info.set_input_summary(self.info.NoInput)
+        self.info.set_output_summary(self.info.NoOutput)
+
         self.resize(600, 600)
 
     @property
@@ -343,11 +347,13 @@ class OWSelectAttributes(widget.OWWidget):
             self.class_attrs[:] = classes
             self.meta_attrs[:] = metas
             self.available_attrs[:] = available
+            self.info.set_input_summary(len(data), format_summary_details(data))
         else:
             self.used_attrs[:] = []
             self.class_attrs[:] = []
             self.meta_attrs[:] = []
             self.available_attrs[:] = []
+            self.info.set_input_summary(self.info.NoInput)
 
     def update_domain_role_hints(self):
         """ Update the domain hints to be stored in the widgets settings.
@@ -522,10 +528,13 @@ class OWSelectAttributes(widget.OWWidget):
             self.output_data = newdata
             self.Outputs.data.send(newdata)
             self.Outputs.features.send(AttributeList(attributes))
+            self.info.set_output_summary(len(newdata),
+                                         format_summary_details(newdata))
         else:
             self.output_data = None
             self.Outputs.data.send(None)
             self.Outputs.features.send(None)
+            self.info.set_output_summary(self.info.NoOutput)
 
     def reset(self):
         self.enable_used_attrs()

{"Orange/widgets/data/owselectcolumns.py": "from functools import partial\nfrom typing import Optional\n\nfrom AnyQt.QtWidgets import QWidget, QGridLayout\nfrom AnyQt.QtWidgets import QListView\nfrom AnyQt.QtCore import (\n    Qt, QTimer, QSortFilterProxyModel, QItemSelection, QItemSelectionModel,\n    QMimeData, QAbstractItemModel\n)\n\nfrom Orange.widgets import gui, widget\nfrom Orange.widgets.data.contexthandlers import \\\n    SelectAttributesDomainContextHandler\nfrom Orange.widgets.settings import ContextSetting, Setting\nfrom Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter\nfrom Orange.widgets.utils.widgetpreview import WidgetPreview\nfrom Orange.widgets.widget import Input, Output, AttributeList, Msg\nfrom Orange.data.table import Table\nfrom Orange.widgets.utils import vartype\nfrom Orange.widgets.utils.itemmodels import VariableListModel\nimport Orange\n\n\ndef source_model(view):\n    \"\"\" Return the source model for the Qt Item View if it uses\n    the QSortFilterProxyModel.\n    \"\"\"\n    if isinstance(view.model(), QSortFilterProxyModel):\n        return view.model().sourceModel()\n    else:\n        return view.model()\n\n\ndef source_indexes(indexes, view):\n    \"\"\" Map model indexes through a views QSortFilterProxyModel\n    \"\"\"\n    model = view.model()\n    if isinstance(model, QSortFilterProxyModel):\n        return list(map(model.mapToSource, indexes))\n    else:\n        return indexes\n\n\nclass VariablesListItemModel(VariableListModel):\n    \"\"\"\n    An Variable list item model specialized for Drag and Drop.\n    \"\"\"\n    MIME_TYPE = \"application/x-Orange-VariableListModelData\"\n\n    def flags(self, index):\n        flags = super().flags(index)\n        if index.isValid():\n            flags |= Qt.ItemIsDragEnabled\n        else:\n            flags |= Qt.ItemIsDropEnabled\n        return flags\n\n    @staticmethod\n    def supportedDropActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    @staticmethod\n    def supportedDragActions():\n        return Qt.MoveAction  # pragma: no cover\n\n    def mimeTypes(self):\n        return [self.MIME_TYPE]\n\n    def mimeData(self, indexlist):\n        \"\"\"\n        Reimplemented.\n\n        For efficiency reasons only the variable instances are set on the\n        mime data (under `'_items'` property)\n        \"\"\"\n        items = [self[index.row()] for index in indexlist]\n        mime = QMimeData()\n        # the encoded 'data' is empty, variables are passed by properties\n        mime.setData(self.MIME_TYPE, b'')\n        mime.setProperty(\"_items\", items)\n        return mime\n\n    def dropMimeData(self, mime, action, row, column, parent):\n        \"\"\"\n        Reimplemented.\n        \"\"\"\n        if action == Qt.IgnoreAction:\n            return True  # pragma: no cover\n        if not mime.hasFormat(self.MIME_TYPE):\n            return False  # pragma: no cover\n        variables = mime.property(\"_items\")\n        if variables is None:\n            return False  # pragma: no cover\n        if row < 0:\n            row = self.rowCount()\n\n        self[row:row] = variables\n        return True\n\n\nclass OWSelectAttributes(widget.OWWidget):\n    # pylint: disable=too-many-instance-attributes\n    name = \"Select Columns\"\n    description = \"Select columns from the data table and assign them to \" \\\n                  \"data features, classes or meta variables.\"\n    icon = \"icons/SelectColumns.svg\"\n    priority = 100\n    keywords = [\"filter\", \"attributes\", \"target\", \"variable\"]\n\n    class Inputs:\n        data = Input(\"Data\", Table, default=True)\n        features = Input(\"Features\", AttributeList)\n\n    class Outputs:\n        data = Output(\"Data\", Table)\n        features = Output(\"Features\", AttributeList, dynamic=False)\n\n    want_main_area = False\n    want_control_area = True\n\n    settingsHandler = SelectAttributesDomainContextHandler()\n    domain_role_hints = ContextSetting({})\n    use_input_features = Setting(False)\n    auto_commit = Setting(True)\n\n    class Warning(widget.OWWidget.Warning):\n        mismatching_domain = Msg(\"Features and data domain do not match\")\n\n    def __init__(self):\n        super().__init__()\n        self.data = None\n        self.features = None\n\n        # Schedule interface updates (enabled buttons) using a coalescing\n        # single shot timer (complex interactions on selection and filtering\n        # updates in the 'available_attrs_view')\n        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)\n        self.__interface_update_timer.timeout.connect(\n            self.__update_interface_state)\n        # The last view that has the selection for move operation's source\n        self.__last_active_view = None  # type: Optional[QListView]\n\n        def update_on_change(view):\n            # Schedule interface state update on selection change in `view`\n            self.__last_active_view = view\n            self.__interface_update_timer.start()\n\n        self.controlArea = QWidget(self.controlArea)\n        self.layout().addWidget(self.controlArea)\n        layout = QGridLayout()\n        self.controlArea.setLayout(layout)\n        layout.setContentsMargins(4, 4, 4, 4)\n        box = gui.vBox(self.controlArea, \"Available Variables\",\n                       addToLayout=False)\n\n        self.available_attrs = VariablesListItemModel()\n        filter_edit, self.available_attrs_view = variables_filter(\n            parent=self, model=self.available_attrs)\n        box.layout().addWidget(filter_edit)\n\n        def dropcompleted(action):\n            if action == Qt.MoveAction:\n                self.commit()\n\n        self.available_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.available_attrs_view))\n        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n\n        box.layout().addWidget(self.available_attrs_view)\n        layout.addWidget(box, 0, 0, 3, 1)\n\n        box = gui.vBox(self.controlArea, \"Features\", addToLayout=False)\n        self.used_attrs = VariablesListItemModel()\n        filter_edit, self.used_attrs_view = variables_filter(\n            parent=self, model=self.used_attrs,\n            accepted_type=(Orange.data.DiscreteVariable,\n                           Orange.data.ContinuousVariable))\n        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)\n        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)\n        self.used_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.used_attrs_view))\n        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.use_features_box = gui.auto_commit(\n            self.controlArea, self, \"use_input_features\",\n            \"Use input features\", \"Always use input features\",\n            box=False, commit=self.__use_features_clicked,\n            callback=self.__use_features_changed, addToLayout=False\n        )\n        self.enable_use_features_box()\n        box.layout().addWidget(self.use_features_box)\n        box.layout().addWidget(filter_edit)\n        box.layout().addWidget(self.used_attrs_view)\n        layout.addWidget(box, 0, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Target Variable\", addToLayout=False)\n        self.class_attrs = VariablesListItemModel()\n        self.class_attrs_view = VariablesListItemView(\n            acceptedType=(Orange.data.DiscreteVariable,\n                          Orange.data.ContinuousVariable))\n        self.class_attrs_view.setModel(self.class_attrs)\n        self.class_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.class_attrs_view))\n        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        self.class_attrs_view.setMaximumHeight(72)\n        box.layout().addWidget(self.class_attrs_view)\n        layout.addWidget(box, 1, 2, 1, 1)\n\n        box = gui.vBox(self.controlArea, \"Meta Attributes\", addToLayout=False)\n        self.meta_attrs = VariablesListItemModel()\n        self.meta_attrs_view = VariablesListItemView(\n            acceptedType=Orange.data.Variable)\n        self.meta_attrs_view.setModel(self.meta_attrs)\n        self.meta_attrs_view.selectionModel().selectionChanged.connect(\n            partial(update_on_change, self.meta_attrs_view))\n        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)\n        box.layout().addWidget(self.meta_attrs_view)\n        layout.addWidget(box, 2, 2, 1, 1)\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 0, 1, 1, 1)\n\n        self.up_attr_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.used_attrs_view))\n        self.move_attr_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.used_attrs_view)\n                                          )\n        self.down_attr_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.used_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 1, 1, 1, 1)\n\n        self.up_class_button = gui.button(bbox, self, \"Up\",\n                                          callback=partial(self.move_up, self.class_attrs_view))\n        self.move_class_button = gui.button(bbox, self, \">\",\n                                            callback=partial(self.move_selected,\n                                                             self.class_attrs_view)\n                                           )\n        self.down_class_button = gui.button(bbox, self, \"Down\",\n                                            callback=partial(self.move_down, self.class_attrs_view))\n\n        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)\n        layout.addWidget(bbox, 2, 1, 1, 1)\n        self.up_meta_button = gui.button(bbox, self, \"Up\",\n                                         callback=partial(self.move_up, self.meta_attrs_view))\n        self.move_meta_button = gui.button(bbox, self, \">\",\n                                           callback=partial(self.move_selected,\n                                                            self.meta_attrs_view)\n                                          )\n        self.down_meta_button = gui.button(bbox, self, \"Down\",\n                                           callback=partial(self.move_down, self.meta_attrs_view))\n\n        autobox = gui.auto_send(None, self, \"auto_commit\")\n        layout.addWidget(autobox, 3, 0, 1, 3)\n        reset = gui.button(None, self, \"Reset\", callback=self.reset, width=120)\n        autobox.layout().insertWidget(0, reset)\n        autobox.layout().insertStretch(1, 20)\n\n        layout.setRowStretch(0, 4)\n        layout.setRowStretch(1, 0)\n        layout.setRowStretch(2, 2)\n        layout.setHorizontalSpacing(0)\n        self.controlArea.setLayout(layout)\n\n        self.output_data = None\n        self.original_completer_items = []\n\n        self.resize(600, 600)\n\n    @property\n    def features_from_data_attributes(self):\n        if self.data is None or self.features is None:\n            return []\n        domain = self.data.domain\n        return [domain[feature.name] for feature in self.features\n                if feature.name in domain and domain[feature.name]\n                in domain.attributes]\n\n    def can_use_features(self):\n        return bool(self.features_from_data_attributes) and \\\n               self.features_from_data_attributes != self.used_attrs[:]\n\n    def __use_features_changed(self):  # Use input features check box\n        # Needs a check since callback is invoked before object is created\n        if not hasattr(self, \"use_features_box\"):\n            return\n        self.enable_used_attrs(not self.use_input_features)\n        if self.use_input_features and self.can_use_features():\n            self.use_features()\n        if not self.use_input_features:\n            self.enable_use_features_box()\n\n    def __use_features_clicked(self):  # Use input features button\n        self.use_features()\n\n    def __used_attrs_changed(self):\n        self.enable_use_features_box()\n\n    @Inputs.data\n    def set_data(self, data=None):\n        self.update_domain_role_hints()\n        self.closeContext()\n        self.data = data\n        if data is not None:\n            self.openContext(data)\n            all_vars = data.domain.variables + data.domain.metas\n\n            var_sig = lambda attr: (attr.name, vartype(attr))\n\n            domain_hints = {var_sig(attr): (\"attribute\", i)\n                            for i, attr in enumerate(data.domain.attributes)}\n\n            domain_hints.update({var_sig(attr): (\"meta\", i)\n                                 for i, attr in enumerate(data.domain.metas)})\n\n            if data.domain.class_vars:\n                domain_hints.update(\n                    {var_sig(attr): (\"class\", i)\n                     for i, attr in enumerate(data.domain.class_vars)})\n\n            # update the hints from context settings\n            domain_hints.update(self.domain_role_hints)\n\n            attrs_for_role = lambda role: [\n                (domain_hints[var_sig(attr)][1], attr)\n                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]\n\n            attributes = [\n                attr for place, attr in sorted(attrs_for_role(\"attribute\"),\n                                               key=lambda a: a[0])]\n            classes = [\n                attr for place, attr in sorted(attrs_for_role(\"class\"),\n                                               key=lambda a: a[0])]\n            metas = [\n                attr for place, attr in sorted(attrs_for_role(\"meta\"),\n                                               key=lambda a: a[0])]\n            available = [\n                attr for place, attr in sorted(attrs_for_role(\"available\"),\n                                               key=lambda a: a[0])]\n\n            self.used_attrs[:] = attributes\n            self.class_attrs[:] = classes\n            self.meta_attrs[:] = metas\n            self.available_attrs[:] = available\n        else:\n            self.used_attrs[:] = []\n            self.class_attrs[:] = []\n            self.meta_attrs[:] = []\n            self.available_attrs[:] = []\n\n    def update_domain_role_hints(self):\n        \"\"\" Update the domain hints to be stored in the widgets settings.\n        \"\"\"\n        hints_from_model = lambda role, model: [\n            ((attr.name, vartype(attr)), (role, i))\n            for i, attr in enumerate(model)]\n        hints = dict(hints_from_model(\"available\", self.available_attrs))\n        hints.update(hints_from_model(\"attribute\", self.used_attrs))\n        hints.update(hints_from_model(\"class\", self.class_attrs))\n        hints.update(hints_from_model(\"meta\", self.meta_attrs))\n        self.domain_role_hints = hints\n\n    @Inputs.features\n    def set_features(self, features):\n        self.features = features\n\n    def handleNewSignals(self):\n        self.check_data()\n        self.enable_used_attrs()\n        self.enable_use_features_box()\n        if self.use_input_features and self.features_from_data_attributes:\n            self.enable_used_attrs(False)\n            self.use_features()\n        self.unconditional_commit()\n\n    def check_data(self):\n        self.Warning.mismatching_domain.clear()\n        if self.data is not None and self.features is not None and \\\n                not self.features_from_data_attributes:\n            self.Warning.mismatching_domain()\n\n    def enable_used_attrs(self, enable=True):\n        self.up_attr_button.setEnabled(enable)\n        self.move_attr_button.setEnabled(enable)\n        self.down_attr_button.setEnabled(enable)\n        self.used_attrs_view.setEnabled(enable)\n        self.used_attrs_view.repaint()\n\n    def enable_use_features_box(self):\n        self.use_features_box.button.setEnabled(self.can_use_features())\n        enable_checkbox = bool(self.features_from_data_attributes)\n        self.use_features_box.setHidden(not enable_checkbox)\n        self.use_features_box.repaint()\n\n    def use_features(self):\n        attributes = self.features_from_data_attributes\n        available, used = self.available_attrs[:], self.used_attrs[:]\n        self.available_attrs[:] = [attr for attr in used + available\n                                   if attr not in attributes]\n        self.used_attrs[:] = attributes\n        self.commit()\n\n    @staticmethod\n    def selected_rows(view):\n        \"\"\" Return the selected rows in the view.\n        \"\"\"\n        rows = view.selectionModel().selectedRows()\n        model = view.model()\n        if isinstance(model, QSortFilterProxyModel):\n            rows = [model.mapToSource(r) for r in rows]\n        return [r.row() for r in rows]\n\n    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):\n        rows = [idx.row() for idx in view.selectionModel().selectedRows()]\n        model = view.model()  # type: QAbstractItemModel\n        rowcount = model.rowCount()\n        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]\n\n        def itemData(index):\n            return {role: model.data(index, role) for role in roles}\n\n        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):\n            d1 = itemData(model.index(row, 0))\n            d2 = itemData(model.index(newrow, 0))\n            model.setItemData(model.index(row, 0), d2)\n            model.setItemData(model.index(newrow, 0), d1)\n\n        selection = QItemSelection()\n        for nrow in newrows:\n            index = model.index(nrow, 0)\n            selection.select(index, index)\n        view.selectionModel().select(\n            selection, QItemSelectionModel.ClearAndSelect)\n\n        self.commit()\n\n    def move_up(self, view: QListView):\n        self.move_rows(view, -1)\n\n    def move_down(self, view: QListView):\n        self.move_rows(view, 1)\n\n    def move_selected(self, view):\n        if self.selected_rows(view):\n            self.move_selected_from_to(view, self.available_attrs_view)\n        elif self.selected_rows(self.available_attrs_view):\n            self.move_selected_from_to(self.available_attrs_view, view)\n\n    def move_selected_from_to(self, src, dst):\n        self.move_from_to(src, dst, self.selected_rows(src))\n\n    def move_from_to(self, src, dst, rows):\n        src_model = source_model(src)\n        attrs = [src_model[r] for r in rows]\n\n        for s1, s2 in reversed(list(slices(rows))):\n            del src_model[s1:s2]\n\n        dst_model = source_model(dst)\n\n        dst_model.extend(attrs)\n\n        self.commit()\n\n    def __update_interface_state(self):\n        last_view = self.__last_active_view\n        if last_view is not None:\n            self.update_interface_state(last_view)\n\n    def update_interface_state(self, focus=None):\n        for view in [self.available_attrs_view, self.used_attrs_view,\n                     self.class_attrs_view, self.meta_attrs_view]:\n            if view is not focus and not view.hasFocus() \\\n                    and view.selectionModel().hasSelection():\n                view.selectionModel().clear()\n\n        def selected_vars(view):\n            model = source_model(view)\n            return [model[i] for i in self.selected_rows(view)]\n\n        available_selected = selected_vars(self.available_attrs_view)\n        attrs_selected = selected_vars(self.used_attrs_view)\n        class_selected = selected_vars(self.class_attrs_view)\n        meta_selected = selected_vars(self.meta_attrs_view)\n\n        available_types = set(map(type, available_selected))\n        all_primitive = all(var.is_primitive()\n                            for var in available_types)\n\n        move_attr_enabled = \\\n            ((available_selected and all_primitive) or attrs_selected) and \\\n            self.used_attrs_view.isEnabled()\n\n        self.move_attr_button.setEnabled(bool(move_attr_enabled))\n        if move_attr_enabled:\n            self.move_attr_button.setText(\">\" if available_selected else \"<\")\n\n        move_class_enabled = bool(all_primitive and available_selected) or class_selected\n\n        self.move_class_button.setEnabled(bool(move_class_enabled))\n        if move_class_enabled:\n            self.move_class_button.setText(\">\" if available_selected else \"<\")\n        move_meta_enabled = available_selected or meta_selected\n\n        self.move_meta_button.setEnabled(bool(move_meta_enabled))\n        if move_meta_enabled:\n            self.move_meta_button.setText(\">\" if available_selected else \"<\")\n\n        self.__last_active_view = None\n        self.__interface_update_timer.stop()\n\n    def commit(self):\n        self.update_domain_role_hints()\n        if self.data is not None:\n            attributes = list(self.used_attrs)\n            class_var = list(self.class_attrs)\n            metas = list(self.meta_attrs)\n\n            domain = Orange.data.Domain(attributes, class_var, metas)\n            newdata = self.data.transform(domain)\n            self.output_data = newdata\n            self.Outputs.data.send(newdata)\n            self.Outputs.features.send(AttributeList(attributes))\n        else:\n            self.output_data = None\n            self.Outputs.data.send(None)\n            self.Outputs.features.send(None)\n\n    def reset(self):\n        self.enable_used_attrs()\n        self.use_features_box.checkbox.setChecked(False)\n        if self.data is not None:\n            self.available_attrs[:] = []\n            self.used_attrs[:] = self.data.domain.attributes\n            self.class_attrs[:] = self.data.domain.class_vars\n            self.meta_attrs[:] = self.data.domain.metas\n            self.update_domain_role_hints()\n            self.commit()\n\n    def send_report(self):\n        if not self.data or not self.output_data:\n            return\n        in_domain, out_domain = self.data.domain, self.output_data.domain\n        self.report_domain(\"Input data\", self.data.domain)\n        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (\n                out_domain.attributes, out_domain.class_vars, out_domain.metas):\n            self.report_paragraph(\"Output data\", \"No changes.\")\n        else:\n            self.report_domain(\"Output data\", self.output_data.domain)\n            diff = list(set(in_domain.variables + in_domain.metas) -\n                        set(out_domain.variables + out_domain.metas))\n            if diff:\n                text = \"%i (%s)\" % (len(diff), \", \".join(x.name for x in diff))\n                self.report_items(((\"Removed\", text),))\n\n\nif __name__ == \"__main__\":  # pragma: no cover\n    brown = Orange.data.Table(\"brown-selected\")\n    feats = AttributeList(brown.domain.attributes[:2])\n    WidgetPreview(OWSelectAttributes).run(set_data=brown, set_features=feats)\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:** OWSelectColumns Fails to Update Status Bar with Data Information

**Description:**
When data is provided to the `OWSelectColumns` widget, the status bar is expected to display detailed information about the input and output data. However, the status bar does not update accordingly, leading to confusion about the data being processed.

**Example Buggy Code:**
```python
def test_status_bar_update():
    widget = OWSelectAttributes()
    data = Table("iris")
    widget.send_signal(widget.Inputs.data, data)
    # Expected: Status bar displays "150 instances, 5 variables"
    # Actual: Status bar remains empty or shows default message
```

**Expected Behavior:**
Upon receiving data, the `OWSelectColumns` widget should update the status bar with comprehensive details about the input and output datasets, such as the number of instances and variables.

**Actual Behavior:**
The status bar does not reflect the received data information, causing the summary to remain empty or display incorrect details. This leads to failing tests that check for proper status bar updates when data is received or cleared.
[/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/owselectcolumns.py
from functools import partial
from typing import Optional

from AnyQt.QtWidgets import QWidget, QGridLayout
from AnyQt.QtWidgets import QListView
from AnyQt.QtCore import (
    Qt, QTimer, QSortFilterProxyModel, QItemSelection, QItemSelectionModel,
    QMimeData, QAbstractItemModel
)

from Orange.widgets import gui, widget
from Orange.widgets.data.contexthandlers import \
    SelectAttributesDomainContextHandler
from Orange.widgets.settings import ContextSetting, Setting
from Orange.widgets.utils.listfilter import VariablesListItemView, slices, variables_filter
from Orange.widgets.utils.widgetpreview import WidgetPreview
from Orange.widgets.widget import Input, Output, AttributeList, Msg
from Orange.data.table import Table
from Orange.widgets.utils import vartype
from Orange.widgets.utils.itemmodels import VariableListModel
import Orange


def source_model(view):
    """ Return the source model for the Qt Item View if it uses
    the QSortFilterProxyModel.
    """
    if isinstance(view.model(), QSortFilterProxyModel):
        return view.model().sourceModel()
    else:
        return view.model()


def source_indexes(indexes, view):
    """ Map model indexes through a views QSortFilterProxyModel
    """
    model = view.model()
    if isinstance(model, QSortFilterProxyModel):
        return list(map(model.mapToSource, indexes))
    else:
        return indexes


class VariablesListItemModel(VariableListModel):
    """
    An Variable list item model specialized for Drag and Drop.
    """
    MIME_TYPE = "application/x-Orange-VariableListModelData"

    def flags(self, index):
        flags = super().flags(index)
        if index.isValid():
            flags |= Qt.ItemIsDragEnabled
        else:
            flags |= Qt.ItemIsDropEnabled
        return flags

    @staticmethod
    def supportedDropActions():
        return Qt.MoveAction  # pragma: no cover

    @staticmethod
    def supportedDragActions():
        return Qt.MoveAction  # pragma: no cover

    def mimeTypes(self):
        return [self.MIME_TYPE]

    def mimeData(self, indexlist):
        """
        Reimplemented.

        For efficiency reasons only the variable instances are set on the
        mime data (under `'_items'` property)
        """
        items = [self[index.row()] for index in indexlist]
        mime = QMimeData()
        # the encoded 'data' is empty, variables are passed by properties
        mime.setData(self.MIME_TYPE, b'')
        mime.setProperty("_items", items)
        return mime

    def dropMimeData(self, mime, action, row, column, parent):
        """
        Reimplemented.
        """
        if action == Qt.IgnoreAction:
            return True  # pragma: no cover
        if not mime.hasFormat(self.MIME_TYPE):
            return False  # pragma: no cover
        variables = mime.property("_items")
        if variables is None:
            return False  # pragma: no cover
        if row < 0:
            row = self.rowCount()

        self[row:row] = variables
        return True


class OWSelectAttributes(widget.OWWidget):
    # pylint: disable=too-many-instance-attributes
    name = "Select Columns"
    description = "Select columns from the data table and assign them to " \
                  "data features, classes or meta variables."
    icon = "icons/SelectColumns.svg"
    priority = 100
    keywords = ["filter", "attributes", "target", "variable"]

    class Inputs:
        data = Input("Data", Table, default=True)
        features = Input("Features", AttributeList)

    class Outputs:
        data = Output("Data", Table)
        features = Output("Features", AttributeList, dynamic=False)

    want_main_area = False
    want_control_area = True

    settingsHandler = SelectAttributesDomainContextHandler()
    domain_role_hints = ContextSetting({})
    use_input_features = Setting(False)
    auto_commit = Setting(True)

    class Warning(widget.OWWidget.Warning):
        mismatching_domain = Msg("Features and data domain do not match")

    def __init__(self):
        super().__init__()
        self.data = None
        self.features = None

        # Schedule interface updates (enabled buttons) using a coalescing
        # single shot timer (complex interactions on selection and filtering
        # updates in the 'available_attrs_view')
        self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)
        self.__interface_update_timer.timeout.connect(
            self.__update_interface_state)
        # The last view that has the selection for move operation's source
        self.__last_active_view = None  # type: Optional[QListView]

        def update_on_change(view):
            # Schedule interface state update on selection change in `view`
            self.__last_active_view = view
            self.__interface_update_timer.start()

        self.controlArea = QWidget(self.controlArea)
        self.layout().addWidget(self.controlArea)
        layout = QGridLayout()
        self.controlArea.setLayout(layout)
        layout.setContentsMargins(4, 4, 4, 4)
        box = gui.vBox(self.controlArea, "Available Variables",
                       addToLayout=False)

        self.available_attrs = VariablesListItemModel()
        filter_edit, self.available_attrs_view = variables_filter(
            parent=self, model=self.available_attrs)
        box.layout().addWidget(filter_edit)

        def dropcompleted(action):
            if action == Qt.MoveAction:
                self.commit()

        self.available_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.available_attrs_view))
        self.available_attrs_view.dragDropActionDidComplete.connect(dropcompleted)

        box.layout().addWidget(self.available_attrs_view)
        layout.addWidget(box, 0, 0, 3, 1)

        box = gui.vBox(self.controlArea, "Features", addToLayout=False)
        self.used_attrs = VariablesListItemModel()
        filter_edit, self.used_attrs_view = variables_filter(
            parent=self, model=self.used_attrs,
            accepted_type=(Orange.data.DiscreteVariable,
                           Orange.data.ContinuousVariable))
        self.used_attrs.rowsInserted.connect(self.__used_attrs_changed)
        self.used_attrs.rowsRemoved.connect(self.__used_attrs_changed)
        self.used_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.used_attrs_view))
        self.used_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        self.use_features_box = gui.auto_commit(
            self.controlArea, self, "use_input_features",
            "Use input features", "Always use input features",
            box=False, commit=self.__use_features_clicked,
            callback=self.__use_features_changed, addToLayout=False
        )
        self.enable_use_features_box()
        box.layout().addWidget(self.use_features_box)
        box.layout().addWidget(filter_edit)
        box.layout().addWidget(self.used_attrs_view)
        layout.addWidget(box, 0, 2, 1, 1)

        box = gui.vBox(self.controlArea, "Target Variable", addToLayout=False)
        self.class_attrs = VariablesListItemModel()
        self.class_attrs_view = VariablesListItemView(
            acceptedType=(Orange.data.DiscreteVariable,
                          Orange.data.ContinuousVariable))
        self.class_attrs_view.setModel(self.class_attrs)
        self.class_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.class_attrs_view))
        self.class_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        self.class_attrs_view.setMaximumHeight(72)
        box.layout().addWidget(self.class_attrs_view)
        layout.addWidget(box, 1, 2, 1, 1)

        box = gui.vBox(self.controlArea, "Meta Attributes", addToLayout=False)
        self.meta_attrs = VariablesListItemModel()
        self.meta_attrs_view = VariablesListItemView(
            acceptedType=Orange.data.Variable)
        self.meta_attrs_view.setModel(self.meta_attrs)
        self.meta_attrs_view.selectionModel().selectionChanged.connect(
            partial(update_on_change, self.meta_attrs_view))
        self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
        box.layout().addWidget(self.meta_attrs_view)
        layout.addWidget(box, 2, 2, 1, 1)

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 0, 1, 1, 1)

        self.up_attr_button = gui.button(bbox, self, "Up",
                                         callback=partial(self.move_up, self.used_attrs_view))
        self.move_attr_button = gui.button(bbox, self, ">",
                                           callback=partial(self.move_selected,
                                                            self.used_attrs_view)
                                          )
        self.down_attr_button = gui.button(bbox, self, "Down",
                                           callback=partial(self.move_down, self.used_attrs_view))

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 1, 1, 1, 1)

        self.up_class_button = gui.button(bbox, self, "Up",
                                          callback=partial(self.move_up, self.class_attrs_view))
        self.move_class_button = gui.button(bbox, self, ">",
                                            callback=partial(self.move_selected,
                                                             self.class_attrs_view)
                                           )
        self.down_class_button = gui.button(bbox, self, "Down",
                                            callback=partial(self.move_down, self.class_attrs_view))

        bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
        layout.addWidget(bbox, 2, 1, 1, 1)
        self.up_meta_button = gui.button(bbox, self, "Up",
                                         callback=partial(self.move_up, self.meta_attrs_view))
        self.move_meta_button = gui.button(bbox, self, ">",
                                           callback=partial(self.move_selected,
                                                            self.meta_attrs_view)
                                          )
        self.down_meta_button = gui.button(bbox, self, "Down",
                                           callback=partial(self.move_down, self.meta_attrs_view))

        autobox = gui.auto_send(None, self, "auto_commit")
        layout.addWidget(autobox, 3, 0, 1, 3)
        reset = gui.button(None, self, "Reset", callback=self.reset, width=120)
        autobox.layout().insertWidget(0, reset)
        autobox.layout().insertStretch(1, 20)

        layout.setRowStretch(0, 4)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 2)
        layout.setHorizontalSpacing(0)
        self.controlArea.setLayout(layout)

        self.output_data = None
        self.original_completer_items = []

        self.resize(600, 600)

    @property
    def features_from_data_attributes(self):
        if self.data is None or self.features is None:
            return []
        domain = self.data.domain
        return [domain[feature.name] for feature in self.features
                if feature.name in domain and domain[feature.name]
                in domain.attributes]

    def can_use_features(self):
        return bool(self.features_from_data_attributes) and \
               self.features_from_data_attributes != self.used_attrs[:]

    def __use_features_changed(self):  # Use input features check box
        # Needs a check since callback is invoked before object is created
        if not hasattr(self, "use_features_box"):
            return
        self.enable_used_attrs(not self.use_input_features)
        if self.use_input_features and self.can_use_features():
            self.use_features()
        if not self.use_input_features:
            self.enable_use_features_box()

    def __use_features_clicked(self):  # Use input features button
        self.use_features()

    def __used_attrs_changed(self):
        self.enable_use_features_box()

    @Inputs.data
    def set_data(self, data=None):
        self.update_domain_role_hints()
        self.closeContext()
        self.data = data
        if data is not None:
            self.openContext(data)
            all_vars = data.domain.variables + data.domain.metas

            var_sig = lambda attr: (attr.name, vartype(attr))

            domain_hints = {var_sig(attr): ("attribute", i)
                            for i, attr in enumerate(data.domain.attributes)}

            domain_hints.update({var_sig(attr): ("meta", i)
                                 for i, attr in enumerate(data.domain.metas)})

            if data.domain.class_vars:
                domain_hints.update(
                    {var_sig(attr): ("class", i)
                     for i, attr in enumerate(data.domain.class_vars)})

            # update the hints from context settings
            domain_hints.update(self.domain_role_hints)

            attrs_for_role = lambda role: [
                (domain_hints[var_sig(attr)][1], attr)
                for attr in all_vars if domain_hints[var_sig(attr)][0] == role]

            attributes = [
                attr for place, attr in sorted(attrs_for_role("attribute"),
                                               key=lambda a: a[0])]
            classes = [
                attr for place, attr in sorted(attrs_for_role("class"),
                                               key=lambda a: a[0])]
            metas = [
                attr for place, attr in sorted(attrs_for_role("meta"),
                                               key=lambda a: a[0])]
            available = [
                attr for place, attr in sorted(attrs_for_role("available"),
                                               key=lambda a: a[0])]

            self.used_attrs[:] = attributes
            self.class_attrs[:] = classes
            self.meta_attrs[:] = metas
            self.available_attrs[:] = available
        else:
            self.used_attrs[:] = []
            self.class_attrs[:] = []
            self.meta_attrs[:] = []
            self.available_attrs[:] = []

    def update_domain_role_hints(self):
        """ Update the domain hints to be stored in the widgets settings.
        """
        hints_from_model = lambda role, model: [
            ((attr.name, vartype(attr)), (role, i))
            for i, attr in enumerate(model)]
        hints = dict(hints_from_model("available", self.available_attrs))
        hints.update(hints_from_model("attribute", self.used_attrs))
        hints.update(hints_from_model("class", self.class_attrs))
        hints.update(hints_from_model("meta", self.meta_attrs))
        self.domain_role_hints = hints

    @Inputs.features
    def set_features(self, features):
        self.features = features

    def handleNewSignals(self):
        self.check_data()
        self.enable_used_attrs()
        self.enable_use_features_box()
        if self.use_input_features and self.features_from_data_attributes:
            self.enable_used_attrs(False)
            self.use_features()
        self.unconditional_commit()

    def check_data(self):
        self.Warning.mismatching_domain.clear()
        if self.data is not None and self.features is not None and \
                not self.features_from_data_attributes:
            self.Warning.mismatching_domain()

    def enable_used_attrs(self, enable=True):
        self.up_attr_button.setEnabled(enable)
        self.move_attr_button.setEnabled(enable)
        self.down_attr_button.setEnabled(enable)
        self.used_attrs_view.setEnabled(enable)
        self.used_attrs_view.repaint()

    def enable_use_features_box(self):
        self.use_features_box.button.setEnabled(self.can_use_features())
        enable_checkbox = bool(self.features_from_data_attributes)
        self.use_features_box.setHidden(not enable_checkbox)
        self.use_features_box.repaint()

    def use_features(self):
        attributes = self.features_from_data_attributes
        available, used = self.available_attrs[:], self.used_attrs[:]
        self.available_attrs[:] = [attr for attr in used + available
                                   if attr not in attributes]
        self.used_attrs[:] = attributes
        self.commit()

    @staticmethod
    def selected_rows(view):
        """ Return the selected rows in the view.
        """
        rows = view.selectionModel().selectedRows()
        model = view.model()
        if isinstance(model, QSortFilterProxyModel):
            rows = [model.mapToSource(r) for r in rows]
        return [r.row() for r in rows]

    def move_rows(self, view: QListView, offset: int, roles=(Qt.EditRole,)):
        rows = [idx.row() for idx in view.selectionModel().selectedRows()]
        model = view.model()  # type: QAbstractItemModel
        rowcount = model.rowCount()
        newrows = [min(max(0, row + offset), rowcount - 1) for row in rows]

        def itemData(index):
            return {role: model.data(index, role) for role in roles}

        for row, newrow in sorted(zip(rows, newrows), reverse=offset > 0):
            d1 = itemData(model.index(row, 0))
            d2 = itemData(model.index(newrow, 0))
            model.setItemData(model.index(row, 0), d2)
            model.setItemData(model.index(newrow, 0), d1)

        selection = QItemSelection()
        for nrow in newrows:
            index = model.index(nrow, 0)
            selection.select(index, index)
        view.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

        self.commit()

    def move_up(self, view: QListView):
        self.move_rows(view, -1)

    def move_down(self, view: QListView):
        self.move_rows(view, 1)

    def move_selected(self, view):
        if self.selected_rows(view):
            self.move_selected_from_to(view, self.available_attrs_view)
        elif self.selected_rows(self.available_attrs_view):
            self.move_selected_from_to(self.available_attrs_view, view)

    def move_selected_from_to(self, src, dst):
        self.move_from_to(src, dst, self.selected_rows(src))

    def move_from_to(self, src, dst, rows):
        src_model = source_model(src)
        attrs = [src_model[r] for r in rows]

        for s1, s2 in reversed(list(slices(rows))):
            del src_model[s1:s2]

        dst_model = source_model(dst)

        dst_model.extend(attrs)

        self.commit()

    def __update_interface_state(self):
        last_view = self.__last_active_view
        if last_view is not None:
            self.update_interface_state(last_view)

    def update_interface_state(self, focus=None):
        for view in [self.available_attrs_view, self.used_attrs_view,
                     self.class_attrs_view, self.meta_attrs_view]:
            if view is not focus and not view.hasFocus() \
                    and view.selectionModel().hasSelection():
                view.selectionModel().clear()

        def selected_vars(view):
            model = source_model(view)
            return [model[i] for i in self.selected_rows(view)]

        available_selected = selected_vars(self.available_attrs_view)
        attrs_selected = selected_vars(self.used_attrs_view)
        class_selected = selected_vars(self.class_attrs_view)
        meta_selected = selected_vars(self.meta_attrs_view)

        available_types = set(map(type, available_selected))
        all_primitive = all(var.is_primitive()
                            for var in available_types)

        move_attr_enabled = \
            ((available_selected and all_primitive) or attrs_selected) and \
            self.used_attrs_view.isEnabled()

        self.move_attr_button.setEnabled(bool(move_attr_enabled))
        if move_attr_enabled:
            self.move_attr_button.setText(">" if available_selected else "<")

        move_class_enabled = bool(all_primitive and available_selected) or class_selected

        self.move_class_button.setEnabled(bool(move_class_enabled))
        if move_class_enabled:
            self.move_class_button.setText(">" if available_selected else "<")
        move_meta_enabled = available_selected or meta_selected

        self.move_meta_button.setEnabled(bool(move_meta_enabled))
        if move_meta_enabled:
            self.move_meta_button.setText(">" if available_selected else "<")

        self.__last_active_view = None
        self.__interface_update_timer.stop()

    def commit(self):
        self.update_domain_role_hints()
        if self.data is not None:
            attributes = list(self.used_attrs)
            class_var = list(self.class_attrs)
            metas = list(self.meta_attrs)

            domain = Orange.data.Domain(attributes, class_var, metas)
            newdata = self.data.transform(domain)
            self.output_data = newdata
            self.Outputs.data.send(newdata)
            self.Outputs.features.send(AttributeList(attributes))
        else:
            self.output_data = None
            self.Outputs.data.send(None)
            self.Outputs.features.send(None)

    def reset(self):
        self.enable_used_attrs()
        self.use_features_box.checkbox.setChecked(False)
        if self.data is not None:
            self.available_attrs[:] = []
            self.used_attrs[:] = self.data.domain.attributes
            self.class_attrs[:] = self.data.domain.class_vars
            self.meta_attrs[:] = self.data.domain.metas
            self.update_domain_role_hints()
            self.commit()

    def send_report(self):
        if not self.data or not self.output_data:
            return
        in_domain, out_domain = self.data.domain, self.output_data.domain
        self.report_domain("Input data", self.data.domain)
        if (in_domain.attributes, in_domain.class_vars, in_domain.metas) == (
                out_domain.attributes, out_domain.class_vars, out_domain.metas):
            self.report_paragraph("Output data", "No changes.")
        else:
            self.report_domain("Output data", self.output_data.domain)
            diff = list(set(in_domain.variables + in_domain.metas) -
                        set(out_domain.variables + out_domain.metas))
            if diff:
                text = "%i (%s)" % (len(diff), ", ".join(x.name for x in diff))
                self.report_items((("Removed", text),))


if __name__ == "__main__":  # pragma: no cover
    brown = Orange.data.Table("brown-selected")
    feats = AttributeList(brown.domain.attributes[:2])
    WidgetPreview(OWSelectAttributes).run(set_data=brown, set_features=feats)

```
--- 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