| 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, pattern: Pattern, structure): |
||
| 37 | if structure is DISCARD: |
||
| 38 | return pattern |
||
| 39 | return super().__new__(cls, (pattern, structure)) |
||
| 40 | |||
| 41 | @property |
||
| 42 | def pattern(self): |
||
| 43 | """Return the left-hand-side of the as-match.""" |
||
| 44 | return self[0] |
||
| 45 | |||
| 46 | @property |
||
| 47 | def structure(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.structure, self.pattern) |
||
| 55 | return (value.structure, value) |
||
| 56 | return (value, value) |
||
| 57 |