File: collections.py

package info (click to toggle)
orange3 3.40.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,912 kB
  • sloc: python: 162,745; ansic: 622; makefile: 322; sh: 93; cpp: 77
file content (109 lines) | stat: -rw-r--r-- 3,019 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import re
from typing import List, Iterable


class frozendict(dict):
    def clear(self):
        raise AttributeError("FrozenDict does not support method 'clear'")

    def pop(self, _k):
        raise AttributeError("FrozenDict does not support method 'pop'")

    def popitem(self):
        raise AttributeError("FrozenDict does not support method 'popitem'")

    def setdefault(self, _k, _v):
        raise AttributeError("FrozenDict does not support method 'setdefault'")

    def update(self, _d):
        raise AttributeError("FrozenDict does not support method 'update'")

    def __setitem__(self, _key, _value):
        raise AttributeError("FrozenDict does not allow setting elements")

    def __delitem__(self, _key):
        raise AttributeError("FrozenDict does not allow deleting elements")


def natural_sorted(values: Iterable) -> List:
    """
    Sort values with natural sort or human order - [sth1, sth2, sth10] or
    [1, 2, 10]

    Parameters
    ----------
    values
        List with values to sort

    Returns
    -------
    List with sorted values
    """
    def atoi(text):
        return int(text) if text.isdigit() else text

    def natural_keys(element):
        """
        alist.sort(key=natural_keys) or sorted(alist, key=natural_keys) sorts
        in human order
        """
        if isinstance(element, (str, bytes)):
            return [atoi(c) for c in re.split(r'(\d+)', element)]
        else:
            return element

    return sorted(values, key=natural_keys)


class DictMissingConst(dict):
    """
    `dict` with a constant for `__missing__()` value.

    This is mostly used for speed optimizations where
    `DictMissingConst(default, d).__getitem__(k)` is the least overhead
    equivalent to `d.get(k, default)` in the case where misses are not
    frequent by avoiding LOAD_* bytecode instructions for `default` at
    every call.

    Note
    ----
    This differs from `defaultdict(lambda: CONST)` in that misses do not
    grow the dict.

    Parameters
    ----------
    missing: Any
        The missing constant
    *args
    **kwargs
        The `*args`, and `**kwargs` are passed to `dict` constructor.
    """
    __slots__ = ("__missing",)

    def __init__(self, missing, *args, **kwargs):
        self.__missing = missing
        super().__init__(*args, **kwargs)

    @property
    def missing(self):
        return self.__missing

    def __missing__(self, key):
        return self.__missing

    def __eq__(self, other):
        return super().__eq__(other) and isinstance(other, DictMissingConst) \
            and self.missing == other.missing

    def __ne__(self, other):
        return not self.__eq__(other)

    def __reduce_ex__(self, protocol):
        return type(self), (self.missing, list(self.items())), \
               getattr(self, "__dict__", None)

    def copy(self):
        return type(self)(self.missing, self)

    def __repr__(self):
        return f"{type(self).__qualname__}({self.missing!r}, {dict(self)!r})"