Fix inferred type of is_dataclass(Any)#12517
Conversation
|
|
||
| # HACK: `obj: Never` typing matches if object argument is using `Any` type. | ||
| @overload | ||
| def is_dataclass(obj: Never) -> TypeIs[DataclassInstance | type[DataclassInstance]]: ... # type: ignore[narrowed-type-not-subtype] # pyright: ignore[reportGeneralTypeIssues] |
There was a problem hiding this comment.
Suppressing mypy error:
stdlib/dataclasses.pyi:219: error: Narrowed type "DataclassInstance | type[DataclassInstance]" is not a subtype of input type "Never" [narrowed-type-not-subtype]
This comment has been minimized.
This comment has been minimized.
74ea978 to
b8243c1
Compare
| def is_dataclass_object(arg: object) -> None: | ||
| if dc.is_dataclass(arg): | ||
| assert_type(arg, Union["DataclassInstance", Type["DataclassInstance"]]) | ||
|
|
||
|
|
||
| def is_dataclass_type(arg: type) -> None: | ||
| if dc.is_dataclass(arg): | ||
| assert_type(arg, Type["DataclassInstance"]) |
There was a problem hiding this comment.
Actually these cases are already checked by check_other_isdataclass_overloads below and can be removed.
| def is_dataclass_object(arg: object) -> None: | |
| if dc.is_dataclass(arg): | |
| assert_type(arg, Union["DataclassInstance", Type["DataclassInstance"]]) | |
| def is_dataclass_type(arg: type) -> None: | |
| if dc.is_dataclass(arg): | |
| assert_type(arg, Type["DataclassInstance"]) |
|
The primer output looks promising. It mostly changes wrong error messages into true positives. (Due to |
|
Diff from mypy_primer, showing the effect of this PR on open source code: pydantic (https://github.com/pydantic/pydantic)
+ pydantic/v1/json.py:80: error: Argument 1 to "asdict" has incompatible type "DataclassInstance | type[DataclassInstance]"; expected "DataclassInstance" [arg-type]
- pydantic/v1/json.py:80: error: No overload variant of "asdict" matches argument type "type[DataclassInstance]" [call-overload]
- pydantic/v1/json.py:80: note: Possible overload variants:
- pydantic/v1/json.py:80: note: def asdict(obj: DataclassInstance) -> dict[str, Any]
- pydantic/v1/json.py:80: note: def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[list[tuple[str, Any]]], _T]) -> _T
pytest (https://github.com/pytest-dev/pytest)
+ src/_pytest/_io/pprint.py:114: error: Unused "type: ignore" comment [unused-ignore]
+ src/_pytest/_io/pprint.py:116: error: "DataclassInstance" has no attribute "__dataclass_params__" [attr-defined]
+ src/_pytest/_io/pprint.py:122: error: Unused "type: ignore" comment [unused-ignore]
core (https://github.com/home-assistant/core)
+ homeassistant/util/frozen_dataclass_compat.py:114: error: Argument 1 to "__new__" of "object" has incompatible type "DataclassInstance | type[DataclassInstance]"; expected "type[DataclassInstance]" [arg-type]
streamlit (https://github.com/streamlit/streamlit)
+ lib/streamlit/runtime/caching/hashing.py:409:53: error: Argument 1 to "asdict" has incompatible type "Union[DataclassInstance, Type[DataclassInstance]]"; expected "DataclassInstance" [arg-type]
- lib/streamlit/runtime/caching/hashing.py:409:34: error: No overload variant of "asdict" matches argument type "Type[DataclassInstance]" [call-overload]
- lib/streamlit/runtime/caching/hashing.py:409:34: note: Possible overload variants:
- lib/streamlit/runtime/caching/hashing.py:409:34: note: def asdict(obj: DataclassInstance) -> Dict[str, Any]
- lib/streamlit/runtime/caching/hashing.py:409:34: note: def [_T] asdict(obj: DataclassInstance, *, dict_factory: Callable[[List[Tuple[str, Any]]], _T]) -> _T
koda-validate (https://github.com/keithasaurus/koda-validate)
+ koda_validate/typehints.py:119: error: Argument 1 to "DataclassValidator" has incompatible type "DataclassInstance | type[DataclassInstance]"; expected "type[Any]" [arg-type]
+ koda_validate/signature.py:81: error: Argument 1 to "DataclassValidator" has incompatible type "DataclassInstance | type[DataclassInstance]"; expected "type[Any]" [arg-type]
+ koda_validate/signature.py:81: error: Argument 1 to "dataclass_no_coerce" has incompatible type "DataclassInstance | type[DataclassInstance]"; expected "type[DataclassInstance]" [arg-type]
xarray-dataclasses (https://github.com/astropenguin/xarray-dataclasses)
- xarray_dataclasses/typing.py:300: error: Unused "type: ignore" comment [unused-ignore]
|
srittau
left a comment
There was a problem hiding this comment.
LGTM, but I'd like a third opinion.
|
Thoughts on adding a TODO to revert things here? Once python/mypy#17579 is fixed. At least making it clear in the stubs this is a MyPy specific issue we're accounting for. |
Fixes #12401 by adding a hack, in the form of overload
def is_dataclass(obj: Never)-- becauseAnyis compatible withNever, but no real type is.Previously
is_dataclass(Any)matched the wrong overload rule and inferred incorrect return type.