typish.classes._cls_dict.ClsDict.__new__()   A
last analyzed

Complexity

Conditions 5

Size

Total Lines 18
Code Lines 9

Duplication

Lines 18
Ratio 100 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nop 3
dl 18
loc 18
rs 9.3333
c 0
b 0
f 0
1
from collections import OrderedDict
2
from typing import Optional, Any
3
4
5 View Code Duplication
class ClsDict(OrderedDict):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
6
    """
7
    ClsDict is a dict that accepts (only) types as keys and will return its
8
    values depending on instance checks rather than equality checks.
9
    """
10
    def __new__(cls, *args, **kwargs):
11
        """
12
        Construct a new instance of ``ClsDict``.
13
        :param args: a dict.
14
        :param kwargs: any kwargs that ``dict`` accepts.
15
        :return: a ``ClsDict``.
16
        """
17
        from typish.functions._is_type_annotation import is_type_annotation
18
19
        if len(args) > 1:
20
            raise TypeError('TypeDict accepts only one positional argument, '
21
                            'which must be a dict.')
22
        if args and not isinstance(args[0], dict):
23
            raise TypeError('TypeDict accepts only a dict as positional '
24
                            'argument.')
25
        if not all([is_type_annotation(key) for key in args[0]]):
26
            raise TypeError('The given dict must only hold types as keys.')
27
        return super().__new__(cls, args[0], **kwargs)
28
29
    def __getitem__(self, item: Any) -> Any:
30
        """
31
        Return the value of the first encounter of a key for which
32
        ``is_instance(item, key)`` holds ``True``.
33
        :param item: any item.
34
        :return: the value of which the type corresponds with item.
35
        """
36
        from typish.functions._get_type import get_type
37
        from typish.functions._subclass_of import subclass_of
38
39
        item_type = get_type(item, use_union=True)
40
        for key, value in self.items():
41
            if subclass_of(item_type, key):
42
                return value
43
        raise KeyError('No match for {}'.format(item))
44
45
    def get(self, item: Any, default: Any = None) -> Optional[Any]:
46
        try:
47
            return self.__getitem__(item)
48
        except KeyError:
49
            return default
50