@@ -60,9 +60,7 @@ def doc_only_run(self):
6060 docstring = list (node .findall (condition = desc_content ))
6161
6262 if not docstring :
63- logger .warning (
64- f"The docstring for { self .arguments [0 ]} cannot be found."
65- )
63+ logger .warning (f"The docstring for { self .arguments [0 ]} cannot be found." )
6664 return []
6765
6866 return docstring
@@ -100,99 +98,38 @@ def no_doc_run(self):
10098# replacements will be performed globally. Hyperlinks will be added in the
10199# signature if "good type" is a valid (potentially user defined) python type
102100type_replacements = {
103- (
104- r"libsemigroups::Presentation<std::__cxx11::basic_string<char, "
105- r"std::char_traits<char>, std::allocator<char> > >"
106- ): r"Presentation" ,
107- r"libsemigroups::BMat8" : r"BMat8" ,
108101 r"libsemigroups::WordGraph<unsigned int>" : r"WordGraph" ,
109- r"libsemigroups::Gabow<unsigned int>" : r"Gabow" ,
110- (
111- r"libsemigroups::DynamicMatrix<libsemigroups::IntegerPlus<long long>, "
112- r"libsemigroups::IntegerProd<long long>, libsemigroups::IntegerZero"
113- r"<long long>, libsemigroups::IntegerOne<long long>, long long>"
114- ): r"Matrix" ,
115102 r"libsemigroups::SimsStats" : r"SimsStats" ,
116103 r"libsemigroups::Sims1" : r"Sims1" ,
117104 r"libsemigroups::Sims2" : r"Sims2" ,
118105 r"libsemigroups::RepOrc" : r"RepOrc" ,
119106 r"libsemigroups::MinimalRepOrc" : r"MinimalRepOrc" ,
120- (
121- r"libsemigroups::DynamicMatrix<libsemigroups::BooleanPlus, "
122- r"libsemigroups::BooleanProd, libsemigroups::BooleanZero, "
123- r"libsemigroups::BooleanOne, int>"
124- ): r"Matrix" ,
125- r"libsemigroups::Konieczny<BMat8, "
126- "libsemigroups::KoniecznyTraits<BMat8>>::DClass" : "KoniecznyBMat8DClass" ,
127107}
128108
129109# This dictionary should be of the form class_name -> (pattern, repl), where
130110# "pattern" should be replaced by "repl" in the signature of all functions in
131111# "class_name"
132112class_specific_replacements = {
133- "RightActionPPerm1List" : [
134- ("libsemigroups::PPerm<16ul, unsigned char>" , "Element" ),
135- ("libsemigroups::Element" , "Element" ),
136- ("libsemigroups::PPerm<0ul, unsigned char>" , "Element" ),
137- ],
138- "Transf1" : [
139- ("PTransfBase1" , "Transf1" ),
140- ],
141- "PPerm1" : [
142- ("PTransfBase1" , "PPerm1" ),
143- ],
144- "Perm1" : [
145- ("PTransfBase1" , "Perm1" ),
146- ("Transf" , "Perm" ),
147- ],
148- "FroidurePinPBR" : [(r"\bPBR\b" , "Element" )],
149- "SchreierSimsPerm1" : [(r"\bPerm1\b" , "Element" )],
150113 "Sims1" : [("SubclassType" , "Sims1" ), ("SimsSettingsSims1" , "Sims1" )],
151114 "Sims2" : [("SubclassType" , "Sims2" ), ("SimsSettingsSims2" , "Sims2" )],
152115 "MinimalRepOrc" : [
153116 ("SubclassType" , "MinimalRepOrc" ),
154117 ("SimsSettingsMinimalRepOrc" , "MinimalRepOrc" ),
155- (r"\bRepOrc\b" , "MinimalRepOrc" ),
156118 ],
157119 "RepOrc" : [
158120 ("SubclassType" , "RepOrc" ),
159121 ("SimsSettingsRepOrc" , "RepOrc" ),
160122 ],
161- "KoniecznyBMat8" : [
162- (r"\bBMat8\b" , "Element" ),
163- (
164- "libsemigroups::Konieczny<libsemigroups::Element, "
165- "libsemigroups::KoniecznyTraits<libsemigroups::Element>>::DClass" ,
166- "KoniecznyBMat8.DClass" ,
167- ),
168- ],
169123}
170124
171125# This dictionary should be of the form bad_string -> good_string. These
172126# replacements will be made in each docstring, and will be useful for removing
173127# things like the signatures that sphinx inserts into every docstring
174- docstring_replacements = {
175- r"_current_index_of.*$" : "" ,
176- r"_number_of_classes.*$" : "" ,
177- r"_small_overlap_class.*$" : "" ,
178- r"aho_corasick_dot\(.*\)(\s*->\s*(\w+::)*\w*)?" : "" ,
179- r"congruence_non_trivial_classes.*$" : "" ,
180- r"congruence_partition.*$" : "" ,
181- r"kambites_normal_forms.*$" : "" ,
182- r"knuth_bendix_non_trivial_classes.*$" : "" ,
183- r"pbr_one\(\*args, \*\*kwargs\)" : "" ,
184- r"todd_coxeter_is_non_trivial.*$" : "" ,
185- r"todd_coxeter_non_trivial_class.*$" : "" ,
186- r"todd_coxeter_normal_forms.*$" : "" ,
187- r"todd_coxeter_partition.*$" : "" ,
188- r"todd_coxeter_redundant_rule.*$" : "" ,
189- r"word_graph_dot\(.*\)(\s*->\s*(\w+::)*\w*)?" : "" ,
190- r"D_class_of_element\(.*$" : "" ,
191- }
128+ docstring_replacements = {}
192129
193130
194131# This is what sphinx considers to be a signature
195- signature_re = re .compile (
132+ custom_signature_re = re .compile (
196133 r""":sig=([\w.]+::)? # explicit module name
197134 ([\w.]+\.)? # module and/or class name(s)
198135 (?:(\w+) \s*)? # thing name
@@ -202,6 +139,16 @@ def no_doc_run(self):
202139 re .VERBOSE ,
203140)
204141
142+ inserted_signature_re = re .compile (
143+ r"""^([\w.]+::)? # explicit module name
144+ ([\w.]+\.)? # module and/or class name(s)
145+ (?:(\w+) \s*)? # thing name
146+ (?: \[\s*(.*)\s*\])? # type parameters list
147+ (?: \((.*)\))? # arguments
148+ (?:\s* -> \s* (.*))?$""" , # return annotation
149+ re .VERBOSE | re .MULTILINE ,
150+ )
151+
205152
206153def sub_if_not_none (pattern , repl , * strings ):
207154 """Make regex replacement on inputs that are not None"""
@@ -222,14 +169,19 @@ def sub_if_not_none(pattern, repl, *strings):
222169def sig_alternative (doc , signature , return_annotation ):
223170 """Find an alternative signature defined in the docstring
224171
225- If there is not exactly one signature set using :sig=...:, then no changes
226- occur.
172+ If there is no signature specified using :sig=...:, then no changes occur.
173+ If multiple different signatures are specified using :sig=...:, then the
174+ signature is set to (*args, **kwargs). Otherwise, the signature is set to
175+ the unique signature specified using :sig=...:.
227176 """
228177 if not doc :
229178 return signature , return_annotation
230- m = set (re .findall (signature_re , doc ))
231- if len (m ) != 1 :
179+
180+ m = set (re .findall (custom_signature_re , doc ))
181+ if len (m ) == 0 :
232182 return signature , return_annotation
183+ if len (m ) > 1 :
184+ return "(*args, **kwargs)" , ""
233185
234186 _ , _ , _ , _ , args , return_annotation = m .pop ()
235187 new_sig = f"({ args } )"
@@ -368,7 +320,7 @@ def fix_overloads(app, what, name, obj, options, lines):
368320 # Capture the initial indent and the function signature
369321 new_sig = False
370322 if i + 3 < len (input_text ):
371- m = re .match (signature_re , input_text [i + 3 ])
323+ m = re .match (custom_signature_re , input_text [i + 3 ])
372324 if m is not None :
373325 new_sig = True
374326 _ , _ , _ , _ , args , return_annotation = m .groups ()
@@ -403,6 +355,17 @@ def fix_overloads(app, what, name, obj, options, lines):
403355
404356def remove_doc_annotations (app , what , name , obj , options , lines ):
405357 """Remove any special decorations from the documentation"""
358+ if len (lines ) == 0 :
359+ return
360+
361+ # Remove inserted signatures if they have the wrong name
362+ m = re .match (inserted_signature_re , lines [0 ])
363+ if m :
364+ specified_name = m [3 ]
365+ short_name = name .split ("." )[- 1 ]
366+ if short_name != specified_name :
367+ del lines [0 ]
368+
406369 for i in range (len (lines ) - 1 , - 1 , - 1 ):
407370 for bad , good in docstring_replacements .items ():
408371 lines [i ], n = re .subn (bad , good , lines [i ])
@@ -443,8 +406,10 @@ def check_string_replacements(app, env):
443406 return
444407
445408 # Check which replacements were not used
409+ any_warnings = False
446410 for bad_type , good_type in type_replacements .items ():
447411 if bad_type not in strings_replaced :
412+ any_warnings = True
448413 logger .warning (
449414 f'"{ bad_type } " -> "{ good_type } "' ,
450415 type = "unused-replacement" ,
@@ -453,17 +418,20 @@ def check_string_replacements(app, env):
453418 for class_name , repls in class_specific_replacements .items ():
454419 for pattern , repl in repls :
455420 if pattern not in strings_replaced :
421+ any_warnings = True
456422 logger .warning (
457423 f'"{ pattern } " -> "{ repl } " in { class_name } ' ,
458424 type = "unused-replacement" ,
459425 )
460426 for bad_string , good_string in docstring_replacements .items ():
461427 if bad_string not in strings_replaced :
428+ any_warnings = True
462429 logger .warning (
463430 f'"{ bad_string } " -> "{ good_string } "' ,
464431 type = "unused-replacement" ,
465432 )
466- logger .info (f"Please correct this in { __file__ } " )
433+ if any_warnings :
434+ logger .info (f"Please correct this in { __file__ } " )
467435
468436
469437def setup (app ):
0 commit comments