| # SPDX-License-Identifier: MIT | |
| import pytest | |
| import attr | |
| class TestPatternMatching: | |
| """ | |
| Pattern matching syntax test cases. | |
| """ | |
| @pytest.mark.parametrize("dec", [attr.s, attr.define, attr.frozen]) | |
| def test_simple_match_case(self, dec): | |
| """ | |
| Simple match case statement works as expected with all class | |
| decorators. | |
| """ | |
| @dec | |
| class C: | |
| a = attr.ib() | |
| assert ("a",) == C.__match_args__ | |
| matched = False | |
| c = C(a=1) | |
| match c: | |
| case C(a): | |
| matched = True | |
| assert matched | |
| assert 1 == a | |
| def test_explicit_match_args(self): | |
| """ | |
| Does not overwrite a manually set empty __match_args__. | |
| """ | |
| ma = () | |
| @attr.define | |
| class C: | |
| a = attr.field() | |
| __match_args__ = ma | |
| c = C(a=1) | |
| msg = r"C\(\) accepts 0 positional sub-patterns \(1 given\)" | |
| with pytest.raises(TypeError, match=msg): | |
| match c: | |
| case C(_): | |
| pass | |
| def test_match_args_kw_only(self): | |
| """ | |
| kw_only classes don't generate __match_args__. | |
| kw_only fields are not included in __match_args__. | |
| """ | |
| @attr.define | |
| class C: | |
| a = attr.field(kw_only=True) | |
| b = attr.field() | |
| assert ("b",) == C.__match_args__ | |
| c = C(a=1, b=1) | |
| msg = r"C\(\) accepts 1 positional sub-pattern \(2 given\)" | |
| with pytest.raises(TypeError, match=msg): | |
| match c: | |
| case C(a, b): | |
| pass | |
| found = False | |
| match c: | |
| case C(b, a=a): | |
| found = True | |
| assert found | |
| @attr.define(kw_only=True) | |
| class C: | |
| a = attr.field() | |
| b = attr.field() | |
| c = C(a=1, b=1) | |
| msg = r"C\(\) accepts 0 positional sub-patterns \(2 given\)" | |
| with pytest.raises(TypeError, match=msg): | |
| match c: | |
| case C(a, b): | |
| pass | |
| found = False | |
| match c: | |
| case C(a=a, b=b): | |
| found = True | |
| assert found | |
| assert (1, 1) == (a, b) |