From 452b09af33ed15843ae3a38eaf742d46b0d5832a Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Thu, 13 May 2021 14:55:58 +0000 Subject: [PATCH 01/18] Add support to generate __match_args__ for Python 3.10. --- docs/api.rst | 2 +- src/attr/_make.py | 15 ++++++++ tests/test_make.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/docs/api.rst b/docs/api.rst index 3df314504..3fd71d651 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -28,7 +28,7 @@ Core .. autodata:: attr.NOTHING -.. autofunction:: attr.s(these=None, repr_ns=None, repr=None, cmp=None, hash=None, init=None, slots=False, frozen=False, weakref_slot=True, str=False, auto_attribs=False, kw_only=False, cache_hash=False, auto_exc=False, eq=None, order=None, auto_detect=False, collect_by_mro=False, getstate_setstate=None, on_setattr=None, field_transformer=None) +.. autofunction:: attr.s(these=None, repr_ns=None, repr=None, cmp=None, hash=None, init=None, slots=False, frozen=False, weakref_slot=True, str=False, auto_attribs=False, kw_only=False, cache_hash=False, auto_exc=False, eq=None, order=None, auto_detect=False, collect_by_mro=False, getstate_setstate=None, on_setattr=None, field_transformer=None, match_args=True) .. note:: diff --git a/src/attr/_make.py b/src/attr/_make.py index ceb08f910..87318d532 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -966,6 +966,13 @@ def add_init(self): return self + def add_match_args(self): + self._cls_dict["__match_args__"] = tuple( + field.name + for field in self._attrs + if field.init and not field.kw_only + ) + def add_attrs_init(self): self._cls_dict["__attrs_init__"] = self._add_method_dunders( _make_init( @@ -1192,6 +1199,7 @@ def attrs( getstate_setstate=None, on_setattr=None, field_transformer=None, + match_args=True, ): r""" A class decorator that adds `dunder @@ -1407,6 +1415,10 @@ def attrs( this, e.g., to automatically add converters or validators to fields based on their types. See `transform-fields` for more details. + :param bool match_args: + If `True` it sets __match_args__ in the class to support PEP 634. It is a + tuple of __init__ parameter names that are only positional arguments. + .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen* .. versionadded:: 16.3.0 *str* @@ -1556,6 +1568,9 @@ def wrap(cls): " init must be True." ) + if match_args and "__match_args__" not in cls.__dict__: + builder.add_match_args() + return builder.build_class() # maybe_cls's type depends on the usage of the decorator. It's a class diff --git a/tests/test_make.py b/tests/test_make.py index e54b0bb05..48ff8695e 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -2327,3 +2327,92 @@ def __setstate__(self, state): assert True is i.called assert None is getattr(C(), "__getstate__", None) + + +class TestMatchArgs: + def test_match_args(self): + @attr.s() + class C: + a = attr.ib() + + assert C.__match_args__ == ("a",) + + def test_explicit_match_args(self): + ma = () + + @attr.s() + class C: + a = attr.ib() + __match_args__ = ma + + assert C(42).__match_args__ is ma + + @pytest.mark.parametrize("match_args", [True, False]) + def test_match_args_attr_set(self, match_args): + @attr.s(match_args=match_args) + class C: + a = attr.ib() + + if match_args: + assert hasattr(C, "__match_args__") + else: + assert not hasattr(C, "__match_args__") + + def test_match_args_kw_only(self): + @attr.s() + class C: + a = attr.ib(kw_only=True) + b = attr.ib() + + assert C.__match_args__ == ("b",) + + @attr.s(match_args=True, kw_only=True) + class C: + a = attr.ib() + b = attr.ib() + + assert C.__match_args__ == () + + def test_match_args_argument(self): + @attr.s(match_args=False) + class X: + a = attr.ib() + + assert "__match_args__" not in X.__dict__ + + @attr.s(match_args=False) + class Y: + a = attr.ib() + __match_args__ = ("b",) + + assert Y.__match_args__ == ("b",) + + @attr.s(match_args=False) + class Z(Y): + z = attr.ib() + + assert Z.__match_args__ == ("b",) + + @attr.s() + class A: + a = attr.ib() + z = attr.ib() + + @attr.s(match_args=False) + class B(A): + b = attr.ib() + + assert B.__match_args__ == ("a", "z") + + def test_make_class(self): + C1 = make_class("C1", ["a", "b"]) + assert C1.__match_args__ == ("a", "b") + + C1 = make_class("C1", ["a", "b"], match_args=False) + assert not hasattr(C1, "__match_args__") + + C1 = make_class("C1", ["a", "b"], kw_only=True) + assert C1.__match_args__ == () + + C1 = make_class("C1", {"a": attr.ib(kw_only=True), "b": attr.ib()}) + assert C1.__match_args__ == ("b",) From 530e85f53cf5c5a6cdfa20349a2c4e65ea4bf0e3 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Thu, 13 May 2021 15:13:35 +0000 Subject: [PATCH 02/18] Add versionadded directive. --- src/attr/_make.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attr/_make.py b/src/attr/_make.py index 87318d532..d0ba112cf 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1452,6 +1452,7 @@ def attrs( ``init=False`` injects ``__attrs_init__`` .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` .. versionchanged:: 21.1.0 *cmp* undeprecated + .. versionadded:: 21.3.0 *match_args* """ if auto_detect and PY2: raise PythonTooOldError( From 9d8b4413cb6cf794776380175487be3ed68613d7 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Fri, 14 May 2021 05:27:24 +0000 Subject: [PATCH 03/18] Update stubs. --- src/attr/__init__.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/attr/__init__.pyi b/src/attr/__init__.pyi index 3503b073b..7979eb091 100644 --- a/src/attr/__init__.pyi +++ b/src/attr/__init__.pyi @@ -315,6 +315,7 @@ def attrs( getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., ) -> _C: ... @overload @__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) @@ -341,6 +342,7 @@ def attrs( getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., ) -> Callable[[_C], _C]: ... @overload @__dataclass_transform__(field_descriptors=(attrib, field)) From e13c92d248dee932f87bf75c13eeee436ab60b4d Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Fri, 14 May 2021 05:33:01 +0000 Subject: [PATCH 04/18] Update changelog and add a test to typing examples. --- changelog.d/815.changes.rst | 2 ++ tests/typing_example.py | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 changelog.d/815.changes.rst diff --git a/changelog.d/815.changes.rst b/changelog.d/815.changes.rst new file mode 100644 index 000000000..3b4cbe89e --- /dev/null +++ b/changelog.d/815.changes.rst @@ -0,0 +1,2 @@ +Add ``__match_args__`` to generated class to support match case destructuring +in Python 3.10. This can be controlled by ``match_args`` argument to ``@attrib.s``. diff --git a/tests/typing_example.py b/tests/typing_example.py index 13b5638db..2edbce216 100644 --- a/tests/typing_example.py +++ b/tests/typing_example.py @@ -257,3 +257,10 @@ class FactoryTest: a: List[int] = attr.ib(default=attr.Factory(list)) b: List[Any] = attr.ib(default=attr.Factory(list, False)) c: List[int] = attr.ib(default=attr.Factory((lambda s: s.a), True)) + + +# Check match_args stub +@attr.s(match_args=False) +class MatchArgs: + a: int = attr.ib() + b: int = attr.ib() From 69d09282f20326b3a6a94302b4869c97a665f772 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Fri, 14 May 2021 10:19:03 +0000 Subject: [PATCH 05/18] Fix error regarding new-style classes in Python 2. --- tests/test_make.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_make.py b/tests/test_make.py index 48ff8695e..f8c6d6215 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -2332,7 +2332,7 @@ def __setstate__(self, state): class TestMatchArgs: def test_match_args(self): @attr.s() - class C: + class C(object): a = attr.ib() assert C.__match_args__ == ("a",) @@ -2341,7 +2341,7 @@ def test_explicit_match_args(self): ma = () @attr.s() - class C: + class C(object): a = attr.ib() __match_args__ = ma @@ -2350,7 +2350,7 @@ class C: @pytest.mark.parametrize("match_args", [True, False]) def test_match_args_attr_set(self, match_args): @attr.s(match_args=match_args) - class C: + class C(object): a = attr.ib() if match_args: @@ -2360,14 +2360,14 @@ class C: def test_match_args_kw_only(self): @attr.s() - class C: + class C(object): a = attr.ib(kw_only=True) b = attr.ib() assert C.__match_args__ == ("b",) @attr.s(match_args=True, kw_only=True) - class C: + class C(object): a = attr.ib() b = attr.ib() @@ -2375,13 +2375,13 @@ class C: def test_match_args_argument(self): @attr.s(match_args=False) - class X: + class X(object): a = attr.ib() assert "__match_args__" not in X.__dict__ @attr.s(match_args=False) - class Y: + class Y(object): a = attr.ib() __match_args__ = ("b",) @@ -2394,7 +2394,7 @@ class Z(Y): assert Z.__match_args__ == ("b",) @attr.s() - class A: + class A(object): a = attr.ib() z = attr.ib() From 918c1b4f17e401064cd64a1e8dd034126a61c1c9 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Fri, 14 May 2021 10:21:52 +0000 Subject: [PATCH 06/18] Fix lint error regarding line length. --- CHANGELOG.rst | 7 +++++++ src/attr/_make.py | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dcb4823ca..ded92bbe5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,13 @@ Changes for the upcoming release can be found in the `"changelog.d" directory Date: Fri, 14 May 2021 16:54:28 +0000 Subject: [PATCH 07/18] Fix lint error regarding trailing whitespace. --- src/attr/_make.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attr/_make.py b/src/attr/_make.py index 305f6843d..25d2613e8 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1416,8 +1416,8 @@ def attrs( fields based on their types. See `transform-fields` for more details. :param bool match_args: - If `True` it sets __match_args__ in the class to support PEP 634. It - is a tuple of __init__ parameter names that are only positional + If `True` it sets __match_args__ in the class to support PEP 634. It + is a tuple of __init__ parameter names that are only positional arguments. .. versionadded:: 16.0.0 *slots* From 1c246dbc6bac51b7e16e6a783d52fb86380bb7dc Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Sat, 15 May 2021 05:23:16 +0000 Subject: [PATCH 08/18] Add docstrings for interrogate. --- tests/test_make.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/test_make.py b/tests/test_make.py index f8c6d6215..6b5741d67 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -2329,8 +2329,16 @@ def __setstate__(self, state): assert None is getattr(C(), "__getstate__", None) -class TestMatchArgs: +class TestMatchArgs(object): + """ + Tests for match_args and __match_args__ generation. + """ + def test_match_args(self): + """ + Test __match_args__ generation + """ + @attr.s() class C(object): a = attr.ib() @@ -2338,6 +2346,10 @@ class C(object): assert C.__match_args__ == ("a",) def test_explicit_match_args(self): + """ + Test __match_args__ manually set is not overriden. + """ + ma = () @attr.s() @@ -2349,6 +2361,10 @@ class C(object): @pytest.mark.parametrize("match_args", [True, False]) def test_match_args_attr_set(self, match_args): + """ + Test __match_args__ being set depending on match_args. + """ + @attr.s(match_args=match_args) class C(object): a = attr.ib() @@ -2359,6 +2375,11 @@ class C(object): assert not hasattr(C, "__match_args__") def test_match_args_kw_only(self): + """ + Test kw_only being set doesn't generate __match_args__ + Test kw_only field is not included in __match_args__ + """ + @attr.s() class C(object): a = attr.ib(kw_only=True) @@ -2374,6 +2395,10 @@ class C(object): assert C.__match_args__ == () def test_match_args_argument(self): + """ + Test match_args being False with inheritance. + """ + @attr.s(match_args=False) class X(object): a = attr.ib() @@ -2405,6 +2430,10 @@ class B(A): assert B.__match_args__ == ("a", "z") def test_make_class(self): + """ + Test match_args generation with make_class. + """ + C1 = make_class("C1", ["a", "b"]) assert C1.__match_args__ == ("a", "b") From 590e31e7b9f661fcaa6aa7f6ea16bcd8e2501ac0 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 13:42:22 +0000 Subject: [PATCH 09/18] Use _has_own_attribute instead of cls.__dict__ contains check. --- src/attr/_make.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attr/_make.py b/src/attr/_make.py index 25d2613e8..7e3c16ef0 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1570,7 +1570,7 @@ def wrap(cls): " init must be True." ) - if match_args and "__match_args__" not in cls.__dict__: + if match_args and not _has_own_attribute(cls, "__match_args__"): builder.add_match_args() return builder.build_class() From 69bfe66432cb3ce7d43c9c684338309370ddf779 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 13:45:35 +0000 Subject: [PATCH 10/18] Update docs as per review comments. --- changelog.d/815.changes.rst | 5 +++-- src/attr/_make.py | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/changelog.d/815.changes.rst b/changelog.d/815.changes.rst index 3b4cbe89e..a8f16b907 100644 --- a/changelog.d/815.changes.rst +++ b/changelog.d/815.changes.rst @@ -1,2 +1,3 @@ -Add ``__match_args__`` to generated class to support match case destructuring -in Python 3.10. This can be controlled by ``match_args`` argument to ``@attrib.s``. +``__match_args__`` are now generated to support Python 3.10's +`Structural Pattern Matching `_. +This can be controlled by ``match_args`` argument to the class decorators. diff --git a/src/attr/_make.py b/src/attr/_make.py index 7e3c16ef0..cf32080a7 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1416,9 +1416,10 @@ def attrs( fields based on their types. See `transform-fields` for more details. :param bool match_args: - If `True` it sets __match_args__ in the class to support PEP 634. It - is a tuple of __init__ parameter names that are only positional - arguments. + If `True`, set ``__match_args__`` on the class to support `PEP 634 + `_ (Structural Pattern + Matching). It is a tuple of all positional-only ``__init__`` parameter + names. .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen* From 753811ba095787e04511fabd1ff487183f69fa0c Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 13:51:24 +0000 Subject: [PATCH 11/18] Revert mistaken changelog update. --- CHANGELOG.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ded92bbe5..dcb4823ca 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,13 +15,6 @@ Changes for the upcoming release can be found in the `"changelog.d" directory Date: Mon, 17 May 2021 14:12:09 +0000 Subject: [PATCH 12/18] Add Python 3.10 pattern matching syntax test cases. --- conftest.py | 6 +++ pyproject.toml | 4 ++ tests/test_make.py | 14 ++--- tests/test_pattern_matching.py | 97 ++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 tests/test_pattern_matching.py diff --git a/conftest.py b/conftest.py index a2c8d59f2..c1997d27a 100644 --- a/conftest.py +++ b/conftest.py @@ -23,6 +23,12 @@ def pytest_configure(config): "tests/test_next_gen.py", ] ) +if sys.version_info[:2] < (3, 10): + collect_ignore.extend( + [ + "tests/test_pattern_matching.py" + ] + ) if sys.version_info[:2] >= (3, 10): collect_ignore.extend( [ diff --git a/pyproject.toml b/pyproject.toml index 14f65a366..93145c9e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,10 @@ exclude_lines = [ [tool.black] line-length = 79 +extend-exclude = ''' +# Exclude pattern matching test till black gains Python 3.10 support +.*test_pattern_matching.* +''' [tool.interrogate] diff --git a/tests/test_make.py b/tests/test_make.py index 6b5741d67..c1d893e3d 100644 --- a/tests/test_make.py +++ b/tests/test_make.py @@ -2336,7 +2336,7 @@ class TestMatchArgs(object): def test_match_args(self): """ - Test __match_args__ generation + __match_args__ generation """ @attr.s() @@ -2347,7 +2347,7 @@ class C(object): def test_explicit_match_args(self): """ - Test __match_args__ manually set is not overriden. + __match_args__ manually set is not overriden. """ ma = () @@ -2362,7 +2362,7 @@ class C(object): @pytest.mark.parametrize("match_args", [True, False]) def test_match_args_attr_set(self, match_args): """ - Test __match_args__ being set depending on match_args. + __match_args__ being set depending on match_args. """ @attr.s(match_args=match_args) @@ -2376,8 +2376,8 @@ class C(object): def test_match_args_kw_only(self): """ - Test kw_only being set doesn't generate __match_args__ - Test kw_only field is not included in __match_args__ + kw_only being set doesn't generate __match_args__ + kw_only field is not included in __match_args__ """ @attr.s() @@ -2396,7 +2396,7 @@ class C(object): def test_match_args_argument(self): """ - Test match_args being False with inheritance. + match_args being False with inheritance. """ @attr.s(match_args=False) @@ -2431,7 +2431,7 @@ class B(A): def test_make_class(self): """ - Test match_args generation with make_class. + match_args generation with make_class. """ C1 = make_class("C1", ["a", "b"]) diff --git a/tests/test_pattern_matching.py b/tests/test_pattern_matching.py new file mode 100644 index 000000000..96b24de48 --- /dev/null +++ b/tests/test_pattern_matching.py @@ -0,0 +1,97 @@ +# flake8: noqa +# Python 3.10 issue in flake8 : https://github.com/PyCQA/pyflakes/issues/634 +import pytest + +import attr +from attr._make import make_class + + +class TestPatternMatching(object): + """ + Pattern matching syntax test cases. + """ + + def test_simple_match_case(self): + """ + Simple match case statement + """ + + @attr.s() + class C(object): + a = attr.ib() + + assert C.__match_args__ == ("a",) + + matched = False + c = C(a=1) + match c: + case C(a): + matched = True + + assert matched + + def test_explicit_match_args(self): + """ + Manually set empty __match_args__ will not match. + """ + + ma = () + + @attr.s() + class C(object): + a = attr.ib() + __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(a): + pass + + def test_match_args_kw_only(self): + """ + kw_only being set doesn't generate __match_args__ + kw_only field is not included in __match_args__ + """ + + @attr.s() + class C(object): + a = attr.ib(kw_only=True) + b = attr.ib() + + assert C.__match_args__ == ("b",) + + 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.s(match_args=True, kw_only=True) + class C(object): + a = attr.ib() + b = attr.ib() + + 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 From 0cd51b485e560d201b7703c37eeb1b1d854cd8b6 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 14:36:11 +0000 Subject: [PATCH 13/18] Update define signature with match_args. --- src/attr/__init__.pyi | 2 ++ src/attr/_next_gen.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/attr/__init__.pyi b/src/attr/__init__.pyi index 7979eb091..7221836c1 100644 --- a/src/attr/__init__.pyi +++ b/src/attr/__init__.pyi @@ -367,6 +367,7 @@ def define( getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., ) -> _C: ... @overload @__dataclass_transform__(field_descriptors=(attrib, field)) @@ -391,6 +392,7 @@ def define( getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., field_transformer: Optional[_FieldTransformer] = ..., + match_args: bool = ..., ) -> Callable[[_C], _C]: ... mutable = define diff --git a/src/attr/_next_gen.py b/src/attr/_next_gen.py index fab0af966..1d8acac36 100644 --- a/src/attr/_next_gen.py +++ b/src/attr/_next_gen.py @@ -32,6 +32,7 @@ def define( getstate_setstate=None, on_setattr=None, field_transformer=None, + match_args=True, ): r""" The only behavioral differences are the handling of the *auto_attribs* @@ -72,6 +73,7 @@ def do_it(cls, auto_attribs): getstate_setstate=getstate_setstate, on_setattr=on_setattr, field_transformer=field_transformer, + match_args=match_args, ) def wrap(cls): From 3793bcdc14cfcc25287a019da4e68ecffe8a65cc Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 14:55:22 +0000 Subject: [PATCH 14/18] Fix conftest formatting. --- conftest.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/conftest.py b/conftest.py index c1997d27a..85659a8a2 100644 --- a/conftest.py +++ b/conftest.py @@ -24,11 +24,7 @@ def pytest_configure(config): ] ) if sys.version_info[:2] < (3, 10): - collect_ignore.extend( - [ - "tests/test_pattern_matching.py" - ] - ) + collect_ignore.extend(["tests/test_pattern_matching.py"]) if sys.version_info[:2] >= (3, 10): collect_ignore.extend( [ From 075db99ec494acb5598a20c1e8d07ce8a4059f10 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 15:07:02 +0000 Subject: [PATCH 15/18] Fix isort formatting. --- tests/test_pattern_matching.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_pattern_matching.py b/tests/test_pattern_matching.py index 96b24de48..6a1cb84dc 100644 --- a/tests/test_pattern_matching.py +++ b/tests/test_pattern_matching.py @@ -3,6 +3,7 @@ import pytest import attr + from attr._make import make_class From a0f426d1c22b4e3ffd10ddcd075b1a8935ed9d1f Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 15:32:50 +0000 Subject: [PATCH 16/18] Bump to Python 3.10 to parse syntax. --- .pre-commit-config.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb59b3a36..d029e1dad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,6 +4,7 @@ repos: rev: 20.8b1 hooks: - id: black + exclude: tests/test_pattern_matching.py language_version: python3.8 - repo: https://github.com/PyCQA/isort @@ -22,8 +23,9 @@ repos: rev: 1.3.2 hooks: - id: interrogate + exclude: tests/test_pattern_matching.py args: [tests] - language_version: python3.8 + language_version: python3.10 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v3.4.0 @@ -31,4 +33,5 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: debug-statements + language_version: python3.10 - id: check-toml From db4fc7d38e7a26b44c124ddaa04b2fb46e7c0d5a Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 16:13:58 +0000 Subject: [PATCH 17/18] Bump basepython of lint to Python 3.10 for parsing. --- .pre-commit-config.yaml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d029e1dad..6d042f496 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: rev: 3.8.4 hooks: - id: flake8 - language_version: python3.8 + language_version: python3.10 - repo: https://github.com/econchick/interrogate rev: 1.3.2 diff --git a/tox.ini b/tox.ini index a9f67b296..a2147e16d 100644 --- a/tox.ini +++ b/tox.ini @@ -71,7 +71,7 @@ commands = [testenv:lint] -basepython = python3.8 +basepython = python3.10 skip_install = true deps = pre-commit From e3a803634ebfe0d4c10b3f5c74c87a45a6147b10 Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Mon, 17 May 2021 16:24:14 +0000 Subject: [PATCH 18/18] Move lint to py310 --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index a2147e16d..d796d0383 100644 --- a/tox.ini +++ b/tox.ini @@ -14,9 +14,9 @@ python = 3.5: py35 3.6: py36 3.7: py37, docs - 3.8: py38, lint, manifest, typing, changelog + 3.8: py38, manifest, typing, changelog 3.9: py39, pyright - 3.10: py310 + 3.10: py310, lint pypy2: pypy2 pypy3: pypy3