14

I have many functions in Python of the type:

def foobar(one, two):
    """
    My function.
    :param int one: My one argument.
    :param int two: My two argument.
    :rtype: Something nice.
    """
    return 100 + one + two

And I need to parse the docstring to have a dictionary something like:

{
    'sdesc'  : 'My function.',
    'params' : [('one', 'My one argument.'), ('two', 'My two argument.')],
    'rtype'  : 'Something nice.'
}

I can use sphinx.util.docstrings.prepare_docstring as follows:

>>> prepare_docstring(foobar.__doc__)
['My function.', ':param int one: My one argument.', ':param int two: My two argument.', ':rtype: Something nice.', '']

I could create my own parser, maybe using regex for params and rtype, and stuff.

But is there a better way to do it or a better approach? How sphinx.ext.autodoc does it? Any other advice on how to parse this kind of docstrings?

Havok
  • 5,776
  • 1
  • 35
  • 44
  • 1
    Since Sphinx is open-source, you can find the autodoc module [here](https://bitbucket.org/birkenfeld/sphinx/src/122bbbbd002e0b1c66145d81097b7a69c216e917/sphinx/ext/autodoc.py?at=default). – Sam Mussmann Mar 06 '14 at 16:54

3 Answers3

14

openstack/rally's parse_docstrings() (permalink) take a function's docstring in reStructuredText (reST) format as an input and returns 4 values-short_description, long_description, params and returns

For e.g. if the function and its docstring is

def sample(self, task, deployment=None):
    """Start benchmark task.

    Implement sample function's long description.

    :param task: Path to the input task file.
    :param deployment: UUID or name of the deployment

    :returns: NIL
    """

Then parse_docstrings() function will return-

{ "short_description" : "Start benchmark task.",
  "long_description" : "Implement sample function's long description.",
  "params": [ { "name" : "task", "doc": "Path to the unput task file" },
              { "name" : "deployment", "doc" :  "UUID or name of the deployment" } ]
  "returns" : "NIL"
}

You can modify the above function as per your needs.

joar
  • 15,077
  • 1
  • 29
  • 54
piyush_raman
  • 318
  • 2
  • 5
  • 1
    Two years later but finally a great response. Thanks! – Havok Oct 18 '17 at 23:12
  • Looks like the function referenced in this answer doesn't support alternate `param type` specification format: when param is specified like `:param str name: User's name` (instead of `:param name: User's name` `:type name: str`) then it will not notice such param. This does not happen with the regex used in another answer. – MarSoft Nov 30 '17 at 10:14
  • @MarSoft - I forked it to support types - https://github.com/SamuelMarks/doctrans/blob/37810ff/doctrans/info.py – Samuel Marks Jul 17 '20 at 12:05
3

pip install docstring-parser

support both ReST-style and Google-style docstrings,

see https://github.com/rr-/docstring_parser for details

Felix Liu
  • 199
  • 2
  • 9
  • I had issues with this parser not support the ReST format properly. Maybe I'll open a PR? - It also definitely lacks ReST type support IIRC… keep an eye on https://github.com/SamuelMarks/doctrans/blob/37810ff/doctrans/info.py though, will see what else I'll add… – Samuel Marks Jul 17 '20 at 12:07
2

EDIT:

This question had two years without a response. See the accepted response for a better option.


OLD:

I ended up using regular expressions. The particular system used by Sphinx of nested Nodes, where each node type has to parse their children is not very useful for my purposes. If someone care, this is the regex I used:

param_regex = re.compile(
    '^:param (?P<type>\w+)? (?P<param>\w+): (?P<doc>.*)$'
)
Havok
  • 5,776
  • 1
  • 35
  • 44
  • 2
    The accepted answer seems robust, but I had trouble installing Rally. This answer work and is easy to implement, imho. – MikeyE Jan 31 '18 at 09:32
  • @MikeyE - You don't need to install Rally, just take the one Python file out, `info.py` – Samuel Marks Jul 17 '20 at 12:05