@@ -504,27 +504,57 @@ def __init__(
504504
505505 self .current_file = None
506506
507- def match (self , search_name ):
507+ def _resolve_nickname (self , name ):
508+ """Return intended name if `name` is a nickname.
509+
510+ Parameters
511+ ----------
512+ name : str
513+
514+ Returns
515+ -------
516+ resolved : str
517+ """
518+ original = name
519+ resolved = name
520+ for _ in range (1000 ):
521+ name = self .type_nicknames .get (name )
522+ if name is None :
523+ break
524+ resolved = name
525+ else :
526+ logger .warning (
527+ "reached limit while resolving nicknames for %r in %s, using %r" ,
528+ original ,
529+ self .current_file or "<file not known>" ,
530+ resolved ,
531+ )
532+ return resolved
533+
534+ def match (self , search ):
508535 """Search for a known annotation name.
509536
510537 Parameters
511538 ----------
512- search_name : str
539+ search : str
513540 current_module : Path, optional
514541
515542 Returns
516543 -------
517544 type_name : str | None
518545 py_import : PyImport | None
519546 """
547+ original_search = search
520548 type_name = None
521549 py_import = None
522550
523551 module = module_name_from_path (self .current_file ) if self .current_file else None
524552
525- if search_name .startswith ("~." ):
553+ search = self ._resolve_nickname (search )
554+
555+ if search .startswith ("~." ):
526556 # Sphinx like matching with abbreviated name
527- pattern = search_name .replace ("." , r"\." )
557+ pattern = search .replace ("." , r"\." )
528558 pattern = pattern .replace ("~" , ".*" )
529559 regex = re .compile (pattern + "$" )
530560 # Might be slow, but works for now
@@ -539,43 +569,41 @@ def match(self, search_name):
539569 py_import = matches [shortest_key ]
540570 type_name = shortest_key
541571 logger .warning (
542- "%r in %s matches multiple types %r, using %r" ,
543- search_name ,
572+ "%r (original %r) in %s matches multiple types %r, using %r" ,
573+ search ,
574+ original_search ,
544575 self .current_file or "<file not known>" ,
545576 matches .keys (),
546577 shortest_key ,
547578 )
548579 elif len (matches ) == 1 :
549580 type_name , py_import = matches .popitem ()
550581 else :
551- search_name = search_name [2 :]
582+ search = search [2 :]
552583 logger .debug (
553584 "couldn't match %r in %s" ,
554- search_name ,
585+ search ,
555586 self .current_file or "<file not known>" ,
556587 )
557588
558- # Replace alias
559- search_name = self .type_nicknames .get (search_name , search_name )
560-
561589 if py_import is None and module :
562590 # Look for matching type in current module
563- py_import = self .types .get (f"{ module } :{ search_name } " )
564- py_import = self .types .get (f"{ module } .{ search_name } " , py_import )
591+ py_import = self .types .get (f"{ module } :{ search } " )
592+ py_import = self .types .get (f"{ module } .{ search } " , py_import )
565593 if py_import :
566- type_name = search_name
594+ type_name = search
567595
568- if py_import is None and search_name in self .types :
569- type_name = search_name
570- py_import = self .types [search_name ]
596+ if py_import is None and search in self .types :
597+ type_name = search
598+ py_import = self .types [search ]
571599
572600 if py_import is None :
573601 # Try a subset of the qualname (first 'a.b.c', then 'a.b' and 'a')
574- for partial_qualname in reversed (accumulate_qualname (search_name )):
602+ for partial_qualname in reversed (accumulate_qualname (search )):
575603 py_import = self .type_prefixes .get (f"{ module } :{ partial_qualname } " )
576604 py_import = self .type_prefixes .get (partial_qualname , py_import )
577605 if py_import :
578- type_name = search_name
606+ type_name = search
579607 break
580608
581609 if (
@@ -590,6 +618,6 @@ def match(self, search_name):
590618 if type_name is not None :
591619 self .successful_queries += 1
592620 else :
593- self .unknown_qualnames .append (search_name )
621+ self .unknown_qualnames .append (search )
594622
595623 return type_name , py_import
0 commit comments