Closed
Description
hi, this is continuing from #14868, a user found another variant which points to something that likely needs to be adjusted in the fix just made in #15006.
same test case as #14868, but we add an additional alternative input type for the setter; the new logic does not interpret "optional" correctly (pyright works):
from __future__ import annotations
from typing import Any
from typing import Generic
from typing import Optional
from typing import overload
from typing import TYPE_CHECKING
from typing import TypeVar
from typing import Union
from typing_extensions import dataclass_transform
_T = TypeVar("_T")
def model_field(
*,
default: Optional[Any] = None,
init: bool = True,
) -> Any:
raise NotImplementedError()
@dataclass_transform(
eq_default=True, order_default=True, field_specifiers=(model_field,)
)
class ModelBase:
def __init_subclass__(
cls,
*,
init: bool = True,
frozen: bool = False,
eq: bool = True,
order: bool = True,
):
...
class SpecialWrapper(Generic[_T]):
"""some special kind of type that is generic around a _T"""
class Mapped(Generic[_T]):
if TYPE_CHECKING:
@overload
def __get__(self, instance: None, owner: Any) -> Mapped[_T]:
...
@overload
def __get__(self, instance: object, owner: Any) -> _T:
...
def __get__(
self, instance: Optional[object], owner: Any
) -> Union[Mapped[_T], _T]:
...
def __set__(self, instance: Any, value: Union[SpecialWrapper[_T], _T]) -> None:
"""the set method can accept values that are wrapped in the
SpecialWrapper as well as the value directly. this is what
causes the mypy issue.
"""
...
def __delete__(self, instance: Any) -> None:
...
class Customer(ModelBase):
a: Mapped[Optional[str]] = model_field(default=None)
# works
c1 = Customer(a='asdf')
# fails
c2 = Customer(a=None)
where the second case, Optional is not unwrapping the inner type correctly:
$ mypy test4.py
test4.py:77: error: Argument "a" to "Customer" has incompatible type "None"; expected "Union[SpecialWrapper[Optional[str]], str]" [arg-type]
Found 1 error in 1 file (checked 1 source file)