@@ -807,3 +807,217 @@ reveal_type(bar.base) # N: Revealed type is "builtins.int"
807
807
808
808
[typing fixtures/typing-full.pyi]
809
809
[builtins fixtures/dataclasses.pyi]
810
+
811
+ [case testDataclassTransformSimpleDescriptor]
812
+ # flags: --python-version 3.11
813
+
814
+ from typing import dataclass_transform, overload, Any
815
+
816
+ @dataclass_transform()
817
+ def my_dataclass(cls): ...
818
+
819
+ class Desc:
820
+ @overload
821
+ def __get__(self, instance: None, owner: Any) -> Desc: ...
822
+ @overload
823
+ def __get__(self, instance: object, owner: Any) -> str: ...
824
+ def __get__(self, instance: object | None, owner: Any) -> Desc | str: ...
825
+
826
+ def __set__(self, instance: Any, value: str) -> None: ...
827
+
828
+ @my_dataclass
829
+ class C:
830
+ x: Desc
831
+ y: int
832
+
833
+ C(x='x', y=1)
834
+ C(x=1, y=1) # E: Argument "x" to "C" has incompatible type "int"; expected "str"
835
+ reveal_type(C(x='x', y=1).x) # N: Revealed type is "builtins.str"
836
+ reveal_type(C(x='x', y=1).y) # N: Revealed type is "builtins.int"
837
+ reveal_type(C.x) # N: Revealed type is "__main__.Desc"
838
+
839
+ [typing fixtures/typing-full.pyi]
840
+ [builtins fixtures/dataclasses.pyi]
841
+
842
+ [case testDataclassTransformUnannotatedDescriptor]
843
+ # flags: --python-version 3.11
844
+
845
+ from typing import dataclass_transform, overload, Any
846
+
847
+ @dataclass_transform()
848
+ def my_dataclass(cls): ...
849
+
850
+ class Desc:
851
+ @overload
852
+ def __get__(self, instance: None, owner: Any) -> Desc: ...
853
+ @overload
854
+ def __get__(self, instance: object, owner: Any) -> str: ...
855
+ def __get__(self, instance: object | None, owner: Any) -> Desc | str: ...
856
+
857
+ def __set__(*args, **kwargs): ...
858
+
859
+ @my_dataclass
860
+ class C:
861
+ x: Desc
862
+ y: int
863
+
864
+ C(x='x', y=1)
865
+ C(x=1, y=1)
866
+ reveal_type(C(x='x', y=1).x) # N: Revealed type is "builtins.str"
867
+ reveal_type(C(x='x', y=1).y) # N: Revealed type is "builtins.int"
868
+ reveal_type(C.x) # N: Revealed type is "__main__.Desc"
869
+
870
+ [typing fixtures/typing-full.pyi]
871
+ [builtins fixtures/dataclasses.pyi]
872
+
873
+ [case testDataclassTransformGenericDescriptor]
874
+ # flags: --python-version 3.11
875
+
876
+ from typing import dataclass_transform, overload, Any, TypeVar, Generic
877
+
878
+ @dataclass_transform()
879
+ def my_dataclass(frozen: bool = False): ...
880
+
881
+ T = TypeVar("T")
882
+
883
+ class Desc(Generic[T]):
884
+ @overload
885
+ def __get__(self, instance: None, owner: Any) -> Desc[T]: ...
886
+ @overload
887
+ def __get__(self, instance: object, owner: Any) -> T: ...
888
+ def __get__(self, instance: object | None, owner: Any) -> Desc | T: ...
889
+
890
+ def __set__(self, instance: Any, value: T) -> None: ...
891
+
892
+ @my_dataclass()
893
+ class C:
894
+ x: Desc[str]
895
+
896
+ C(x='x')
897
+ C(x=1) # E: Argument "x" to "C" has incompatible type "int"; expected "str"
898
+ reveal_type(C(x='x').x) # N: Revealed type is "builtins.str"
899
+ reveal_type(C.x) # N: Revealed type is "__main__.Desc[builtins.str]"
900
+
901
+ @my_dataclass()
902
+ class D(C):
903
+ y: Desc[int]
904
+
905
+ d = D(x='x', y=1)
906
+ reveal_type(d.x) # N: Revealed type is "builtins.str"
907
+ reveal_type(d.y) # N: Revealed type is "builtins.int"
908
+ reveal_type(D.x) # N: Revealed type is "__main__.Desc[builtins.str]"
909
+ reveal_type(D.y) # N: Revealed type is "__main__.Desc[builtins.int]"
910
+
911
+ @my_dataclass(frozen=True)
912
+ class F:
913
+ x: Desc[str] = Desc()
914
+
915
+ F(x='x')
916
+ F(x=1) # E: Argument "x" to "F" has incompatible type "int"; expected "str"
917
+ reveal_type(F(x='x').x) # N: Revealed type is "builtins.str"
918
+ reveal_type(F.x) # N: Revealed type is "__main__.Desc[builtins.str]"
919
+
920
+ [typing fixtures/typing-full.pyi]
921
+ [builtins fixtures/dataclasses.pyi]
922
+
923
+ [case testDataclassTransformGenericDescriptorWithInheritance]
924
+ # flags: --python-version 3.11
925
+
926
+ from typing import dataclass_transform, overload, Any, TypeVar, Generic
927
+
928
+ @dataclass_transform()
929
+ def my_dataclass(cls): ...
930
+
931
+ T = TypeVar("T")
932
+
933
+ class Desc(Generic[T]):
934
+ @overload
935
+ def __get__(self, instance: None, owner: Any) -> Desc[T]: ...
936
+ @overload
937
+ def __get__(self, instance: object, owner: Any) -> T: ...
938
+ def __get__(self, instance: object | None, owner: Any) -> Desc | T: ...
939
+
940
+ def __set__(self, instance: Any, value: T) -> None: ...
941
+
942
+ class Desc2(Desc[str]):
943
+ pass
944
+
945
+ @my_dataclass
946
+ class C:
947
+ x: Desc2
948
+
949
+ C(x='x')
950
+ C(x=1) # E: Argument "x" to "C" has incompatible type "int"; expected "str"
951
+ reveal_type(C(x='x').x) # N: Revealed type is "builtins.str"
952
+ reveal_type(C.x) # N: Revealed type is "__main__.Desc[builtins.str]"
953
+
954
+ [typing fixtures/typing-full.pyi]
955
+ [builtins fixtures/dataclasses.pyi]
956
+
957
+ [case testDataclassTransformDescriptorWithDifferentGetSetTypes]
958
+ # flags: --python-version 3.11
959
+
960
+ from typing import dataclass_transform, overload, Any
961
+
962
+ @dataclass_transform()
963
+ def my_dataclass(cls): ...
964
+
965
+ class Desc:
966
+ @overload
967
+ def __get__(self, instance: None, owner: Any) -> int: ...
968
+ @overload
969
+ def __get__(self, instance: object, owner: Any) -> str: ...
970
+ def __get__(self, instance, owner): ...
971
+
972
+ def __set__(self, instance: Any, value: bytes) -> None: ...
973
+
974
+ @my_dataclass
975
+ class C:
976
+ x: Desc
977
+
978
+ c = C(x=b'x')
979
+ C(x=1) # E: Argument "x" to "C" has incompatible type "int"; expected "bytes"
980
+ reveal_type(c.x) # N: Revealed type is "builtins.str"
981
+ reveal_type(C.x) # N: Revealed type is "builtins.int"
982
+ c.x = b'x'
983
+ c.x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "bytes")
984
+
985
+ [typing fixtures/typing-full.pyi]
986
+ [builtins fixtures/dataclasses.pyi]
987
+
988
+ [case testDataclassTransformUnsupportedDescriptors]
989
+ # flags: --python-version 3.11
990
+
991
+ from typing import dataclass_transform, overload, Any
992
+
993
+ @dataclass_transform()
994
+ def my_dataclass(cls): ...
995
+
996
+ class Desc:
997
+ @overload
998
+ def __get__(self, instance: None, owner: Any) -> int: ...
999
+ @overload
1000
+ def __get__(self, instance: object, owner: Any) -> str: ...
1001
+ def __get__(self, instance, owner): ...
1002
+
1003
+ def __set__(*args, **kwargs) -> None: ...
1004
+
1005
+ class Desc2:
1006
+ @overload
1007
+ def __get__(self, instance: None, owner: Any) -> int: ...
1008
+ @overload
1009
+ def __get__(self, instance: object, owner: Any) -> str: ...
1010
+ def __get__(self, instance, owner): ...
1011
+
1012
+ @overload
1013
+ def __set__(self, instance: Any, value: bytes) -> None: ...
1014
+ @overload
1015
+ def __set__(self) -> None: ...
1016
+ def __set__(self, *args, **kawrga) -> None: ...
1017
+
1018
+ @my_dataclass
1019
+ class C:
1020
+ x: Desc # E: Unsupported signature for "__set__" in "Desc"
1021
+ y: Desc2 # E: Unsupported "__set__" in "Desc2"
1022
+ [typing fixtures/typing-full.pyi]
1023
+ [builtins fixtures/dataclasses.pyi]
0 commit comments