How to get Sphinx's autodoc to omit the module name? - python

I'm having trouble controlling Sphinx's autodoc feature.
My directory structure is:
projname
+ projname
__init__.py
Scheduler.py containing class Scheduler
+ docs
conf.py
index.rst
conf.py contains:
sys.path.insert(0, os.path.abspath('../projname'))
And index.rst contains:
.. automodule:: Scheduler
This does what I want, except that the generated Scheduler class documentation comes out as:
class Scheduler.Scheduler()
...[all the methods etc documented correctly]ΒΆ
I could live with that, but in order to cross reference the class elsewhere, I have to refer to is as
:class:`Scheduler.Scheduler`
which leads to horribly ungainly documentation.
How do I persuade autodoc to omit the module name from the class documentation - I think it must be possible as other package documentation does seem to have it?
Charles

I think the ..currentmodule directive will help you here.

Related

Can I use Sphinx automodule but drop the module name in the signature?

I have a module mod with some submodule submod and use .. automodule:: mod.submod to generate documentation for it.
The signatures of the elements (functions, classes etc.) in the modules now show the qualified name, like mod.submod.my_function(*args, **kwargs).
I would instead like Sphinx to just show the name of the function, i.e. the signature my_function(*args, **kwargs).
Do I have any way to drop the leading module and submodules in the signature?
Omitting module and package names preceding functions, methods and variables is done by setting the add_module_name configuration in your conf.py:
add_module_names = False
This is not obvious because of the numerous autodoc configurations that together with the sphinx-napoleon configurations make you expect the configuration elsewhere.
Yes, try this in docs/mod/submod.rst:
.. automodule:: mod.submod
.. autofunction:: my_function
See example HTML build and reST source in Pyramid documentation.
Bonus: see the Sphinx docs for Cross-referencing syntax:
If you prefix the content with ~, the link text will only be the last component of the target. For example, :py:meth:~Queue.Queue.get will refer to Queue.Queue.get but only display get as the link text.

Python: how to embed all docstring help at package level help menu?

