{
    "file_diffs": [
        {
            "old_file_content": "import re\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.data import DiscreteVariable, Domain\nfrom Orange.data.sql.table import SqlTable\nfrom Orange.preprocess.util import _RefuseDataInConstructor\nfrom Orange.statistics import distribution, contingency\nfrom Orange.statistics.basic_stats import BasicStats\nfrom Orange.util import Reprable\nfrom .transformation import Transformation\nfrom . import _discretize\n\n__all__ = [\"EqualFreq\", \"EqualWidth\", \"EntropyMDL\", \"DomainDiscretizer\"]\n\n\nclass Discretizer(Transformation):\n    \"\"\"Value transformer that returns an index of the bin for the given value.\n    \"\"\"\n    def __init__(self, variable, points):\n        super().__init__(variable)\n        self.points = points\n\n    @staticmethod\n    def digitize(x, bins):\n        if sp.issparse(x):\n            if len(bins):\n                x.data = np.digitize(x.data, bins)\n            else:\n                x = sp.csr_matrix(x.shape)\n            return x\n        else:\n            return np.digitize(x, bins) if len(bins) else [0]*len(x)\n\n    def transform(self, c):\n        if sp.issparse(c):\n            return self.digitize(c, self.points)\n        elif c.size:\n            return np.where(np.isnan(c), np.NaN, self.digitize(c, self.points))\n        else:\n            return np.array([], dtype=int)\n\n    @staticmethod\n    def _fmt_interval(low, high, formatter):\n        assert low is not None or high is not None\n        assert low is None or high is None or low < high\n        if low is None or np.isinf(low):\n            return f\"< {formatter(high)}\"\n        if high is None or np.isinf(high):\n            return f\"≥ {formatter(low)}\"\n        return f\"{formatter(low)} - {formatter(high)}\"\n\n    @classmethod\n    def create_discretized_var(cls, var, points):\n        def fmt(val):\n            sval = var.str_val(val)\n            # For decimal numbers, remove trailing 0's and . if no decimals left\n            if re.match(r\"^\\d+\\.\\d+\", sval):\n                return sval.rstrip(\"0\").rstrip(\".\")\n            return sval\n\n        lpoints = list(points)\n        if lpoints:\n            values = [\n                cls._fmt_interval(low, high, fmt)\n                for low, high in zip([-np.inf] + lpoints, lpoints + [np.inf])]\n            to_sql = BinSql(var, lpoints)\n        else:\n            values = [\"single_value\"]\n            to_sql = SingleValueSql(values[0])\n\n        dvar = DiscreteVariable(name=var.name, values=values,\n                                compute_value=cls(var, points),\n                                sparse=var.sparse)\n        dvar.source_variable = var\n        dvar.to_sql = to_sql\n        return dvar\n\n\nclass BinSql:\n    def __init__(self, var, points):\n        self.var = var\n        self.points = points\n\n    def __call__(self):\n        return 'width_bucket(%s, ARRAY%s::double precision[])' % (\n            self.var.to_sql(), str(self.points))\n\n\nclass SingleValueSql:\n    def __init__(self, value):\n        self.value = value\n\n    def __call__(self):\n        return \"'%s'\" % self.value\n\n\nclass Discretization(Reprable):\n    \"\"\"Abstract base class for discretization classes.\"\"\"\n    def __call__(self, data, variable):\n        \"\"\"\n        Compute discretization of the given variable on the given data.\n        Return a new variable with the appropriate domain\n        (:obj:`Orange.data.DiscreteVariable.values`) and transformer\n        (:obj:`Orange.data.Variable.compute_value`).\n        \"\"\"\n        raise NotImplementedError(\n            \"Subclasses of 'Discretization' need to implement \"\n            \"the call operator\")\n\n\nclass EqualFreq(Discretization):\n    \"\"\"Discretization into bins with approximately equal number of data\n    instances.\n\n    .. attribute:: n\n\n        Number of bins (default: 4). The actual number may be lower if the\n        variable has less than n distinct values.\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute):\n        if type(data) == SqlTable:\n            att = attribute.to_sql()\n            quantiles = [(i + 1) / self.n for i in range(self.n - 1)]\n            query = data._sql_query(\n                ['quantile(%s, ARRAY%s)' % (att, str(quantiles))],\n                use_time_sample=1000)\n            with data._execute_sql_query(query) as cur:\n                points = sorted(set(cur.fetchone()[0]))\n        else:\n            d = distribution.get_distribution(data, attribute)\n            points = _discretize.split_eq_freq(d, self.n)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\nclass EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = np.nanmin(values), np.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]\n\n\n# noinspection PyPep8Naming\nclass EntropyMDL(Discretization):\n    \"\"\"\n    Discretization into bins inferred by recursively splitting the values to\n    minimize the class-entropy. The procedure stops when further splits would\n    decrease the entropy for less than the corresponding increase of minimal\n    description length (MDL). [FayyadIrani93].\n\n    If there are no suitable cut-off points, the procedure returns a single bin,\n    which means that the new feature is constant and can be removed.\n\n    .. attribute:: force\n\n        Induce at least one cut-off point, even when its information\n        gain is lower than MDL (default: False).\n\n    \"\"\"\n    def __init__(self, force=False):\n        self.force = force\n\n    def __call__(self, data, attribute):\n        cont = contingency.get_contingency(data, attribute)\n        values, I = cont.values, cont.counts.T\n        cut_ind = np.array(self._entropy_discretize_sorted(I, self.force))\n        if len(cut_ind) > 0:\n            # \"the midpoint between each successive pair of examples\" (FI p.1)\n            points = (values[cut_ind] + values[cut_ind - 1]) / 2.\n        else:\n            points = []\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    @classmethod\n    def _normalize(cls, X, axis=None, out=None):\n        \"\"\"\n        Normalize `X` array so it sums to 1.0 over the `axis`.\n\n        Parameters\n        ----------\n        X : array\n            Array to normalize.\n        axis : optional int\n            Axis over which the resulting array sums to 1.\n        out : optional array\n            Output array of the same shape as X.\n        \"\"\"\n        X = np.asarray(X, dtype=float)\n        scale = np.sum(X, axis=axis, keepdims=True)\n        if out is None:\n            return X / scale\n        else:\n            if out is not X:\n                assert out.shape == X.shape\n                out[:] = X\n            out /= scale\n            return out\n\n    @classmethod\n    def _entropy_normalized(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution array `D`.\n\n        `D` must be a distribution (i.e. sum to 1.0 over `axis`)\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        # req: (np.sum(D, axis=axis) >= 0).all()\n        # req: (np.sum(D, axis=axis) <= 1).all()\n        # req: np.all(np.abs(np.sum(D, axis=axis) - 1) < 1e-9)\n\n        D = np.asarray(D)\n        Dc = np.clip(D, np.finfo(D.dtype).eps, 1.0)\n        return - np.sum(D * np.log2(Dc), axis=axis)\n\n    @classmethod\n    def _entropy(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution `D`.\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        D = cls._normalize(D, axis=axis)\n        return cls._entropy_normalized(D, axis=axis)\n\n    @classmethod\n    def _entropy1(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D)\n        return _discretize.entropy_normalized1(D)\n\n    @classmethod\n    def _entropy2(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D, axis=1)\n        return _discretize.entropy_normalized2(D)\n\n    @classmethod\n    def _entropy_cuts_sorted(cls, CS):\n        \"\"\"\n        Return the class information entropy induced by partitioning\n        the `CS` distribution at all N-1 candidate cut points.\n\n        Parameters\n        ----------\n        CS : (N, K) array of class distributions.\n        \"\"\"\n        CS = np.asarray(CS)\n        # |--|-------|--------|\n        #  S1    ^       S2\n        # S1 contains all points which are <= to cut point\n        # Cumulative distributions for S1 and S2 (left right set)\n        # i.e. a cut at index i separates the CS into S1Dist[i] and S2Dist[i]\n        S1Dist = np.cumsum(CS, axis=0)[:-1]\n        S2Dist = np.cumsum(CS[::-1], axis=0)[-2::-1]\n\n        # Entropy of S1[i] and S2[i] sets\n        ES1 = cls._entropy2(S1Dist)\n        ES2 = cls._entropy2(S2Dist)\n\n        # Number of cases in S1[i] and S2[i] sets\n        S1_count = np.sum(S1Dist, axis=1)\n        S2_count = np.sum(S2Dist, axis=1)\n\n        # Number of all cases\n        S_count = np.sum(CS)\n\n        ES1w = ES1 * S1_count / S_count\n        ES2w = ES2 * S2_count / S_count\n\n        # E(A, T; S) Class information entropy of the partition S\n        E = ES1w + ES2w\n\n        return E, ES1, ES2\n\n    @classmethod\n    def _entropy_discretize_sorted(cls, C, force=False):\n        \"\"\"\n        Entropy discretization on a sorted C.\n\n        :param C: (N, K) array of class distributions.\n\n        \"\"\"\n        E, ES1, ES2 = cls._entropy_cuts_sorted(C)\n        # TODO: Also get the left right distribution counts from\n        # entropy_cuts_sorted,\n\n        # Note the + 1\n        if len(E) == 0:\n            return []\n        cut_index = np.argmin(E) + 1\n\n        # Distribution of classed in S1, S2 and S\n        S1_c = np.sum(C[:cut_index], axis=0)\n        S2_c = np.sum(C[cut_index:], axis=0)\n        S_c = S1_c + S2_c\n\n        ES = cls._entropy1(np.sum(C, axis=0))\n        ES1, ES2 = ES1[cut_index - 1], ES2[cut_index - 1]\n\n        # Information gain of the best split\n        Gain = ES - E[cut_index - 1]\n        # Number of different classes in S, S1 and S2\n        k = float(np.sum(S_c > 0))\n        k1 = float(np.sum(S1_c > 0))\n        k2 = float(np.sum(S2_c > 0))\n\n        assert k > 0\n        delta = np.log2(3 ** k - 2) - (k * ES - k1 * ES1 - k2 * ES2)\n        N = float(np.sum(S_c))\n\n        if Gain > np.log2(N - 1) / N + delta / N:\n            # Accept the cut point and recursively split the subsets.\n            left, right = [], []\n            if k1 > 1 and cut_index > 1:\n                left = cls._entropy_discretize_sorted(C[:cut_index, :])\n            if k2 > 1 and cut_index < len(C) - 1:\n                right = cls._entropy_discretize_sorted(C[cut_index:, :])\n            return left + [cut_index] + [i + cut_index for i in right]\n        elif force:\n            return [cut_index]\n        else:\n            return []\n\n\nclass DomainDiscretizer(_RefuseDataInConstructor, Reprable):\n    \"\"\"Discretizes all continuous features in the data.\n\n    .. attribute:: method\n\n        Feature discretization method (instance of\n        :obj:`Orange.preprocess.Discretization`). If `None` (default),\n        :class:`Orange.preprocess.EqualFreq` with 4 intervals is\n        used.\n\n    .. attribute:: clean\n\n        If `True`, features discretized into a single interval constant are\n        removed. This is useful for discretization methods that infer the\n        number of intervals from the data, such as\n        :class:`Orange.preprocess.EntropyMDL` (default: `True`).\n\n    .. attribute:: discretize_class\n\n        Determines whether a target is also discretized if it is continuous.\n        (default: `False`)\n    \"\"\"\n    def __init__(self, discretize_class=False, method=None, clean=True,\n                 fixed=None):\n        self.discretize_class = discretize_class\n        self.method = method\n        self.clean = clean\n        self.fixed = fixed\n\n    def __call__(self, data, fixed=None):\n        \"\"\"\n        Compute and return discretized domain.\n\n        :param data: Data to discretize.\n        \"\"\"\n\n        def transform_list(s, fixed=None):\n            new_vars = []\n            for var in s:\n                if var.is_continuous:\n                    if fixed and var.name in fixed.keys():\n                        nv = method(data, var, fixed)\n                    else:\n                        nv = method(data, var)\n                    if not self.clean or len(nv.values) > 1:\n                        new_vars.append(nv)\n                else:\n                    new_vars.append(var)\n            return new_vars\n        if self.method is None:\n            method = EqualFreq(n=4)\n        else:\n            method = self.method\n        domain = data.domain\n        new_attrs = transform_list(domain.attributes, fixed or self.fixed)\n        if self.discretize_class:\n            new_classes = transform_list(domain.class_vars)\n        else:\n            new_classes = domain.class_vars\n        return Domain(new_attrs, new_classes)\n",
            "new_file_content": "import re\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.data import DiscreteVariable, Domain\nfrom Orange.data.sql.table import SqlTable\nfrom Orange.preprocess.util import _RefuseDataInConstructor\nfrom Orange.statistics import distribution, contingency, util as ut\nfrom Orange.statistics.basic_stats import BasicStats\nfrom Orange.util import Reprable\nfrom .transformation import Transformation\nfrom . import _discretize\n\n__all__ = [\"EqualFreq\", \"EqualWidth\", \"EntropyMDL\", \"DomainDiscretizer\"]\n\n\nclass Discretizer(Transformation):\n    \"\"\"Value transformer that returns an index of the bin for the given value.\n    \"\"\"\n    def __init__(self, variable, points):\n        super().__init__(variable)\n        self.points = points\n\n    @staticmethod\n    def digitize(x, bins):\n        if sp.issparse(x):\n            if len(bins):\n                x.data = np.digitize(x.data, bins)\n            else:\n                x = sp.csr_matrix(x.shape)\n            return x\n        else:\n            return np.digitize(x, bins) if len(bins) else [0]*len(x)\n\n    def transform(self, c):\n        if sp.issparse(c):\n            return self.digitize(c, self.points)\n        elif c.size:\n            return np.where(np.isnan(c), np.NaN, self.digitize(c, self.points))\n        else:\n            return np.array([], dtype=int)\n\n    @staticmethod\n    def _fmt_interval(low, high, formatter):\n        assert low is not None or high is not None\n        assert low is None or high is None or low < high\n        if low is None or np.isinf(low):\n            return f\"< {formatter(high)}\"\n        if high is None or np.isinf(high):\n            return f\"≥ {formatter(low)}\"\n        return f\"{formatter(low)} - {formatter(high)}\"\n\n    @classmethod\n    def create_discretized_var(cls, var, points):\n        def fmt(val):\n            sval = var.str_val(val)\n            # For decimal numbers, remove trailing 0's and . if no decimals left\n            if re.match(r\"^\\d+\\.\\d+\", sval):\n                return sval.rstrip(\"0\").rstrip(\".\")\n            return sval\n\n        lpoints = list(points)\n        if lpoints:\n            values = [\n                cls._fmt_interval(low, high, fmt)\n                for low, high in zip([-np.inf] + lpoints, lpoints + [np.inf])]\n            to_sql = BinSql(var, lpoints)\n        else:\n            values = [\"single_value\"]\n            to_sql = SingleValueSql(values[0])\n\n        dvar = DiscreteVariable(name=var.name, values=values,\n                                compute_value=cls(var, points),\n                                sparse=var.sparse)\n        dvar.source_variable = var\n        dvar.to_sql = to_sql\n        return dvar\n\n\nclass BinSql:\n    def __init__(self, var, points):\n        self.var = var\n        self.points = points\n\n    def __call__(self):\n        return 'width_bucket(%s, ARRAY%s::double precision[])' % (\n            self.var.to_sql(), str(self.points))\n\n\nclass SingleValueSql:\n    def __init__(self, value):\n        self.value = value\n\n    def __call__(self):\n        return \"'%s'\" % self.value\n\n\nclass Discretization(Reprable):\n    \"\"\"Abstract base class for discretization classes.\"\"\"\n    def __call__(self, data, variable):\n        \"\"\"\n        Compute discretization of the given variable on the given data.\n        Return a new variable with the appropriate domain\n        (:obj:`Orange.data.DiscreteVariable.values`) and transformer\n        (:obj:`Orange.data.Variable.compute_value`).\n        \"\"\"\n        raise NotImplementedError(\n            \"Subclasses of 'Discretization' need to implement \"\n            \"the call operator\")\n\n\nclass EqualFreq(Discretization):\n    \"\"\"Discretization into bins with approximately equal number of data\n    instances.\n\n    .. attribute:: n\n\n        Number of bins (default: 4). The actual number may be lower if the\n        variable has less than n distinct values.\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute):\n        if type(data) == SqlTable:\n            att = attribute.to_sql()\n            quantiles = [(i + 1) / self.n for i in range(self.n - 1)]\n            query = data._sql_query(\n                ['quantile(%s, ARRAY%s)' % (att, str(quantiles))],\n                use_time_sample=1000)\n            with data._execute_sql_query(query) as cur:\n                points = sorted(set(cur.fetchone()[0]))\n        else:\n            d = distribution.get_distribution(data, attribute)\n            points = _discretize.split_eq_freq(d, self.n)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\nclass EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = ut.nanmin(values), ut.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]\n\n\n# noinspection PyPep8Naming\nclass EntropyMDL(Discretization):\n    \"\"\"\n    Discretization into bins inferred by recursively splitting the values to\n    minimize the class-entropy. The procedure stops when further splits would\n    decrease the entropy for less than the corresponding increase of minimal\n    description length (MDL). [FayyadIrani93].\n\n    If there are no suitable cut-off points, the procedure returns a single bin,\n    which means that the new feature is constant and can be removed.\n\n    .. attribute:: force\n\n        Induce at least one cut-off point, even when its information\n        gain is lower than MDL (default: False).\n\n    \"\"\"\n    def __init__(self, force=False):\n        self.force = force\n\n    def __call__(self, data, attribute):\n        cont = contingency.get_contingency(data, attribute)\n        values, I = cont.values, cont.counts.T\n        cut_ind = np.array(self._entropy_discretize_sorted(I, self.force))\n        if len(cut_ind) > 0:\n            # \"the midpoint between each successive pair of examples\" (FI p.1)\n            points = (values[cut_ind] + values[cut_ind - 1]) / 2.\n        else:\n            points = []\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    @classmethod\n    def _normalize(cls, X, axis=None, out=None):\n        \"\"\"\n        Normalize `X` array so it sums to 1.0 over the `axis`.\n\n        Parameters\n        ----------\n        X : array\n            Array to normalize.\n        axis : optional int\n            Axis over which the resulting array sums to 1.\n        out : optional array\n            Output array of the same shape as X.\n        \"\"\"\n        X = np.asarray(X, dtype=float)\n        scale = np.sum(X, axis=axis, keepdims=True)\n        if out is None:\n            return X / scale\n        else:\n            if out is not X:\n                assert out.shape == X.shape\n                out[:] = X\n            out /= scale\n            return out\n\n    @classmethod\n    def _entropy_normalized(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution array `D`.\n\n        `D` must be a distribution (i.e. sum to 1.0 over `axis`)\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        # req: (np.sum(D, axis=axis) >= 0).all()\n        # req: (np.sum(D, axis=axis) <= 1).all()\n        # req: np.all(np.abs(np.sum(D, axis=axis) - 1) < 1e-9)\n\n        D = np.asarray(D)\n        Dc = np.clip(D, np.finfo(D.dtype).eps, 1.0)\n        return - np.sum(D * np.log2(Dc), axis=axis)\n\n    @classmethod\n    def _entropy(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution `D`.\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        D = cls._normalize(D, axis=axis)\n        return cls._entropy_normalized(D, axis=axis)\n\n    @classmethod\n    def _entropy1(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D)\n        return _discretize.entropy_normalized1(D)\n\n    @classmethod\n    def _entropy2(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D, axis=1)\n        return _discretize.entropy_normalized2(D)\n\n    @classmethod\n    def _entropy_cuts_sorted(cls, CS):\n        \"\"\"\n        Return the class information entropy induced by partitioning\n        the `CS` distribution at all N-1 candidate cut points.\n\n        Parameters\n        ----------\n        CS : (N, K) array of class distributions.\n        \"\"\"\n        CS = np.asarray(CS)\n        # |--|-------|--------|\n        #  S1    ^       S2\n        # S1 contains all points which are <= to cut point\n        # Cumulative distributions for S1 and S2 (left right set)\n        # i.e. a cut at index i separates the CS into S1Dist[i] and S2Dist[i]\n        S1Dist = np.cumsum(CS, axis=0)[:-1]\n        S2Dist = np.cumsum(CS[::-1], axis=0)[-2::-1]\n\n        # Entropy of S1[i] and S2[i] sets\n        ES1 = cls._entropy2(S1Dist)\n        ES2 = cls._entropy2(S2Dist)\n\n        # Number of cases in S1[i] and S2[i] sets\n        S1_count = np.sum(S1Dist, axis=1)\n        S2_count = np.sum(S2Dist, axis=1)\n\n        # Number of all cases\n        S_count = np.sum(CS)\n\n        ES1w = ES1 * S1_count / S_count\n        ES2w = ES2 * S2_count / S_count\n\n        # E(A, T; S) Class information entropy of the partition S\n        E = ES1w + ES2w\n\n        return E, ES1, ES2\n\n    @classmethod\n    def _entropy_discretize_sorted(cls, C, force=False):\n        \"\"\"\n        Entropy discretization on a sorted C.\n\n        :param C: (N, K) array of class distributions.\n\n        \"\"\"\n        E, ES1, ES2 = cls._entropy_cuts_sorted(C)\n        # TODO: Also get the left right distribution counts from\n        # entropy_cuts_sorted,\n\n        # Note the + 1\n        if len(E) == 0:\n            return []\n        cut_index = np.argmin(E) + 1\n\n        # Distribution of classed in S1, S2 and S\n        S1_c = np.sum(C[:cut_index], axis=0)\n        S2_c = np.sum(C[cut_index:], axis=0)\n        S_c = S1_c + S2_c\n\n        ES = cls._entropy1(np.sum(C, axis=0))\n        ES1, ES2 = ES1[cut_index - 1], ES2[cut_index - 1]\n\n        # Information gain of the best split\n        Gain = ES - E[cut_index - 1]\n        # Number of different classes in S, S1 and S2\n        k = float(np.sum(S_c > 0))\n        k1 = float(np.sum(S1_c > 0))\n        k2 = float(np.sum(S2_c > 0))\n\n        assert k > 0\n        delta = np.log2(3 ** k - 2) - (k * ES - k1 * ES1 - k2 * ES2)\n        N = float(np.sum(S_c))\n\n        if Gain > np.log2(N - 1) / N + delta / N:\n            # Accept the cut point and recursively split the subsets.\n            left, right = [], []\n            if k1 > 1 and cut_index > 1:\n                left = cls._entropy_discretize_sorted(C[:cut_index, :])\n            if k2 > 1 and cut_index < len(C) - 1:\n                right = cls._entropy_discretize_sorted(C[cut_index:, :])\n            return left + [cut_index] + [i + cut_index for i in right]\n        elif force:\n            return [cut_index]\n        else:\n            return []\n\n\nclass DomainDiscretizer(_RefuseDataInConstructor, Reprable):\n    \"\"\"Discretizes all continuous features in the data.\n\n    .. attribute:: method\n\n        Feature discretization method (instance of\n        :obj:`Orange.preprocess.Discretization`). If `None` (default),\n        :class:`Orange.preprocess.EqualFreq` with 4 intervals is\n        used.\n\n    .. attribute:: clean\n\n        If `True`, features discretized into a single interval constant are\n        removed. This is useful for discretization methods that infer the\n        number of intervals from the data, such as\n        :class:`Orange.preprocess.EntropyMDL` (default: `True`).\n\n    .. attribute:: discretize_class\n\n        Determines whether a target is also discretized if it is continuous.\n        (default: `False`)\n    \"\"\"\n    def __init__(self, discretize_class=False, method=None, clean=True,\n                 fixed=None):\n        self.discretize_class = discretize_class\n        self.method = method\n        self.clean = clean\n        self.fixed = fixed\n\n    def __call__(self, data, fixed=None):\n        \"\"\"\n        Compute and return discretized domain.\n\n        :param data: Data to discretize.\n        \"\"\"\n\n        def transform_list(s, fixed=None):\n            new_vars = []\n            for var in s:\n                if var.is_continuous:\n                    if fixed and var.name in fixed.keys():\n                        nv = method(data, var, fixed)\n                    else:\n                        nv = method(data, var)\n                    if not self.clean or len(nv.values) > 1:\n                        new_vars.append(nv)\n                else:\n                    new_vars.append(var)\n            return new_vars\n        if self.method is None:\n            method = EqualFreq(n=4)\n        else:\n            method = self.method\n        domain = data.domain\n        new_attrs = transform_list(domain.attributes, fixed or self.fixed)\n        if self.discretize_class:\n            new_classes = transform_list(domain.class_vars)\n        else:\n            new_classes = domain.class_vars\n        return Domain(new_attrs, new_classes)\n",
            "header": {
                "file": {
                    "path": "Orange/preprocess/discretize.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "26c753c86",
                "new_commit_hash": "33c106a19",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/preprocess/discretize.py"
            },
            "plus_file": {
                "path": "b/Orange/preprocess/discretize.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 6,
                            "length": 7
                        },
                        "new_range": {
                            "start": 6,
                            "length": 7
                        },
                        "section": "import scipy.sparse as sp"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from Orange.data import DiscreteVariable, Domain",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.data.sql.table import SqlTable",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.preprocess.util import _RefuseDataInConstructor",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.statistics import distribution, contingency",
                                "type": "deleted"
                            },
                            {
                                "content": "from Orange.statistics import distribution, contingency, util as ut",
                                "type": "added"
                            },
                            {
                                "content": "from Orange.statistics.basic_stats import BasicStats",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.util import Reprable",
                                "type": "context"
                            },
                            {
                                "content": "from .transformation import Transformation",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/preprocess/discretize.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.statistics import distribution, contingency, util as ut",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 9,
                            "end_lineno": 9,
                            "parent": null
                        }
                    ],
                    "deleted_entities": [
                        {
                            "file_name": "Orange/preprocess/discretize.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.statistics import distribution, contingency",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 9,
                            "end_lineno": 9,
                            "parent": null
                        }
                    ]
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 160,
                            "length": 7
                        },
                        "new_range": {
                            "start": 160,
                            "length": 7
                        },
                        "section": "class EqualWidth(Discretization):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "            else:",
                                "type": "context"
                            },
                            {
                                "content": "                values = data[:, attribute]",
                                "type": "context"
                            },
                            {
                                "content": "                values = values.X if values.X.size else values.Y",
                                "type": "context"
                            },
                            {
                                "content": "                min, max = np.nanmin(values), np.nanmax(values)",
                                "type": "deleted"
                            },
                            {
                                "content": "                min, max = ut.nanmin(values), ut.nanmax(values)",
                                "type": "added"
                            },
                            {
                                "content": "                points = self._split_eq_width(min, max)",
                                "type": "context"
                            },
                            {
                                "content": "        return Discretizer.create_discretized_var(",
                                "type": "context"
                            },
                            {
                                "content": "            data.domain[attribute], points)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/preprocess/discretize.py",
                            "type": "class",
                            "name": "EqualWidth",
                            "content": "class EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = np.nanmin(values), np.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 141,
                            "end_lineno": 172,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/preprocess/discretize.py",
                            "type": "method",
                            "name": "EqualWidth.__call__",
                            "content": "class EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = np.nanmin(values), np.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 152,
                            "end_lineno": 166,
                            "parent": {
                                "file_name": "Orange/preprocess/discretize.py",
                                "type": "class",
                                "name": "EqualWidth",
                                "content": "class EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = np.nanmin(values), np.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 141,
                                "end_lineno": 172,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport random\nfrom unittest import TestCase\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.preprocess import discretize, Discretize\nfrom Orange import data\nfrom Orange.data import Table, Instance, Domain, ContinuousVariable, DiscreteVariable\n\n\n# noinspection PyPep8Naming\nclass TestEqualFreq(TestCase):\n    def test_equifreq_with_too_few_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_equifreq_100_to_4(self):\n        X = np.arange(100).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_equifreq_with_k_instances(self):\n        X = np.array([[1], [2], [3], [4]])\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [1.5, 2.5, 3.5])\n\n\n# noinspection PyPep8Naming\nclass TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    def test_equalwidth_100_to_4(self):\n        X = np.arange(101).reshape((101, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n\n# noinspection PyPep8Naming\nclass TestEntropyMDL(TestCase):\n    def test_entropy_with_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_entropy_with_two_values_useless(self):\n        X = np.array([0] * 50 + [1] * 50).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 50 + [0] * 25)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy_constant(self):\n        X = np.zeros((100, 1))\n        domain = Domain([ContinuousVariable('v1')],\n                        [DiscreteVariable('c1', values=[\"1\"])])\n        table = data.Table(domain, X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy(self):\n        X = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25\n                    ).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 75)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizer(TestCase):\n    def setUp(self):\n        self.var = data.ContinuousVariable(\"x\", number_of_decimals=1)\n\n    def test_create_discretized_var(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertIsInstance(dvar.compute_value,\n                              discretize.Discretizer)\n        self.assertEqual(dvar.compute_value.points, [1, 2, 3])\n\n\n    def test_create_discretized_var_formatting(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertEqual(dvar.values, [\"< 1\", \"1 - 2\", \"2 - 3\", \"≥ 3\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10])\n        self.assertEqual(dvar.values, [\"< 10\", \"≥ 10\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10.1234])\n        self.assertEqual(dvar.values, [\"< 10.1\", \"≥ 10.1\"])\n\n        self.var.number_of_decimals = 3\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [5, 10.1234])\n        self.assertEqual(dvar.values, [\"< 5\", \"5 - 10.123\", \"≥ 10.123\"])\n\n    def test_discretizer_computation(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5])\n        np.testing.assert_equal(dvar.compute_value.transform(X), np.floor(X))\n\n    def test_discretizer_computation_sparse(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        self.assertEqual((dvar.compute_value.transform(X) != np.floor(X)).nnz, 0)\n\n    def test_discretizer_computation_sparse_no_points(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        empty = sp.csr_matrix(X.shape)\n        self.assertEqual((dvar.compute_value.transform(X) != empty).nnz, 0)\n\n    def test_transform(self):\n        table = data.Table('iris')\n        table2 = Discretize()(table)\n        ins = data.Instance(table2.domain, table[0])\n        table3 = data.Table(table2.domain, table[:10])\n        self.assertEqual(ins, table3[0])\n\n    def test_remove_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=True)\n        new_table = discretize(table)\n        self.assertNotEqual(len(table.domain.attributes),\n                            len(new_table.domain.attributes))\n\n    def test_keep_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertEqual(len(table.domain.attributes),\n                         len(new_table.domain.attributes))\n\n    def test_discretize_class(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.class_vars[0],\n                      new_table.domain.class_vars[0])\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n        discretize = Discretize(remove_const=False, discretize_classes=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.class_vars[0], DiscreteVariable)\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n    def test_discretize_metas(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.metas[0],\n                      new_table.domain.metas[0])\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n        discretize = Discretize(remove_const=False, discretize_metas=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.metas[0], DiscreteVariable)\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizeTable(TestCase):\n    @classmethod\n    def setUpClass(cls):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        cls.table_no_class = data.Table(X)\n        cls.table_class = data.Table(X, X1)\n\n    def test_discretize_exclude_constant(self):\n        dom = discretize.DomainDiscretizer()(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n        dom = discretize.DomainDiscretizer(clean=False)(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 3)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertEqual(dom[2].compute_value.points, [])\n\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_discretize_class(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n        dom = discretize.DomainDiscretizer(discretize_class=True)\n        dom = dom(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n    def test_method(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom[1].values), 4)\n\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2))\n        dom = dom(self.table_class)\n        self.assertEqual(len(dom[1].values), 2)\n\n    def test_fixed(self):\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2),\n                                           fixed={\"Feature 2\": [1, 11]})\n        dom = dom(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [6])\n\n    def test_leave_discrete(self):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.ContinuousVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.DiscreteVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n\nclass TestInstanceConversion(TestCase):\n    def test_single_instance(self):\n        iris = Table(\"iris\")\n        inst = Instance(iris.domain, [5.2, 3.8, 1.4, 0.5, \"Iris-virginica\"])\n        d_iris = Discretize()(iris)\n        Instance(d_iris.domain, inst)\n",
            "new_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport random\nfrom unittest import TestCase\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.preprocess import discretize, Discretize\nfrom Orange import data\nfrom Orange.data import Table, Instance, Domain, ContinuousVariable, DiscreteVariable\n\n\n# noinspection PyPep8Naming\nfrom Orange.widgets.tests.utils import table_dense_sparse\n\n\nclass TestEqualFreq(TestCase):\n    def test_equifreq_with_too_few_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_equifreq_100_to_4(self):\n        X = np.arange(100).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_equifreq_with_k_instances(self):\n        X = np.array([[1], [2], [3], [4]])\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [1.5, 2.5, 3.5])\n\n\n# noinspection PyPep8Naming\nclass TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    @table_dense_sparse\n    def test_equalwidth_100_to_4(self, prepare_table):\n        X = np.arange(101).reshape((101, 1))\n        table = prepare_table(data.Table(X))\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n\n# noinspection PyPep8Naming\nclass TestEntropyMDL(TestCase):\n    def test_entropy_with_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_entropy_with_two_values_useless(self):\n        X = np.array([0] * 50 + [1] * 50).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 50 + [0] * 25)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy_constant(self):\n        X = np.zeros((100, 1))\n        domain = Domain([ContinuousVariable('v1')],\n                        [DiscreteVariable('c1', values=[\"1\"])])\n        table = data.Table(domain, X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy(self):\n        X = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25\n                    ).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 75)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizer(TestCase):\n    def setUp(self):\n        self.var = data.ContinuousVariable(\"x\", number_of_decimals=1)\n\n    def test_create_discretized_var(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertIsInstance(dvar.compute_value,\n                              discretize.Discretizer)\n        self.assertEqual(dvar.compute_value.points, [1, 2, 3])\n\n\n    def test_create_discretized_var_formatting(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertEqual(dvar.values, [\"< 1\", \"1 - 2\", \"2 - 3\", \"≥ 3\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10])\n        self.assertEqual(dvar.values, [\"< 10\", \"≥ 10\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10.1234])\n        self.assertEqual(dvar.values, [\"< 10.1\", \"≥ 10.1\"])\n\n        self.var.number_of_decimals = 3\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [5, 10.1234])\n        self.assertEqual(dvar.values, [\"< 5\", \"5 - 10.123\", \"≥ 10.123\"])\n\n    def test_discretizer_computation(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5])\n        np.testing.assert_equal(dvar.compute_value.transform(X), np.floor(X))\n\n    def test_discretizer_computation_sparse(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        self.assertEqual((dvar.compute_value.transform(X) != np.floor(X)).nnz, 0)\n\n    def test_discretizer_computation_sparse_no_points(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        empty = sp.csr_matrix(X.shape)\n        self.assertEqual((dvar.compute_value.transform(X) != empty).nnz, 0)\n\n    def test_transform(self):\n        table = data.Table('iris')\n        table2 = Discretize()(table)\n        ins = data.Instance(table2.domain, table[0])\n        table3 = data.Table(table2.domain, table[:10])\n        self.assertEqual(ins, table3[0])\n\n    def test_remove_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=True)\n        new_table = discretize(table)\n        self.assertNotEqual(len(table.domain.attributes),\n                            len(new_table.domain.attributes))\n\n    def test_keep_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertEqual(len(table.domain.attributes),\n                         len(new_table.domain.attributes))\n\n    def test_discretize_class(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.class_vars[0],\n                      new_table.domain.class_vars[0])\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n        discretize = Discretize(remove_const=False, discretize_classes=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.class_vars[0], DiscreteVariable)\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n    def test_discretize_metas(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.metas[0],\n                      new_table.domain.metas[0])\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n        discretize = Discretize(remove_const=False, discretize_metas=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.metas[0], DiscreteVariable)\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizeTable(TestCase):\n    @classmethod\n    def setUpClass(cls):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        cls.table_no_class = data.Table(X)\n        cls.table_class = data.Table(X, X1)\n\n    def test_discretize_exclude_constant(self):\n        dom = discretize.DomainDiscretizer()(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n        dom = discretize.DomainDiscretizer(clean=False)(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 3)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertEqual(dom[2].compute_value.points, [])\n\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_discretize_class(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n        dom = discretize.DomainDiscretizer(discretize_class=True)\n        dom = dom(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n    def test_method(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom[1].values), 4)\n\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2))\n        dom = dom(self.table_class)\n        self.assertEqual(len(dom[1].values), 2)\n\n    def test_fixed(self):\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2),\n                                           fixed={\"Feature 2\": [1, 11]})\n        dom = dom(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [6])\n\n    def test_leave_discrete(self):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.ContinuousVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.DiscreteVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n\nclass TestInstanceConversion(TestCase):\n    def test_single_instance(self):\n        iris = Table(\"iris\")\n        inst = Instance(iris.domain, [5.2, 3.8, 1.4, 0.5, \"Iris-virginica\"])\n        d_iris = Discretize()(iris)\n        Instance(d_iris.domain, inst)\n",
            "header": {
                "file": {
                    "path": "Orange/tests/test_discretize.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "9d35a0475",
                "new_commit_hash": "ff755cc58",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/tests/test_discretize.py"
            },
            "plus_file": {
                "path": "b/Orange/tests/test_discretize.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 13,
                            "length": 6
                        },
                        "new_range": {
                            "start": 13,
                            "length": 9
                        },
                        "section": "from Orange.data import Table, Instance, Domain, ContinuousVariable, DiscreteVar"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "# noinspection PyPep8Naming",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.tests.utils import table_dense_sparse",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "class TestEqualFreq(TestCase):",
                                "type": "context"
                            },
                            {
                                "content": "    def test_equifreq_with_too_few_values(self):",
                                "type": "context"
                            },
                            {
                                "content": "        s = [0] * 50 + [1] * 50",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/tests/test_discretize.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.widgets.tests.utils import table_dense_sparse",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 16,
                            "end_lineno": 16,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 53,
                            "length": 9
                        },
                        "new_range": {
                            "start": 56,
                            "length": 10
                        },
                        "section": "class TestEqualWidth(TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertEqual(len(dvar.values), 4)",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    def test_equalwidth_100_to_4(self):",
                                "type": "deleted"
                            },
                            {
                                "content": "    @table_dense_sparse",
                                "type": "added"
                            },
                            {
                                "content": "    def test_equalwidth_100_to_4(self, prepare_table):",
                                "type": "added"
                            },
                            {
                                "content": "        X = np.arange(101).reshape((101, 1))",
                                "type": "context"
                            },
                            {
                                "content": "        table = data.Table(X)",
                                "type": "deleted"
                            },
                            {
                                "content": "        table = prepare_table(data.Table(X))",
                                "type": "added"
                            },
                            {
                                "content": "        disc = discretize.EqualWidth(n=4)",
                                "type": "context"
                            },
                            {
                                "content": "        dvar = disc(table, table.domain[0])",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(len(dvar.values), 4)",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/tests/test_discretize.py",
                            "type": "class",
                            "name": "TestEqualWidth",
                            "content": "class TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    def test_equalwidth_100_to_4(self):\n        X = np.arange(101).reshape((101, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 45,
                            "end_lineno": 70,
                            "parent": null
                        },
                        {
                            "file_name": "Orange/tests/test_discretize.py",
                            "type": "method",
                            "name": "TestEqualWidth.test_equalwidth_100_to_4",
                            "content": "class TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    def test_equalwidth_100_to_4(self):\n        X = np.arange(101).reshape((101, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 56,
                            "end_lineno": 62,
                            "parent": {
                                "file_name": "Orange/tests/test_discretize.py",
                                "type": "class",
                                "name": "TestEqualWidth",
                                "content": "class TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    def test_equalwidth_100_to_4(self):\n        X = np.arange(101).reshape((101, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 45,
                                "end_lineno": 70,
                                "parent": null
                            }
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring,protected-access\n\nfrom Orange.data import Table, Domain, DiscreteVariable\nfrom Orange.data.table import dataset_dirs\nfrom Orange.tests import test_dirname\nfrom Orange.widgets.tests.base import WidgetTest, datasets\nfrom Orange.widgets.visualize.owdistributions import OWDistributions\n\n\nclass TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n",
            "new_file_content": "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring,protected-access\n\nfrom Orange.data import Table, Domain, DiscreteVariable\nfrom Orange.data.table import dataset_dirs\nfrom Orange.tests import test_dirname\nfrom Orange.widgets.tests.base import WidgetTest, datasets\nfrom Orange.widgets.tests.utils import table_dense_sparse\nfrom Orange.widgets.visualize.owdistributions import OWDistributions\n\n\nclass TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n\n    @table_dense_sparse\n    def test_binning_numeric_variables(self, prepare_table):\n        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"\n        data = prepare_table(self.iris)\n        self.send_signal(self.widget.Inputs.data, data)\n\n        self.widget.controls.disc_cont.setChecked(True)\n        self.wait_until_stop_blocking()\n\n        self.widget.controls.disc_cont.setChecked(False)\n        self.wait_until_stop_blocking()\n",
            "header": {
                "file": {
                    "path": "Orange/widgets/visualize/tests/test_owdistributions.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "52782421c",
                "new_commit_hash": "ddd612ee2",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/Orange/widgets/visualize/tests/test_owdistributions.py"
            },
            "plus_file": {
                "path": "b/Orange/widgets/visualize/tests/test_owdistributions.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 5,
                            "length": 6
                        },
                        "new_range": {
                            "start": 5,
                            "length": 7
                        },
                        "section": "from Orange.data import Table, Domain, DiscreteVariable"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from Orange.data.table import dataset_dirs",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.tests import test_dirname",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.tests.base import WidgetTest, datasets",
                                "type": "context"
                            },
                            {
                                "content": "from Orange.widgets.tests.utils import table_dense_sparse",
                                "type": "added"
                            },
                            {
                                "content": "from Orange.widgets.visualize.owdistributions import OWDistributions",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/visualize/tests/test_owdistributions.py",
                            "type": "statement",
                            "name": "",
                            "content": "from Orange.widgets.tests.utils import table_dense_sparse",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 8,
                            "end_lineno": 8,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 85,
                            "length": 3
                        },
                        "new_range": {
                            "start": 86,
                            "length": 15
                        },
                        "section": "class TestOWDistributions(WidgetTest):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.send_signal(self.widget.Inputs.data, None)",
                                "type": "context"
                            },
                            {
                                "content": "        cb.setChecked(True)",
                                "type": "context"
                            },
                            {
                                "content": "        cb.click()",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "    @table_dense_sparse",
                                "type": "added"
                            },
                            {
                                "content": "    def test_binning_numeric_variables(self, prepare_table):",
                                "type": "added"
                            },
                            {
                                "content": "        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"",
                                "type": "added"
                            },
                            {
                                "content": "        data = prepare_table(self.iris)",
                                "type": "added"
                            },
                            {
                                "content": "        self.send_signal(self.widget.Inputs.data, data)",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        self.widget.controls.disc_cont.setChecked(True)",
                                "type": "added"
                            },
                            {
                                "content": "        self.wait_until_stop_blocking()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "        self.widget.controls.disc_cont.setChecked(False)",
                                "type": "added"
                            },
                            {
                                "content": "        self.wait_until_stop_blocking()",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "Orange/widgets/visualize/tests/test_owdistributions.py",
                            "type": "class",
                            "name": "TestOWDistributions",
                            "content": "class TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n\n    @table_dense_sparse\n    def test_binning_numeric_variables(self, prepare_table):\n        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"\n        data = prepare_table(self.iris)\n        self.send_signal(self.widget.Inputs.data, data)\n\n        self.widget.controls.disc_cont.setChecked(True)\n        self.wait_until_stop_blocking()\n\n        self.widget.controls.disc_cont.setChecked(False)\n        self.wait_until_stop_blocking()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 12,
                            "end_lineno": 100,
                            "parent": null
                        }
                    ],
                    "added_entities": [
                        {
                            "file_name": "Orange/widgets/visualize/tests/test_owdistributions.py",
                            "type": "method",
                            "name": "TestOWDistributions.test_binning_numeric_variables",
                            "content": "class TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n\n    @table_dense_sparse\n    def test_binning_numeric_variables(self, prepare_table):\n        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"\n        data = prepare_table(self.iris)\n        self.send_signal(self.widget.Inputs.data, data)\n\n        self.widget.controls.disc_cont.setChecked(True)\n        self.wait_until_stop_blocking()\n\n        self.widget.controls.disc_cont.setChecked(False)\n        self.wait_until_stop_blocking()",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 91,
                            "end_lineno": 100,
                            "parent": {
                                "file_name": "Orange/widgets/visualize/tests/test_owdistributions.py",
                                "type": "class",
                                "name": "TestOWDistributions",
                                "content": "class TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n\n    @table_dense_sparse\n    def test_binning_numeric_variables(self, prepare_table):\n        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"\n        data = prepare_table(self.iris)\n        self.send_signal(self.widget.Inputs.data, data)\n\n        self.widget.controls.disc_cont.setChecked(True)\n        self.wait_until_stop_blocking()\n\n        self.widget.controls.disc_cont.setChecked(False)\n        self.wait_until_stop_blocking()",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 12,
                                "end_lineno": 100,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "1995ceb1306231032de3f842fe6a5b6eb06a75bd^",
    "new_commit_hash": "1995ceb1306231032de3f842fe6a5b6eb06a75bd",
    "commit_message": "Merge pull request #3864 from pavlin-policar/discretize-sparse\n\nOWDistributions: Fix crash on binning sparse data",
    "commit_date": "2019-06-07T10:33:32+02:00",
    "metadata": {}
}
{
    "repo_name": "orange3",
    "new_commit_hash": "1995ceb1306231032de3f842fe6a5b6eb06a75bd",
    "test_file_codes": [
        "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring,protected-access\n\nfrom Orange.data import Table, Domain, DiscreteVariable\nfrom Orange.data.table import dataset_dirs\nfrom Orange.tests import test_dirname\nfrom Orange.widgets.tests.base import WidgetTest, datasets\nfrom Orange.widgets.tests.utils import table_dense_sparse\nfrom Orange.widgets.visualize.owdistributions import OWDistributions\n\n\nclass TestOWDistributions(WidgetTest):\n    @classmethod\n    def setUpClass(cls):\n        super().setUpClass()\n        dataset_dirs.append(test_dirname())\n        cls.data = Table(\"datasets/test9.tab\")\n        cls.iris = Table(\"iris\")\n\n    def setUp(self):\n        self.widget = self.create_widget(OWDistributions)\n\n    def test_metas(self):\n        self.send_signal(self.widget.Inputs.data, self.data)\n\n        # check metas in list views\n        for meta in self.data.domain.metas:\n            if meta.is_discrete or meta.is_continuous:\n                self.assertIn(meta, self.widget.varmodel)\n        for meta in self.data.domain.metas:\n            if meta.is_discrete:\n                self.assertIn(meta, self.widget.groupvarmodel)\n\n        # select meta attribute\n        self.widget.controls.disc_cont.setChecked(True)\n        self.widget.variable_idx = 2\n        self.widget._setup()\n\n    def test_remove_data(self):\n        \"\"\"Check widget when data is removed\"\"\"\n        prob = self.widget.controls.show_prob\n        self.send_signal(self.widget.Inputs.data, self.iris)\n        self.assertEqual(prob.count(), 5)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 2)\n        self.send_signal(self.widget.Inputs.data, None)\n        self.assertEqual(prob.count(), 0)\n        self.assertEqual(self.widget.controls.groupvar_idx.count(), 0)\n\n    def test_discretize_meta(self):\n        \"\"\"The widget discretizes continuous meta attributes\"\"\"\n        domain = self.iris.domain\n        mdomain = Domain(domain.attributes[:-1], domain.class_var,\n                         metas=domain.attributes[-1:])\n        miris = Table(mdomain, self.iris)\n        self.send_signal(self.widget.Inputs.data, miris)\n        widget = self.widget\n        widget.disc_cont = True\n        widget.varview.selectionModel().select(\n            widget.varview.model().index(4, 0))\n        self.assertIsInstance(widget.var, DiscreteVariable)\n        self.assertEqual(widget.var.name, mdomain.metas[0].name)\n\n    def test_variable_group_combinations(self):\n        \"\"\"Check widget for all combinations of variable and group for dataset\n        with constant columns and missing data\"\"\"\n        self.send_signal(self.widget.Inputs.data, Table(datasets.path(\"testing_dataset_cls\")))\n        for groupvar_idx in range(len(self.widget.groupvarmodel)):\n            self.widget.groupvar_idx = groupvar_idx\n            for var_idx in range(len(self.widget.varmodel)):\n                self.widget.variable_idx = var_idx\n                self.widget._setup()\n\n    def test_no_distributions(self):\n        \"\"\"\n        Do not fail when there is no data and when sb clicks\n        \"Show relative frequencies\".\n        GH-2383\n        GH-2428\n        \"\"\"\n        cb = self.widget.controls.relative_freq\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, self.data)\n        cb.setChecked(False)\n        cb.click()\n        self.send_signal(self.widget.Inputs.data, None)\n        cb.setChecked(True)\n        cb.click()\n\n    @table_dense_sparse\n    def test_binning_numeric_variables(self, prepare_table):\n        \"\"\"The widget should not crash when checking `Bin numeric variables`\"\"\"\n        data = prepare_table(self.iris)\n        self.send_signal(self.widget.Inputs.data, data)\n\n        self.widget.controls.disc_cont.setChecked(True)\n        self.wait_until_stop_blocking()\n\n        self.widget.controls.disc_cont.setChecked(False)\n        self.wait_until_stop_blocking()\n",
        "# Test methods with long descriptive names can omit docstrings\n# pylint: disable=missing-docstring\n\nimport random\nfrom unittest import TestCase\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.preprocess import discretize, Discretize\nfrom Orange import data\nfrom Orange.data import Table, Instance, Domain, ContinuousVariable, DiscreteVariable\n\n\n# noinspection PyPep8Naming\nfrom Orange.widgets.tests.utils import table_dense_sparse\n\n\nclass TestEqualFreq(TestCase):\n    def test_equifreq_with_too_few_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_equifreq_100_to_4(self):\n        X = np.arange(100).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_equifreq_with_k_instances(self):\n        X = np.array([[1], [2], [3], [4]])\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [1.5, 2.5, 3.5])\n\n\n# noinspection PyPep8Naming\nclass TestEqualWidth(TestCase):\n    def test_equalwidth_on_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [0.25, 0.5, 0.75])\n\n    @table_dense_sparse\n    def test_equalwidth_100_to_4(self, prepare_table):\n        X = np.arange(101).reshape((101, 1))\n        table = prepare_table(data.Table(X))\n        disc = discretize.EqualWidth(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 4)\n        self.assertEqual(dvar.compute_value.points, [25, 50, 75])\n\n    def test_equalwidth_const_value(self):\n        X = np.ones((100, 1))\n        table = data.Table(X)\n        disc = discretize.EqualFreq(n=4)\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n\n# noinspection PyPep8Naming\nclass TestEntropyMDL(TestCase):\n    def test_entropy_with_two_values(self):\n        s = [0] * 50 + [1] * 50\n        random.shuffle(s)\n        X = np.array(s).reshape((100, 1))\n        table = data.Table(X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n    def test_entropy_with_two_values_useless(self):\n        X = np.array([0] * 50 + [1] * 50).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 50 + [0] * 25)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy_constant(self):\n        X = np.zeros((100, 1))\n        domain = Domain([ContinuousVariable('v1')],\n                        [DiscreteVariable('c1', values=[\"1\"])])\n        table = data.Table(domain, X, X)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 1)\n        self.assertEqual(dvar.compute_value.points, [])\n\n    def test_entropy(self):\n        X = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25\n                    ).reshape((100, 1))\n        Y = np.array([0] * 25 + [1] * 75)\n        table = data.Table(X, Y)\n        disc = discretize.EntropyMDL()\n        dvar = disc(table, table.domain[0])\n        self.assertEqual(len(dvar.values), 2)\n        self.assertEqual(dvar.compute_value.points, [0.5])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizer(TestCase):\n    def setUp(self):\n        self.var = data.ContinuousVariable(\"x\", number_of_decimals=1)\n\n    def test_create_discretized_var(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertIsInstance(dvar.compute_value,\n                              discretize.Discretizer)\n        self.assertEqual(dvar.compute_value.points, [1, 2, 3])\n\n\n    def test_create_discretized_var_formatting(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        self.assertEqual(dvar.values, [\"< 1\", \"1 - 2\", \"2 - 3\", \"≥ 3\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10])\n        self.assertEqual(dvar.values, [\"< 10\", \"≥ 10\"])\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [10.1234])\n        self.assertEqual(dvar.values, [\"< 10.1\", \"≥ 10.1\"])\n\n        self.var.number_of_decimals = 3\n\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [5, 10.1234])\n        self.assertEqual(dvar.values, [\"< 5\", \"5 - 10.123\", \"≥ 10.123\"])\n\n    def test_discretizer_computation(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5])\n        np.testing.assert_equal(dvar.compute_value.transform(X), np.floor(X))\n\n    def test_discretizer_computation_sparse(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        self.assertEqual((dvar.compute_value.transform(X) != np.floor(X)).nnz, 0)\n\n    def test_discretizer_computation_sparse_no_points(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n        empty = sp.csr_matrix(X.shape)\n        self.assertEqual((dvar.compute_value.transform(X) != empty).nnz, 0)\n\n    def test_transform(self):\n        table = data.Table('iris')\n        table2 = Discretize()(table)\n        ins = data.Instance(table2.domain, table[0])\n        table3 = data.Table(table2.domain, table[:10])\n        self.assertEqual(ins, table3[0])\n\n    def test_remove_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=True)\n        new_table = discretize(table)\n        self.assertNotEqual(len(table.domain.attributes),\n                            len(new_table.domain.attributes))\n\n    def test_keep_constant(self):\n        table = data.Table('iris')\n        table[:, 0] = 1\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertEqual(len(table.domain.attributes),\n                         len(new_table.domain.attributes))\n\n    def test_discretize_class(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.class_vars[0],\n                      new_table.domain.class_vars[0])\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n        discretize = Discretize(remove_const=False, discretize_classes=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.class_vars[0], DiscreteVariable)\n        self.assertIs(new_table.domain.class_vars[1],\n                      new_table.domain.class_vars[1])\n\n    def test_discretize_metas(self):\n        table = data.Table('iris')\n        domain = table.domain\n        regr_domain = data.Domain(domain.attributes[:3],\n                                  [],\n                                  [domain.attributes[3], domain.class_var])\n        table = data.Table.from_table(regr_domain, table)\n\n        discretize = Discretize(remove_const=False)\n        new_table = discretize(table)\n        self.assertIs(new_table.domain.metas[0],\n                      new_table.domain.metas[0])\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n        discretize = Discretize(remove_const=False, discretize_metas=True)\n        new_table = discretize(table)\n        self.assertIsInstance(new_table.domain.metas[0], DiscreteVariable)\n        self.assertIs(new_table.domain.metas[1],\n                      new_table.domain.metas[1])\n\n\n# noinspection PyPep8Naming\nclass TestDiscretizeTable(TestCase):\n    @classmethod\n    def setUpClass(cls):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        cls.table_no_class = data.Table(X)\n        cls.table_class = data.Table(X, X1)\n\n    def test_discretize_exclude_constant(self):\n        dom = discretize.DomainDiscretizer()(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n        dom = discretize.DomainDiscretizer(clean=False)(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 3)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertEqual(dom[2].compute_value.points, [])\n\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n\n    def test_discretize_class(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n        dom = discretize.DomainDiscretizer(discretize_class=True)\n        dom = dom(self.table_class)\n        self.assertIs(dom.class_var, self.table_class.domain.class_var)\n\n    def test_method(self):\n        dom = discretize.DomainDiscretizer()(self.table_class)\n        self.assertEqual(len(dom[1].values), 4)\n\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2))\n        dom = dom(self.table_class)\n        self.assertEqual(len(dom[1].values), 2)\n\n    def test_fixed(self):\n        dom = discretize.DomainDiscretizer(method=discretize.EqualWidth(n=2),\n                                           fixed={\"Feature 2\": [1, 11]})\n        dom = dom(self.table_no_class)\n        self.assertEqual(len(dom.attributes), 2)\n        self.assertEqual(dom[0].compute_value.points, [0.5])\n        self.assertEqual(dom[1].compute_value.points, [6])\n\n    def test_leave_discrete(self):\n        s = [0] * 50 + [1] * 50\n        X1 = np.array(s).reshape((100, 1))\n        X2 = np.arange(100).reshape((100, 1))\n        X3 = np.ones((100, 1))\n        X = np.hstack([X1, X2, X3])\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.ContinuousVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n        domain = data.Domain([data.DiscreteVariable(\"a\", values=\"MF\"),\n                              data.ContinuousVariable(\"b\"),\n                              data.DiscreteVariable(\"c\", values=\"AB\")],\n                             data.DiscreteVariable(\"d\"))\n        table = data.Table(domain, X, X1)\n        dom = discretize.DomainDiscretizer()(table)\n        self.assertIs(dom[0], table.domain[0])\n        self.assertEqual(dom[1].compute_value.points, [24.5, 49.5, 74.5])\n        self.assertIs(dom[2], table.domain[2])\n        self.assertIs(dom.class_var, table.domain.class_var)\n\n\nclass TestInstanceConversion(TestCase):\n    def test_single_instance(self):\n        iris = Table(\"iris\")\n        inst = Instance(iris.domain, [5.2, 3.8, 1.4, 0.5, \"Iris-virginica\"])\n        d_iris = Discretize()(iris)\n        Instance(d_iris.domain, inst)\n"
    ],
    "test_file_names": [
        "test_1.py",
        "test_2.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Orange installation attempts...\nAttempting installation with Python 3.7...\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\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.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/tmp4a0wn6is/tmp\ncreating /tmp/tmp4a0wn6is/tmp/tmp4a0wn6is\ncompile options: '-MMD -MF /tmp/tmp4a0wn6is/file.c.d -c'\ncc: /tmp/tmp4a0wn6is/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/tmp2pt3iwe1/tmp\ncreating /tmp/tmp2pt3iwe1/tmp/tmp2pt3iwe1\ncompile options: '-MMD -MF /tmp/tmp2pt3iwe1/file.c.d -c'\ncc: /tmp/tmp2pt3iwe1/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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include -I/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\nWarning: 'keywords' should be a list, got type 'tuple'\nWarning: 'classifiers' should be a list, got type 'tuple'\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.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 '*.html' under directory 'Orange/canvas'\nwarning: no files found matching '*.css' 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/tmpf6ezkzw0/tmp\ncreating /tmp/tmpf6ezkzw0/tmp/tmpf6ezkzw0\ncompile options: '-MMD -MF /tmp/tmpf6ezkzw0/file.c.d -c'\ncc: /tmp/tmpf6ezkzw0/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/tmpv63tciux/tmp\ncreating /tmp/tmpv63tciux/tmp/tmpv63tciux\ncompile options: '-MMD -MF /tmp/tmpv63tciux/file.c.d -c'\ncc: /tmp/tmpv63tciux/file.c\ncustomize UnixCCompiler using build_ext\nCreating /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/Orange3.egg-link (link to .)\nAdding Orange3 3.22.0.dev0+1995ceb to easy-install.pth file\nInstalling orange-canvas script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nInstalled /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd\nProcessing dependencies for Orange3==3.22.0.dev0+1995ceb\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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages\nSearching for pyqtgraph==0.12.4\nBest match: pyqtgraph 0.12.4\nAdding pyqtgraph 0.12.4 to easy-install.pth file\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling pip3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling pip3.10 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling f2py3 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling f2py3.7 script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling pyftmerge script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling pyftsubset script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\nInstalling ttx script to /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/bin\n\nUsing /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages\nFinished processing dependencies for Orange3==3.22.0.dev0+1995ceb\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 174ms\nPrepared 18 packages in 2ms\nInstalled 18 packages in 614ms\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 33 packages in 127ms\nInstalled 28 packages in 439ms\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 + 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 + more-itertools==9.1.0\n + networkx==2.6.3\n + opentsne==1.0.1\n + pip==24.0\n + pycparser==2.21\n + python-louvain==0.16\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 + threadpoolctl==3.1.0\n + urllib3==2.0.7\n + xlrd==2.0.1\n + xlsxwriter==3.2.0\nResolved 14 packages in 41ms\nInstalled 11 packages in 137ms\n + anyqt==0.2.0\n + cycler==0.11.0\n + docutils==0.20.1\n + fonttools==4.38.0\n + kiwisolver==1.4.5\n + matplotlib==3.5.3\n + pillow==9.5.0\n + pyparsing==3.1.4\n + pyqtgraph==0.12.4\n + python-dateutil==2.9.0.post0\n + six==1.17.0\nResolved 2 packages in 15ms\nInstalled 2 packages in 86ms\n + psycopg2==2.9.9\n + pymssql==2.3.2\nResolved 5 packages in 19ms\nInstalled 2 packages in 154ms\n + pandas==1.3.5\n + pytz==2024.2\nAudited 2 packages in 1ms\nOrange/classification/_simple_tree.c: In function ‘gain_ratio_c’:\nOrange/classification/_simple_tree.c:63:9: warning: implicit declaration of function ‘qsort_r’; did you mean ‘qsort’? [-Wimplicit-function-declaration]\n   63 |         qsort_r(base, nel, size, compar, thunk)\n      |         ^~~~~~~\nOrange/classification/_simple_tree.c:147:9: note: in expansion of macro ‘QSORT_R_FUNC’\n  147 |         QSORT_R_FUNC(examples, size, sizeof(struct Example), (void*) &compar_attr, compar_examples);\n      |         ^~~~~~~~~~~~\nIn file included from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/data/_contingency.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from Orange/distance/_distance.c:567:\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1830,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.venv/lib/python3.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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      |  ^~~~~~~\n/home/gcpuser/buckets/local_repoeval_bucket/repos/orange3_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd/.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_1995ceb1306231032de3f842fe6a5b6eb06a75bd\ncollected 34 items\n\nr2e_tests/test_1.py .EEEEEEE                                             [ 23%]\nr2e_tests/test_2.py ...............F..........                           [100%]\n\n==================================== ERRORS ====================================\n_____ ERROR at setup of TestOWDistributions.test_binning_numeric_variables _____\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n__________ ERROR at setup of TestOWDistributions.test_discretize_meta __________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n_______________ ERROR at setup of TestOWDistributions.test_metas _______________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n___________ ERROR at setup of TestOWDistributions.test_minimum_size ____________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n        \"\"\"Prepare environment for test execution\n    \n        Construct a dummy signal manager and monkey patch\n        OWReport.get_instance to return a manually created instance.\n        \"\"\"\n        super().setUpClass()\n    \n        cls.widgets = []\n    \n        cls.signal_manager = DummySignalManager()\n    \n>       report = OWReport()\n\nOrange/widgets/tests/base.py:116: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n_________ ERROR at setup of TestOWDistributions.test_no_distributions __________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n____________ ERROR at setup of TestOWDistributions.test_remove_data ____________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n____ ERROR at setup of TestOWDistributions.test_variable_group_combinations ____\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x72ec030fe2d0>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n=================================== FAILURES ===================================\n_____________ TestDiscretizer.test_discretizer_computation_sparse ______________\n\nself = <r2e_tests.test_2.TestDiscretizer testMethod=test_discretizer_computation_sparse>\n\n    def test_discretizer_computation_sparse(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n>       self.assertEqual((dvar.compute_value.transform(X) != np.floor(X)).nnz, 0)\nE       TypeError: must be real number, not csr_matrix\n\nr2e_tests/test_2.py:161: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_dirname\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_100_to_4\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_with_k_instances\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_with_too_few_values\nPASSED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_100_to_4\nPASSED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_const_value\nPASSED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_on_two_values\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_constant\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_with_two_values\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_with_two_values_useless\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_create_discretized_var\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_create_discretized_var_formatting\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretize_class\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretize_metas\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation_sparse_no_points\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_keep_constant\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_remove_constant\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_transform\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_discretize_class\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_discretize_exclude_constant\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_fixed\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_leave_discrete\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_method\nPASSED r2e_tests/test_2.py::TestInstanceConversion::test_single_instance\nERROR r2e_tests/test_1.py::TestOWDistributions::test_binning_numeric_variables\nERROR r2e_tests/test_1.py::TestOWDistributions::test_discretize_meta - TypeEr...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_metas - TypeError: addWi...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_minimum_size - TypeError...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_no_distributions - TypeE...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_remove_data - TypeError:...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_variable_group_combinations\nFAILED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation_sparse\n==================== 1 failed, 26 passed, 7 errors in 3.32s ====================\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_1995ceb1306231032de3f842fe6a5b6eb06a75bd\ncollected 34 items\n\nr2e_tests/test_1.py .EEEEEEE                                             [ 23%]\nr2e_tests/test_2.py ...F...........F..........                           [100%]\n\n==================================== ERRORS ====================================\n_____ ERROR at setup of TestOWDistributions.test_binning_numeric_variables _____\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n__________ ERROR at setup of TestOWDistributions.test_discretize_meta __________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n_______________ ERROR at setup of TestOWDistributions.test_metas _______________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n___________ ERROR at setup of TestOWDistributions.test_minimum_size ____________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n        \"\"\"Prepare environment for test execution\n    \n        Construct a dummy signal manager and monkey patch\n        OWReport.get_instance to return a manually created instance.\n        \"\"\"\n        super().setUpClass()\n    \n        cls.widgets = []\n    \n        cls.signal_manager = DummySignalManager()\n    \n>       report = OWReport()\n\nOrange/widgets/tests/base.py:116: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n_________ ERROR at setup of TestOWDistributions.test_no_distributions __________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n____________ ERROR at setup of TestOWDistributions.test_remove_data ____________\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n____ ERROR at setup of TestOWDistributions.test_variable_group_combinations ____\n\ncls = <class 'r2e_tests.test_1.TestOWDistributions'>\n\n    @classmethod\n    def setUpClass(cls):\n>       super().setUpClass()\n\nr2e_tests/test_1.py:15: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/widgets/tests/base.py:116: in setUpClass\n    report = OWReport()\nOrange/widgets/report/owreport.py:136: in __init__\n    self._setup_ui_()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <Orange.widgets.report.owreport.OWReport object at 0x788a648c1730>\n\n    def _setup_ui_(self):\n        self.table_model = ReportItemModel(0, len(Column.__members__))\n        self.table = ReportTable(self.controlArea)\n        self.table.setModel(self.table_model)\n        self.table.setShowGrid(False)\n        self.table.setSelectionBehavior(QTableView.SelectRows)\n        self.table.setSelectionMode(QTableView.SingleSelection)\n        self.table.setWordWrap(False)\n        self.table.setMouseTracking(True)\n        self.table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)\n        self.table.verticalHeader().setDefaultSectionSize(20)\n        self.table.verticalHeader().setVisible(False)\n        self.table.horizontalHeader().setVisible(False)\n        self.table.setFixedWidth(250)\n        self.table.setColumnWidth(Column.item, 200)\n        self.table.setColumnWidth(Column.remove, 23)\n        self.table.setColumnWidth(Column.scheme, 25)\n        self.table.clicked.connect(self._table_clicked)\n        self.table.selectionModel().selectionChanged.connect(\n            self._table_selection_changed)\n        self.controlArea.layout().addWidget(self.table)\n    \n        self.last_scheme = None\n        self.scheme_button = gui.button(\n            self.controlArea, self, \"Back to Last Scheme\",\n            callback=self._show_last_scheme\n        )\n        box = gui.hBox(self.controlArea)\n        box.setContentsMargins(-6, 0, -6, 0)\n        self.save_button = gui.button(\n            box, self, \"Save\", callback=self.save_report, disabled=True\n        )\n        self.print_button = gui.button(\n            box, self, \"Print\", callback=self._print_report, disabled=True\n        )\n    \n        class PyBridge(QObject):\n            @pyqtSlot(str)\n            def _select_item(myself, item_id):\n                item = self.table_model.get_item_by_id(item_id)\n                self.table.selectRow(self.table_model.indexFromItem(item).row())\n                self._change_selected_item(item)\n    \n            @pyqtSlot(str, str)\n            def _add_comment(myself, item_id, value):\n                item = self.table_model.get_item_by_id(item_id)\n                item.comment = value\n                self.report_changed = True\n    \n        self.report_view = WebviewWidget(self.mainArea, bridge=PyBridge(self))\n>       self.mainArea.layout().addWidget(self.report_view)\nE       TypeError: addWidget(self, a0: Optional[QWidget], stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Mock'\n\nOrange/widgets/report/owreport.py:193: TypeError\n=================================== FAILURES ===================================\n___________________ TestEqualWidth.test_equalwidth_100_to_4 ____________________\n\nself = <r2e_tests.test_2.TestEqualWidth testMethod=test_equalwidth_100_to_4>\nprepare_table = <function table_dense_sparse.<locals>._wrapper.<locals>.<lambda> at 0x788a61ed1830>\n\n    @table_dense_sparse\n    def test_equalwidth_100_to_4(self, prepare_table):\n        X = np.arange(101).reshape((101, 1))\n        table = prepare_table(data.Table(X))\n        disc = discretize.EqualWidth(n=4)\n>       dvar = disc(table, table.domain[0])\n\nr2e_tests/test_2.py:64: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \nOrange/preprocess/discretize.py:164: in __call__\n    points = self._split_eq_width(min, max)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = EqualWidth()\nmin = <101x1 sparse matrix of type '<class 'numpy.float64'>'\n\twith 100 stored elements in Compressed Sparse Column format>\nmax = <101x1 sparse matrix of type '<class 'numpy.float64'>'\n\twith 100 stored elements in Compressed Sparse Column format>\n\n    def _split_eq_width(self, min, max):\n>       if np.isnan(min) or np.isnan(max) or min == max:\nE       TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''\n\nOrange/preprocess/discretize.py:169: TypeError\n_____________ TestDiscretizer.test_discretizer_computation_sparse ______________\n\nself = <r2e_tests.test_2.TestDiscretizer testMethod=test_discretizer_computation_sparse>\n\n    def test_discretizer_computation_sparse(self):\n        dvar = discretize.Discretizer.create_discretized_var(\n            self.var, [1, 2, 3])\n        X = sp.csr_matrix(np.array([0, 0.9, 1, 1.1, 1.9, 2, 2.5, 3, 3.5]))\n>       self.assertEqual((dvar.compute_value.transform(X) != np.floor(X)).nnz, 0)\nE       TypeError: must be real number, not csr_matrix\n\nr2e_tests/test_2.py:161: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_dirname\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_100_to_4\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_with_k_instances\nPASSED r2e_tests/test_2.py::TestEqualFreq::test_equifreq_with_too_few_values\nPASSED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_const_value\nPASSED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_on_two_values\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_constant\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_with_two_values\nPASSED r2e_tests/test_2.py::TestEntropyMDL::test_entropy_with_two_values_useless\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_create_discretized_var\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_create_discretized_var_formatting\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretize_class\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretize_metas\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation_sparse_no_points\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_keep_constant\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_remove_constant\nPASSED r2e_tests/test_2.py::TestDiscretizer::test_transform\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_discretize_class\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_discretize_exclude_constant\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_fixed\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_leave_discrete\nPASSED r2e_tests/test_2.py::TestDiscretizeTable::test_method\nPASSED r2e_tests/test_2.py::TestInstanceConversion::test_single_instance\nERROR r2e_tests/test_1.py::TestOWDistributions::test_binning_numeric_variables\nERROR r2e_tests/test_1.py::TestOWDistributions::test_discretize_meta - TypeEr...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_metas - TypeError: addWi...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_minimum_size - TypeError...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_no_distributions - TypeE...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_remove_data - TypeError:...\nERROR r2e_tests/test_1.py::TestOWDistributions::test_variable_group_combinations\nFAILED r2e_tests/test_2.py::TestEqualWidth::test_equalwidth_100_to_4 - TypeEr...\nFAILED r2e_tests/test_2.py::TestDiscretizer::test_discretizer_computation_sparse\n==================== 2 failed, 25 passed, 7 errors in 2.38s ====================\n",
    "old_commit_res_stderr": ""
}
Orange/preprocess/discretize.py Orange/tests/test_discretize.py Orange/widgets/visualize/tests/test_owdistributions.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** TypeError When Binning Sparse Data Due to Unsupported 'isnan' Operation

**Description:**
When using the `EqualWidth` discretization method on sparse data, the process crashes with a `TypeError`. The issue arises because the method attempts to apply `np.isnan` on sparse matrix inputs, which is not supported.

**Example Code:**
```python
import numpy as np
from Orange.preprocess import discretize
from Orange.data import Table

# Create sparse data
X = np.arange(101).reshape((101, 1))
table = Table(X)  # Assuming this creates a sparse table

# Attempt to discretize
disc = discretize.EqualWidth(n=4)
dvar = disc(table, table.domain[0])
```

**Expected Behavior:**
The `EqualWidth` discretization should handle sparse data without errors, correctly computing the minimum and maximum values to perform binning.

**Actual Behavior:**
A `TypeError` is raised:
```
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule 'safe'
```

This error prevents the discretization process from completing successfully when working with sparse datasets.

[/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/preprocess/discretize.py
import re

import numpy as np
import scipy.sparse as sp

from Orange.data import DiscreteVariable, Domain
from Orange.data.sql.table import SqlTable
from Orange.preprocess.util import _RefuseDataInConstructor
from Orange.statistics import distribution, contingency
from Orange.statistics.basic_stats import BasicStats
from Orange.util import Reprable
from .transformation import Transformation
from . import _discretize

__all__ = ["EqualFreq", "EqualWidth", "EntropyMDL", "DomainDiscretizer"]


class Discretizer(Transformation):
    """Value transformer that returns an index of the bin for the given value.
    """
    def __init__(self, variable, points):
        super().__init__(variable)
        self.points = points

    @staticmethod
    def digitize(x, bins):
        if sp.issparse(x):
            if len(bins):
                x.data = np.digitize(x.data, bins)
            else:
                x = sp.csr_matrix(x.shape)
            return x
        else:
            return np.digitize(x, bins) if len(bins) else [0]*len(x)

    def transform(self, c):
        if sp.issparse(c):
            return self.digitize(c, self.points)
        elif c.size:
            return np.where(np.isnan(c), np.NaN, self.digitize(c, self.points))
        else:
            return np.array([], dtype=int)

    @staticmethod
    def _fmt_interval(low, high, formatter):
        assert low is not None or high is not None
        assert low is None or high is None or low < high
        if low is None or np.isinf(low):
            return f"< {formatter(high)}"
        if high is None or np.isinf(high):
            return f"≥ {formatter(low)}"
        return f"{formatter(low)} - {formatter(high)}"

    @classmethod
    def create_discretized_var(cls, var, points):
        def fmt(val):
            sval = var.str_val(val)
            # For decimal numbers, remove trailing 0's and . if no decimals left
            if re.match(r"^\d+\.\d+", sval):
                return sval.rstrip("0").rstrip(".")
            return sval

        lpoints = list(points)
        if lpoints:
            values = [
                cls._fmt_interval(low, high, fmt)
                for low, high in zip([-np.inf] + lpoints, lpoints + [np.inf])]
            to_sql = BinSql(var, lpoints)
        else:
            values = ["single_value"]
            to_sql = SingleValueSql(values[0])

        dvar = DiscreteVariable(name=var.name, values=values,
                                compute_value=cls(var, points),
                                sparse=var.sparse)
        dvar.source_variable = var
        dvar.to_sql = to_sql
        return dvar


class BinSql:
    def __init__(self, var, points):
        self.var = var
        self.points = points

    def __call__(self):
        return 'width_bucket(%s, ARRAY%s::double precision[])' % (
            self.var.to_sql(), str(self.points))


class SingleValueSql:
    def __init__(self, value):
        self.value = value

    def __call__(self):
        return "'%s'" % self.value


class Discretization(Reprable):
    """Abstract base class for discretization classes."""
    def __call__(self, data, variable):
        """
        Compute discretization of the given variable on the given data.
        Return a new variable with the appropriate domain
        (:obj:`Orange.data.DiscreteVariable.values`) and transformer
        (:obj:`Orange.data.Variable.compute_value`).
        """
        raise NotImplementedError(
            "Subclasses of 'Discretization' need to implement "
            "the call operator")


class EqualFreq(Discretization):
    """Discretization into bins with approximately equal number of data
    instances.

    .. attribute:: n

        Number of bins (default: 4). The actual number may be lower if the
        variable has less than n distinct values.
    """
    def __init__(self, n=4):
        self.n = n

    # noinspection PyProtectedMember
    def __call__(self, data, attribute):
        if type(data) == SqlTable:
            att = attribute.to_sql()
            quantiles = [(i + 1) / self.n for i in range(self.n - 1)]
            query = data._sql_query(
                ['quantile(%s, ARRAY%s)' % (att, str(quantiles))],
                use_time_sample=1000)
            with data._execute_sql_query(query) as cur:
                points = sorted(set(cur.fetchone()[0]))
        else:
            d = distribution.get_distribution(data, attribute)
            points = _discretize.split_eq_freq(d, self.n)
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

class EqualWidth(Discretization):
    """Discretization into a fixed number of bins with equal widths.

    .. attribute:: n

        Number of bins (default: 4).
    """
    def __init__(self, n=4):
        self.n = n

    # noinspection PyProtectedMember
    def __call__(self, data, attribute, fixed=None):
        if fixed:
            min, max = fixed[attribute.name]
            points = self._split_eq_width(min, max)
        else:
            if type(data) == SqlTable:
                stats = BasicStats(data, attribute)
                points = self._split_eq_width(stats.min, stats.max)
            else:
                values = data[:, attribute]
                values = values.X if values.X.size else values.Y
                min, max = np.nanmin(values), np.nanmax(values)
                points = self._split_eq_width(min, max)
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

    def _split_eq_width(self, min, max):
        if np.isnan(min) or np.isnan(max) or min == max:
            return []
        dif = (max - min) / self.n
        return [min + (i + 1) * dif for i in range(self.n - 1)]


# noinspection PyPep8Naming
class EntropyMDL(Discretization):
    """
    Discretization into bins inferred by recursively splitting the values to
    minimize the class-entropy. The procedure stops when further splits would
    decrease the entropy for less than the corresponding increase of minimal
    description length (MDL). [FayyadIrani93].

    If there are no suitable cut-off points, the procedure returns a single bin,
    which means that the new feature is constant and can be removed.

    .. attribute:: force

        Induce at least one cut-off point, even when its information
        gain is lower than MDL (default: False).

    """
    def __init__(self, force=False):
        self.force = force

    def __call__(self, data, attribute):
        cont = contingency.get_contingency(data, attribute)
        values, I = cont.values, cont.counts.T
        cut_ind = np.array(self._entropy_discretize_sorted(I, self.force))
        if len(cut_ind) > 0:
            # "the midpoint between each successive pair of examples" (FI p.1)
            points = (values[cut_ind] + values[cut_ind - 1]) / 2.
        else:
            points = []
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

    @classmethod
    def _normalize(cls, X, axis=None, out=None):
        """
        Normalize `X` array so it sums to 1.0 over the `axis`.

        Parameters
        ----------
        X : array
            Array to normalize.
        axis : optional int
            Axis over which the resulting array sums to 1.
        out : optional array
            Output array of the same shape as X.
        """
        X = np.asarray(X, dtype=float)
        scale = np.sum(X, axis=axis, keepdims=True)
        if out is None:
            return X / scale
        else:
            if out is not X:
                assert out.shape == X.shape
                out[:] = X
            out /= scale
            return out

    @classmethod
    def _entropy_normalized(cls, D, axis=None):
        """
        Compute the entropy of distribution array `D`.

        `D` must be a distribution (i.e. sum to 1.0 over `axis`)

        Parameters
        ----------
        D : array
            Distribution.
        axis : optional int
            Axis of `D` along which to compute the entropy.

        """
        # req: (np.sum(D, axis=axis) >= 0).all()
        # req: (np.sum(D, axis=axis) <= 1).all()
        # req: np.all(np.abs(np.sum(D, axis=axis) - 1) < 1e-9)

        D = np.asarray(D)
        Dc = np.clip(D, np.finfo(D.dtype).eps, 1.0)
        return - np.sum(D * np.log2(Dc), axis=axis)

    @classmethod
    def _entropy(cls, D, axis=None):
        """
        Compute the entropy of distribution `D`.

        Parameters
        ----------
        D : array
            Distribution.
        axis : optional int
            Axis of `D` along which to compute the entropy.

        """
        D = cls._normalize(D, axis=axis)
        return cls._entropy_normalized(D, axis=axis)

    @classmethod
    def _entropy1(cls, D):
        """
        Compute the entropy of distributions in `D`
        (one per each row).
        """
        D = cls._normalize(D)
        return _discretize.entropy_normalized1(D)

    @classmethod
    def _entropy2(cls, D):
        """
        Compute the entropy of distributions in `D`
        (one per each row).
        """
        D = cls._normalize(D, axis=1)
        return _discretize.entropy_normalized2(D)

    @classmethod
    def _entropy_cuts_sorted(cls, CS):
        """
        Return the class information entropy induced by partitioning
        the `CS` distribution at all N-1 candidate cut points.

        Parameters
        ----------
        CS : (N, K) array of class distributions.
        """
        CS = np.asarray(CS)
        # |--|-------|--------|
        #  S1    ^       S2
        # S1 contains all points which are <= to cut point
        # Cumulative distributions for S1 and S2 (left right set)
        # i.e. a cut at index i separates the CS into S1Dist[i] and S2Dist[i]
        S1Dist = np.cumsum(CS, axis=0)[:-1]
        S2Dist = np.cumsum(CS[::-1], axis=0)[-2::-1]

        # Entropy of S1[i] and S2[i] sets
        ES1 = cls._entropy2(S1Dist)
        ES2 = cls._entropy2(S2Dist)

        # Number of cases in S1[i] and S2[i] sets
        S1_count = np.sum(S1Dist, axis=1)
        S2_count = np.sum(S2Dist, axis=1)

        # Number of all cases
        S_count = np.sum(CS)

        ES1w = ES1 * S1_count / S_count
        ES2w = ES2 * S2_count / S_count

        # E(A, T; S) Class information entropy of the partition S
        E = ES1w + ES2w

        return E, ES1, ES2

    @classmethod
    def _entropy_discretize_sorted(cls, C, force=False):
        """
        Entropy discretization on a sorted C.

        :param C: (N, K) array of class distributions.

        """
        E, ES1, ES2 = cls._entropy_cuts_sorted(C)
        # TODO: Also get the left right distribution counts from
        # entropy_cuts_sorted,

        # Note the + 1
        if len(E) == 0:
            return []
        cut_index = np.argmin(E) + 1

        # Distribution of classed in S1, S2 and S
        S1_c = np.sum(C[:cut_index], axis=0)
        S2_c = np.sum(C[cut_index:], axis=0)
        S_c = S1_c + S2_c

        ES = cls._entropy1(np.sum(C, axis=0))
        ES1, ES2 = ES1[cut_index - 1], ES2[cut_index - 1]

        # Information gain of the best split
        Gain = ES - E[cut_index - 1]
        # Number of different classes in S, S1 and S2
        k = float(np.sum(S_c > 0))
        k1 = float(np.sum(S1_c > 0))
        k2 = float(np.sum(S2_c > 0))

        assert k > 0
        delta = np.log2(3 ** k - 2) - (k * ES - k1 * ES1 - k2 * ES2)
        N = float(np.sum(S_c))

        if Gain > np.log2(N - 1) / N + delta / N:
            # Accept the cut point and recursively split the subsets.
            left, right = [], []
            if k1 > 1 and cut_index > 1:
                left = cls._entropy_discretize_sorted(C[:cut_index, :])
            if k2 > 1 and cut_index < len(C) - 1:
                right = cls._entropy_discretize_sorted(C[cut_index:, :])
            return left + [cut_index] + [i + cut_index for i in right]
        elif force:
            return [cut_index]
        else:
            return []


class DomainDiscretizer(_RefuseDataInConstructor, Reprable):
    """Discretizes all continuous features in the data.

    .. attribute:: method

        Feature discretization method (instance of
        :obj:`Orange.preprocess.Discretization`). If `None` (default),
        :class:`Orange.preprocess.EqualFreq` with 4 intervals is
        used.

    .. attribute:: clean

        If `True`, features discretized into a single interval constant are
        removed. This is useful for discretization methods that infer the
        number of intervals from the data, such as
        :class:`Orange.preprocess.EntropyMDL` (default: `True`).

    .. attribute:: discretize_class

        Determines whether a target is also discretized if it is continuous.
        (default: `False`)
    """
    def __init__(self, discretize_class=False, method=None, clean=True,
                 fixed=None):
        self.discretize_class = discretize_class
        self.method = method
        self.clean = clean
        self.fixed = fixed

    def __call__(self, data, fixed=None):
        """
        Compute and return discretized domain.

        :param data: Data to discretize.
        """

        def transform_list(s, fixed=None):
            new_vars = []
            for var in s:
                if var.is_continuous:
                    if fixed and var.name in fixed.keys():
                        nv = method(data, var, fixed)
                    else:
                        nv = method(data, var)
                    if not self.clean or len(nv.values) > 1:
                        new_vars.append(nv)
                else:
                    new_vars.append(var)
            return new_vars
        if self.method is None:
            method = EqualFreq(n=4)
        else:
            method = self.method
        domain = data.domain
        new_attrs = transform_list(domain.attributes, fixed or self.fixed)
        if self.discretize_class:
            new_classes = transform_list(domain.class_vars)
        else:
            new_classes = domain.class_vars
        return Domain(new_attrs, new_classes)

```
--- 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:** TypeError When Binning Sparse Data Due to Unsupported 'isnan' Operation

**Description:**
When using the `EqualWidth` discretization method on sparse data, the process crashes with a `TypeError`. The issue arises because the method attempts to apply `np.isnan` on sparse matrix inputs, which is not supported.

**Example Code:**
```python
import numpy as np
from Orange.preprocess import discretize
from Orange.data import Table

# Create sparse data
X = np.arange(101).reshape((101, 1))
table = Table(X)  # Assuming this creates a sparse table

# Attempt to discretize
disc = discretize.EqualWidth(n=4)
dvar = disc(table, table.domain[0])
```

**Expected Behavior:**
The `EqualWidth` discretization should handle sparse data without errors, correctly computing the minimum and maximum values to perform binning.

**Actual Behavior:**
A `TypeError` is raised:
```
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule 'safe'
```

This error prevents the discretization process from completing successfully when working with sparse datasets.

[/ISSUE]
{
    "test_dirname": "PASSED",
    "TestEqualFreq.test_equifreq_100_to_4": "PASSED",
    "TestEqualFreq.test_equifreq_with_k_instances": "PASSED",
    "TestEqualFreq.test_equifreq_with_too_few_values": "PASSED",
    "TestEqualWidth.test_equalwidth_100_to_4": "PASSED",
    "TestEqualWidth.test_equalwidth_const_value": "PASSED",
    "TestEqualWidth.test_equalwidth_on_two_values": "PASSED",
    "TestEntropyMDL.test_entropy": "PASSED",
    "TestEntropyMDL.test_entropy_constant": "PASSED",
    "TestEntropyMDL.test_entropy_with_two_values": "PASSED",
    "TestEntropyMDL.test_entropy_with_two_values_useless": "PASSED",
    "TestDiscretizer.test_create_discretized_var": "PASSED",
    "TestDiscretizer.test_create_discretized_var_formatting": "PASSED",
    "TestDiscretizer.test_discretize_class": "PASSED",
    "TestDiscretizer.test_discretize_metas": "PASSED",
    "TestDiscretizer.test_discretizer_computation": "PASSED",
    "TestDiscretizer.test_discretizer_computation_sparse_no_points": "PASSED",
    "TestDiscretizer.test_keep_constant": "PASSED",
    "TestDiscretizer.test_remove_constant": "PASSED",
    "TestDiscretizer.test_transform": "PASSED",
    "TestDiscretizeTable.test_discretize_class": "PASSED",
    "TestDiscretizeTable.test_discretize_exclude_constant": "PASSED",
    "TestDiscretizeTable.test_fixed": "PASSED",
    "TestDiscretizeTable.test_leave_discrete": "PASSED",
    "TestDiscretizeTable.test_method": "PASSED",
    "TestInstanceConversion.test_single_instance": "PASSED",
    "TestOWDistributions.test_binning_numeric_variables": "ERROR",
    "TestOWDistributions.test_discretize_meta": "ERROR",
    "TestOWDistributions.test_metas": "ERROR",
    "TestOWDistributions.test_minimum_size": "ERROR",
    "TestOWDistributions.test_no_distributions": "ERROR",
    "TestOWDistributions.test_remove_data": "ERROR",
    "TestOWDistributions.test_variable_group_combinations": "ERROR",
    "TestDiscretizer.test_discretizer_computation_sparse": "FAILED"
}
diff --git a/Orange/preprocess/discretize.py b/Orange/preprocess/discretize.py
index 26c753c86..33c106a19 100644
--- a/Orange/preprocess/discretize.py
+++ b/Orange/preprocess/discretize.py
@@ -6,7 +6,7 @@ import scipy.sparse as sp
 from Orange.data import DiscreteVariable, Domain
 from Orange.data.sql.table import SqlTable
 from Orange.preprocess.util import _RefuseDataInConstructor
-from Orange.statistics import distribution, contingency
+from Orange.statistics import distribution, contingency, util as ut
 from Orange.statistics.basic_stats import BasicStats
 from Orange.util import Reprable
 from .transformation import Transformation
@@ -160,7 +160,7 @@ class EqualWidth(Discretization):
             else:
                 values = data[:, attribute]
                 values = values.X if values.X.size else values.Y
-                min, max = np.nanmin(values), np.nanmax(values)
+                min, max = ut.nanmin(values), ut.nanmax(values)
                 points = self._split_eq_width(min, max)
         return Discretizer.create_discretized_var(
             data.domain[attribute], points)

{"Orange/preprocess/discretize.py": "import re\n\nimport numpy as np\nimport scipy.sparse as sp\n\nfrom Orange.data import DiscreteVariable, Domain\nfrom Orange.data.sql.table import SqlTable\nfrom Orange.preprocess.util import _RefuseDataInConstructor\nfrom Orange.statistics import distribution, contingency\nfrom Orange.statistics.basic_stats import BasicStats\nfrom Orange.util import Reprable\nfrom .transformation import Transformation\nfrom . import _discretize\n\n__all__ = [\"EqualFreq\", \"EqualWidth\", \"EntropyMDL\", \"DomainDiscretizer\"]\n\n\nclass Discretizer(Transformation):\n    \"\"\"Value transformer that returns an index of the bin for the given value.\n    \"\"\"\n    def __init__(self, variable, points):\n        super().__init__(variable)\n        self.points = points\n\n    @staticmethod\n    def digitize(x, bins):\n        if sp.issparse(x):\n            if len(bins):\n                x.data = np.digitize(x.data, bins)\n            else:\n                x = sp.csr_matrix(x.shape)\n            return x\n        else:\n            return np.digitize(x, bins) if len(bins) else [0]*len(x)\n\n    def transform(self, c):\n        if sp.issparse(c):\n            return self.digitize(c, self.points)\n        elif c.size:\n            return np.where(np.isnan(c), np.NaN, self.digitize(c, self.points))\n        else:\n            return np.array([], dtype=int)\n\n    @staticmethod\n    def _fmt_interval(low, high, formatter):\n        assert low is not None or high is not None\n        assert low is None or high is None or low < high\n        if low is None or np.isinf(low):\n            return f\"< {formatter(high)}\"\n        if high is None or np.isinf(high):\n            return f\"\u2265 {formatter(low)}\"\n        return f\"{formatter(low)} - {formatter(high)}\"\n\n    @classmethod\n    def create_discretized_var(cls, var, points):\n        def fmt(val):\n            sval = var.str_val(val)\n            # For decimal numbers, remove trailing 0's and . if no decimals left\n            if re.match(r\"^\\d+\\.\\d+\", sval):\n                return sval.rstrip(\"0\").rstrip(\".\")\n            return sval\n\n        lpoints = list(points)\n        if lpoints:\n            values = [\n                cls._fmt_interval(low, high, fmt)\n                for low, high in zip([-np.inf] + lpoints, lpoints + [np.inf])]\n            to_sql = BinSql(var, lpoints)\n        else:\n            values = [\"single_value\"]\n            to_sql = SingleValueSql(values[0])\n\n        dvar = DiscreteVariable(name=var.name, values=values,\n                                compute_value=cls(var, points),\n                                sparse=var.sparse)\n        dvar.source_variable = var\n        dvar.to_sql = to_sql\n        return dvar\n\n\nclass BinSql:\n    def __init__(self, var, points):\n        self.var = var\n        self.points = points\n\n    def __call__(self):\n        return 'width_bucket(%s, ARRAY%s::double precision[])' % (\n            self.var.to_sql(), str(self.points))\n\n\nclass SingleValueSql:\n    def __init__(self, value):\n        self.value = value\n\n    def __call__(self):\n        return \"'%s'\" % self.value\n\n\nclass Discretization(Reprable):\n    \"\"\"Abstract base class for discretization classes.\"\"\"\n    def __call__(self, data, variable):\n        \"\"\"\n        Compute discretization of the given variable on the given data.\n        Return a new variable with the appropriate domain\n        (:obj:`Orange.data.DiscreteVariable.values`) and transformer\n        (:obj:`Orange.data.Variable.compute_value`).\n        \"\"\"\n        raise NotImplementedError(\n            \"Subclasses of 'Discretization' need to implement \"\n            \"the call operator\")\n\n\nclass EqualFreq(Discretization):\n    \"\"\"Discretization into bins with approximately equal number of data\n    instances.\n\n    .. attribute:: n\n\n        Number of bins (default: 4). The actual number may be lower if the\n        variable has less than n distinct values.\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute):\n        if type(data) == SqlTable:\n            att = attribute.to_sql()\n            quantiles = [(i + 1) / self.n for i in range(self.n - 1)]\n            query = data._sql_query(\n                ['quantile(%s, ARRAY%s)' % (att, str(quantiles))],\n                use_time_sample=1000)\n            with data._execute_sql_query(query) as cur:\n                points = sorted(set(cur.fetchone()[0]))\n        else:\n            d = distribution.get_distribution(data, attribute)\n            points = _discretize.split_eq_freq(d, self.n)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\nclass EqualWidth(Discretization):\n    \"\"\"Discretization into a fixed number of bins with equal widths.\n\n    .. attribute:: n\n\n        Number of bins (default: 4).\n    \"\"\"\n    def __init__(self, n=4):\n        self.n = n\n\n    # noinspection PyProtectedMember\n    def __call__(self, data, attribute, fixed=None):\n        if fixed:\n            min, max = fixed[attribute.name]\n            points = self._split_eq_width(min, max)\n        else:\n            if type(data) == SqlTable:\n                stats = BasicStats(data, attribute)\n                points = self._split_eq_width(stats.min, stats.max)\n            else:\n                values = data[:, attribute]\n                values = values.X if values.X.size else values.Y\n                min, max = np.nanmin(values), np.nanmax(values)\n                points = self._split_eq_width(min, max)\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    def _split_eq_width(self, min, max):\n        if np.isnan(min) or np.isnan(max) or min == max:\n            return []\n        dif = (max - min) / self.n\n        return [min + (i + 1) * dif for i in range(self.n - 1)]\n\n\n# noinspection PyPep8Naming\nclass EntropyMDL(Discretization):\n    \"\"\"\n    Discretization into bins inferred by recursively splitting the values to\n    minimize the class-entropy. The procedure stops when further splits would\n    decrease the entropy for less than the corresponding increase of minimal\n    description length (MDL). [FayyadIrani93].\n\n    If there are no suitable cut-off points, the procedure returns a single bin,\n    which means that the new feature is constant and can be removed.\n\n    .. attribute:: force\n\n        Induce at least one cut-off point, even when its information\n        gain is lower than MDL (default: False).\n\n    \"\"\"\n    def __init__(self, force=False):\n        self.force = force\n\n    def __call__(self, data, attribute):\n        cont = contingency.get_contingency(data, attribute)\n        values, I = cont.values, cont.counts.T\n        cut_ind = np.array(self._entropy_discretize_sorted(I, self.force))\n        if len(cut_ind) > 0:\n            # \"the midpoint between each successive pair of examples\" (FI p.1)\n            points = (values[cut_ind] + values[cut_ind - 1]) / 2.\n        else:\n            points = []\n        return Discretizer.create_discretized_var(\n            data.domain[attribute], points)\n\n    @classmethod\n    def _normalize(cls, X, axis=None, out=None):\n        \"\"\"\n        Normalize `X` array so it sums to 1.0 over the `axis`.\n\n        Parameters\n        ----------\n        X : array\n            Array to normalize.\n        axis : optional int\n            Axis over which the resulting array sums to 1.\n        out : optional array\n            Output array of the same shape as X.\n        \"\"\"\n        X = np.asarray(X, dtype=float)\n        scale = np.sum(X, axis=axis, keepdims=True)\n        if out is None:\n            return X / scale\n        else:\n            if out is not X:\n                assert out.shape == X.shape\n                out[:] = X\n            out /= scale\n            return out\n\n    @classmethod\n    def _entropy_normalized(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution array `D`.\n\n        `D` must be a distribution (i.e. sum to 1.0 over `axis`)\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        # req: (np.sum(D, axis=axis) >= 0).all()\n        # req: (np.sum(D, axis=axis) <= 1).all()\n        # req: np.all(np.abs(np.sum(D, axis=axis) - 1) < 1e-9)\n\n        D = np.asarray(D)\n        Dc = np.clip(D, np.finfo(D.dtype).eps, 1.0)\n        return - np.sum(D * np.log2(Dc), axis=axis)\n\n    @classmethod\n    def _entropy(cls, D, axis=None):\n        \"\"\"\n        Compute the entropy of distribution `D`.\n\n        Parameters\n        ----------\n        D : array\n            Distribution.\n        axis : optional int\n            Axis of `D` along which to compute the entropy.\n\n        \"\"\"\n        D = cls._normalize(D, axis=axis)\n        return cls._entropy_normalized(D, axis=axis)\n\n    @classmethod\n    def _entropy1(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D)\n        return _discretize.entropy_normalized1(D)\n\n    @classmethod\n    def _entropy2(cls, D):\n        \"\"\"\n        Compute the entropy of distributions in `D`\n        (one per each row).\n        \"\"\"\n        D = cls._normalize(D, axis=1)\n        return _discretize.entropy_normalized2(D)\n\n    @classmethod\n    def _entropy_cuts_sorted(cls, CS):\n        \"\"\"\n        Return the class information entropy induced by partitioning\n        the `CS` distribution at all N-1 candidate cut points.\n\n        Parameters\n        ----------\n        CS : (N, K) array of class distributions.\n        \"\"\"\n        CS = np.asarray(CS)\n        # |--|-------|--------|\n        #  S1    ^       S2\n        # S1 contains all points which are <= to cut point\n        # Cumulative distributions for S1 and S2 (left right set)\n        # i.e. a cut at index i separates the CS into S1Dist[i] and S2Dist[i]\n        S1Dist = np.cumsum(CS, axis=0)[:-1]\n        S2Dist = np.cumsum(CS[::-1], axis=0)[-2::-1]\n\n        # Entropy of S1[i] and S2[i] sets\n        ES1 = cls._entropy2(S1Dist)\n        ES2 = cls._entropy2(S2Dist)\n\n        # Number of cases in S1[i] and S2[i] sets\n        S1_count = np.sum(S1Dist, axis=1)\n        S2_count = np.sum(S2Dist, axis=1)\n\n        # Number of all cases\n        S_count = np.sum(CS)\n\n        ES1w = ES1 * S1_count / S_count\n        ES2w = ES2 * S2_count / S_count\n\n        # E(A, T; S) Class information entropy of the partition S\n        E = ES1w + ES2w\n\n        return E, ES1, ES2\n\n    @classmethod\n    def _entropy_discretize_sorted(cls, C, force=False):\n        \"\"\"\n        Entropy discretization on a sorted C.\n\n        :param C: (N, K) array of class distributions.\n\n        \"\"\"\n        E, ES1, ES2 = cls._entropy_cuts_sorted(C)\n        # TODO: Also get the left right distribution counts from\n        # entropy_cuts_sorted,\n\n        # Note the + 1\n        if len(E) == 0:\n            return []\n        cut_index = np.argmin(E) + 1\n\n        # Distribution of classed in S1, S2 and S\n        S1_c = np.sum(C[:cut_index], axis=0)\n        S2_c = np.sum(C[cut_index:], axis=0)\n        S_c = S1_c + S2_c\n\n        ES = cls._entropy1(np.sum(C, axis=0))\n        ES1, ES2 = ES1[cut_index - 1], ES2[cut_index - 1]\n\n        # Information gain of the best split\n        Gain = ES - E[cut_index - 1]\n        # Number of different classes in S, S1 and S2\n        k = float(np.sum(S_c > 0))\n        k1 = float(np.sum(S1_c > 0))\n        k2 = float(np.sum(S2_c > 0))\n\n        assert k > 0\n        delta = np.log2(3 ** k - 2) - (k * ES - k1 * ES1 - k2 * ES2)\n        N = float(np.sum(S_c))\n\n        if Gain > np.log2(N - 1) / N + delta / N:\n            # Accept the cut point and recursively split the subsets.\n            left, right = [], []\n            if k1 > 1 and cut_index > 1:\n                left = cls._entropy_discretize_sorted(C[:cut_index, :])\n            if k2 > 1 and cut_index < len(C) - 1:\n                right = cls._entropy_discretize_sorted(C[cut_index:, :])\n            return left + [cut_index] + [i + cut_index for i in right]\n        elif force:\n            return [cut_index]\n        else:\n            return []\n\n\nclass DomainDiscretizer(_RefuseDataInConstructor, Reprable):\n    \"\"\"Discretizes all continuous features in the data.\n\n    .. attribute:: method\n\n        Feature discretization method (instance of\n        :obj:`Orange.preprocess.Discretization`). If `None` (default),\n        :class:`Orange.preprocess.EqualFreq` with 4 intervals is\n        used.\n\n    .. attribute:: clean\n\n        If `True`, features discretized into a single interval constant are\n        removed. This is useful for discretization methods that infer the\n        number of intervals from the data, such as\n        :class:`Orange.preprocess.EntropyMDL` (default: `True`).\n\n    .. attribute:: discretize_class\n\n        Determines whether a target is also discretized if it is continuous.\n        (default: `False`)\n    \"\"\"\n    def __init__(self, discretize_class=False, method=None, clean=True,\n                 fixed=None):\n        self.discretize_class = discretize_class\n        self.method = method\n        self.clean = clean\n        self.fixed = fixed\n\n    def __call__(self, data, fixed=None):\n        \"\"\"\n        Compute and return discretized domain.\n\n        :param data: Data to discretize.\n        \"\"\"\n\n        def transform_list(s, fixed=None):\n            new_vars = []\n            for var in s:\n                if var.is_continuous:\n                    if fixed and var.name in fixed.keys():\n                        nv = method(data, var, fixed)\n                    else:\n                        nv = method(data, var)\n                    if not self.clean or len(nv.values) > 1:\n                        new_vars.append(nv)\n                else:\n                    new_vars.append(var)\n            return new_vars\n        if self.method is None:\n            method = EqualFreq(n=4)\n        else:\n            method = self.method\n        domain = data.domain\n        new_attrs = transform_list(domain.attributes, fixed or self.fixed)\n        if self.discretize_class:\n            new_classes = transform_list(domain.class_vars)\n        else:\n            new_classes = domain.class_vars\n        return Domain(new_attrs, new_classes)\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:** TypeError When Binning Sparse Data Due to Unsupported 'isnan' Operation

**Description:**
When using the `EqualWidth` discretization method on sparse data, the process crashes with a `TypeError`. The issue arises because the method attempts to apply `np.isnan` on sparse matrix inputs, which is not supported.

**Example Code:**
```python
import numpy as np
from Orange.preprocess import discretize
from Orange.data import Table

# Create sparse data
X = np.arange(101).reshape((101, 1))
table = Table(X)  # Assuming this creates a sparse table

# Attempt to discretize
disc = discretize.EqualWidth(n=4)
dvar = disc(table, table.domain[0])
```

**Expected Behavior:**
The `EqualWidth` discretization should handle sparse data without errors, correctly computing the minimum and maximum values to perform binning.

**Actual Behavior:**
A `TypeError` is raised:
```
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule 'safe'
```

This error prevents the discretization process from completing successfully when working with sparse datasets.

[/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/preprocess/discretize.py
import re

import numpy as np
import scipy.sparse as sp

from Orange.data import DiscreteVariable, Domain
from Orange.data.sql.table import SqlTable
from Orange.preprocess.util import _RefuseDataInConstructor
from Orange.statistics import distribution, contingency
from Orange.statistics.basic_stats import BasicStats
from Orange.util import Reprable
from .transformation import Transformation
from . import _discretize

__all__ = ["EqualFreq", "EqualWidth", "EntropyMDL", "DomainDiscretizer"]


class Discretizer(Transformation):
    """Value transformer that returns an index of the bin for the given value.
    """
    def __init__(self, variable, points):
        super().__init__(variable)
        self.points = points

    @staticmethod
    def digitize(x, bins):
        if sp.issparse(x):
            if len(bins):
                x.data = np.digitize(x.data, bins)
            else:
                x = sp.csr_matrix(x.shape)
            return x
        else:
            return np.digitize(x, bins) if len(bins) else [0]*len(x)

    def transform(self, c):
        if sp.issparse(c):
            return self.digitize(c, self.points)
        elif c.size:
            return np.where(np.isnan(c), np.NaN, self.digitize(c, self.points))
        else:
            return np.array([], dtype=int)

    @staticmethod
    def _fmt_interval(low, high, formatter):
        assert low is not None or high is not None
        assert low is None or high is None or low < high
        if low is None or np.isinf(low):
            return f"< {formatter(high)}"
        if high is None or np.isinf(high):
            return f"≥ {formatter(low)}"
        return f"{formatter(low)} - {formatter(high)}"

    @classmethod
    def create_discretized_var(cls, var, points):
        def fmt(val):
            sval = var.str_val(val)
            # For decimal numbers, remove trailing 0's and . if no decimals left
            if re.match(r"^\d+\.\d+", sval):
                return sval.rstrip("0").rstrip(".")
            return sval

        lpoints = list(points)
        if lpoints:
            values = [
                cls._fmt_interval(low, high, fmt)
                for low, high in zip([-np.inf] + lpoints, lpoints + [np.inf])]
            to_sql = BinSql(var, lpoints)
        else:
            values = ["single_value"]
            to_sql = SingleValueSql(values[0])

        dvar = DiscreteVariable(name=var.name, values=values,
                                compute_value=cls(var, points),
                                sparse=var.sparse)
        dvar.source_variable = var
        dvar.to_sql = to_sql
        return dvar


class BinSql:
    def __init__(self, var, points):
        self.var = var
        self.points = points

    def __call__(self):
        return 'width_bucket(%s, ARRAY%s::double precision[])' % (
            self.var.to_sql(), str(self.points))


class SingleValueSql:
    def __init__(self, value):
        self.value = value

    def __call__(self):
        return "'%s'" % self.value


class Discretization(Reprable):
    """Abstract base class for discretization classes."""
    def __call__(self, data, variable):
        """
        Compute discretization of the given variable on the given data.
        Return a new variable with the appropriate domain
        (:obj:`Orange.data.DiscreteVariable.values`) and transformer
        (:obj:`Orange.data.Variable.compute_value`).
        """
        raise NotImplementedError(
            "Subclasses of 'Discretization' need to implement "
            "the call operator")


class EqualFreq(Discretization):
    """Discretization into bins with approximately equal number of data
    instances.

    .. attribute:: n

        Number of bins (default: 4). The actual number may be lower if the
        variable has less than n distinct values.
    """
    def __init__(self, n=4):
        self.n = n

    # noinspection PyProtectedMember
    def __call__(self, data, attribute):
        if type(data) == SqlTable:
            att = attribute.to_sql()
            quantiles = [(i + 1) / self.n for i in range(self.n - 1)]
            query = data._sql_query(
                ['quantile(%s, ARRAY%s)' % (att, str(quantiles))],
                use_time_sample=1000)
            with data._execute_sql_query(query) as cur:
                points = sorted(set(cur.fetchone()[0]))
        else:
            d = distribution.get_distribution(data, attribute)
            points = _discretize.split_eq_freq(d, self.n)
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

class EqualWidth(Discretization):
    """Discretization into a fixed number of bins with equal widths.

    .. attribute:: n

        Number of bins (default: 4).
    """
    def __init__(self, n=4):
        self.n = n

    # noinspection PyProtectedMember
    def __call__(self, data, attribute, fixed=None):
        if fixed:
            min, max = fixed[attribute.name]
            points = self._split_eq_width(min, max)
        else:
            if type(data) == SqlTable:
                stats = BasicStats(data, attribute)
                points = self._split_eq_width(stats.min, stats.max)
            else:
                values = data[:, attribute]
                values = values.X if values.X.size else values.Y
                min, max = np.nanmin(values), np.nanmax(values)
                points = self._split_eq_width(min, max)
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

    def _split_eq_width(self, min, max):
        if np.isnan(min) or np.isnan(max) or min == max:
            return []
        dif = (max - min) / self.n
        return [min + (i + 1) * dif for i in range(self.n - 1)]


# noinspection PyPep8Naming
class EntropyMDL(Discretization):
    """
    Discretization into bins inferred by recursively splitting the values to
    minimize the class-entropy. The procedure stops when further splits would
    decrease the entropy for less than the corresponding increase of minimal
    description length (MDL). [FayyadIrani93].

    If there are no suitable cut-off points, the procedure returns a single bin,
    which means that the new feature is constant and can be removed.

    .. attribute:: force

        Induce at least one cut-off point, even when its information
        gain is lower than MDL (default: False).

    """
    def __init__(self, force=False):
        self.force = force

    def __call__(self, data, attribute):
        cont = contingency.get_contingency(data, attribute)
        values, I = cont.values, cont.counts.T
        cut_ind = np.array(self._entropy_discretize_sorted(I, self.force))
        if len(cut_ind) > 0:
            # "the midpoint between each successive pair of examples" (FI p.1)
            points = (values[cut_ind] + values[cut_ind - 1]) / 2.
        else:
            points = []
        return Discretizer.create_discretized_var(
            data.domain[attribute], points)

    @classmethod
    def _normalize(cls, X, axis=None, out=None):
        """
        Normalize `X` array so it sums to 1.0 over the `axis`.

        Parameters
        ----------
        X : array
            Array to normalize.
        axis : optional int
            Axis over which the resulting array sums to 1.
        out : optional array
            Output array of the same shape as X.
        """
        X = np.asarray(X, dtype=float)
        scale = np.sum(X, axis=axis, keepdims=True)
        if out is None:
            return X / scale
        else:
            if out is not X:
                assert out.shape == X.shape
                out[:] = X
            out /= scale
            return out

    @classmethod
    def _entropy_normalized(cls, D, axis=None):
        """
        Compute the entropy of distribution array `D`.

        `D` must be a distribution (i.e. sum to 1.0 over `axis`)

        Parameters
        ----------
        D : array
            Distribution.
        axis : optional int
            Axis of `D` along which to compute the entropy.

        """
        # req: (np.sum(D, axis=axis) >= 0).all()
        # req: (np.sum(D, axis=axis) <= 1).all()
        # req: np.all(np.abs(np.sum(D, axis=axis) - 1) < 1e-9)

        D = np.asarray(D)
        Dc = np.clip(D, np.finfo(D.dtype).eps, 1.0)
        return - np.sum(D * np.log2(Dc), axis=axis)

    @classmethod
    def _entropy(cls, D, axis=None):
        """
        Compute the entropy of distribution `D`.

        Parameters
        ----------
        D : array
            Distribution.
        axis : optional int
            Axis of `D` along which to compute the entropy.

        """
        D = cls._normalize(D, axis=axis)
        return cls._entropy_normalized(D, axis=axis)

    @classmethod
    def _entropy1(cls, D):
        """
        Compute the entropy of distributions in `D`
        (one per each row).
        """
        D = cls._normalize(D)
        return _discretize.entropy_normalized1(D)

    @classmethod
    def _entropy2(cls, D):
        """
        Compute the entropy of distributions in `D`
        (one per each row).
        """
        D = cls._normalize(D, axis=1)
        return _discretize.entropy_normalized2(D)

    @classmethod
    def _entropy_cuts_sorted(cls, CS):
        """
        Return the class information entropy induced by partitioning
        the `CS` distribution at all N-1 candidate cut points.

        Parameters
        ----------
        CS : (N, K) array of class distributions.
        """
        CS = np.asarray(CS)
        # |--|-------|--------|
        #  S1    ^       S2
        # S1 contains all points which are <= to cut point
        # Cumulative distributions for S1 and S2 (left right set)
        # i.e. a cut at index i separates the CS into S1Dist[i] and S2Dist[i]
        S1Dist = np.cumsum(CS, axis=0)[:-1]
        S2Dist = np.cumsum(CS[::-1], axis=0)[-2::-1]

        # Entropy of S1[i] and S2[i] sets
        ES1 = cls._entropy2(S1Dist)
        ES2 = cls._entropy2(S2Dist)

        # Number of cases in S1[i] and S2[i] sets
        S1_count = np.sum(S1Dist, axis=1)
        S2_count = np.sum(S2Dist, axis=1)

        # Number of all cases
        S_count = np.sum(CS)

        ES1w = ES1 * S1_count / S_count
        ES2w = ES2 * S2_count / S_count

        # E(A, T; S) Class information entropy of the partition S
        E = ES1w + ES2w

        return E, ES1, ES2

    @classmethod
    def _entropy_discretize_sorted(cls, C, force=False):
        """
        Entropy discretization on a sorted C.

        :param C: (N, K) array of class distributions.

        """
        E, ES1, ES2 = cls._entropy_cuts_sorted(C)
        # TODO: Also get the left right distribution counts from
        # entropy_cuts_sorted,

        # Note the + 1
        if len(E) == 0:
            return []
        cut_index = np.argmin(E) + 1

        # Distribution of classed in S1, S2 and S
        S1_c = np.sum(C[:cut_index], axis=0)
        S2_c = np.sum(C[cut_index:], axis=0)
        S_c = S1_c + S2_c

        ES = cls._entropy1(np.sum(C, axis=0))
        ES1, ES2 = ES1[cut_index - 1], ES2[cut_index - 1]

        # Information gain of the best split
        Gain = ES - E[cut_index - 1]
        # Number of different classes in S, S1 and S2
        k = float(np.sum(S_c > 0))
        k1 = float(np.sum(S1_c > 0))
        k2 = float(np.sum(S2_c > 0))

        assert k > 0
        delta = np.log2(3 ** k - 2) - (k * ES - k1 * ES1 - k2 * ES2)
        N = float(np.sum(S_c))

        if Gain > np.log2(N - 1) / N + delta / N:
            # Accept the cut point and recursively split the subsets.
            left, right = [], []
            if k1 > 1 and cut_index > 1:
                left = cls._entropy_discretize_sorted(C[:cut_index, :])
            if k2 > 1 and cut_index < len(C) - 1:
                right = cls._entropy_discretize_sorted(C[cut_index:, :])
            return left + [cut_index] + [i + cut_index for i in right]
        elif force:
            return [cut_index]
        else:
            return []


class DomainDiscretizer(_RefuseDataInConstructor, Reprable):
    """Discretizes all continuous features in the data.

    .. attribute:: method

        Feature discretization method (instance of
        :obj:`Orange.preprocess.Discretization`). If `None` (default),
        :class:`Orange.preprocess.EqualFreq` with 4 intervals is
        used.

    .. attribute:: clean

        If `True`, features discretized into a single interval constant are
        removed. This is useful for discretization methods that infer the
        number of intervals from the data, such as
        :class:`Orange.preprocess.EntropyMDL` (default: `True`).

    .. attribute:: discretize_class

        Determines whether a target is also discretized if it is continuous.
        (default: `False`)
    """
    def __init__(self, discretize_class=False, method=None, clean=True,
                 fixed=None):
        self.discretize_class = discretize_class
        self.method = method
        self.clean = clean
        self.fixed = fixed

    def __call__(self, data, fixed=None):
        """
        Compute and return discretized domain.

        :param data: Data to discretize.
        """

        def transform_list(s, fixed=None):
            new_vars = []
            for var in s:
                if var.is_continuous:
                    if fixed and var.name in fixed.keys():
                        nv = method(data, var, fixed)
                    else:
                        nv = method(data, var)
                    if not self.clean or len(nv.values) > 1:
                        new_vars.append(nv)
                else:
                    new_vars.append(var)
            return new_vars
        if self.method is None:
            method = EqualFreq(n=4)
        else:
            method = self.method
        domain = data.domain
        new_attrs = transform_list(domain.attributes, fixed or self.fixed)
        if self.discretize_class:
            new_classes = transform_list(domain.class_vars)
        else:
            new_classes = domain.class_vars
        return Domain(new_attrs, new_classes)

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