Can sphinx link to documents that are not located in directories below the root document?
Asked Answered
M

8

126

I am using Sphinx to document a non-Python project. I want to distribute ./doc folders in each submodule, containing submodule_name.rst files to document that module. I then want to suck those files into the master hierarchy to create a spec for the entire design.

I.e.:

Project
  docs
    spec
      project_spec.rst
      conf.py
  modules
    module1
      docs
        module1.rst
      src
    module2
      docs
        module2.rst
      src

I attempted to include files in the master project_spec.rst document toctree like this:

.. toctree::
   :numbered:
   :maxdepth: 2

   Module 1 <../../modules/module1/docs/module1>

However this error message results:

WARNING: toctree contains reference to nonexisting document u'modules/module1/docs/module1'

Is it not possible to use ../ in a document path somehow?

Update: Added conf.py location

Update: Other than the include trick below, this is still (2019) not possible. There is an open issue that keeps getting pushed forward: https://github.com/sphinx-doc/sphinx/issues/701

Ministry answered 17/4, 2012 at 21:12 Comment(5)
Do you need to add the .rst extension to the line Module 1 <../../modules/module1/docs/module1>?Noiseless
I don't think so because in the Sphinx Docs: Since the reST source files can have different extensions (some people like .txt, some like .rst – the extension can be configured with source_suffix) and different OSes have different path separators, Sphinx abstracts them: all “document names” are relative to the source directory, the extension is stripped, and path separators are converted to slashes.Ministry
OK, just a guess! So I presume that source_suffix is set to .rst in your conf.py configuration file. Also, where is this file in your directory hierarchy, since it seems that all paths are relative to this file?Noiseless
Yes, source_suffix is set to .rst and the conf.py is in the same folder as the project_spec.rst file.Ministry
Did you find a solution at the present date?Labyrinthodont
C
145

Yes, you can!

In lieu of a symlink (which won't work on Windows), create a stub document that has nothing in it but a .. include:: directive.

I ran into this trying to link to a README file that was in the top of the source tree. I put the following in a file called readme_link.rst:

.. include:: ../README

Then in index.rst, I made the toctree look like:

Contents:

.. toctree::
   :maxdepth: 2

   readme_link
   other_stuff

And now I have a link to my release notes on my index page.

Thanks to http://reinout.vanrees.org/weblog/2010/12/08/include-external-in-sphinx.html for the suggestion

Clouet answered 20/6, 2013 at 14:58 Comment(12)
It the README has images or similar that have relative paths that aren't valid within the directory index.rst is in, how do you handle it? I get 'image file not readable' errors.Vinnie
Yes, you can also do that in Unix with symlinks. You can create a link with the same name as the docs-folder (ie docs) that links to current-dir('.'). Then you can use :download:docs\foo.rst and this would work for fileswithin the docs folder or it's parent.Lyssa
This works for me. I think this should be the accepted answer, as the solution seems cleaner and more portable, than the symlink solution.Psychosexual
I just ended up back here and accepted this answer, thanks! Not sure about the images, but you can always copy them in the conf.py.Ministry
I needed to use .. include:: ../readme.rst including the extension.Rye
This is only a partial solution to symlinks since the include directive doesn't resolve relative paths from the original document. I needed to symlink my images folder from the other directoryMascia
To include only part of the README.rst: muffinresearch.co.uk/…Painstaking
I got "doesn't have a title" as described in #14080155 ; so I had to add a title above the include directive (and remove the same title from the pointed-to README.rst, to avoid redundancy)Echolocation
I had to add the .md file extension in the include directive to make it work.Shoulder
@PierreThibault That indeed includes the .md document's contents, but it renders it as .rst, not as Markdown. Don't know how to solve that though.Ornstead
@Ornstead I use recommonmark. See: recommonmark.readthedocs.io/en/latestShoulder
@Ornstead Here is the solution: recommonmark.readthedocs.io/en/latest/#autostructifyShoulder
N
15

It seems that the answer is no, the documents listed in the toc-tree must reside within the source directory, that is, the directory containing your master document and conf.py (and any subdirectories).

From the sphinx-dev mailing list:

At STScI, we write documentation for individual projects in Sphinx, and then also produce a "master document" that includes (using toctree) a number of these other project-specific documents. To do this, we create symlinks in the master document's doc source directory to the projects' doc source directories, since toctree really doesn't seem to want to include files outside of the doc source tree.

So rather than copying files using shutil you could try adding symlinks to all of your modules in the Project/docs/spec directory. If you create a symlink to Project/modules you would then reference these files in your toc-tree simply as modules/module1/docs/module1 etc.

Noiseless answered 18/4, 2012 at 13:48 Comment(3)
That's too bad. One of the advantages I see in trying to switch from Word docs to Sphinx is that you can import a reusable hardware module into your project and just include it's documentation in the master documentation for the design. I would use symlinks but alas I am on windows.Ministry
For posterity, I tried adding the submodule doc folder to the sys.path in the conf.py but that didn't worky.Ministry
@Ministry For symlinks on Windows, use the mklink command.Nix
I
10

In conf.py, add the relative paths to system using sys.path and os.path

For example:

import os
import sys

sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('../../Directory1'))
sys.path.insert(0, os.path.abspath('../../Directory2'))

