1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
"""
Sphinx autodoc hooks for documenting Invoke-level objects such as tasks.
Unlike most of the rest of Invocations, this module isn't for reuse in the
"import and call functions" sense, but instead acts as a Sphinx extension which
allows Sphinx's `autodoc`_ functionality to see and document
Invoke tasks and similar Invoke objects.
.. note::
This functionality is mostly useful for redistributable/reusable tasks
which have been defined as importable members of some Python package or
module, as opposed to "local-only" tasks that live in a single project's
``tasks.py``.
However, it will work for any tasks that Sphinx autodoc can import, so in a
pinch you could for example tweak ``sys.path`` in your Sphinx ``conf.py``
to get it loading up a "local" tasks file for import.
To use:
- Add ``"invocations.autodoc"`` to your Sphinx ``conf.py``'s ``extensions``
list.
- Use Sphinx autodoc's ``automodule`` directive normally, aiming it at your
tasks module(s), e.g. ``.. automodule:: myproject.tasks`` in some ``.rst``
document of your choosing.
- As noted above, this only works for modules that are importable, like any
other Sphinx autodoc use case.
- Unless you want to opt-in which module members get documented, use
``:members:`` or add ``"members": True`` to your ``conf.py``'s
``autodoc_default_options``.
- By default, only tasks with docstrings will be picked up, unless you also
give the ``:undoc-members:`` flag or add ``:undoc-members:`` / add
``"undoc-members": True`` to ``autodoc_default_options``.
- Please see the `autodoc`_ docs for details on these settings and more!
- Build your docs, and you should see your tasks showing up as documented
functions in the result.
.. _autodoc: http://www.sphinx-doc.org/en/master/ext/autodoc.html
"""
import inspect
from invoke import Task
# For sane mock patching. Meh.
from sphinx.ext import autodoc
class TaskDocumenter(
autodoc.DocstringSignatureMixin, autodoc.ModuleLevelDocumenter
):
objtype = "task"
directivetype = "function"
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
return isinstance(member, Task)
def format_args(self):
function = self.object.body
# TODO: consider extending (or adding a sibling to) Task.argspec so it
# preserves more of the full argspec tuple.
# TODO: whether to preserve the initial context argument is an open
# question. For now, it will appear, but only pending invoke#170 -
# after which point "call tasks as raw functions" may be less common.
# TODO: also, it may become moot-ish if we turn this all into emission
# of custom domain objects and/or make the CLI arguments the focus
return autodoc.stringify_signature(inspect.signature(function))
def document_members(self, all_members=False):
# Neuter this so superclass bits don't introspect & spit out autodoc
# directives for task attributes. Most of that's not useful.
pass
def setup(app):
app.setup_extension("sphinx.ext.autodoc")
app.add_autodocumenter(TaskDocumenter)
|