24
24
import sphinx
25
25
import inspect
26
26
import collections
27
+ import hashlib
27
28
28
29
if sphinx .__version__ < '1.0.1' :
29
30
raise RuntimeError ("Sphinx 1.0.1 or newer is required" )
36
37
sixu = lambda s : unicode (s , 'unicode_escape' )
37
38
38
39
39
- def rename_references (app , what , name , obj , options , lines ,
40
- reference_offset = [ 0 ]):
41
- # replace reference numbers so that there are no duplicates
40
+ def rename_references (app , what , name , obj , options , lines ):
41
+ # decorate reference numbers so that there are no duplicates
42
+ # these are later undecorated in the doctree, in relabel_references
42
43
references = set ()
43
44
for line in lines :
44
45
line = line .strip ()
@@ -48,19 +49,41 @@ def rename_references(app, what, name, obj, options, lines,
48
49
references .add (m .group (1 ))
49
50
50
51
if references :
51
- for r in references :
52
- if r .isdigit ():
53
- new_r = sixu ("R%d" ) % (reference_offset [0 ] + int (r ))
54
- else :
55
- new_r = sixu ("%s%d" ) % (r , reference_offset [0 ])
52
+ # we use a hash to mangle the reference name to avoid invalid names
53
+ sha = hashlib .sha256 ()
54
+ sha .update (name .encode ('utf8' ))
55
+ prefix = 'R' + sha .hexdigest ()
56
56
57
+ for r in references :
58
+ new_r = prefix + '-' + r
57
59
for i , line in enumerate (lines ):
58
60
lines [i ] = lines [i ].replace (sixu ('[%s]_' ) % r ,
59
61
sixu ('[%s]_' ) % new_r )
60
62
lines [i ] = lines [i ].replace (sixu ('.. [%s]' ) % r ,
61
63
sixu ('.. [%s]' ) % new_r )
62
64
63
- reference_offset [0 ] += len (references )
65
+
66
+ def relabel_references (app , doc ):
67
+ # Change name_ref to ref in label text
68
+ from docutils .nodes import citation , Text
69
+ from sphinx .addnodes import pending_xref
70
+ for citation_node in doc .traverse (citation ):
71
+ label_node = citation_node [0 ]
72
+ new_text = Text (citation_node ['names' ][0 ].split ('-' )[- 1 ])
73
+ label_node .replace (label_node [0 ], new_text )
74
+
75
+ for id in citation_node ['backrefs' ]:
76
+ ref = doc .ids [id ]
77
+ ref_text = ref [0 ]
78
+
79
+ # Sphinx has created pending_xref nodes with [reftext] text.
80
+ def matching_pending_xref (node ):
81
+ return (isinstance (node , pending_xref ) and
82
+ node [0 ].astext () == '[%s]' % ref_text )
83
+
84
+ for xref_node in ref .parent .traverse ():
85
+ xref_node .replace (xref_node [0 ], Text ('[%s]' % new_text ))
86
+ ref .replace (ref_text , new_text .copy ())
64
87
65
88
66
89
DEDUPLICATION_TAG = ['..' , ' processed by numpydoc' ]
@@ -137,6 +160,7 @@ def setup(app, get_doc_object_=get_doc_object):
137
160
138
161
app .connect ('autodoc-process-docstring' , mangle_docstrings )
139
162
app .connect ('autodoc-process-signature' , mangle_signature )
163
+ app .connect ('doctree-read' , relabel_references )
140
164
app .add_config_value ('numpydoc_edit_link' , None , False )
141
165
app .add_config_value ('numpydoc_use_plots' , None , False )
142
166
app .add_config_value ('numpydoc_show_class_members' , True , True )
0 commit comments