What I mean to ask is:
TLDR: how do I have my package's help include all underlying docstrings?
I have created a package. That package has all the proper __init__.py files and all the proper docstrings (module, function, class, and method level docstrings). However, when I perform help(mypackage), the only help provided is the help provided at that top level __init__.py module.
Often package-level help does not include all of the underlying docstrings, but sometimes it does.
I want to make sure that I am embedding all of the underlying docstrings.
For instance, within the numpy package all underlying docstrings are available in the help at the command prompt, even though they are not provided at the top-level __init__.py.
I.e., I can type
>>> help(numpy)
and see all of the documentation, including documentation defined outside of the dunder init module.
However, many other packages, including popular ones like the pandas package do not capture all of the underlying documentation.
I.e., typing
>>> help(pandas)
only provides me the documentation defined in __init__.py.
I want to create package-level documentation mirroring how numpy does it.
I have tried to look through numpy to see how it is performing this magic, with no luck. I have performed Google searches, but it seems there is no way to phrase this question and get any decent links back.
numpy shows you documentation on classes and functions defined outside __init__.py module because of adding their names to __all__ variable in __init__.py. Try to comment lines 169-173 (don't forget to uncomment!):
#__all__.extend(['__version__', 'show_config'])
#__all__.extend(core.__all__)
#__all__.extend(_mat.__all__)
#__all__.extend(lib.__all__)
#__all__.extend(['linalg', 'fft', 'random', 'ctypeslib', 'ma'])
After doing this output of help(numpy) will be very limited.
Also let's reproduce this behaviour. Starting from '/some/path', create folder folder, file named file.py inside it with the following content:
class Class:
"""Class docstring"""
And __init__.py:
from .file import *
Now let's see the help:
/some/path$ python3.5
>>> import folder
>>> help(folder)
Help on package folder:
NAME
folder
PACKAGE CONTENTS
file
FILE
/some/path/folder/__init__.py
And now add this line to __init__.py:
__all__ = ['Class']
After reimporting folder the command help(folder) will contain information about class Class which includes your docstring:
Help on package folder:
NAME
folder
PACKAGE CONTENTS
file
CLASSES
builtins.object
folder.file.Class
class Class(builtins.object)
| Class docstring
|
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
DATA
__all__ = ['Class']
FILE
/some/path/folder/__init__.py

Approach to Python package contents that are both part of the 'public interface' and 'used internally'?

I am in the midst of refactoring some single-file Python modules into multi-file packages and I am encountering the same problem pattern repeatedly: I have objects that are part of the public interface of the package, but must also be used internally by submodules the package.
mypackage/
__init__.py # <--- Contains object 'cssURL'
views.py # <--- Needs to use object 'cssURL'
In this case, it's important that clients of mypackage have access to mypackage.cssURL. However, my submodule, views.py, also needs it, but has no access to the contents of __init__.py. Sure, I can create another submodule like so:
mypackage/
__init__.py
views.py
style.py # <--- New home for 'cssURL'
However, if I did this every time, it seems like it would multiply the number of submodules exceedingly. Moreover, clients must now refer to mypackage.cssURL as mypackage.style.cssURL, or else I must create a synonym in __init__.py like this:
import style
cssURL = style.cssURL
I think I am doing something wrong. Is there a better way to handle these kinds of package members that are both part of the public interface and used internally?
You can refer to the current package as .:
# views.py
from . import cssURL
See here for more information.
I would structure it as follows:
/mypackage
__init__.py
from style import cssURL
...
style.py
cssURL = '...' # or whatever
...
views.py
from .style import cssURL
...
If other modules within the same package need them, I wouldn't define names in __init__.py; just create an alias there for external consumers to use.
As far as I know, the preferred way is to create a "synonym" in __init__.py with "from .style import cssURL"; cf. the source for the json module.

How do I document classes imported from other modules - hence without the declaration module's name?

The package I am documenting consists of a set of *.py files, most containing one class with a couple of files being genuine modules with functions defined. I do not need to expose the fact that each class is in a module so I have added suitable from statements in the __init__.py file e.g.
from base import Base
so that the user can use the import pkg command and does not then have to specify the module that contains the class:
import pkg
class MyBase(pkg.Base): # instead of pkg.base.Base ...
...
The problem is that Sphinx insists on documenting the class as pkg.base.Base. I have tried to set the add_module_names = False in conf.py. However this results in Sphinx showing the class as simply Base instead of pkg.Base. Additionally this also ruins the documentation of the couple of *.py files that are modules.
How do I make Sphinx show a class as pkg.Base?
And how do I set the add_module_names directive selectively for each *.py file?
Here is a way to accomplish what the OP asks for:
Add an __all__ list in pkg/__init__.py:
from base import Base # Or use 'from base import *'
__all__ = ["Base"]
Use .. automodule:: pkg in the .rst file.
Sphinx will now output documentation where the class name is shown as pkg.Base instead of pkg.base.Base.
I've incorporated the answers I found in a scalable-ish form factor:
my_project/
__init__.py
mess.py
mess.py:
class MyClass:
pass
class MyOtherClass(MyClass):
pass
__init__.py:
from .mess import MyClass, MyOtherClass
__all_exports = [MyClass, MyOtherClass]
for e in __all_exports:
e.__module__ = __name__
__all__ = [e.__name__ for e in __all_exports]
This seems to have worked pretty well for me.
I would like to provide a more generalized approach.
The variable __all__ is filled up based on dir(). But the sub-packages name (here mypackage) and all in-build attributes (starting with __) are ignored.
from .mypackage import *
__all__ = []
for v in dir():
if not v.startswith('__') and v != 'mypackage':
__all__.append(v)
Short answer: You shouldn't. Just point the sphinx to the directory of your code. Sphinx documents the code and shows the module hirarchy. How the module finally will be imported is purely in the hand of the developer, but not a responsibility of the documentation tool.

Using sphinx to auto-document a python class, module

I have installed Sphinx in order to document some Python modules and class I'm working on. While the markup language looks very nice, I haven't managed to auto-document a Python code.
Basically, I have the following Python module:
SegLib.py
And A class called Seg in it. I would like to display the docstrings of the class and module within the generated Sphinx document, and add further formatted text to it.
My index.rst looks like this:
Contents:
.. toctree::
:maxdepth: 2
chapter1.rst
and chapter1.rst:
This is a header
================
Some text, *italic text*, **bold text**
* bulleted list. There needs to be a space right after the "*"
* item 2
.. note::
This is a note.
See :class:`Seg`
But Seg is just printed in bold, and not linked to an auto-generated documentation of the class.
Trying the following didn't help, either:
See :class:`Seg`
Module :mod:'SegLib'
Module :mod:'SegLib.py'
Edit: changed SegLib to segments (thanks, iElectric!), and changed chapter1.rst to:
The :mod:`segments` Module
--------------------------
.. automodule:: segments.segments
.. autoclass:: segments.segments.Seg
Still, can't get Sphinx to directly document functions within a class, or better - to automatically add all the functions within a class to the document. Tried:
.. autofunction:: segments.segments.Seg.sid
and got:
autodoc can't import/find function 'segments.segments.Seg.sid', it reported error: "No module named Seg"
Any ideas how to auto-document the functions and classes with a short command?
Add to the beginning of the file:
.. module:: SegLib
Try using :autoclass: directive for class doc.
BTW: module names should be lower_case.
EDIT: I learned a lot from reading other source files.

Categories

Resources