From d6f2d8cbc3d8c1aa549e22aff10bcf4e220c8dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20K=C5=82oczko?= Date: Sun, 17 Mar 2024 21:10:15 +0000 Subject: [PATCH 1/4] drop python<=37 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 3.7 has been EOSed at 27 Jun 2023 (https://endoflife.date/python) Filter all code over `pyupgrade --py38'. Signed-off-by: Tomasz Kłoczko --- src/attr/__init__.py | 5 +---- src/attr/_compat.py | 8 +------- src/attr/_make.py | 14 +++++++------- tests/test_packaging.py | 5 +---- tests/test_slots.py | 4 ++-- tests/typing_example.py | 2 +- 6 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/attr/__init__.py b/src/attr/__init__.py index 9226258a2..7cd4734ea 100644 --- a/src/attr/__init__.py +++ b/src/attr/__init__.py @@ -98,10 +98,7 @@ def __getattr__(name: str) -> str: import sys import warnings - if sys.version_info < (3, 8): - from importlib_metadata import metadata - else: - from importlib.metadata import metadata + from importlib.metadata import metadata if name not in ("__version__", "__version_info__"): warnings.warn( diff --git a/src/attr/_compat.py b/src/attr/_compat.py index b7d7a4b86..7edb762a5 100644 --- a/src/attr/_compat.py +++ b/src/attr/_compat.py @@ -17,13 +17,7 @@ PY_3_13_PLUS = sys.version_info[:2] >= (3, 13) -if sys.version_info < (3, 8): - try: - from typing_extensions import Protocol - except ImportError: # pragma: no cover - Protocol = object -else: - from typing import Protocol # noqa: F401 +from typing import Protocol # noqa: F401 class _AnnotationExtractor: diff --git a/src/attr/_make.py b/src/attr/_make.py index 0114582aa..8b1e19f8c 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1979,9 +1979,9 @@ def _make_repr(attrs, ns, cls): "self." + name if i else 'getattr(self, "' + name + '", NOTHING)' ) fragment = ( - "%s={%s!r}" % (name, accessor) + "{}={{{}!r}}".format(name, accessor) if r == repr - else "%s={%s_repr(%s)}" % (name, name, accessor) + else "{}={{{}_repr({})}}".format(name, name, accessor) ) attribute_fragments.append(fragment) repr_fragment = ", ".join(attribute_fragments) @@ -2208,7 +2208,7 @@ def _setattr_with_converter(attr_name, value_var, has_on_setattr): Use the cached object.setattr to set *attr_name* to *value_var*, but run its converter first. """ - return "_setattr('%s', %s(%s))" % ( + return "_setattr('{}', {}({}))".format( attr_name, _INIT_CONVERTER_PAT % (attr_name,), value_var, @@ -2234,7 +2234,7 @@ def _assign_with_converter(attr_name, value_var, has_on_setattr): if has_on_setattr: return _setattr_with_converter(attr_name, value_var, True) - return "self.%s = %s(%s)" % ( + return "self.{} = {}({})".format( attr_name, _INIT_CONVERTER_PAT % (attr_name,), value_var, @@ -2267,7 +2267,7 @@ def fmt_setter_with_converter(attr_name, value_var, has_on_setattr): attr_name, value_var, has_on_setattr ) - return "_inst_dict['%s'] = %s(%s)" % ( + return "_inst_dict['{}'] = {}({})".format( attr_name, _INIT_CONVERTER_PAT % (attr_name,), value_var, @@ -2514,12 +2514,12 @@ def _attrs_to_init_script( args = ", ".join(args) pre_init_args = args if kw_only_args: - args += "%s*, %s" % ( + args += "{}*, {}".format( ", " if args else "", # leading comma ", ".join(kw_only_args), # kw_only args ) pre_init_kw_only_args = ", ".join( - ["%s=%s" % (kw_arg, kw_arg) for kw_arg in kw_only_args] + ["{}={}".format(kw_arg, kw_arg) for kw_arg in kw_only_args] ) pre_init_args += ( ", " if pre_init_args else "" diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 5a2fdb269..669f9203e 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -8,10 +8,7 @@ import attrs -if sys.version_info < (3, 8): - import importlib_metadata as metadata -else: - from importlib import metadata +from importlib import metadata @pytest.fixture(name="mod", params=(attr, attrs)) diff --git a/tests/test_slots.py b/tests/test_slots.py index c1332f2d3..bd6e27858 100644 --- a/tests/test_slots.py +++ b/tests/test_slots.py @@ -597,7 +597,7 @@ class C: field = attr.ib() def f(self, a): - super(C, self).__init__() # noqa: UP008 + super().__init__() # noqa: UP008 C(field=1) @@ -685,7 +685,7 @@ def f(self): class C(A): @property def f(self): - return super(C, self).f ** 2 # noqa: UP008 + return super().f ** 2 # noqa: UP008 assert B(11).f == 121 assert B(17).f == 289 diff --git a/tests/typing_example.py b/tests/typing_example.py index 2124912c8..d5899ddc6 100644 --- a/tests/typing_example.py +++ b/tests/typing_example.py @@ -56,7 +56,7 @@ class DD: @attr.s class EE: - y: "list[int]" = attr.ib() + y: list[int] = attr.ib() @attr.s From 958e9e9aea44ed36aa60756cd5fbb2281ed9f25e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:16:02 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/attr/_make.py | 24 ++++++------------------ tests/test_packaging.py | 6 ++---- tests/test_slots.py | 4 ++-- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/attr/_make.py b/src/attr/_make.py index 8b1e19f8c..d5fa6023f 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -1979,9 +1979,9 @@ def _make_repr(attrs, ns, cls): "self." + name if i else 'getattr(self, "' + name + '", NOTHING)' ) fragment = ( - "{}={{{}!r}}".format(name, accessor) + f"{name}={{{accessor}!r}}" if r == repr - else "{}={{{}_repr({})}}".format(name, name, accessor) + else f"{name}={{{name}_repr({accessor})}}" ) attribute_fragments.append(fragment) repr_fragment = ", ".join(attribute_fragments) @@ -2208,11 +2208,7 @@ def _setattr_with_converter(attr_name, value_var, has_on_setattr): Use the cached object.setattr to set *attr_name* to *value_var*, but run its converter first. """ - return "_setattr('{}', {}({}))".format( - attr_name, - _INIT_CONVERTER_PAT % (attr_name,), - value_var, - ) + return f"_setattr('{attr_name}', {_INIT_CONVERTER_PAT % (attr_name,)}({value_var}))" def _assign(attr_name, value, has_on_setattr): @@ -2234,11 +2230,7 @@ def _assign_with_converter(attr_name, value_var, has_on_setattr): if has_on_setattr: return _setattr_with_converter(attr_name, value_var, True) - return "self.{} = {}({})".format( - attr_name, - _INIT_CONVERTER_PAT % (attr_name,), - value_var, - ) + return f"self.{attr_name} = {_INIT_CONVERTER_PAT % (attr_name,)}({value_var})" def _determine_setters(frozen, slots, base_attr_map): @@ -2267,11 +2259,7 @@ def fmt_setter_with_converter(attr_name, value_var, has_on_setattr): attr_name, value_var, has_on_setattr ) - return "_inst_dict['{}'] = {}({})".format( - attr_name, - _INIT_CONVERTER_PAT % (attr_name,), - value_var, - ) + return f"_inst_dict['{attr_name}'] = {_INIT_CONVERTER_PAT % (attr_name,)}({value_var})" return ( ("_inst_dict = self.__dict__",), @@ -2519,7 +2507,7 @@ def _attrs_to_init_script( ", ".join(kw_only_args), # kw_only args ) pre_init_kw_only_args = ", ".join( - ["{}={}".format(kw_arg, kw_arg) for kw_arg in kw_only_args] + [f"{kw_arg}={kw_arg}" for kw_arg in kw_only_args] ) pre_init_args += ( ", " if pre_init_args else "" diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 669f9203e..f22464345 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT -import sys + +from importlib import metadata import pytest @@ -8,9 +9,6 @@ import attrs -from importlib import metadata - - @pytest.fixture(name="mod", params=(attr, attrs)) def _mod(request): return request.param diff --git a/tests/test_slots.py b/tests/test_slots.py index bd6e27858..7dd6224a1 100644 --- a/tests/test_slots.py +++ b/tests/test_slots.py @@ -597,7 +597,7 @@ class C: field = attr.ib() def f(self, a): - super().__init__() # noqa: UP008 + super().__init__() C(field=1) @@ -685,7 +685,7 @@ def f(self): class C(A): @property def f(self): - return super().f ** 2 # noqa: UP008 + return super().f ** 2 assert B(11).f == 121 assert B(17).f == 289 From e4d5d83e560dbec641ef8b89b8fce7828578acae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20K=C5=82oczko?= Date: Sun, 17 Mar 2024 21:21:04 +0000 Subject: [PATCH 3/4] manually update pyproject.toml about python>=3.8 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomasz Kłoczko --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c7ec20704..2c9faa23f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,13 +9,12 @@ build-backend = "hatchling.build" name = "attrs" authors = [{ name = "Hynek Schlawack", email = "hs@ox.cx" }] license = "MIT" -requires-python = ">=3.7" +requires-python = ">=3.8" description = "Classes Without Boilerplate" keywords = ["class", "attribute", "boilerplate"] classifiers = [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From 91a4ae2e2b23bbad7babe4c355c144c588cfc209 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:21:44 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/attr/_make.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/attr/_make.py b/src/attr/_make.py index d5fa6023f..6be03b660 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -2230,7 +2230,9 @@ def _assign_with_converter(attr_name, value_var, has_on_setattr): if has_on_setattr: return _setattr_with_converter(attr_name, value_var, True) - return f"self.{attr_name} = {_INIT_CONVERTER_PAT % (attr_name,)}({value_var})" + return ( + f"self.{attr_name} = {_INIT_CONVERTER_PAT % (attr_name,)}({value_var})" + ) def _determine_setters(frozen, slots, base_attr_map):