Total Complexity | 13 |
Total Lines | 57 |
Duplicated Lines | 0 % |
Changes | 0 |
1 | import keyword |
||
2 | |||
3 | from .compound_match import CompoundMatch |
||
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(CompoundMatch, 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 | def destructure(self, value): |
||
52 | if isinstance(value, AsPattern): |
||
53 | if value is self: |
||
54 | return (self.match, self.matcher) |
||
55 | return (value.match, value) |
||
56 | return (value, value) |
||
57 |