|
| 1 | +Sphinx eager ".. only::" directive and other selective rendition extensions |
| 2 | +=========================================================================== |
| 3 | + |
| 4 | +Project home page: https://github.com/pfalcon/sphinx_selective_exclude |
| 5 | + |
| 6 | +The implementation of ".. only::" directive in Sphinx documentation |
| 7 | +generation tool is known to violate principles of least user surprise |
| 8 | +and user expectations in general. Instead of excluding content early |
| 9 | +in the pipeline (pre-processor style), Sphinx defers exclusion until |
| 10 | +output phase, and what's the worst, various stages processing ignore |
| 11 | +"only" blocks and their exclusion status, so they may leak unexpected |
| 12 | +information into ToC, indexes, etc. |
| 13 | + |
| 14 | +There's multiple issues submitted upstream on this matter: |
| 15 | + |
| 16 | +* https://github.com/sphinx-doc/sphinx/issues/2150 |
| 17 | +* https://github.com/sphinx-doc/sphinx/issues/1717 |
| 18 | +* https://github.com/sphinx-doc/sphinx/issues/1488 |
| 19 | +* etc. |
| 20 | + |
| 21 | +They are largely ignored by Sphinx maintainers. |
| 22 | + |
| 23 | +This projects tries to rectify situation on users' side. It actually |
| 24 | +changes the way Sphinx processes "only" directive, but does this |
| 25 | +without forking the project, and instead is made as a standard |
| 26 | +Sphinx extension, which a user may add to their documentation config. |
| 27 | +Unlike normal extensions, extensions provided in this package |
| 28 | +monkey-patch Sphinx core to work in a way expected by users. |
| 29 | + |
| 30 | +eager_only |
| 31 | +---------- |
| 32 | + |
| 33 | +The core extension provided by the package is called `eager_only` and |
| 34 | +is based on the idea by Andrea Cassioli (see bugreports above) to |
| 35 | +process "only" directive as soon as possible during parsing phase. |
| 36 | +This approach has some drawbacks, like producing warnings like |
| 37 | +"WARNING: document isn't included in any toctree" if "only" is used |
| 38 | +to shape up a toctree, or the fact that changing a documentation |
| 39 | +builder (html/latex/etc.) will almost certainly require complete |
| 40 | +rebuild of documentation. But these are relatively minor issues |
| 41 | +comparing to completely broken way "only" works in upstream Sphinx. |
| 42 | + |
| 43 | +modindex_exclude |
| 44 | +---------------- |
| 45 | + |
| 46 | +"only" directive allows for fine-grained conditional exclusion, but |
| 47 | +sometimes you may want to exclude entire module(s) at once. Even if |
| 48 | +you wrap an entire module description in "only" directive, like: |
| 49 | + |
| 50 | + .. only: option1 |
| 51 | + .. module:: my_module |
| 52 | + |
| 53 | + ... |
| 54 | + |
| 55 | +You will still have an HTML page generated, albeit empty. It may also |
| 56 | +go into indexes, so will be discoverable by users, leading to less |
| 57 | +than ideal experience. `modindex_exclude` extension is design to |
| 58 | +resolve this issue, by making sure that any reference of a module |
| 59 | +is excluded from Python module index ("modindex"), as well as |
| 60 | +general cross-reference index ("genindex"). In the latter case, |
| 61 | +any symbol belong to a module will be excluded. Unlike `eager_only` |
| 62 | +extension which appear to have issued with "latexpdf" builder, |
| 63 | +`modindex_exclude` is useful for PDF, and allows to get cleaner |
| 64 | +index for PDF, just the same as for HTML. |
| 65 | + |
| 66 | +search_auto_exclude |
| 67 | +------------------- |
| 68 | + |
| 69 | +Even if you exclude soem documents from toctree:: using only:: |
| 70 | +directive, they will be indexed for full-text search, so user may |
| 71 | +find them and get confused. This plugin follows very simple idea |
| 72 | +that if you didn't include some documents in the toctree, then |
| 73 | +you didn't want them to be accessible (e.g. for a particular |
| 74 | +configuration), and so will make sure they aren't indexed either. |
| 75 | + |
| 76 | +This extension depends on `eager_only` and won't work without it. |
| 77 | +Note that Sphinx will issue warnings, as usual, for any documents |
| 78 | +not included in a toctree. This is considered a feature, and gives |
| 79 | +you a chance to check that document exclusions are indeed right |
| 80 | +for a particular configuration you build (and not that you forgot |
| 81 | +to add something to a toctree). |
| 82 | + |
| 83 | +Summary |
| 84 | +------- |
| 85 | + |
| 86 | +Based on the above, sphinx_selective_exclude offers extension to let |
| 87 | +you: |
| 88 | + |
| 89 | +* Make "only::" directive work in an expected, intuitive manner, using |
| 90 | + `eager_only` extension. |
| 91 | +* However, if you apply only:: to toctree::, excluded documents will |
| 92 | + still be available via full-text search, so you need to use |
| 93 | + `search_auto_exclude` for that to work as expected. |
| 94 | +* Similar to search, indexes may also require special treatment, hence |
| 95 | + there's the `modindex_exclude` extension. |
| 96 | + |
| 97 | +Most likely, you will want to use all 3 extensions together - if you |
| 98 | +really want build subsets of docimentation covering sufficiently different |
| 99 | +configurations from a single doctree. However, if one of them is enough |
| 100 | +to cover your usecase, that's OK to (and why they were separated into |
| 101 | +3 extensions, to follow KISS and "least surprise" principles and to |
| 102 | +not make people deal with things they aren't interested in). In this case, |
| 103 | +however remember there're other extensions, if you later hit a usecase |
| 104 | +when they're needed. |
| 105 | + |
| 106 | +Usage |
| 107 | +----- |
| 108 | + |
| 109 | +To use these extensions, add https://github.com/pfalcon/sphinx_selective_exclude |
| 110 | +as a git submodule to your project, in documentation folder (where |
| 111 | +Sphinx conf.py is located). Alternatively, commit sphinx_selective_exclude |
| 112 | +directory instead of making it a submodule (you will need to pick up |
| 113 | +any project updates manually then). |
| 114 | + |
| 115 | +Add following lines to "extensions" settings in your conf.py (you |
| 116 | +likely already have some standard Sphinx extensions enabled): |
| 117 | + |
| 118 | + extensions = [ |
| 119 | + ... |
| 120 | + 'sphinx_selective_exclude.eager_only', |
| 121 | + 'sphinx_selective_exclude.search_auto_exclude', |
| 122 | + 'sphinx_selective_exclude.modindex_exclude', |
| 123 | + ] |
| 124 | + |
| 125 | +As discussed above, you may enable all extensions, or one by one. |
| 126 | + |
| 127 | +Please note that to make sure these extensions work well and avoid producing |
| 128 | +output docs with artifacts, it is IMPERATIVE to remove cached doctree if |
| 129 | +you rebuild documentation with another builder (i.e. with different output |
| 130 | +format). Also, to stay on safe side, it's recommended to remove old doctree |
| 131 | +anyway before generating production-ready documentation for publishing. To |
| 132 | +do that, run something like: |
| 133 | + |
| 134 | + rm -rf _build/doctrees/ |
| 135 | + |
| 136 | +A typical artificat when not following these simple rules is that content |
| 137 | +of some sections may be missing. If you face anything like that, just |
| 138 | +remember what's written above and remove cached doctrees. |
0 commit comments