Total Complexity | 10 |
Total Lines | 48 |
Duplicated Lines | 0 % |
Changes | 0 |
1 | import keyword |
||
2 | |||
3 | DISCARD = object() |
||
4 | |||
5 | |||
6 | class Pattern(tuple): |
||
7 | """A matcher that binds a value to a name.""" |
||
8 | |||
9 | __slots__ = () |
||
10 | |||
11 | def __new__(cls, name: str): |
||
12 | if name == '_': |
||
13 | return DISCARD |
||
14 | if not name.isidentifier(): |
||
15 | raise ValueError |
||
16 | if keyword.iskeyword(name): |
||
17 | raise ValueError |
||
18 | return super().__new__(cls, (name,)) |
||
19 | |||
20 | @property |
||
21 | def name(self): |
||
22 | """Return the name of the matcher.""" |
||
23 | return self[0] |
||
24 | |||
25 | def __matmul__(self, other): |
||
26 | return AsPattern(self, other) |
||
27 | |||
28 | |||
29 | class AsPattern(tuple): |
||
30 | """A matcher that contains further bindings.""" |
||
31 | |||
32 | __slots__ = () |
||
33 | |||
34 | def __new__(cls, matcher: Pattern, match): |
||
35 | if match is DISCARD: |
||
36 | return matcher |
||
37 | return super().__new__(cls, (matcher, match)) |
||
38 | |||
39 | @property |
||
40 | def matcher(self): |
||
41 | """Return the left-hand-side of the as-match.""" |
||
42 | return self[0] |
||
43 | |||
44 | @property |
||
45 | def match(self): |
||
46 | """Return the right-hand-side of the as-match.""" |
||
47 | return self[1] |
||
48 |