Then use your index.rst as usual, referencing the rst files in the same directory. So in my index.rst in my local Sphinx folder:

Contents:

.. toctree::
   :maxdepth: 4

   Package1 <package1.rst>
   Package2 <package2.rst>
   Package3 <package3.rst>

Then in package1.rst, you should be able to just reference the relative packages normally.

Package1 package
=====================

Submodules
----------

Submodule1 module
----------------------------------

.. automodule:: file_within_directory_1
    :members:
    :undoc-members:
    :show-inheritance:

Submodule1 module
----------------------------------

.. automodule:: file_within_directory_2
    :members:
    :undoc-members:
    :show-inheritance:
Insomniac answered 30/8, 2017 at 6:10 Comment(4)
Is this new behavior? What version was it added in?Ministry
Would be great if further described to inform beginners. For example, what is Package1? Is that first path specified using sys.path.insert? Or, is there a tutorial somewhere? I can't seem to find the relevant doc.Spencerspencerian
Package1 is a named entry so that the TOC shows "Package1" as the title of the section.Potshot
This allows you to autodoc Python modules in another directory, but it doesn't allow you to include RST files in another directory.Ministry
H
5

I solved my quite similar problem with the difference I wanted to include an external jupyter notebook. I had installed nbsphinx but I couldn't get it to work. What did not work:

  1. I had the directory I wanted to include the root in the path:

    conf.py :

    import os import sys sys.path.insert(...

  2. Using the .. include:: directive the file was included in the documentation but as is.

Finally what solved the problem was installing package nbsphinx-link

Herisau answered 13/4, 2020 at 18:30 Comment(1)
Also important comment. Although the name has the nb. It is not only for notebooks but also works for rst files in general.Sphenoid
S
3

My answer is in essence the @Dan Menes, but for Myst parser instead of reStructured.

I would prefer to add this as a comment to @Dan Menes answer as it belongs there, but comments do not allow me to do the formatting, the Myst syntax is sensitive to newlines and the comments are limited in characters. So I'm posting it as a separate answer, even when it's related to an existing answer.

To do include in the Myst you have to format it slightly differently:

```{include} ../main/post_installation_windows.md
```

It can wrap itself to do the reStructured markup too (which then included file will be treated as it's written in restructured):

```{eval-rst}
.. include:: snippets/include-rst.rst
```

However, using the native Myst syntax is easier. And it has better features, for example, just including the file will not resolve correctly any references inside the included file, while include-literal should:

```{include-literal} ../../example.md
:language: md
```

As you might discover that including a simple document is ok, but then including a complex document with many references will cause more headaches, so I would recommend the experimental include-literal (from version 0.12.7)

Reference: https://myst-parser.readthedocs.io/en/latest/using/howto.html

Shwalb answered 6/5, 2021 at 12:33 Comment(0)
M
1

One solution, if it's really impossible to use relative links that back up ../ is that I could use shutil to copy the files into the spec folder tree in the conf.py for the spec, but I'd rather not have multiple copies unless absolutely necessary.

Ministry answered 18/4, 2012 at 12:46 Comment(0)
A
1

It is also possible to configure sphinx to have only the index.rst file in the root and the all the other sphinx stuff in Project/docs:

For windows I moved all sphinx files and dirs (except index.rst) into docs/ and changed:

docs/make.bat: Change

set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS%  .

to

set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS%  -c . ..

docs/conf.py: Add

sys.path.insert(0, os.path.abspath('..'))
Attitudinize answered 7/9, 2015 at 8:9 Comment(1)
Thanks! That configuration works just well for me when having multiple related packages in one repository, referenced from the same documentation.Mizell
C
1

An alternate technique which does not require the creation of stub files is to use absolute references (starting with /) within your toctree root, and setting the source directory to the lowest common ancestor when calling sphinx-build. Example directory layout:

/path/to/common/ancestor
├── a
│   └── foo.rst
├── b
│   ├── bar.rst
│   ├── x
│   │   └── index.rst
│   └── y
│       └── boz.rst
└── c
    └── baz.rst


And b/x/index.rst:

.. toctree::
   /a/foo
   /b/bar
   /b/y/boz
   /c/baz

And your sphinx-build command might look like this:

sphinx-build -c <confdir> -b html -D masterdoc=b/x/index /path/to/common/ancestor <outdir>

I tested this with sphinx 3.0.2.

Carri answered 10/3, 2021 at 7:12 Comment(2)
One drawback of this technique is that the main output document is not ./index.html but ./b/x/index.html in your output directory.Carri
Changed in sphinx version 4.0: master_doc to root_doc. Use -D root_doc=b/x/index.Amphipod

© 2022 - 2024 — McMap. All rights reserved.