Conditionally compile document sections in Sphinx - python

We are planning on creating a user manual for our software project. Currently, everything related to the code is documented in Sphinx, and we would like to use Sphinx for the manual.
Since we are writing scientific/engineering software, there will be a lot of topics on things like stress, strain, numerical algorithms, etc. For each topic, we will have a few stages of information:
Basic information: This one or two sentence description can be used anywhere we need a short summary of the topic. Example: simple definition of mechanical stress.
More detailed description: This one paragraph explanation can be used as the opening to a help page, or a summary in a more detailed listing of topics. Example, a paragraph about mechanical stress introducing the equation for axial stress.
Technical information. This can be multiple paragraphs on how the topic applies to the problems encountered by users of our software.
Code information. This will be documentation related to where the topic is encountered in the code. For example, we can point to our implementation of a certain numerical algorithm. We can use sphinx-apidoc like we currently do.
As you can see, the information gradually gets more complex. We would like to manage each topic in their own .rst file, and get the required information as needed. For example, maybe we want to use the basic information section in a tooltip. In the actual help menu, we can use the detailed description in a table of contents on a certain class of topics. In the full article on the topic, like what would be present in a full pdf manual, we can present the technical information along with the basic and more detailed descriptions. Lastly, we would like to keep code information only in our internal documentation.
It would be nice to keep all of the information for a single topic in one file, but to conditionally compile different sections based on the documentation we are generating.
Is there a built-in way to do something like this in Sphinx? If someone is doing something similar, can you tell us about it and give us some highlights of your workflow?

In past I wanted to compile two docs, a public and a private but I didn't want to split my source file (rst).
First step I found the only directive and I thought it was the solution. But when I wanted a entire full rst file in just public or private documentation I can't without indent the whole file.
So I write my own Sphinx plugin (scope) to manage all my case. To succeed I used the meta directive that can be place on the top of the file.
Thus
a_doc_for_basic.rst
.. meta::
:scope: basic
Title
=====
My content
a_doc_for_code.rst
.. meta::
:scope: code
Title
=====
My content
And you can continue to use .. only:: directive on file
a_doc_for_all.rst
Title
=====
My content
.. only:: code
a piece of code
You can find plugin source here
As you can see the plugin is pretty simple and works thanks to regexp. That means (regexp) that there is limitation:
The directive .. meta:: :scope: must be place at the top of the file (no line before)
The directive .. meta:: :scope: must match the regexp ^\.\. meta::\s+:scope: ([a-zA-Z0-9_-]+)
The directive .. meta:: :scope: can manage multiple tag but you can easily update the plugin for your needs
Plugin deviate the original use of meta directive docutils.sourceforge.net/docs/ref/rst/directives.html#meta
After that you can build your doc using the following command
sphinx-build ... -t <tag> ...
sphinx-build ... -t code ...
Other thing, you can use the same toctree for all tag because when compiling a doc per tag the toctree will be edited by the plugin to generate a tree without reference to the no-matching documentation.
PS: my plugin is not perfect but I replied to my needs, you can inspired and update it.

Related

When documenting with Sphinx, how do I insert [source] links manually

I'm using the sphinx.ext.viewcode extension to generate [source] links to classes and functions.
This works great for documentation produced via autodoc, but there doesn't seem to be any restructured-text syntax available for me to make my own links.
I tried getting Sphinx to dump an rst version of its output, but that contains no trace of any markup relating to source code links.
EDIT: To be more specific, I do get proper source links when applying directives such as .. py:function: somefunction, but for a page documenting a single module I would like the header to have a [source] link to the module file, but .. py:module: mymodule does not produce such a link, and neither does ..automodule::.
I guess I'm really asking the underlying question of: How does viewcode decide where to put in [source] links and how can I control it?

How to prevent automatic toctree entry numbering?

