@@ -306,8 +306,9 @@ def get_handler_info(host: Any, method_name: str) -> tuple[str, str] | None:
306306 if len (params ) != 1 :
307307 return None
308308
309+ method = getattr (host , method_name )
309310 param : Parameter = next (iter (params .values ()))
310- annotation = param .annotation
311+ annotation = _resolve_annotation ( host , method , param .annotation )
311312
312313 if annotation == Parameter .empty :
313314 return None
@@ -322,6 +323,42 @@ def get_handler_info(host: Any, method_name: str) -> tuple[str, str] | None:
322323 return None
323324
324325
326+ def _resolve_annotation (host : Any , method : Callable , annotation : Any ) -> Any :
327+ if not isinstance (annotation , str ):
328+ return annotation
329+
330+ globalns = _annotation_globalns (method )
331+ localns = _annotation_localns (host )
332+
333+ try :
334+ resolved = eval (annotation , globalns , localns ) # noqa: B307
335+ except Exception :
336+ resolved = annotation
337+
338+ if isinstance (resolved , str ):
339+ # Quoted postponed annotations evaluate to a string first.
340+ try :
341+ resolved = eval (resolved , globalns , localns ) # noqa: B307
342+ except Exception :
343+ if "." in resolved :
344+ return resolved
345+ return Parameter .empty
346+
347+ return resolved
348+
349+
350+ def _annotation_globalns (method : Callable ) -> dict [str , Any ]:
351+ function = getattr (method , "__func__" , method )
352+ return getattr (function , "__globals__" , {})
353+
354+
355+ def _annotation_localns (host : Any ) -> dict [str , Any ]:
356+ namespace : dict [str , Any ] = {}
357+ for klass in reversed (type (host ).__mro__ ):
358+ namespace .update (vars (klass ))
359+ return namespace
360+
361+
325362def _message_class_name (message_type : Any ) -> str | None :
326363 if isinstance (message_type , str ):
327364 return message_type
0 commit comments