Skip to content

Commit

Permalink
Merge pull request #6613 from janezd/util-lint
Browse files Browse the repository at this point in the history
Orange.utils: Some random pylinting
  • Loading branch information
PrimozGodec committed Nov 3, 2023
2 parents 5412e74 + 83241f3 commit 5555314
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 28 deletions.
58 changes: 50 additions & 8 deletions Orange/tests/test_util.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from itertools import count
import os
import unittest
import warnings
Expand All @@ -6,8 +7,7 @@
import scipy.sparse as sp

from Orange.util import export_globals, flatten, deprecated, try_, deepgetattr, \
OrangeDeprecationWarning, nan_eq, nan_hash_stand
from Orange.data import Table
OrangeDeprecationWarning, nan_eq, nan_hash_stand, Registry, namegen
from Orange.data.util import vstack, hstack, array_equal
from Orange.statistics.util import stats
from Orange.tests.test_statistics import dense_sparse
Expand Down Expand Up @@ -43,10 +43,11 @@ def identity(x):

def test_try_(self):
self.assertTrue(try_(lambda: np.ones(3).any()))
self.assertFalse(try_(lambda: np.whatever()))
self.assertFalse(try_(lambda: 1 / 0))
self.assertEqual(try_(len, default=SOMETHING), SOMETHING)

def test_reprable(self):
# pylint: disable=import-outside-toplevel
from Orange.data import ContinuousVariable
from Orange.preprocess.impute import ReplaceUnknownsRandom
from Orange.statistics.distribution import Continuous
Expand All @@ -66,7 +67,7 @@ def test_reprable(self):
self.assertEqual(repr(logit), 'LogisticRegressionLearner()')

def test_deepgetattr(self):
class a:
class a: # pylint: disable=invalid-name
l = []
self.assertTrue(deepgetattr(a, 'l.__len__.__call__'), a.l.__len__.__call__)
self.assertTrue(deepgetattr(a, 'l.__nx__.__x__', 42), 42)
Expand Down Expand Up @@ -134,10 +135,8 @@ def test_raise_deprecations(self):
warnings.warn('foo', OrangeDeprecationWarning)

def test_stats_sparse(self):
"""
Stats should not fail when trying to calculate mean on sparse data.
GH-2357
"""
# pylint: disable=import-outside-toplevel
from Orange.data import Table
data = Table("iris")
sparse_x = sp.csr_matrix(data.X)
self.assertTrue(stats(data.X).all() == stats(sparse_x).all())
Expand Down Expand Up @@ -198,6 +197,49 @@ def func(i):
self.assertEqual(f(0.1), 0.17)
self.assertEqual(f(1), 0.8)

def test_registry(self):
# pylint: disable=invalid-name, unused-variable
class A(metaclass=Registry):
pass

class BBB(A):
pass

class CC(A):
pass

class DDDD(BBB):
pass

self.assertEqual(set(A), {"BBB", "CC", "DDDD"})
self.assertEqual(str(A), "A({BBB, CC, DDDD})")

class D(metaclass=Registry):
pass

self.assertEqual(set(A), {"BBB", "CC", "DDDD"})
self.assertEqual(str(A), "A({BBB, CC, DDDD})")
self.assertEqual(set(D), set())
self.assertEqual(str(D), "D({})")

class E(D):
pass

self.assertEqual(set(A), {"BBB", "CC", "DDDD"})
self.assertEqual(str(A), "A({BBB, CC, DDDD})")
self.assertEqual(set(D), set("E"))
self.assertEqual(str(D), "D({E})")

def test_namegen(self):
self.assertEqual([name for name, _ in zip(namegen(), range(3))],
["_0", "_1", "_2"])

self.assertEqual([name for name, _ in zip(namegen("foo "), range(3))],
["foo 0", "foo 1", "foo 2"])

self.assertEqual([name for name, _ in zip(namegen("foo ", 2, spec_count=count), range(3))],
["foo 2", "foo 3", "foo 4"])


if __name__ == "__main__":
unittest.main()
46 changes: 26 additions & 20 deletions Orange/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from operator import attrgetter
from itertools import chain, count, repeat

from collections import OrderedDict, namedtuple
from collections import namedtuple
import warnings

