Skip to content

Commit

Permalink
Fix @Frozen typing to work on PEP-681 checkers (#1084)
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanforbes authored Jan 12, 2023
1 parent d4934b1 commit 46053d7
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
1 change: 1 addition & 0 deletions changelog.d/1084.change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`@frozen` now works with type checkers that implement [PEP-681](https://peps.python.org/pep-0681/) (ex. [pyright](https://github.com/microsoft/pyright/)).
58 changes: 57 additions & 1 deletion src/attr/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def __dataclass_transform__(
eq_default: bool = True,
order_default: bool = False,
kw_only_default: bool = False,
frozen_default: bool = False,
field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
) -> Callable[[_T], _T]: ...

Expand Down Expand Up @@ -426,8 +427,63 @@ def define(
) -> Callable[[_C], _C]: ...

mutable = define
frozen = define # they differ only in their defaults

@overload
@__dataclass_transform__(
frozen_default=True, field_descriptors=(attrib, field)
)
def frozen(
maybe_cls: _C,
*,
these: Optional[Dict[str, Any]] = ...,
repr: bool = ...,
unsafe_hash: Optional[bool] = ...,
hash: Optional[bool] = ...,
init: bool = ...,
slots: bool = ...,
frozen: bool = ...,
weakref_slot: bool = ...,
str: bool = ...,
auto_attribs: bool = ...,
kw_only: bool = ...,
cache_hash: bool = ...,
auto_exc: bool = ...,
eq: Optional[bool] = ...,
order: Optional[bool] = ...,
auto_detect: bool = ...,
getstate_setstate: Optional[bool] = ...,
on_setattr: Optional[_OnSetAttrArgType] = ...,
field_transformer: Optional[_FieldTransformer] = ...,
match_args: bool = ...,
) -> _C: ...
@overload
@__dataclass_transform__(
frozen_default=True, field_descriptors=(attrib, field)
)
def frozen(
maybe_cls: None = ...,
*,
these: Optional[Dict[str, Any]] = ...,
repr: bool = ...,
unsafe_hash: Optional[bool] = ...,
hash: Optional[bool] = ...,
init: bool = ...,
slots: bool = ...,
frozen: bool = ...,
weakref_slot: bool = ...,
str: bool = ...,
auto_attribs: bool = ...,
kw_only: bool = ...,
cache_hash: bool = ...,
auto_exc: bool = ...,
eq: Optional[bool] = ...,
order: Optional[bool] = ...,
auto_detect: bool = ...,
getstate_setstate: Optional[bool] = ...,
on_setattr: Optional[_OnSetAttrArgType] = ...,
field_transformer: Optional[_FieldTransformer] = ...,
match_args: bool = ...,
) -> Callable[[_C], _C]: ...
def fields(cls: Type[AttrsInstance]) -> Any: ...
def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ...
def validate(inst: AttrsInstance) -> None: ...
Expand Down
2 changes: 0 additions & 2 deletions tests/dataclass_transform_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class DefineConverter:
reveal_type(DefineConverter.__init__) # noqa


# mypy plugin supports attr.frozen, pyright does not
@attr.frozen()
class Frozen:
a: str
Expand All @@ -34,7 +33,6 @@ class Frozen:
reveal_type(d.a) # noqa


# but pyright supports attr.define(frozen)
@attr.define(frozen=True)
class FrozenDefine:
a: str
Expand Down
5 changes: 5 additions & 0 deletions tests/test_pyright.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ def test_pyright_baseline():
message='Type of "DefineConverter.__init__" is '
'"(self: DefineConverter, with_converter: int) -> None"',
),
PyrightDiagnostic(
severity="error",
message='Cannot assign member "a" for type '
'"Frozen"\n\xa0\xa0"Frozen" is frozen',
),
PyrightDiagnostic(
severity="information",
message='Type of "d.a" is "Literal[\'new\']"',
Expand Down

0 comments on commit 46053d7

Please sign in to comment.