Showing posts with label python-sphinx. Show all posts
Showing posts with label python-sphinx. Show all posts

Saturday, August 25, 2018

How can I use Sphinx with subpackages without duplicating everything?

Leave a Comment

I have the following package structure as a minimal example (for convenience, all is uploaded here):

. ├── sphinx │   ├── build │   ├── Makefile │   └── source │       ├── conf.py │       ├── index.rst │       └── train.rst └── train     ├── __init__.py     └── train.py 

When writing Python packages, one must specifiy the __all__ constant in the __init__.py of any package in order for Sphinx to be able to map a reference such as train.DatasetMeta to train.train.DatasetMeta or similar. However, sphinx-apidoc generates the following sections for these packages:

train package =============  Submodules ----------  train.train module ------------------  .. automodule:: train.train     :members:     :undoc-members:     :show-inheritance:   Module contents ---------------  .. automodule:: train     :members:     :undoc-members:     :show-inheritance: 

Which duplicates the entire documentation as it contains .. automodule:: module.file as well as .. automodule:: module, which refer to the same thing. Removing either of these sections results in undefined reference warnings (turned into errors when using -n to SPHINXOPTS).

sphinx_test/train/train.py:docstring of train.DatasetMeta:1:py:class reference target not found: train.train.DatasetMeta 

How can I solve this?

train/train.py

from collections import namedtuple   class DatasetMeta(namedtuple('DatasetMeta', ['dataset', 'num_classes', 'shape'])):     @property     def size(self):         '''int: Number of examples in the dataset'''         return self.shape[0] 

train/__init__.py

from .train import *  __all__ = ['DatasetMeta'] 

sphinx/source/conf.py

import os import sys sys.path.insert(0, os.path.abspath('.')) sys.path.insert(0, os.path.abspath('../../'))   project = 'test' copyright = '' author = ''  version = '' release = '0'  extensions = [     'sphinx.ext.autodoc', ]  source_suffix = '.rst' master_doc = 'index' 

I just cannot figure out what the logic is here.

1 Answers

Answers 1

One thing we can do to make the situation simpler is a minor rename:

class DatasetMeta(namedtuple('DatasetMetaBase', ['dataset', 'num_classes', 'shape'])): 

which should make it obvious that the missing reference is train.train.DatasetMetaBase when you remove the train.train block from the rst file generated by sphinx-apidoc. The documentation for train.DatasetMeta and train.train.DatasetMeta is going to refer to train.train.DatasetMetaBase; I don't know way to hack around that without patching autodoc or adding your own directives.

From here, I see a few options:

(1) Move DatasetMetaBase to a different module that is not imported in __init__.py. For example

from .abstract import DatasetMetaBase class DatasetMeta(DatasetMetaBase): 

That way the autodoc for DatasetMeta refers to train.abstract.DatasetMetaBase, which should be a unique ref in your case.

(2) Create a separate rst file (say, hidden.rst) that renders the docs for train.train.DatasetMetaBase, but hidden from the main rst.

# hidden.rst .. autodata:: train.train.DatasetMetaBase 

That should be enough to add train.train.DatasetMetaBase to sphinx and resolve the class reference target not found warning.

Read More

Friday, September 29, 2017

Embed plotly graph in a Sphinx doc

Leave a Comment

I tried using nbsphinx to embed a Jupyter notebook containing plotly plots, but the plots don't show up in the documentation, even though they look fine on the Jupyter notebook.

How can I embed a plotly graph in Sphinx documentation? I could include them as images, but is there a better way? It'd be nice to have the interactivity!

What I want to do is replicate this page. It has Jupyter notebook style in and out blocks, and it shows interactive plots made using plotly. How can I do that?

0 Answers

Read More

Friday, June 9, 2017

Python: docstrings and type annotations

Leave a Comment

Having a function like:

def foo(x: int) -> float:     return float(x) 

I would like to use a NumPy-like docstring like the following:

def foo(x: int) -> float:     """     Parameters     ----------     x         Input parameter      Returns     -------     The output value.     """     return float(x) 

Note that:

  • I do not want to specify the parameter type again.
  • I do not want to specify the return type again.
  • I would like that extension to be able to read the annotated types (and write them in the generated HTML documentation).

Is there a Sphinx extension that supports that? Would you recommend another syntax?

1 Answers

Answers 1

Standard extension is autodoc. Napoleon extension supports Google- and NumPy-style docstrings.

Read More

Wednesday, June 15, 2016

Creating a node cross-referencing another domain in Sphinx

Leave a Comment

Within a custom Sphinx domain, I'd like to create a reference to another node in a different domain. For example:

.. py:class:: foo.bar     Lorem ipsum.  .. example:directive:: baz -> foo.bar     Sit amet, sit. 

My example:directive:: says that my "method" baz returns something of type foo.bar, which is a Python class. So I'd like to cross-reference that to the other py:class:: foo.bar description.

from sphinx.directives import ObjectDescription  class ExampleDescription(ObjectDescription):     def handle_signature(self, sig, signode):          # lots of parsing and node creation here          # parsed_annotation = "foo.bar"         signode += addnodes.desc_returns(parsed_annotation, parsed_annotation) 

Within my custom domain I'm parsing my directives and building the elements and it's all fine, even cross-referencing within my example domain works just fine by subclassing the sphinx.domains.Domain:resolve_xref method. I'm just unsure how I would programmatically insert a node in my handle_signature method which is later resolved to a node in another domain. Would I somehow have to instantiate a sphinx.domains.python.PyXRefRole?

The expected result in HTML would be something like:

<dl>   <dt>     <code>baz</code>     →     <a href="example.html#py.class.foo.bar">       <code>foo.bar</code>     </a>   </dt> </dl> 

0 Answers

Read More