@@ -201,15 +201,22 @@ def resove_annotations(obj: typing.Callable):
201201 e ,
202202 ) from e
203203 elif inspect .isclass (obj ) or hasattr (obj , "__class__" ):
204+ if not inspect .isclass (obj ):
205+ objclass = type (obj )
206+ else :
207+ objclass = obj
208+ namespace = dict (vars (objclass ))
209+ bases = set (objclass .__bases__ )
210+ bases .add (objclass )
211+ while len (bases ) > 0 :
212+ base = bases .pop ()
213+ namespace .update (vars (inspect .getmodule (base )))
214+ if hasattr (base , "bases" ):
215+ bases .update (set (base .bases ))
204216 for k , v in obj .__annotations__ .items ():
205217 if isinstance (v , str ):
206218 try :
207- obj .__annotations__ [k ] = eval (
208- v ,
209- dict (vars (obj ))
210- | dict (vars (type (obj )))
211- | dict (vars (inspect .getmodule (obj ))),
212- )
219+ obj .__annotations__ [k ] = eval (v , namespace )
213220 except Exception as e :
214221 raise Exception (
215222 f"Annotation of attribute `{ k } ` of { get_name (obj )} "
@@ -225,7 +232,7 @@ def is_annoted(func: typing.Callable) -> bool:
225232 return hasattr (func , "__pyod_annotate__" )
226233
227234
228- WARN_RET = set ()
235+ WARNED_ABOUT_NO_RETURN_TYPE = set ()
229236
230237
231238def annotate (
@@ -311,12 +318,15 @@ def wrapper(*call_posargs, **call_kwargs):
311318 + f" { signature .return_annotation !r} "
312319 + f" of function { get_name (obj )} (#{ message } )" ,
313320 )
314- elif ret is not None and get_name (obj ) not in WARN_RET :
321+ elif (
322+ ret is not None
323+ and get_name (obj ) not in WARNED_ABOUT_NO_RETURN_TYPE
324+ ):
315325 warnings .warn (
316326 f"Function { get_name (obj )} "
317327 + " returned a value but had no return annotation."
318328 )
319- WARN_RET .add (get_name (obj ))
329+ WARNED_ABOUT_NO_RETURN_TYPE .add (get_name (obj ))
320330 return ret
321331
322332 return wrapper
0 commit comments