I am building my documentation with Sphinx, to use with readthedocs.io. So far this always worked well. I'm orienting myself at the (in my opinion) excellent documentation of the godot engine.
Since I appreciated the titles in the documentation of the godot documentation, I tried to replicate these, by first having a look at the way they did it. Here's the link to the source for their index file. (Note: the relevant section is at the end of the document)
This seemed reasonable, as they used multiple toctrees, to give every toctree a caption.
When I do the same however, sphinx seems to automatically number my sections, something I do not want. The toctrees do not contain the :numbered: tag.
Here's a code sample, explaining how my toctrees are structured in principle:
.. toctree::
:caption: Section 1
Entry1
Entry2
.. toctree::
:caption: Section 2
Entry2
The expected result would be similar to the godot documentation, with sections having titles but no numbers. Instead I am getting numbers, which seem arbitrary to me:
Section1
1.Entry1
2.Entry2
Section2
1.Entry1
I can't find anything in the godot documentation explaining why they do not have these numbers, and I can't find any mention of it in the Sphinx toctree documentation either.
Any help or pointers towards help are greatly appreciated, thank you for your time.
Edit:
Uploading the repo, with the built static html files to readthedocs.io seems to remove/fix the numbering. It persists in the local built though (the index.html file I built with sphinx in the first place).
The answer to the question, courtesy of mzjn (see comment thread):
A rebuild of the project solved the issue. This can be done by entering
make clean html
in the console, fixing the weird numbering issue.
The relevant github issue can be found here.
This may possibly be caused by sphinx trying to find changes in the code and update these, instead of rebuilding the project every time. In this instance it did not update the toctree correctly.

Using tags/keywords in Sphinx/Jinja to create a page which contains a list of links to all other pages containing said tag/keyword

OK, I feel like this should be explained in some obvious place but I have searched and found nothing (and I always found an answer for my previous 999 problems, so normally I am not bad at searching).
Basically, I am making a manual for my physical product, the Foomaster. The manual contains a range of information (individual .rst files) on the Foomaster, which are organised (using toctree in index.rst and other .rst sub structure files) by physical location on the Foomaster. Some of these pages are service procedures, some are safety warnings, some are general information.
Now I would like to create a separate page, monthly_service.rst, which lists all of the pages (.rst files) which describe a service procedure which should be checked monthly. This list of monthly procedures would not be broken if the 'destination' page is moved (i.e. it would find where the rst is located based on the inclusion of a tag, and then create the link to this location). For example, with pseudocode:
change_foobulb.rst
.. tag:: monthly_maintenance
(description of how to change foobulb)
clean_footank.rst
.. tag:: monthly_maintenance
(description of how to clean footank)
monthly_service.rst
Make sure the following procedures are followed at least monthly:
.. maketocusing::
tags: monthly_maintenance
Apologies if this is already explained somewhere... I found explanations on .. index:: directive which led me to try adding:
.. index::
single: monthly
to each of change_foobulb and clean_footank rst files. The result of this was addition of an entry in the index (under 'M') of 'monthly, [1]', with links to both pages - i.e. they were treated as duplicated index entries, as I suppose is the purpose of the index directive. Since this does not show the name of each monthly process (like a toctree, and presented in a separate 'monthly.rst' page), this was not useful for my case.
I also found that someone created a custom .. tag:: directive but as far as I understood this is not used to dynamically generate such a list of links - I think it was rather used for deciding what pages to include when building the HTML when using make.bat.
I guess it might need some Jinja solution, but I'm not too strong in Jina... thanks in advance for any help!

using :ref: in Python docstrings using Sphinx

