Skip to content

Commit daf8922

Browse files
authored
Add a few more tests for mypyc_attr native_class (dunder methods and metaclasses) (#18999)
1 parent c0218a4 commit daf8922

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

mypyc/test-data/irbuild-classes.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,3 +1370,14 @@ class NonNativeClassContradiction(): # E: Class is marked as native_class=True
13701370
@mypyc_attr(native_class="yes")
13711371
class BadUse(): # E: native_class must be used with True or False only
13721372
pass
1373+
1374+
[case testMypycAttrNativeClassMetaError]
1375+
from mypy_extensions import mypyc_attr
1376+
1377+
@mypyc_attr(native_class=True)
1378+
class M(type): # E: Inheriting from most builtin types is unimplemented
1379+
pass
1380+
1381+
@mypyc_attr(native_class=True)
1382+
class A(metaclass=M): # E: Class is marked as native_class=True but it can't be a native class
1383+
pass

mypyc/test-data/run-classes.test

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)