Sent from my Metro By T-Mobile 4G LTE Android Device
________________________________
From: [email protected] <[email protected]> on behalf
of Sean Leavey <[email protected]>
Sent: Saturday, April 4, 2020 4:15:59 AM
To: sphinx-users <[email protected]>
Subject: [sphinx-users] Implementing custom "autodoc" style objects
Hello Sphinx users,
I want to create a Sphinx directive that documents custom objects for a
domain-specific language. I want to define an object like this...
My Custom Item
==============
.. dmn:component:: myitemcls
This is some extra text!
and have Sphinx document it like it were a Python class, but not quite -
something like this:
[cid:autoGeneratedInlineImage1]
(That's a mock-up of what I'd like - so far I've not managed it. Note also I'd
like the "This is some extra text!" text to appear somewhere there too...)
The idea is that the custom Sphinx directive would look up myitemcls in my
library and introspect its parameters and then document them here.
I figure this is the same as the Python autodoc module, but I'm having trouble
understanding how it works - I find it's horrendously complicated and makes
calls to other modules all over the place, not all of which are documented or
require calls to non-public APIs. I tried to get it to work instead using a
custom directive class, but I had to do something hacky - in the run method I
grab the output from the parent (ObjectDescription) and inject some parameters
into the middle of the node list - the problem is that the ObjectDescription
directive appears to want the :param A: notation to have already been injected
in before instantiation, as I believe autodoc would do. In contrast, with my
method I have to inject these parameter strings into the object after
instantiation (in run()), and that seems to be my problem. I guess the solution
is to subclass some part of autodoc, but as I said I find it hard to figure out
how.
Here's what I've got so far:
import docutils
from docutils import nodes
import sphinx
from docutils.parsers import rst
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx.domains import Domain, Index
from sphinx.domains.std import StandardDomain
from sphinx.roles import XRefRole
from sphinx.directives import ObjectDescription
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import DocFieldTransformer, GroupedField
from sphinx import addnodes
class ComponentNode(ObjectDescription):
"""A custom node that describes a component."""
required_arguments = 1
option_spec = {}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._component_name = self.arguments[0]
# Argument node list, filled later.
self._arglist = None
self._paramlist = None
# This is my own function, not shown, that populates self._paramlist
with a list of strings containing ":param name:" etc. It also builds
self._arglist with addnodes.desc_parameter nodes.
self._parse_parameters()
def run(self, *args, **kwargs):
nodes = super().run(*args, **kwargs)
# The following is a bit of a hack. I first overwrite the field type
map to set up the
# "param" parser. I then create a list of strings containing ":param
[x]: [description]"
# entries and parse the contents into a new node. Finally I stitch this
node into the
# middle of the node list returned by the parent run() method.
self._doc_field_type_map = {
"param": (
GroupedField("parameters", label="Parameters",
names=('param',), can_collapse=True),
False # is typed
),
}
# Add parameters to content.
extra = StringList(
self._paramlist,
source=((self.content.parent, 0)*len(self._paramlist)),
parent=self.content.parent,
parent_offset=self.content.parent_offset
)
contentnode = addnodes.desc_content()
self.state.nested_parse(extra, self.content_offset, contentnode)
DocFieldTransformer(self).transform_all(contentnode)
return nodes[0:2] + [contentnode] + nodes[2:]
I'm not happy with this, it's quite hacky and I figure I'm not doing it
properly. It also generates documentation that looks different to that of class
documentation - the "parameter" labels are blue not grey:
[cid:autoGeneratedInlineImage2]
Can anyone help me figure out how to implement this custom directive, ideally
using autodoc?
--
You received this message because you are subscribed to the Google Groups
"sphinx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to
[email protected]<mailto:[email protected]>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/sphinx-users/5f306f1b-a565-4d16-a515-8dd2b2861d51%40googlegroups.com<https://groups.google.com/d/msgid/sphinx-users/5f306f1b-a565-4d16-a515-8dd2b2861d51%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"sphinx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sphinx-users/DM6PR07MB73243C927C5EF2984CBC56B2A1C20%40DM6PR07MB7324.namprd07.prod.outlook.com.