@@ -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] |