diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ee7e5762..f66c04b49 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.6 + rev: v0.9.2 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/pyproject.toml b/pyproject.toml index 8c0e890d6..1f0cd6320 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ name = "attrs" authors = [{ name = "Hynek Schlawack", email = "hs@ox.cx" }] license = "MIT" license-files = ["LICENSE"] -requires-python = ">=3.8" +requires-python = ">=3.9" description = "Classes Without Boilerplate" keywords = ["class", "attribute", "boilerplate"] classifiers = [ @@ -226,6 +226,8 @@ ignore = [ "TD", # we don't follow other people's todo style "TRY301", # I'm sorry, but this makes not sense for us. "UP031", # format() is slow as molasses; % and f'' FTW. + "UP006", # replace Dict etc by dict etc later. + "UP035", # replace Dict etc by dict etc later. ] [tool.ruff.lint.per-file-ignores] @@ -242,6 +244,7 @@ ignore = [ "PLR0124", # pointless comparison in tests aren't pointless "PT011", # broad is fine "PT012", # sometimes we need more than a single stmt + "RUF009", # using results of function calls as defaults is fine "RUF012", # we don't do ClassVar annotations in tests "S", # security concerns don't matter in tests "SIM201", # sometimes we need to check `not ==` diff --git a/src/attr/_compat.py b/src/attr/_compat.py index 22fcd7838..130de4303 100644 --- a/src/attr/_compat.py +++ b/src/attr/_compat.py @@ -10,7 +10,6 @@ PYPY = platform.python_implementation() == "PyPy" -PY_3_9_PLUS = sys.version_info[:2] >= (3, 9) PY_3_10_PLUS = sys.version_info[:2] >= (3, 10) PY_3_11_PLUS = sys.version_info[:2] >= (3, 11) PY_3_12_PLUS = sys.version_info[:2] >= (3, 12) diff --git a/src/attr/_funcs.py b/src/attr/_funcs.py index c39fb8aa5..1ef973fc6 100644 --- a/src/attr/_funcs.py +++ b/src/attr/_funcs.py @@ -3,7 +3,7 @@ import copy -from ._compat import PY_3_9_PLUS, get_generic_base +from ._compat import get_generic_base from ._make import _OBJ_SETATTR, NOTHING, fields from .exceptions import AttrsAttributeNotFoundError @@ -450,10 +450,11 @@ class yet. if getattr(cls, "__attrs_types_resolved__", None) != cls: import typing - kwargs = {"globalns": globalns, "localns": localns} - - if PY_3_9_PLUS: - kwargs["include_extras"] = include_extras + kwargs = { + "globalns": globalns, + "localns": localns, + "include_extras": include_extras, + } hints = typing.get_type_hints(cls, **kwargs) for field in fields(cls) if attribs is None else attribs: diff --git a/src/attr/_make.py b/src/attr/_make.py index f00fec48c..152bb4f95 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -2285,7 +2285,7 @@ def _attrs_to_init_script( NL = "\n " return ( f"""def {method_name}(self, {args}): - {NL.join(lines) if lines else 'pass'} + {NL.join(lines) if lines else "pass"} """, names_for_globals, annotations, diff --git a/tests/test_annotations.py b/tests/test_annotations.py index 6fbae3ca6..abb1bd1a5 100644 --- a/tests/test_annotations.py +++ b/tests/test_annotations.py @@ -11,6 +11,7 @@ import pytest import attr +import attrs from attr._compat import PY_3_14_PLUS from attr._make import _is_class_var @@ -107,7 +108,7 @@ def test_auto_attribs(self, slots): class C: cls_var: typing.ClassVar[int] = 23 a: int - x: typing.List[int] = attr.Factory(list) + x: typing.List[int] = attrs.Factory(list) y: int = 2 z: int = attr.ib(default=3) foo: typing.Any = None @@ -407,7 +408,7 @@ class C: cls_var2: "ClassVar[int]" = 23 cls_var3: "t.ClassVar[int]" = 23 a: "int" - x: "typing.List[int]" = attr.Factory(list) + x: "typing.List[int]" = attrs.Factory(list) y: "int" = 2 z: "int" = attr.ib(default=3) foo: "typing.Any" = None diff --git a/tests/test_validators.py b/tests/test_validators.py index e238a78c1..45e7050d3 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -1074,8 +1074,7 @@ def test_repr(self): v = not_(wrapped) assert ( - f"" + f"" ) == repr(v) def test_success_because_fails(self): diff --git a/tests/typing_example.py b/tests/typing_example.py index b8d414ba8..465760601 100644 --- a/tests/typing_example.py +++ b/tests/typing_example.py @@ -269,7 +269,7 @@ class Validated2: @attrs.define class Validated3: - num: int = attr.field(validator=attr.validators.ge(0)) + num: int = attrs.field(validator=attr.validators.ge(0)) with attr.validators.disabled(): diff --git a/tox.ini b/tox.ini index b01466737..fa057dfb6 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ min_version = 4 env_list = pre-commit, - py3{8,9,10,11,12,13}-tests, + py3{9,10,11,12,13}-tests, py3{10,11,12,13}-mypy, pypy3-tests, pyright, @@ -31,7 +31,7 @@ commands = dependency_groups = tests commands = pytest tests/test_functional.py -[testenv:py3{8,10,13}-tests] +[testenv:py3{9,10,13}-tests] dependency_groups = cov # Python 3.6+ has a number of compile-time warnings on invalid string escapes. # PYTHONWARNINGS=d makes them visible during the tox run. @@ -46,7 +46,7 @@ commands = # Keep base_python in-sync with .python-version-default base_python = py313 # Keep depends in-sync with testenv above that has the cov dependency group. -depends = py3{8,10,13}-tests +depends = py3{9,10,13}-tests skip_install = true dependency_groups = cov commands =