I'm using Sphinx to document a python project, and I'm trying to create a reusable tip to be used in several locations.
Typically, I'll use the following syntax in a python file:
"""
.. tip::
I want this tip to be used in several locations. Why?
- Save time
- Work less
"""
Now this works whether I put it at the beginning of the file, right under class definition or right under function definition.
I found Sphinx's manual for :ref:, which suggests to use a label:
.. _my_reusable_tip:
.. tip::
...
And then call this tip with :ref:`my_reusable_tip` anywhere I want.
The manual states that 'it works across files, when section headings are changed, and for all builders that support cross-references'
The thing is, it doesn't matter in which .py file in the project I write the label and tip definition, the :ref:`my_reusable_tip` just displays 'my_reusable_tip', and not the tip itself.
What I'm using to build the documentation is
sphinx-apidoc -f -F -o
make html
I'm pretty sure my logic is flawed in some way, but I can't figure out why.
I know that Sphinx searches the project for reStructuredText and renders it if it can, but I think I'm missing something here.
I tried to add this label in a seperate .py file enclosed in """, and in a separate .txt file without enclosed """.
I tried creating an .rst file with the label definition and rebuild the html documentation.
What am I missing here?
Python 3.4.3 BTW.
In sphinx, a :ref: is simply a more robust way of linking (or referencing) another part of the document. Thus, your use of :ref: will simply provide a hyperlink to the label.
It is not a way of substituting or expanding a block.
Inline substitutions are available using using |...|, however an inline substitution cannot be used to substitute a block as you seem to require.
RestructuredText is not a template language, and thus doesn't provide macro like facilities. In the event you need it, an alternative solution is to use a template library such as mako or jinja to deal with this kind of issue.
Just using reStructuredText directive
.. include:: ./my_reusable_tip.txt
in your rst files?

How can I configure Sphinx to conditionally exclude some pages?

When generating documentation using Sphinx, I would like to be able to generate two versions of my documentation: one including everything, and one with only a particular set of pages. What's the best way of achieving that?
I could write a build script that moves files around to achieve this but it would be really nice if there was a way to tell sphinx to exclude or include particular documents during a particular build.
Maybe my answer comes a bit late, but I managed to do this with Sphinx via exclude patterns in the config file.
My documentation is partly for users and partly for admins.
Some pages have file names that contain the word admin, and like you, I wanted to build two versions: one with everything (the admin docs) and one with all "admin" pages excluded (the user docs).
To exclude all "admin" pages in all subfolders, you have to add this line to the config file conf.py:
exclude_patterns = ['**/*admin*']
That was the easy part.
My problem was that I didn't know how to run the build two times, one with and one without the exclude patterns without using two different config files.
I didn't find a solution by myself, so I asked a question here on SO and got an answer:
The config file is just a Python file and can contain Python code, which will be executed on build.
You can pass parameters ("tags") via the command line which can be queried in the config file.
So I have this exclude pattern in my config file:
exclude_patterns = ['**/*admin*']
if tags.has('adminmode'):
exclude_patterns = []
Now I can run the build without passing anything, which will exclude the "admin" files:
make clean
make html
⇒ this is my user documentation
...and I can set the "adminmode" tag, which will not exclude anything:
(Windows command line syntax)
set SPHINXOPTS=-t adminmode
make clean
make html
⇒ this is my admin documentation.
Bonus:
I can use the same tag to ignore some specific content on a page, by Including content based on tags.
Example:
regular documentation
=====================
This paragraph and its headline will always be visible.
.. only:: adminmode
secret admin stuff
------------------
This paragraph will be visible in the admin docs only.
This will (again) always be visible.
The only and ifconfig directives can be used to apply conditions within pages.
There does not seem to be any simple way to use conditions to completely exclude entire pages (.rst files).
The following (in index.rst) excludes the reference to doc2.html in the toctree in index.html when generating HTML output:
.. toctree::
doc1.rst
.. only:: latex
.. toctree::
doc2.rst
But this does not really work. The doc2.html file is still generated, and it is reachable via the "Next topic" link when doc1.html is the current topic.
How about sphinx.ext.ifconfig? You set config values in your conf.py file. As that is a regular Python file, you can make your inclusion criteria smart and automatic if you need to.

Categories

Resources