Passed
Push — master ( c07ac7...918a2a )
by Max
55s
created

structured_data._patterns.Bind.structure()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
import keyword
2
3
from ._not_in import not_in
4
5
DISCARD = object()
6
7
8
class Pattern(tuple):
9
    """A matcher that binds a value to a name."""
10
11
    __slots__ = ()
12
13
    def __new__(cls, name: str):
14
        if name == "_":
15
            return DISCARD
16
        if not name.isidentifier():
17
            raise ValueError
18
        if keyword.iskeyword(name):
19
            raise ValueError
20
        return super().__new__(cls, (name,))
21
22
    @property
23
    def name(self):
24
        """Return the name of the matcher."""
25
        return tuple.__getitem__(self, 0)
26
27
    def __getitem__(self, other):
28
        return AsPattern(self, other)
29
30
31
class AsPattern(tuple):
32
    """A matcher that contains further bindings."""
33
34
    __slots__ = ()
35
36
    def __new__(cls, matcher: Pattern, match):
37
        if match is DISCARD:
38
            return matcher
39
        return super().__new__(cls, (matcher, match))
40
41
    @property
42
    def matcher(self):
43
        """Return the left-hand-side of the as-match."""
44
        return self[0]
45
46
    @property
47
    def match(self):
48
        """Return the right-hand-side of the as-match."""
49
        return self[1]
50
51
52
class AttrPattern(tuple):
53
    """A matcher that destructures an object using attribute access."""
54
55
    __slots__ = ()
56
57
    def __new__(*args, **kwargs):
58
        cls, *args = args
59
        if args:
60
            raise ValueError(args)
61
        return super(AttrPattern, cls).__new__(cls, (tuple(kwargs.items()),))
62
63
    @property
64
    def match_dict(self):
65
        return self[0]
66
67
68
class DictPattern(tuple):
69
    """A matcher that destructures a dictionary by key."""
70
71
    __slots__ = ()
72
73
    def __new__(cls, match_dict, *, exhaustive=False):
74
        return super(DictPattern, cls).__new__(
75
            cls, (tuple(match_dict.items()), exhaustive)
76
        )
77
78
    @property
79
    def match_dict(self):
80
        return self[0]
81
82
    @property
83
    def exhaustive(self):
84
        return self[1]
85
86
87
class Bind(tuple):
88
    """A wrapper that adds additional bindings to a successful match."""
89
90
    __slots__ = ()
91
92
    def __new__(*args, **kwargs):
93
        cls, structure = args
94
        not_in(kwargs, "_")
95
        return super(Bind, cls).__new__(cls, (structure, tuple(kwargs.items())))
96
97
    @property
98
    def structure(self):
99
        return self[0]
100
101
    @property
102
    def bindings(self):
103
        return self[1]
104