File: MEP10.rst

package info (click to toggle)
matplotlib 3.6.3-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 76,280 kB
  • sloc: python: 133,763; cpp: 66,599; objc: 1,699; ansic: 1,367; javascript: 765; makefile: 153; sh: 48
file content (190 lines) | stat: -rw-r--r-- 6,996 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
==============================
 MEP10: Docstring consistency
==============================
.. contents::
   :local:

Status
======

**Progress**

This is still an on-going effort

Branches and Pull requests
==========================


Abstract
========

matplotlib has a great deal of inconsistency between docstrings.  This
not only makes the docs harder to read, but it is harder on
contributors, because they don't know which specifications to follow.
There should be a clear docstring convention that is followed
consistently.

The organization of the API documentation is difficult to follow.
Some pages, such as pyplot and axes, are enormous and hard to browse.
There should instead be short summary tables that link to detailed
documentation.  In addition, some of the docstrings themselves are
quite long and contain redundant information.

Building the documentation takes a long time and uses a :file:`make.py`
script rather than a Makefile.

Detailed description
====================

There are number of new tools and conventions available since
matplotlib started using Sphinx that make life easier.  The following
is a list of proposed changes to docstrings, most of which involve
these new features.

Numpy docstring format
----------------------

`Numpy docstring format
<https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt>`_:
This format divides the docstring into clear sections, each having
different parsing rules that make the docstring easy to read both as
raw text and as HTML.  We could consider alternatives, or invent our
own, but this is a strong choice, as it's well used and understood in
the Numpy/Scipy community.

Cross references
----------------

Most of the docstrings in matplotlib use explicit "roles" when linking
to other items, for example: ``:func:`myfunction```.  As of Sphinx
0.4, there is a "default_role" that can be set to "obj", which will
polymorphically link to a Python object of any type.  This allows one
to write ```myfunction``` instead.  This makes docstrings much easier
to read and edit as raw text.  Additionally, Sphinx allows for setting
a current module, so links like ```~matplotlib.axes.Axes.set_xlim```
could be written as ```~axes.Axes.set_xlim```.

Overriding signatures
---------------------

Many methods in matplotlib use the ``*args`` and ``**kwargs`` syntax
to dynamically handle the keyword arguments that are accepted by the
function, or to delegate on to another function.  This, however, is
often not useful as a signature in the documentation.  For this
reason, many matplotlib methods include something like::

    def annotate(self, *args, **kwargs):
        """
        Create an annotation: a piece of text referring to a data
        point.

        Call signature::

          annotate(s, xy, xytext=None, xycoords='data',
                   textcoords='data', arrowprops=None, **kwargs)
        """

This can't be parsed by Sphinx, and is rather verbose in raw text.  As
of Sphinx 1.1, if the ``autodoc_docstring_signature`` config value is
set to True, Sphinx will extract a replacement signature from the
first line of the docstring, allowing this::

    def annotate(self, *args, **kwargs):
        """
        annotate(s, xy, xytext=None, xycoords='data',
                   textcoords='data', arrowprops=None, **kwargs)

        Create an annotation: a piece of text referring to a data
        point.
        """

The explicit signature will replace the actual Python one in the
generated documentation.

Linking rather than duplicating
-------------------------------

Many of the docstrings include long lists of accepted keywords by
interpolating things into the docstring at load time.  This makes the
docstrings very long.  Also, since these tables are the same across
many docstrings, it inserts a lot of redundant information in the docs
-- particularly a problem in the printed version.

These tables should be moved to docstrings on functions whose only
purpose is for help.  The docstrings that refer to these tables should
link to them, rather than including them verbatim.

autosummary extension
---------------------

The Sphinx autosummary extension should be used to generate summary
tables, that link to separate pages of documentation.  Some classes
that have many methods (e.g. `~.axes.Axes`) should be documented with
one method per page, whereas smaller classes should have all of their
methods together.

Examples linking to relevant documentation
------------------------------------------

The examples, while helpful at illustrating how to use a feature, do
not link back to the relevant docstrings.  This could be addressed by
adding module-level docstrings to the examples, and then including
that docstring in the parsed content on the example page.  These
docstrings could easily include references to any other part of the
documentation.

Documentation using help() vs. a browser
----------------------------------------

Using Sphinx markup in the source allows for good-looking docs in your
browser, but the markup also makes the raw text returned using help()
look terrible. One of the aims of improving the docstrings should be
to make both methods of accessing the docs look good.

Implementation
==============

1. The numpydoc extensions should be turned on for matplotlib.  There
   is an important question as to whether these should be included in
   the matplotlib source tree, or used as a dependency.  Installing
   Numpy is not sufficient to get the numpydoc extensions -- it's a
   separate install procedure.  In any case, to the extent that they
   require customization for our needs, we should endeavor to submit
   those changes upstream and not fork them.

2. Manually go through all of the docstrings and update them to the
   new format and conventions.  Updating the cross references (from
   ```:func:`myfunc``` to ```func```) may be able to be
   semi-automated.  This is a lot of busy work, and perhaps this labor
   should be divided on a per-module basis so no single developer is
   over-burdened by it.

3. Reorganize the API docs using autosummary and ``sphinx-autogen``.
   This should hopefully have minimal impact on the narrative
   documentation.

4. Modify the example page generator (:file:`gen_rst.py`) so that it
   extracts the module docstring from the example and includes it in a
   non-literal part of the example page.

5. Use ``sphinx-quickstart`` to generate a new-style Sphinx Makefile.
   The following features in the current :file:`make.py` will have to be
   addressed in some other way:

   - Copying of some static content

   - Specifying a "small" build (only low-resolution PNG files for examples)

Steps 1, 2, and 3 are interdependent.  4 and 5 may be done
independently, though 5 has some dependency on 3.

Backward compatibility
======================

As this mainly involves docstrings, there should be minimal impact on
backward compatibility.

Alternatives
============

None yet discussed.