# Exposed here for convenience. Prefer patching to try-finally blocks
Expand Down Expand Up @@ -161,18 +161,18 @@ def deprecated(obj):
... return 'new behavior'
>>> C().old() # doctest: +SKIP
/... OrangeDeprecationWarning: Call to deprecated ... C.old ...
Instead, use C.new() ...
use use C.new() instead ...
'old behavior'
"""
alternative = ('; Instead, use ' + obj) if isinstance(obj, str) else ''
alternative = f'; use {obj} instead' if isinstance(obj, str) else ''

def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
name = '{}.{}'.format(
func.__self__.__class__,
func.__name__) if hasattr(func, '__self__') else func
warnings.warn('Call to deprecated {}{}'.format(name, alternative),
name = func.__name__
if hasattr(func, "__self__"):
name = f'{func.__self__.__class__}.{name}'
warnings.warn(f'Call to deprecated {name}{alternative}',
OrangeDeprecationWarning, stacklevel=2)
return func(*args, **kwargs)
return wrapper
Expand All @@ -181,7 +181,7 @@ def wrapper(*args, **kwargs):


def literal_eval(literal):
import ast
import ast # pylint: disable=import-outside-toplevel
# ast.literal_eval does not parse empty set ¯\_(ツ)_/¯

if literal == "set()":
Expand Down Expand Up @@ -225,11 +225,11 @@ def requirementsSatisfied(required_state, local_state, req_type=None):
for req_string in required_state:
# parse requirement
req = None
for op_str in op_map:
for op_str, op in op_map.items():
split = req_string.split(op_str)
# if operation is not in req_string, continue
if len(split) == 2:
req = _Requirement(split[0], op_map[op_str], split[1])
req = _Requirement(split[0], op, split[1])
break

if req is None:
Expand Down Expand Up @@ -269,7 +269,7 @@ class Registry(type):
def __new__(mcs, name, bases, attrs):
cls = type.__new__(mcs, name, bases, attrs)
if not hasattr(cls, 'registry'):
cls.registry = OrderedDict()
cls.registry = {}
else:
cls.registry[name] = cls
return cls
Expand All @@ -280,11 +280,14 @@ def __iter__(cls):
def __str__(cls):
if cls in cls.registry.values():
return cls.__name__
return '{}({{{}}})'.format(cls.__name__, ', '.join(cls.registry))
return f'{cls.__name__}({{{", ".join(cls.registry)}}})'


# it is what it is, we keep for compatibility:
# pylint: disable=keyword-arg-before-vararg
def namegen(prefix='_', *args, spec_count=count, **kwargs):
"""Continually generate names with `prefix`, e.g. '_1', '_2', ..."""
# pylint: disable=stop-iteration-return
spec_count = iter(spec_count(*args, **kwargs))
while True:
yield prefix + str(next(spec_count))
Expand Down Expand Up @@ -325,6 +328,7 @@ def deepgetattr(obj, attr, default=_NOTSET):


def color_to_hex(color):
# pylint: disable=consider-using-f-string
return "#{:02X}{:02X}{:02X}".format(*color)


Expand All @@ -337,9 +341,9 @@ def inherit_docstrings(cls):
for method in cls.__dict__.values():
if inspect.isfunction(method) and method.__doc__ is None:
for parent in cls.__mro__[1:]:
__doc__ = getattr(parent, method.__name__, None).__doc__
if __doc__:
method.__doc__ = __doc__
doc = getattr(parent, method.__name__, None).__doc__
if doc:
method.__doc__ = doc
break
return cls

Expand Down Expand Up @@ -379,7 +383,7 @@ def interleave(seq1, seq2):
def Reprable_repr_pretty(name, itemsiter, printer, cycle):
# type: (str, Iterable[Tuple[str, Any]], Ipython.lib.pretty.PrettyPrinter, bool) -> None
if cycle:
printer.text("{0}(...)".format("name"))
printer.text(f"{name}(...)")
else:
def printitem(field, value):
printer.text(field + "=")
Expand All @@ -392,9 +396,10 @@ def printsep():
itemsiter = (partial(printitem, *item) for item in itemsiter)
sepiter = repeat(printsep)

with printer.group(len(name) + 1, "{0}(".format(name), ")"):
with printer.group(len(name) + 1, f"{name}(", ")"):
for part in interleave(itemsiter, sepiter):
part()
part()


class _Undef:
Expand Down Expand Up @@ -458,6 +463,7 @@ def _reprable_fields(self):
param.kind not in (param.VAR_POSITIONAL, param.VAR_KEYWORD):
yield param.name, param.default

# pylint: disable=unused-argument
def _reprable_omit_param(self, name, default, value):
if default is value:
return True
Expand Down Expand Up @@ -503,9 +509,9 @@ def __repr__(self):
nameparts = (([str(module)] if module else []) +
[self.__class__.__name__])
name = ".".join(nameparts)
return "{}({})".format(
name, ", ".join("{}={!r}".format(f, v) for f, _, v in self._reprable_items())
)
items = ", ".join(f"{f}={repr(v)}"
for f, _, v in self._reprable_items())
return f"{name}({items})"


def wrap_callback(progress_callback, start=0, end=1):
Expand Down

0 comments on commit 5555314

Please sign in to comment.