Hi, Autodoc is one of complex extension in Sphinx, I think. It is hard to understand how it implemented. It adopted two-layered model. The first layer; python domain describes python object in reST level. It provides many directives for that purpose; `py:function`, `py:class`, `py:method` and so on. The second layer is autodoc itself. It generates reStructuredText source code based on the first layer internally.
And the `ObjectDescription` class you used is a base class of the first layer. It is a kind of mini framework to create object-description directives. It expects to derived classes to override `handle_signature()` and some methods. You can see examples of it on sphinx/domains/*.py. If your goal is making autodoc by one directive, there are no example to do that. So I propose you to make the first layer at first. Thanks, Takeshi KOMIYA 2020年4月4日(土) 17:16 Sean Leavey <sean.lea...@gmail.com>: > 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: > > > (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: > > > 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 sphinx-users+unsubscr...@googlegroups.com. > 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 sphinx-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sphinx-users/CAFmkQAMcddm%3D8kgaTTi5iMmxLpN-rBoMbVvVNpu3F830%2BOUSgg%40mail.gmail.com.