@@ -128,44 +128,55 @@ def get_mypyc_attrs(stmt: ClassDef | Decorator) -> dict[str, Any]:
128128
129129def is_extension_class (path : str , cdef : ClassDef , errors : Errors ) -> bool :
130130 # Check for @mypyc_attr(native_class=True/False) decorator.
131+ explicit_native_class = get_explicit_native_class (path , cdef , errors )
132+
131133 # Classes with native_class=False are explicitly marked as non extension.
132- # Classes with native_class=True should be extension classes, but they might
133- # not be able to be due to other reasons. Print an error in that case.
134- forced_native_class = False
135- for d in cdef .decorators :
136- mypyc_attr_call = get_mypyc_attr_call (d )
137- if mypyc_attr_call :
138- for i , name in enumerate (mypyc_attr_call .arg_names ):
139- if name != "native_class" :
140- continue
141-
142- if not isinstance (mypyc_attr_call .args [i ], NameExpr ):
143- errors .error (
144- "native_class must be used with True or False only" , path , cdef .line
145- )
146- break
147-
148- if mypyc_attr_call .args [i ].name == "False" :
149- return False
150- elif mypyc_attr_call .args [i ].name == "True" :
151- forced_native_class = True
152- break
153- else :
154- errors .error (
155- "native_class must be used with True or False only" , path , cdef .line
156- )
157- break
134+ if explicit_native_class is False :
135+ return False
158136
159137 implicit_extension_class = is_implicit_extension_class (cdef )
160138
161- if forced_native_class and not implicit_extension_class :
139+ # Classes with native_class=True should be extension classes, but they might
140+ # not be able to be due to other reasons. Print an error in that case.
141+ if explicit_native_class is True and not implicit_extension_class :
162142 errors .error (
163143 "Class is marked as native_class=True but it can't be a native class" , path , cdef .line
164144 )
165145
166146 return implicit_extension_class
167147
168148
149+ def get_explicit_native_class (path : str , cdef : ClassDef , errors : Errors ) -> bool | None :
150+ """Return value of @mypyc_attr(native_class=True/False) decorator.
151+
152+ Look for a @mypyc_attr decorator with native_class=True/False and return
153+ the value assigned or None if it doesn't exist. Other values are an error.
154+ """
155+
156+ for d in cdef .decorators :
157+ mypyc_attr_call = get_mypyc_attr_call (d )
158+ if not mypyc_attr_call :
159+ continue
160+
161+ for i , name in enumerate (mypyc_attr_call .arg_names ):
162+ if name != "native_class" :
163+ continue
164+
165+ arg = mypyc_attr_call .args [i ]
166+ if not isinstance (arg , NameExpr ):
167+ errors .error ("native_class must be used with True or False only" , path , cdef .line )
168+ return None
169+
170+ if arg .name == "False" :
171+ return False
172+ elif arg .name == "True" :
173+ return True
174+ else :
175+ errors .error ("native_class must be used with True or False only" , path , cdef .line )
176+ return None
177+ return None
178+
179+
169180def is_implicit_extension_class (cdef : ClassDef ) -> bool :
170181 for d in cdef .decorators :
171182 # Classes that have any decorator other than supported decorators, are not extension classes
0 commit comments