In my code I have
X_DEFAULT = ['a', 'long', 'list', 'of', 'values', 'that', 'is', 'really', 'ugly', 'to', 'see', 'over', 'and', 'over', 'again', 'every', 'time', 'it', 'is', 'referred', 'to', 'in', 'the', 'documentation']
and later
def some_function(..., x=X_DEFAULT, ...):
so that in my Sphinx documentation, using (e.g., using .. autofunction::
, etc.) I get the entire long and unwieldy value of X_DEFAULT
expanded in the signature for some_function
:
some_function(..., x=['a', 'long', 'list', 'of', 'values', 'that', 'is', 'really', 'ugly', 'to', 'see', 'over', 'and', 'over', 'again', 'every', 'time', 'it', 'is', 'referred', 'to', 'in', 'the', 'documentation'], ...)
Is there a way to suppress this substitution in the generated documentation, ideally with a link back to the definition of X_DEFAULT
:
some_function(..., x=X_DEFAULT, ...)
I'm aware that I can manually override the signature for each function and method that I explicitly list as arguments to Sphinx documentation directives, but that's not my goal here. I'm also aware that I could use autodoc_docstring_signature
and the first line of the docstring, but that would produce bad docstrings, really intended for cases where introspection fails (like C). I suspect that there's something I could do in autodoc-process-signature
that might be adequate (but not perfect), though I'm unsure how to proceed.
To support Markdown-based documentation, Sphinx can use MyST-Parser. MyST-Parser is a Docutils bridge to markdown-it-py, a Python package for parsing the CommonMark Markdown flavor.
toctree:: :maxdepth: 2 intro strings datatypes numeric (many more documents listed here) This accomplishes two things: Tables of contents from all those documents are inserted, with a maximum depth of two, that means one nested heading. toctree directives in those documents are also taken into account.
ext. intersphinx – Link to other projects' documentation. New in version 0.5. This extension can generate links to the documentation of objects in external projects, either explicitly through the external role, or as a fallback resolution for any other cross-reference.
One approach, that will, for example, "revert" substitution of all values that have been defined at the module level as "public constants" (recognized by all-caps names with no leading underscore) for which a unique name can be found in the module in which it was defined:
def pretty_signature(app, what, name, obj, options, signature, return_annotation):
if what not in ('function', 'method', 'class'):
return
if signature is None:
return
import inspect
mod = inspect.getmodule(obj)
new_sig = signature
# Get all-caps names with no leading underscore
global_names = [name for name in dir(mod) if name.isupper() if name[0] != '_']
# Get only names of variables with distinct values
names_to_replace = [name for name in global_names
if [mod.__dict__[n] for n in global_names].count(mod.__dict__[name]) == 1]
# Substitute name for value in signature, including quotes in a string value
for var_name in names_to_replace:
var_value = mod.__dict__[var_name]
value_string = str(var_value) if type(var_value) is not str else "'{0}'".format(var_value)
new_sig = new_sig.replace(value_string, var_name)
return new_sig, return_annotation
def setup(app):
app.connect('autodoc-process-signature', pretty_signature)
An alternative is to simply take the docstring directly from the source:
import inspect
import re
def pretty_signature(app, what, name, obj, options, signature, return_annotation):
"""Prevent substitution of values for names in signatures by preserving source text."""
if what not in ('function', 'method', 'class') or signature is None:
return
new_sig = signature
if inspect.isfunction(obj) or inspect.isclass(obj) or inspect.ismethod(obj):
sig_obj = obj if not inspect.isclass(obj) else obj.__init__
sig_re = '\((self|cls)?,?\s*(.*?)\)\:'
new_sig = ' '.join(re.search(sig_re, inspect.getsource(sig_obj), re.S).group(2).replace('\n', '').split())
new_sig = '(' + new_sig + ')'
return new_sig, return_annotation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With