@@ -2887,3 +2887,78 @@ def test_function():
28872887 explicit_ext_inst = AnnotatedExtensionClass()
28882888 with assertRaises(AttributeError):
28892889 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