Created
August 5, 2019 19:26
-
-
Save goerz/9be64b2a8d9a569d8586def1259685f0 to your computer and use it in GitHub Desktop.
Sphinx plugin for inserting a warning on the "latest" version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Add a warning to the top of any documentation page for the "latest" version | |
on ReadTheDocs (RTD). Somewhat confusingly, "latest" is the latest development | |
version, not the latest release (which is stable). | |
Note that RTD has a builtin feature to show a similar warning on the | |
documentation of old releases. This can be enable in the Admin section on RTD, | |
under "Advanced Settings", "Show version warning" | |
""" | |
# This program is public domain | |
# Author: Michael Goerz | |
import os | |
import re | |
MSG = r''' | |
.. warning:: | |
You are reading the documentation for an unreleased development version. | |
Consider the most recent `stable </en/stable/>`_ version. | |
''' | |
def split_metadata(rst): | |
"""Split Sphinx metadata from the rest of the rst body. | |
See https://www.sphinx-doc.org/en/1.5/markup/misc.html#file-wide-metadata. | |
""" | |
metadatalines = [] | |
bodylines = [] | |
region = 0 # 0: start of file, 1: in metadata, 2: in body | |
rx_field = re.compile(r'^:[\w\s]+:.*$') | |
for line in rst.splitlines(): | |
if region == 0: | |
if line == '': | |
region = 1 | |
metadatalines.append(line) | |
elif rx_field.match(line): | |
region = 1 | |
metadatalines.append(line) | |
else: | |
region = 2 | |
bodylines.append(line) | |
elif region == 1: | |
if line == '': | |
metadatalines.append(line) | |
elif rx_field.match(line): # another tag | |
metadatalines.append(line) | |
elif line.startswith(" "): # indented continuation | |
metadatalines.append(line) | |
else: | |
region = 2 | |
bodylines.append(line) | |
elif region == 2: | |
bodylines.append(line) | |
else: | |
raise ValueError("Invalid region %s" % region) | |
bodylines.append('') # final newline | |
return "\n".join(metadatalines), "\n".join(bodylines) | |
def add_warning(rst): | |
"""Add a the warning MSG to the top of the given rst content.""" | |
metadata, body = split_metadata(rst) | |
return metadata + MSG + body | |
def rewrite_rst(app, docname, source): | |
"""Rewrite Sphinx RST data to contain warning MSG.""" | |
if app.env.doc2path(docname).endswith('rst'): | |
source[0] = add_warning(source[0]) | |
def setup(app): | |
"""Initialize plugin.""" | |
if os.environ.get('READTHEDOCS_VERSION', '') == 'latest': | |
app.connect('source-read', rewrite_rst) | |
############################################################################### | |
# TESTING | |
_TEST_RST = r''' | |
:autogenerated: | |
krotov.optimize module | |
====================== | |
.. currentmodule:: krotov.optimize | |
.. automodule:: krotov.optimize | |
:members: optimize_pulses | |
:undoc-members: | |
:show-inheritance: | |
:member-order: bysource | |
Summary | |
------- | |
Functions: | |
.. autosummary:: | |
:nosignatures: | |
optimize_pulses | |
``__all__``: :func:`optimize_pulses <krotov.optimize.optimize_pulses>` | |
Reference | |
--------- | |
''' | |
_TEST_RST_EXPECTED = r''' | |
:autogenerated: | |
.. warning:: | |
You are reading the documentation for an unreleased development version. | |
krotov.optimize module | |
====================== | |
.. currentmodule:: krotov.optimize | |
.. automodule:: krotov.optimize | |
:members: optimize_pulses | |
:undoc-members: | |
:show-inheritance: | |
:member-order: bysource | |
Summary | |
------- | |
Functions: | |
.. autosummary:: | |
:nosignatures: | |
optimize_pulses | |
``__all__``: :func:`optimize_pulses <krotov.optimize.optimize_pulses>` | |
Reference | |
--------- | |
''' | |
def test_split_metadata(): | |
"""Test split_metadata function.""" | |
metadata, body = split_metadata(_TEST_RST) | |
assert metadata == '\n:autogenerated:\n' | |
assert body.startswith('krotov.optimize module\n======================') | |
assert body.endswith('Reference\n ---------\n') | |
def test_add_warning(): | |
"""Test add_warning function.""" | |
rst_with_warning = add_warning(_TEST_RST) | |
assert rst_with_warning == _TEST_RST_EXPECTED | |
if __name__ == "__main__": | |
test_split_metadata() | |
test_add_warning() | |
print("OK") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment