@@ -80,45 +80,53 @@ class ModuleEntry(NamedTuple):
8080 deprecated : bool
8181
8282
83- def type_to_xref (target : str , env : BuildEnvironment = None , suppress_prefix : bool = False
84- ) -> addnodes .pending_xref :
85- """Convert a type string to a cross reference node."""
86- if target == 'None' or target .startswith ('typing.' ):
83+ def parse_reftarget (reftarget : str , suppress_prefix : bool = False
84+ ) -> Tuple [str , str , str , bool ]:
85+ """Parse a type string and return (reftype, reftarget, title, refspecific flag)"""
86+ refspecific = False
87+ if reftarget .startswith ('.' ):
88+ reftarget = reftarget [1 :]
89+ title = reftarget
90+ refspecific = True
91+ elif reftarget .startswith ('~' ):
92+ reftarget = reftarget [1 :]
93+ title = reftarget .split ('.' )[- 1 ]
94+ elif suppress_prefix :
95+ title = reftarget .split ('.' )[- 1 ]
96+ elif reftarget .startswith ('typing.' ):
97+ title = reftarget [7 :]
98+ else :
99+ title = reftarget
100+
101+ if reftarget == 'None' or reftarget .startswith ('typing.' ):
87102 # typing module provides non-class types. Obj reference is good to refer them.
88103 reftype = 'obj'
89104 else :
90105 reftype = 'class'
91106
107+ return reftype , reftarget , title , refspecific
108+
109+
110+ def type_to_xref (target : str , env : BuildEnvironment = None , suppress_prefix : bool = False
111+ ) -> addnodes .pending_xref :
112+ """Convert a type string to a cross reference node."""
92113 if env :
93114 kwargs = {'py:module' : env .ref_context .get ('py:module' ),
94115 'py:class' : env .ref_context .get ('py:class' )}
95116 else :
96117 kwargs = {}
97118
98- refspecific = False
99- if target .startswith ('.' ):
100- target = target [1 :]
101- text = target
102- refspecific = True
103- elif target .startswith ('~' ):
104- target = target [1 :]
105- text = target .split ('.' )[- 1 ]
106- elif suppress_prefix :
107- text = target .split ('.' )[- 1 ]
108- elif target .startswith ('typing.' ):
109- text = target [7 :]
110- else :
111- text = target
119+ reftype , target , title , refspecific = parse_reftarget (target , suppress_prefix )
112120
113121 if env .config .python_use_unqualified_type_names :
114122 # Note: It would be better to use qualname to describe the object to support support
115123 # nested classes. But python domain can't access the real python object because this
116124 # module should work not-dynamically.
117- shortname = text .split ('.' )[- 1 ]
125+ shortname = title .split ('.' )[- 1 ]
118126 contnodes : List [Node ] = [pending_xref_condition ('' , shortname , condition = 'resolved' ),
119- pending_xref_condition ('' , text , condition = '*' )]
127+ pending_xref_condition ('' , title , condition = '*' )]
120128 else :
121- contnodes = [nodes .Text (text )]
129+ contnodes = [nodes .Text (title )]
122130
123131 return pending_xref ('' , * contnodes ,
124132 refdomain = 'py' , reftype = reftype , reftarget = target ,
@@ -354,27 +362,27 @@ def make_xref(self, rolename: str, domain: str, target: str,
354362 result = super ().make_xref (rolename , domain , target , # type: ignore
355363 innernode , contnode ,
356364 env , inliner = None , location = None )
357- result [ 'refspecific' ] = True
358- result ['py:module ' ] = env . ref_context . get ( 'py:module' )
359- result ['py:class ' ] = env .ref_context .get ('py:class ' )
360- if target . startswith (( '.' , '~' )):
361- prefix , result [ 'reftarget' ] = target [ 0 ], target [ 1 :]
362- if prefix == '.' :
363- text = target [ 1 :]
364- elif prefix == '~' :
365- text = target . split ( '.' )[ - 1 ]
366- for node in list ( result . traverse ( nodes . Text )):
367- node . parent [ node . parent . index ( node )] = nodes . Text ( text )
368- break
369- elif isinstance ( result , pending_xref ) and env .config .python_use_unqualified_type_names :
370- children = result .children
371- result .clear ()
372-
373- shortname = target .split ('.' )[- 1 ]
374- textnode = innernode ('' , shortname )
375- contnodes = [pending_xref_condition ('' , '' , textnode , condition = 'resolved' ),
376- pending_xref_condition ('' , '' , * children , condition = '*' )]
377- result .extend (contnodes )
365+ if isinstance ( result , pending_xref ):
366+ result ['refspecific ' ] = True
367+ result ['py:module ' ] = env .ref_context .get ('py:module ' )
368+ result [ 'py:class' ] = env . ref_context . get ( 'py:class' )
369+
370+ reftype , reftarget , reftitle , _ = parse_reftarget ( target )
371+ if reftarget != reftitle :
372+ result [ 'reftype' ] = reftype
373+ result [ 'reftarget' ] = reftarget
374+
375+ result . clear ( )
376+ result += innernode ( reftitle , reftitle )
377+ elif env .config .python_use_unqualified_type_names :
378+ children = result .children
379+ result .clear ()
380+
381+ shortname = target .split ('.' )[- 1 ]
382+ textnode = innernode ('' , shortname )
383+ contnodes = [pending_xref_condition ('' , '' , textnode , condition = 'resolved' ),
384+ pending_xref_condition ('' , '' , * children , condition = '*' )]
385+ result .extend (contnodes )
378386
379387 return result
380388
@@ -407,33 +415,15 @@ def make_xrefs(self, rolename: str, domain: str, target: str,
407415
408416
409417class PyField (PyXrefMixin , Field ):
410- def make_xref (self , rolename : str , domain : str , target : str ,
411- innernode : Type [TextlikeNode ] = nodes .emphasis ,
412- contnode : Node = None , env : BuildEnvironment = None ,
413- inliner : Inliner = None , location : Node = None ) -> Node :
414- if rolename == 'class' and target == 'None' :
415- # None is not a type, so use obj role instead.
416- rolename = 'obj'
417-
418- return super ().make_xref (rolename , domain , target , innernode , contnode ,
419- env , inliner , location )
418+ pass
420419
421420
422421class PyGroupedField (PyXrefMixin , GroupedField ):
423422 pass
424423
425424
426425class PyTypedField (PyXrefMixin , TypedField ):
427- def make_xref (self , rolename : str , domain : str , target : str ,
428- innernode : Type [TextlikeNode ] = nodes .emphasis ,
429- contnode : Node = None , env : BuildEnvironment = None ,
430- inliner : Inliner = None , location : Node = None ) -> Node :
431- if rolename == 'class' and target == 'None' :
432- # None is not a type, so use obj role instead.
433- rolename = 'obj'
434-
435- return super ().make_xref (rolename , domain , target , innernode , contnode ,
436- env , inliner , location )
426+ pass
437427
438428
439429class PyObject (ObjectDescription [Tuple [str , str ]]):
0 commit comments