From 37438af7feecfad112ae384d1d066a4e5c0f69a4 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sat, 7 Oct 2017 15:17:43 -0700 Subject: [PATCH] Update docs on docs. Update PULL_REQUEST_TEMPLATE.md to emphasize markup specificities in RST (as opposed to md) regarding double/single backquotes and asterisks. In documenting_mpl.rst: - Various reformattings/line wrappings/rewordings. - Explicitly mark the highlighting language of each code block, as we have a mix of python/shell/rst (and emacs lisp). - Drop unneeded `:func:`/`:class:` markups. - Drop request to line wrap docstrings at 70 characters (in practice they are line-wrapped at 79 like normal Python sources). - Do not forbid spanned cells in tables, which recent Sphinxes handles just fine. In make.py: - Simplify argument parsing, slightly improving output of `./make.py --help` --- .github/PULL_REQUEST_TEMPLATE.md | 4 + doc/devel/documenting_mpl.rst | 322 +++++++++++++++++-------------- doc/make.py | 40 ++-- 3 files changed, 200 insertions(+), 166 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9d9ddcd8303b..7be8f9f1c1c8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,6 +10,10 @@ Please do not create the PR out of master, but out of a separate branch. --> example "Raises ValueError on Non-Numeric Input to set_xlim". Please avoid non-descriptive titles such as "Addresses issue #8576".--> + ## PR Summary diff --git a/doc/devel/documenting_mpl.rst b/doc/devel/documenting_mpl.rst index cd91aaaea7a8..dd23790654cb 100644 --- a/doc/devel/documenting_mpl.rst +++ b/doc/devel/documenting_mpl.rst @@ -1,7 +1,7 @@ .. _documenting-matplotlib: =========================================== -Developer's tips for documenting matplotlib +Developer's tips for documenting Matplotlib =========================================== Getting started @@ -10,75 +10,73 @@ Getting started Installing dependencies ----------------------- -The documentation for matplotlib is generated from reStructuredText using the -Sphinx_ documentation generation tool. There are several extra requirements that -are needed to build the documentation. They are listed in the file -`doc-requirements.txt `_ -as well as listed below: +The documentation for Matplotlib is generated from reStructuredText using +the Sphinx_ documentation generation tool. There are several extra +requirements that are needed to build the documentation. They are listed in +:file:`doc-requirements.txt` as well as listed below: -1. Sphinx-1.3 or later(Version 1.5.0 is not supported) +1. Sphinx 1.3 or later (1.5.0 is not supported) 2. numpydoc 0.4 or later 3. IPython -4. Mock +4. mock 5. colorspacious -6. pillow -7. graphviz +6. Pillow +7. Graphviz .. note:: * You'll need a minimal working LaTeX distribution for many examples to run. - * `Graphviz `_ is not a python package, and needs - to be installed separately. + * `Graphviz `_ is not a Python package, + and needs to be installed separately. General structure ----------------- -All documentation is built from the :file:`doc/` directory. This directory contains both -``.rst`` files that contain pages in the documentation, directories that contain more -``.rst`` files, and configuration files for Sphinx_. +All documentation is built from the :file:`doc/` directory. This directory +contains both ``.rst`` files that contain pages in the documentation, +directories that contain more ``.rst`` files, and configuration files for +Sphinx_. .. note:: - An exception to this are the directories :file:`gallery` and :file:`tutorials`, which - exist in the root directory. These contain Python files that are built by `Sphinx Gallery`_. - When the docs are built, directories of the same name will be generated inside of :file:`docs/`. - The generated directories :file:`docs/gallery` and :file:`docs/tutorials` can be safely deleted. + An exception to this are the directories :file:`gallery` and + :file:`tutorials`, which exist in the root directory. These contain Python + files that are built by `Sphinx Gallery`_. When the docs are built, + directories of the same name will be generated inside of :file:`docs/`. The + generated directories :file:`docs/gallery` and :file:`docs/tutorials` can be + safely deleted. -The configuration file for Sphinx is :file:`doc/conf.py`. It controls which directories -Sphinx parses, how the docs are built, and how the extensions are used. +The configuration file for Sphinx is :file:`doc/conf.py`. It controls which +directories Sphinx parses, how the docs are built, and how the extensions are +used. Building the docs ----------------- The documentation sources are found in the :file:`doc/` directory in the trunk. To build the users guide in html format, cd into -:file:`doc/` and do:: +:file:`doc/` and do: - python make.py html +.. code-block:: sh -or:: + python make.py html - ./make.py html +The list of comamnds and flags for ``make.py`` can be listed by running +``python make.py --help``. In particular, -There are many other flags you can pass to ``make.py``, and you can see the -full list inside that file. Here are two useful ones: +* ``python make.py clean`` will delete the built Sphinx files. Use this + command if you're getting strange errors about missing paths or broken links, + particularly if you move files around. +* ``python make.py latex`` builds a PDF of the documentation. +* The ``--allowsphinxwarnings`` flag allows the docs to continue building even + if Sphinx throws a warning. This is useful for debugging and spot-checking + many warnings at once. -* ``clean`` will delete the built Sphinx files. Use this command if you're getting strange - errors about missing paths or broken links, particularly if you move files around. -* ``latex`` builds a PDF of the documentation. -In addition, these are useful flags: - -* ``--help`` will (among other things) display the allowed commands for ``make.py``. -* ``--allowsphinxwarnings`` will allow the docs to continue building even if Sphinx - throws a warning. This is useful for debugging and spot-checking many warnings - at once. - - -Organization of matplotlib's documentation +Organization of Matplotlib's documentation ========================================== -The actual ReStructured Text files are kept in :file:`doc/users`, +The actual reStructured Text files are kept in :file:`doc/users`, :file:`doc/devel`, :file:`doc/api` and :file:`doc/faq`. The main entry point is :file:`doc/index.rst`, which pulls in the :file:`index.rst` file for the users guide, developers guide, api reference, and faqs. The documentation suite is @@ -97,19 +95,20 @@ docstrings ---------- In addition to the "narrative" documentation described above, -matplotlib also defines its API reference documentation in docstrings. +Matplotlib also defines its API reference documentation in docstrings. For the most part, these are standard Python docstrings, but -matplotlib also includes some features to better support documenting +Matplotlib also includes some features to better support documenting getters and setters. -Matplotlib uses artist introspection of docstrings to support -properties. All properties that you want to support through ``setp`` -and ``getp`` should have a ``set_property`` and ``get_property`` -method in the :class:`~matplotlib.artist.Artist` class. Yes, this is -not ideal given python properties or enthought traits, but it is a -historical legacy for now. The setter methods use the docstring with -the ACCEPTS token to indicate the type of argument the method accepts. -e.g., in :class:`matplotlib.lines.Line2D`:: +Matplotlib uses artist introspection of docstrings to support properties. +All properties that you want to support through `~.pyplot.setp` and +`~.pyplot.getp` should have a ``set_property`` and ``get_property`` method in +the `~.matplotlib.artist.Artist` class. Yes, this is not ideal given python +properties or enthought traits, but it is a historical legacy for now. The +setter methods use the docstring with the ACCEPTS token to indicate the type of +argument the method accepts. e.g., in `.Line2D`: + +.. code-block:: python # in lines.py def set_linestyle(self, linestyle): @@ -119,13 +118,12 @@ e.g., in :class:`matplotlib.lines.Line2D`:: ACCEPTS: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' | ' ' | '' ] """ -Since matplotlib uses a lot of pass-through ``kwargs``, e.g., in every -function that creates a line (:func:`~matplotlib.pyplot.plot`, -:func:`~matplotlib.pyplot.semilogx`, -:func:`~matplotlib.pyplot.semilogy`, etc...), it can be difficult for -the new user to know which ``kwargs`` are supported. Matplotlib uses -a docstring interpolation scheme to support documentation of every -function that takes a ``**kwargs``. The requirements are: +Since Matplotlib uses a lot of pass-through ``kwargs``, e.g., in every function +that creates a line (`~.pyplot.plot`, `~.pyplot.semilogx`, `~.pyplot.semilogy`, +etc...), it can be difficult for the new user to know which ``kwargs`` are +supported. Matplotlib uses a docstring interpolation scheme to support +documentation of every function that takes a ``**kwargs``. The requirements +are: 1. single point of configuration so changes to the properties don't require multiple docstring edits. @@ -133,20 +131,23 @@ function that takes a ``**kwargs``. The requirements are: 2. as automated as possible so that as properties change, the docs are updated automagically. -The function :func:`matplotlib.artist.kwdoc` and the decorator -:func:`matplotlib.docstring.dedent_interpd` facilitate this. They combine -python string interpolation in the docstring with the matplotlib -artist introspection facility that underlies ``setp`` and ``getp``. -The ``kwdoc`` function gives the list of properties as a docstring. In order -to use this in another docstring, first update the -``matplotlib.docstring.interpd`` object, as seen in this example from -:mod:`matplotlib.lines`:: +The function `matplotlib.artist.kwdoc` and the decorator +`matplotlib.docstring.dedent_interpd` facilitate this. They combine python +string interpolation in the docstring with the Matplotlib artist introspection +facility that underlies ``setp`` and ``getp``. The ``kwdoc`` function gives +the list of properties as a docstring. In order to use this in another +docstring, first update the ``matplotlib.docstring.interpd`` object, as seen in +this example from `matplotlib.lines`: + +.. code-block:: python # in lines.py docstring.interpd.update(Line2D=artist.kwdoc(Line2D)) -Then in any function accepting :class:`~matplotlib.lines.Line2D` -pass-through ``kwargs``, e.g., :meth:`matplotlib.axes.Axes.plot`:: +Then in any function accepting `~.Line2D` pass-through ``kwargs``, e.g., +`matplotlib.axes.Axes.plot`: + +.. code-block:: python # in axes.py @docstring.dedent_interpd @@ -164,14 +165,13 @@ pass-through ``kwargs``, e.g., :meth:`matplotlib.axes.Axes.plot`:: """ pass -Note there is a problem for :class:`~matplotlib.artist.Artist` -``__init__`` methods, e.g., :meth:`matplotlib.patches.Patch.__init__`, -which supports ``Patch`` ``kwargs``, since the artist inspector cannot -work until the class is fully defined and we can't modify the -``Patch.__init__.__doc__`` docstring outside the class definition. -There are some some manual hacks in this case, violating the -"single entry point" requirement above -- see the -``docstring.interpd.update`` calls in :mod:`matplotlib.patches`. +Note there is a problem for `~matplotlib.artist.Artist` ``__init__`` methods, +e.g., `matplotlib.patches.Patch.__init__`, which supports ``Patch`` ``kwargs``, +since the artist inspector cannot work until the class is fully defined and +we can't modify the ``Patch.__init__.__doc__`` docstring outside the class +definition. There are some some manual hacks in this case, violating the +"single entry point" requirement above -- see the ``docstring.interpd.update`` +calls in `matplotlib.patches`. .. _formatting-mpl-docs: @@ -186,78 +186,94 @@ working with Sphinx in general. Here are a few additional things to keep in mind other semantic markup. For example, when referring to external files, use the ``:file:`` directive. -* Function arguments and keywords should be referred to using the *emphasis* - role. This will keep matplotlib's documentation consistent with Python's - documentation:: +* Function arguments and keywords should be referred to using the + ``*emphasis*`` role. This will keep Matplotlib's documentation consistent + with Python's documentation: + + .. code-block:: rst - Here is a description of *argument* + Here is a description of *argument* - Please do not use the `default role`:: + Please do not use the ```default role```: - Please do not describe `argument` like this. + .. code-block:: rst - nor the ``literal`` role:: + Please do not describe `argument` like this. - Please do not describe ``argument`` like this. + nor the ````literal```` role: -* Sphinx does not support tables with column- or row-spanning cells for - latex output. Such tables can not be used when documenting matplotlib. + .. code-block:: rst + + Please do not describe ``argument`` like this. * Mathematical expressions can be rendered as png images in html, and in the - usual way by latex. For example: + usual way by LaTeX. For example, - ``:math:`\sin(x_n^2)``` yields: :math:`\sin(x_n^2)`, and:: + .. code-block:: rst - .. math:: + :math:`\sin(x_n^2)` - \int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}} + yields :math:`\sin(x_n^2)`, and: - yields: + .. code-block:: rst - .. math:: + .. math:: - \int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}} + \int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}} + + yields :math:`\int_{-\infty}^{\infty}\frac{e^{i\phi}}{1+x^2\frac{e^{i\phi}}{1+x^2}}`. * Interactive IPython sessions can be illustrated in the documentation using - the following directive:: + the following directive: + + .. code-block:: rst - .. sourcecode:: ipython + .. sourcecode-block:: ipython In [69]: lines = plot([1,2,3]) - which would yield: + which yields - .. sourcecode:: ipython + .. code-block:: ipython In [69]: lines = plot([1,2,3]) -* Footnotes [#]_ can be added using ``[#]_``, followed later by:: +* Footnotes [#]_ can be added using ``[#]_``, followed later by: + + .. code-block:: rst .. rubric:: Footnotes .. [#] + which yields + .. rubric:: Footnotes .. [#] For example. * Use the *note* and *warning* directives, sparingly, to draw attention to - important comments:: + important comments: + + .. code-block:: rst .. note:: - Here is a note + Here is a note. + + .. warning:: + Here is a warning. yields: .. note:: - here is a note - - also: + Here is a note. .. warning:: - here is a warning + Here is a warning. -* Use the *deprecated* directive when appropriate:: +* Use the *deprecated* directive when appropriate: + + .. code-block:: rst .. deprecated:: 0.98 This feature is obsolete, use something else. @@ -268,7 +284,9 @@ working with Sphinx in general. Here are a few additional things to keep in mind This feature is obsolete, use something else. * Use the *versionadded* and *versionchanged* directives, which have similar - syntax to the *deprecated* role:: + syntax to the *deprecated* role: + + .. code-block:: rst .. versionadded:: 0.98 The transforms have been completely revamped. @@ -276,7 +294,9 @@ working with Sphinx in general. Here are a few additional things to keep in mind .. versionadded:: 0.98 The transforms have been completely revamped. -* Use the *seealso* directive, for example:: +* Use the *seealso* directive, for example: + + .. code-block:: rst .. seealso:: @@ -302,12 +322,10 @@ working with Sphinx in general. Here are a few additional things to keep in mind * The autodoc extension will handle index entries for the API, but additional entries in the index_ need to be explicitly added. -* Please limit the text width of docstrings to 70 characters. - * Keyword arguments should be described using a definition list. .. note:: - matplotlib makes extensive use of keyword arguments as pass-through + Matplotlib makes extensive use of keyword arguments as pass-through arguments, there are a many cases where a table is used in place of a definition list for autogenerated sections of docstrings. @@ -326,14 +344,16 @@ The path should be relative to the ``doc`` directory. Any plots specific to the documentation should be added to the ``doc/mpl_examples/pyplots`` directory and committed to git. Plots from the ``examples`` directory may be referenced through the symlink ``mpl_examples`` in the ``doc`` -directory. e.g.:: +directory, e.g.: + +.. code-block:: rst .. plot:: mpl_examples/pylab_examples/simple_plot.py The ``:scale:`` directive rescales the image to some percentage of the original size, though we don't recommend using this in most cases since it is probably better to choose the correct figure size and dpi -in mpl and let it handle the scaling. +in Matplotlib and let it handle the scaling. Plot directive documentation '''''''''''''''''''''''''''' @@ -347,21 +367,25 @@ The source of the files in the ``examples`` directory are automatically included in the HTML docs. An image is generated and included for all examples in the ``api`` and ``pylab_examples`` directories. To exclude the example from having an image rendered, -insert the following special comment anywhere in the script:: +insert the following special comment anywhere in the script: + +.. code-block:: python # -*- noplot -*- Animations ---------- -We have a matplotlib google/gmail account with username ``mplgithub`` +We have a Matplotlib Google/Gmail account with username ``mplgithub`` which we used to setup the github account but can be used for other -purposes, like hosting google docs or youtube videos. You can embed a -matplotlib animation in the docs by first saving the animation as a +purposes, like hosting Google docs or Youtube videos. You can embed a +Matplotlib animation in the docs by first saving the animation as a movie using :meth:`matplotlib.animation.Animation.save`, and then -uploading to `matplotlib's youtube +uploading to `matplotlib's Youtube channel `_ and inserting the -embedding string youtube provides like:: +embedding string youtube provides like: + +.. code-block:: rst .. raw:: html @@ -372,7 +396,7 @@ embedding string youtube provides like:: An example save command to generate a movie looks like this -.. sourcecode:: python +.. code-block:: python ani = animation.FuncAnimation(fig, animate, np.arange(1, len(y)), interval=25, blit=True, init_func=init) @@ -384,20 +408,19 @@ google docs to the mplgithub account. .. _referring-to-mpl-docs: -Referring to mpl documents -========================== +Referring to Matplotlib documents +================================= -In the documentation, you may want to include to a document in the -matplotlib src, e.g., a license file or an image file from `mpl-data`, -refer to it via a relative path from the document where the rst file -resides, e.g., in :file:`users/navigation_toolbar.rst`, we refer to the -image icons with:: +In the documentation, you may want to include to a document in the Matplotlib +sources, e.g., a license file or an image file from :file:`mpl-data`, refer to +it via a relative path from the document where the rst file resides, e.g., in +:file:`users/navigation_toolbar.rst`, we refer to the image icons with:: .. image:: ../../lib/matplotlib/mpl-data/images/subplots.png -In the `users` subdirectory, if I want to refer to a file in the mpl-data -directory, I use the symlink directory. For example, from -`customizing.rst`:: +In the :file:`users` subdirectory, if I want to refer to a file in the +mpl-data directory, I use the symlink directory. For example, from +:file:`customizing.rst`:: .. literalinclude:: ../../lib/matplotlib/mpl-data/matplotlibrc @@ -408,16 +431,19 @@ a symlink to the files at the top doc level directory. This way, API documents like :meth:`matplotlib.pyplot.plot` can refer to the examples in a known location. -In the top level doc directory we have symlinks pointing to -the mpl `examples`:: +In the top level :file:`doc` directory we have symlinks pointing to the +Matplotlib :file:`examples`: + +.. code-block:: sh home:~/mpl/doc> ls -l mpl_* mpl_examples -> ../examples -So we can include plots from the examples dir using the symlink:: +So we can include plots from the examples dir using the symlink: - .. plot:: mpl_examples/pylab_examples/simple_plot.py +.. code-block:: rst + .. plot:: mpl_examples/pylab_examples/simple_plot.py We used to use a symlink for :file:`mpl-data` too, but the distro becomes very large on platforms that do not support links (e.g., the font @@ -429,32 +455,38 @@ Internal section references =========================== To maximize internal consistency in section labeling and references, -use hyphen separated, descriptive labels for section references, e.g.,:: +use hyphen separated, descriptive labels for section references, e.g.: + +.. code-block:: rst .. _howto-webapp: -and refer to it using the standard reference syntax:: +and refer to it using the standard reference syntax: + +.. code-block:: rst See :ref:`howto-webapp` Keep in mind that we may want to reorganize the contents later, so let's avoid top level names in references like ``user`` or ``devel`` or ``faq`` unless necessary, because for example the FAQ "what is a -backend?" could later become part of the users guide, so the label:: +backend?" could later become part of the users guide, so the label: + +.. code-block:: rst .. _what-is-a-backend -is better than:: +is better than: + +.. code-block:: rst .. _faq-backend In addition, since underscores are widely used by Sphinx itself, let's prefer hyphens to separate words. - - -Section names, etc -================== +Section names, etc. +=================== For everything but top level chapters, please use ``Upper lower`` for section titles, e.g., ``Possible hangups`` rather than ``Possible @@ -476,7 +508,9 @@ class ``matplotlib.patches.Patch`` is shown as ``Patch``. If *parts* == 2, it is shown as ``patches.Patch``. If *parts* == 0, the full path is shown. -Example:: +Example: + +.. code-block:: rst .. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text :parts: 2 @@ -484,7 +518,6 @@ Example:: .. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text :parts: 2 - .. _emacs-helpers: Emacs helpers @@ -494,7 +527,9 @@ There is an emacs mode `rst.el `_ which automates many important ReST tasks like building and updating table-of-contents, and promoting or demoting section headings. Here -is the basic ``.emacs`` configuration:: +is the basic ``.emacs`` configuration: + +.. code-block:: lisp (require 'rst) (setq auto-mode-alist @@ -502,7 +537,6 @@ is the basic ``.emacs`` configuration:: ("\\.rst$" . rst-mode) ("\\.rest$" . rst-mode)) auto-mode-alist)) - Some helpful functions:: C-c TAB - rst-toc-insert diff --git a/doc/make.py b/doc/make.py index c23335334d18..dcdb877e4772 100755 --- a/doc/make.py +++ b/doc/make.py @@ -190,36 +190,32 @@ def build_all(): } -small_docs = False -warnings_as_errors = True -n_proc = 1 - # Change directory to the one containing this file current_dir = os.getcwd() os.chdir(os.path.dirname(os.path.join(current_dir, __file__))) copy_if_out_of_date('../INSTALL.rst', 'users/installing.rst') parser = argparse.ArgumentParser(description='Build matplotlib docs') -parser.add_argument("cmd", help=("Command to execute. Can be multiple. " - "Valid options are: %s" % (funcd.keys())), nargs='*') -parser.add_argument("--small", - help="Smaller docs with only low res png figures", - action="store_true") -parser.add_argument("--allowsphinxwarnings", - help="Don't turn Sphinx warnings into errors", - action="store_true") -parser.add_argument("-n", - help="Number of parallel workers to use") +parser.add_argument( + "cmd", nargs="*", + help="Command(s) to execute. Valid commands: {}." + .format(", ".join(sorted(funcd)))) +parser.add_argument( + "--small", action="store_true", default=False, + help="Smaller docs with only low resolution PNG figures.") +parser.add_argument( + "--allowsphinxwarnings", action="store_true", default=False, + help="Don't turn Sphinx warnings into errors.") +parser.add_argument( + "-n", type=int, default=1, + help="Number of parallel workers to use.") args = parser.parse_args() -if args.small: - small_docs = True -if args.allowsphinxwarnings: - warnings_as_errors = False -if args.n is not None: - n_proc = int(args.n) - -_valid_commands = "Valid targets are: {}".format(", ".join(sorted(funcd))) +small_docs = args.small +warnings_as_errors = not args.allowsphinxwarnings +n_proc = args.n + +_valid_commands = "Valid commnds: {}".format(", ".join(sorted(funcd))) if args.cmd: for command in args.cmd: func = funcd.get(command)