I have a python module which defines a multi-line string constant. I want to have the multi-line string display nicely in the Sphinx-based documentation.
Below, is some example Python code, RST, and how it renders with sphinx-build
. However, I would rather get something like the "desired sphinx docs".
Is this possible?
mymodule.py
#: Default configuration
DEFAULT_CONFIG = r"""
{ "foo": "bar",
"baz": "rex" }
"""
mydocs.rst
...
--------------
Default Config
--------------
.. autodata:: mymodule.DEFAULT_CONFIG
Resulting Sphinx Docs
mymodule.DEFAULT_CONFIG
= "{ \"foo\": \"bar\",\n \"bar\": \"rex\" }"
str(object=’‘) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object.
If encoding or errors is specified, then the object
must expose a data buffer that will be decoded using
the given encoding and error handler. Otherwise, returns
the result of object.__str__() (if defined) or repr(object).
encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
Desired Sphinx Docs
mymodule.DEFAULT_CONFIG = Default configuration
{ "foo": "bar",
"baz": "rex" }
This cannot be supported directly, but since you're using Sphinx and Python the following hack is what I decided to go with:
In this example, it is important that you can import
the variable you desire. This should already be working, since autodoc
is able to produce output.
This hack will enable you to have a more human friendly output, but you will also still have the value of the variable (as far as sphinx is concerned) in the undesireable (with a bunch of \n
characters).
I will be reusing my own project for this, but using your variable / value. My package name is exhale
and the file I'm putting this in is exhale/configs.py
, so that's where that stuff is coming from. So this is the layout:
exhale/configs.py
This is your actual python code. It looks like this:
__name__ = "configs"
__docformat__ = "reStructuredText"
DEFAULT_CONFIG = r"""
{ "foo": "bar",
"baz": "rex" }
"""
'''
This is some description of the use of / intended purpose of the variable.
The contents of this variable are a multi-line string with value:
.. include:: DEFAULT_CONFIG_value.rst
.. note::
The above value is presented for readability, take special care in use of
this variable that the real value has both a leading and trailing ``\\n``.
'''
In whatever file you had the autodata
above (I used automodule
, it doesn't matter). The docs look like this (to be clear, you've already got this, and do not need to change it). The things you need to change are your actual python docstring, and the next section. This is here for completeness of the answer.
Exhale Configs Module
=====================
.. automodule:: exhale.configs
:members:
:undoc-members:
conf.py
This is the fancy part, and a huge benefit to using Sphinx -- Python is so freaking convenient when it comes to writing files. In the above docstring, you'll see that I deliberately have a .. include
directive. The crazy part about this is we can write this file dynamically. At the bottom of your conf.py
, you can just add something like
# Import the variable from wherever it lives
from exhale.configs import DEFAULT_CONFIG
default_parts = DEFAULT_CONFIG.strip().splitlines()
# Because I am deliberately putting this underneath a '.. code-block:: py',
# we need to indent by **THREE** spaces.
#
# Similarly, when writing to the file, the "\n\n " before
# {default_config_value} (the three spaces) is also important ;)
default_config_value = "\n ".join(p for p in default_parts)
with open("DEFAULT_CONFIG_value.rst", "w") as dcv:
dcv.write(".. code-block:: py\n\n {default_config_value}\n\n".format(
default_config_value=default_config_value
))
If you are using Python 3, instead of splitting and joining, just use textwrap.indent
. I did the above just to make sure Python 2 users can replicate.
When you run make html
, it will regenerate the file DEFAULT_CONFIG_value.rst
every time! So even if you change the value of the variable, it should be good to go. For reference, the generated file for me looks like this
.. code-block:: py
{ "foo": "bar",
"baz": "rex" }
Note: this is not a standalone reStructuredText document, it should only every be used via .. include::
!
Last but not least, the rendered output looks like this:
As stated in the preamble, Sphinx is going to include the \n
version in the value. We are just putting this in the docstring. It's very useful to have both. The reason is because with the .. code-block:: py
approach, Sphinx will strip leading / trailing newlines (hence the .. note::
in the docstring). So it is very helpful to have the human-readable version, but it's also useful to know the raw value.
The only other thing worth mentioning here is that the sky is the limit! I chose to use .. code-block:: py
for my purposes, but since you're literally writing the file yourself you can do whatever you want. You could write the file so that it instead produces
.. code-block:: py
DEFAULT_CONFIG = r"""
{ "foo": "bar",
"baz": "rex" }
"""
by changing the part in conf.py
. It's up to you! When changing the output you may get bugs, open up the generated .rst
document and make sure it's valid :)