Hi Daniel, I didn't see anything in your reply - did you mean to say 
something or was that a mistake?

In any case, I got something to work by indeed subclassing from 
sphinx.ext.autodoc. Here is my working solution:

from sphinx.ext.autodoc import Documenter, ClassDocumenter, 
ModuleLevelDocumenter

__version__ = "0.1"


class MyDocumenter(ModuleLevelDocumenter):
    """Custom Sphinx autodocumeter.

    Note: this disables the hooks used by numpydoc to stop it from mangling 
the function signature
    and docstring. This is required because numpy assumes it is documenting 
a Python function and
    therefore that the arguments are contained in brackets.
    """

    objtype = "myobj"
    directivetype = "attribute"

    @classmethod
    def can_document_member(cls, member, membername, isattr, parent):
        return False

    def document_members(self, all_members=False):
        pass

    def process_doc(self, docstrings):
        # Stop extensions from preprocessing the docstrings.
        for docstringlines in docstrings:
            yield from docstringlines

    def get_doc(self, ignore=1):
        # Add your custom document fields here.
        lines.append([":My Section:"])
        lines.append([""])
        lines.append(["::"])
        lines.append([""])
        lines.append(["    Some paragraph..."])
        lines.append([""])

        return lines

    def format_name(self):
        # Ensure Python module is not added to name.
        return self.name

    def format_signature(self, **kwargs):
        return ""

    def resolve_name(self, modname, parents, path, base):
        # Needs something here for Documenter to generate output; this is 
also used for the index.
        return "fake", [base]

    def import_object(self):
        return True


def setup(app):
    app.add_autodocumenter(MyDocumenter)

    return {"version": __version__, "parallel_read_safe": True}



On Monday, 6 April 2020 01:45:42 UTC, Daniel Scott wrote:
>
>
>
> Sent from my Metro By T-Mobile 4G LTE Android Device
> ------------------------------
> *From:* [email protected] <javascript:> <
> [email protected] <javascript:>> on behalf of Sean Leavey <
> [email protected] <javascript:>>
> *Sent:* Saturday, April 4, 2020 4:15:59 AM
> *To:* sphinx-users <[email protected] <javascript:>>
> *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:
>
>
> (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 [email protected] <javascript:>.
> 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/cdce6eb4-e070-47f4-bf1b-4edf058bf7ec%40googlegroups.com.

Reply via email to