@@ -2887,3 +2887,78 @@ def test_function():
2887
2887
explicit_ext_inst = AnnotatedExtensionClass()
2888
2888
with assertRaises(AttributeError):
2889
2889
setattr(explicit_ext_inst, 'attr_instance', 6)
2890
+
2891
+ [case testMypycAttrNativeClassDunder]
2892
+ from mypy_extensions import mypyc_attr
2893
+ from typing import Generic, Optional, TypeVar
2894
+
2895
+ _T = TypeVar("_T")
2896
+
2897
+ get_count = set_count = del_count = 0
2898
+
2899
+ @mypyc_attr(native_class=False)
2900
+ class Bar(Generic[_T]):
2901
+ # Note the lack of __deletable__
2902
+ def __init__(self) -> None:
2903
+ self.value: str = 'start'
2904
+ def __get__(self, instance: _T, owner: Optional[type[_T]] = None) -> str:
2905
+ global get_count
2906
+ get_count += 1
2907
+ return self.value
2908
+ def __set__(self, instance: _T, value: str) -> None:
2909
+ global set_count
2910
+ set_count += 1
2911
+ self.value = value
2912
+ def __delete__(self, instance: _T) -> None:
2913
+ global del_count
2914
+ del_count += 1
2915
+ del self.value
2916
+
2917
+ @mypyc_attr(native_class=False)
2918
+ class Foo(object):
2919
+ bar: Bar = Bar()
2920
+
2921
+ [file driver.py]
2922
+ import native
2923
+
2924
+ f = native.Foo()
2925
+ assert(hasattr(f, 'bar'))
2926
+ assert(native.get_count == 1)
2927
+ assert(f.bar == 'start')
2928
+ assert(native.get_count == 2)
2929
+ f.bar = 'test'
2930
+ assert(f.bar == 'test')
2931
+ assert(native.set_count == 1)
2932
+ del f.bar
2933
+ assert(not hasattr(f, 'bar'))
2934
+ assert(native.del_count == 1)
2935
+
2936
+ [case testMypycAttrNativeClassMeta]
2937
+ from mypy_extensions import mypyc_attr
2938
+ from typing import ClassVar, TypeVar
2939
+
2940
+ _T = TypeVar("_T")
2941
+
2942
+ @mypyc_attr(native_class=False)
2943
+ class M(type):
2944
+ count: ClassVar[int] = 0
2945
+ def make(cls: type[_T]) -> _T:
2946
+ M.count += 1
2947
+ return cls()
2948
+
2949
+ # implicit native_class=False
2950
+ # see testMypycAttrNativeClassMetaError for when trying to set it True
2951
+ class A(metaclass=M):
2952
+ pass
2953
+
2954
+ [file driver.py]
2955
+ import native
2956
+
2957
+ a: native.A = native.A.make()
2958
+ assert(native.A.count == 1)
2959
+
2960
+ class B(native.A):
2961
+ pass
2962
+
2963
+ b: B = B.make()
2964
+ assert(B.count == 2)
0 commit comments