@@ -179,9 +179,79 @@ def _copy_docstring_and_deprecators(
179
179
method = method .__wrapped__
180
180
for decorator in decorators [::- 1 ]:
181
181
func = decorator (func )
182
+ _add_pyplot_note (func , method )
182
183
return func
183
184
184
185
186
+ _NO_PYPLOT_NOTE = [
187
+ 'FigureBase._gci' , # wrapped_func is private
188
+ '_AxesBase._sci' , # wrapped_func is private
189
+ 'Artist.findobj' , # not a standard pyplot wrapper because it does not operate
190
+ # on the current Figure / Axes. Explanation of relation would
191
+ # be more complex and is not too important.
192
+ ]
193
+
194
+
195
+ def _add_pyplot_note (func , wrapped_func ):
196
+ """
197
+ Add a note to the docstring of *func* that it is a pyplot wrapper.
198
+
199
+ The note is added to the "Notes" section of the docstring. If that does
200
+ not exist, a "Notes" section is created. In numpydoc, the "Notes"
201
+ section is the third last possible section, only potentially followed by
202
+ "References" and "See Also".
203
+ """
204
+ if not func .__doc__ :
205
+ return # nothing to do
206
+
207
+ qualname = wrapped_func .__qualname__
208
+ if qualname in _NO_PYPLOT_NOTE :
209
+ return
210
+
211
+ wrapped_func_is_method = True
212
+ if "." not in qualname :
213
+ # method qualnames are prefixed by the class and ".", e.g. "Axes.plot"
214
+ wrapped_func_is_method = False
215
+ link = f"{ wrapped_func .__module__ } .{ qualname } "
216
+ elif qualname .startswith ("Axes." ): # e.g. "Axes.plot"
217
+ link = ".axes." + qualname
218
+ elif qualname .startswith ("_AxesBase." ): # e.g. "_AxesBase.set_xlabel"
219
+ link = ".axes.Axes" + qualname [9 :]
220
+ elif qualname .startswith ("Figure." ): # e.g. "Figure.figimage"
221
+ link = "." + qualname
222
+ elif qualname .startswith ("FigureBase." ): # e.g. "FigureBase.gca"
223
+ link = ".Figure" + qualname [10 :]
224
+ elif qualname .startswith ("FigureCanvasBase." ): # "FigureBaseCanvas.mpl_connect"
225
+ link = "." + qualname
226
+ else :
227
+ raise RuntimeError (f"Wrapped method from unexpected class: { qualname } " )
228
+
229
+ if wrapped_func_is_method :
230
+ message = f"This is the :ref:`pyplot wrapper <pyplot_interface>` for `{ link } `."
231
+ else :
232
+ message = f"This is equivalent to `{ link } `."
233
+
234
+ # Find the correct insert position:
235
+ # - either we already have a "Notes" section into which we can insert
236
+ # - or we create one before the next present section. Note that in numpydoc, the
237
+ # "Notes" section is the third last possible section, only potentially followed
238
+ # by "References" and "See Also".
239
+ # - or we append a new "Notes" section at the end.
240
+ doc = inspect .cleandoc (func .__doc__ )
241
+ if "\n Notes\n -----" in doc :
242
+ before , after = doc .split ("\n Notes\n -----" , 1 )
243
+ elif (index := doc .find ("\n References\n ----------" )) != - 1 :
244
+ before , after = doc [:index ], doc [index :]
245
+ elif (index := doc .find ("\n See Also\n --------" )) != - 1 :
246
+ before , after = doc [:index ], doc [index :]
247
+ else :
248
+ # No "Notes", "References", or "See Also" --> append to the end.
249
+ before = doc + "\n "
250
+ after = ""
251
+
252
+ func .__doc__ = f"{ before } \n Notes\n -----\n \n .. note::\n \n { message } \n { after } "
253
+
254
+
185
255
## Global ##
186
256
187
257
0 commit comments