diff --git a/changelog.d/1461.change.md b/changelog.d/1461.change.md new file mode 100644 index 000000000..eebd91507 --- /dev/null +++ b/changelog.d/1461.change.md @@ -0,0 +1,2 @@ +Fixed annotations for `attrs.field(converter=...)`. +Previously, a `tuple` of converters was only accepted if it had exactly one element. diff --git a/src/attrs/__init__.pyi b/src/attrs/__init__.pyi index 128c6a79f..124440f7b 100644 --- a/src/attrs/__init__.pyi +++ b/src/attrs/__init__.pyi @@ -98,7 +98,7 @@ def field( metadata: Mapping[Any, Any] | None = ..., converter: _ConverterType | list[_ConverterType] - | tuple[_ConverterType] + | tuple[_ConverterType, ...] | None = ..., factory: Callable[[], _T] | None = ..., kw_only: bool | None = ..., @@ -121,7 +121,7 @@ def field( metadata: Mapping[Any, Any] | None = ..., converter: _ConverterType | list[_ConverterType] - | tuple[_ConverterType] + | tuple[_ConverterType, ...] | None = ..., factory: Callable[[], _T] | None = ..., kw_only: bool | None = ..., @@ -144,7 +144,7 @@ def field( metadata: Mapping[Any, Any] | None = ..., converter: _ConverterType | list[_ConverterType] - | tuple[_ConverterType] + | tuple[_ConverterType, ...] | None = ..., factory: Callable[[], _T] | None = ..., kw_only: bool | None = ..., diff --git a/tests/test_pyright.py b/tests/test_pyright.py index b974114ce..62603ceb3 100644 --- a/tests/test_pyright.py +++ b/tests/test_pyright.py @@ -106,3 +106,36 @@ def test_pyright_attrsinstance_compat(tmp_path): ) } assert diagnostics == expected_diagnostics + + +def test_pyright_field_converters_tuple(tmp_path): + """ + Test that `field(converter=(_, _, ...))` raises no FPs in Pyright. + """ + test_pyright_field_converters_tuple_path = ( + tmp_path / "test_pyright_field_converters_tuple.py" + ) + test_pyright_field_converters_tuple_path.write_text( + """\ +import attrs + + +def square(value: int) -> int: + return value * value + +def negate(value: int) -> int: + return -value + + +@attrs.define +class SomeClass: + + value: int = attrs.field(converter=(square, negate)) +""" + ) + + diagnostics = parse_pyright_output( + test_pyright_field_converters_tuple_path + ) + + assert not diagnostics