Skip to content

Commit

Permalink
Fix strict optional handling in attrs plugin (#17451)
Browse files Browse the repository at this point in the history
Fixes #13794

Fix is trivial (but unlike for dataclasses, the calls to type ops are
scattered, so I simply put the whole hook inside a single `with`).
  • Loading branch information
ilevkivskyi committed Jun 29, 2024
1 parent e4de4e3 commit 177c8ee
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
17 changes: 16 additions & 1 deletion mypy/plugins/attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
deserialize_and_fixup_type,
)
from mypy.server.trigger import make_wildcard_trigger
from mypy.state import state
from mypy.typeops import get_type_vars, make_simplified_union, map_type_from_supertype
from mypy.types import (
AnyType,
Expand Down Expand Up @@ -317,9 +318,23 @@ def attr_class_maker_callback(
See https://www.attrs.org/en/stable/how-does-it-work.html for information on how attrs works.
If this returns False, some required metadata was not ready yet and we need another
If this returns False, some required metadata was not ready yet, and we need another
pass.
"""
with state.strict_optional_set(ctx.api.options.strict_optional):
# This hook is called during semantic analysis, but it uses a bunch of
# type-checking ops, so it needs the strict optional set properly.
return attr_class_maker_callback_impl(
ctx, auto_attribs_default, frozen_default, slots_default
)


def attr_class_maker_callback_impl(
ctx: mypy.plugin.ClassDefContext,
auto_attribs_default: bool | None,
frozen_default: bool,
slots_default: bool,
) -> bool:
info = ctx.cls.info

init = _get_decorator_bool_argument(ctx, "init", True)
Expand Down
20 changes: 20 additions & 0 deletions test-data/unit/check-plugin-attrs.test
Original file line number Diff line number Diff line change
Expand Up @@ -2475,3 +2475,23 @@ class B:
reveal_type(B.__hash__) # N: Revealed type is "None"

[builtins fixtures/plugin_attrs.pyi]

[case testAttrsStrictOptionalSetProperly]
from typing import Generic, Optional, TypeVar

import attr

T = TypeVar("T")

@attr.mutable()
class Parent(Generic[T]):
run_type: Optional[int] = None

@attr.mutable()
class Child(Parent[float]):
pass

Parent(run_type = None)
c = Child(run_type = None)
reveal_type(c.run_type) # N: Revealed type is "Union[builtins.int, None]"
[builtins fixtures/plugin_attrs.pyi]

0 comments on commit 177c8ee

Please sign in to comment.