-
Notifications
You must be signed in to change notification settings - Fork 306
/
automodapi.py
826 lines (643 loc) · 29.7 KB
/
automodapi.py
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
"""
This module contains the functionality used to define the :rst:dir:`automodapi`
directive and its :ref:`supporting configuration values <automodapi-confvals>`.
.. contents:: Content
:local:
`automodapi` Directive
----------------------
.. rst:directive:: automodapi
The :rst:dir:`automodapi` directive is a wrapper on Sphinx's
:rst:dir:`automodule` directive and registered as one of the
`sphinx.ext.autodoc` directives. As such, many of the :rst:dir:`automodule`
options still work, except any of the *member* options and *ignore-module-all*.
The registration of :rst:dir:`automodapi` with `~sphinx.ext.autodoc` means
:rst:dir:`automodapi` is used by Sphinx when indexing the documented module.
:rst:dir:`automodapi` is used to document modules (i.e. packages and ``.py``
files. The contents of the `plasmapy_sphinx.utils` page shows an example
of how the following declaration is rendered.
.. code-block:: rst
`plasmapy_sphinx.utils`
=======================
.. automodapi:: plasmapy_sphinx.utils
The module level docstring is first rendered and then the categorized groups
are rendered in :rst:dir:`automodsumm` tables filtered for the associated group
and placed under the appropriate object type heading. The order in which the
:rst:dir:`automodsumm` tables are displayed is controlled by the configuration
value :confval:`automodapi_group_order`.
.. rst:directive:option:: groups
When a module is inspected all the identified objects are categorized into
groups. The built-in groups are:
+----------------+-------------------------------------------------------------+
| **modules** | Direct sub-packages and modules. |
+----------------+-------------------------------------------------------------+
| **classes** | Python classes. (excluding **exceptions** and **warnings**) |
+----------------+-------------------------------------------------------------+
| **exceptions** | Classes that inherit from `BaseException`. (excluding |
| | **warnings**) |
+----------------+-------------------------------------------------------------+
| **warnings** | Classes that inherit from `Warning`. |
+----------------+-------------------------------------------------------------+
| **functions** | Objects that satisfy :func:`inspect.isroutine`. |
+----------------+-------------------------------------------------------------+
| **variables** | All other objects. |
+----------------+-------------------------------------------------------------+
In addition to the built-in groups, groups defined in
:confval:`automodapi_custom_groups` will be categorized. When objects are
collected and grouped the **modules** will be done first, followed by any
custom group, and, finally, the built-in groups. By default, tables will
be generated for **all** groups.
The contents of the :ref:`API section <automodapi-api>` below shows
an example of how the follow declaration is rendered.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-main-docstring:
or
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-main-docstring:
:groups: all
The behavior of ``:no-main-docstring:`` is described below
in the :rst:dir:`automodapi:no-main-docstring` section. If you
only want to display only **classes**, then the following can be done.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-main-docstring:
:groups: classes
If you want to include multiple groups, then specify all groups as a
comma separated list.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:groups: classes, functions
.. rst:directive:option:: exclude-groups
This option behaves just like :rst:dir:`automodapi:groups` except
you are selectively excluding groups for the generated tables. Using the
same example as before, a table of just **classes** can be generated by
doing
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:exclude-groups: functions
.. rst:directive:option:: no-groups
Specify if you want to exclude all :rst:dir:`automodsumm` tables from
being generated.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-groups:
.. rst:directive:option:: skip
This option allows you to skip (exclude) selected objects from the
generated tables. The argument is given as a comma separated list of
the object's short name. Continuing with the example from above, let's
skip `~plasmapy_sphinx.autodoc.automodapi.ModAPIDocumenter` and
`~plasmapy_sphinx.autodoc.automodapi.setup` from the tables.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-main-docstrings:
:skip: ModAPIDocumenter, setup
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:noindex:
:no-toctree:
:no-main-docstring:
:skip: ModAPIDocumenter, setup
.. rst:directive:option:: noindex
Like the rest of Sphinx's `~sphinx.ext.autodoc` directives,
:rst:dir:`automodapi` is used by Sphinx to index the documented module
and make available cross-referencing. To prevent multiple
cross-references to the same documented module, ``:noindex:`` can be used
to prevent the indexing.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:noindex:
.. rst:directive:option:: include-heading
This option will create a top level heading for the documented module.
.. code-block:: rst
.. automodapi:: foo.bar
:include-heading:
If ``bar`` is a package, then the heading will look like
.. code-block:: rst
foo.bar Package
---------------
and if ``bar`` is a ``.py`` file, then the heading will look like
.. code-block:: rst
foo.bar Module
--------------
.. rst:directive:option:: heading-chars
(Default ``-^``) A two character string specifying the underline characters
used for the heading created by :rst:dir:`automodapi`. The following code
.. code-block:: rst
.. automodapi:: foo.bar
:include-heading:
:heading-chars: ^~
would generate reStructuredText equivalent to
.. code-block:: rst
foo.bar Package
^^^^^^^^^^^^^^^
I am the main docstring
Sub-Packages & Modules
~~~~~~~~~~~~~~~~~~~~~~
.. automodsumm:: foo.bar
:toctree: api
:groups: modules
If :rst:dir:`automodapi:include-heading` is not given, then the first
character will be used for the :rst:dir:`automodsumm` table headings.
.. rst:directive:option:: toctree
If you want the tables generated by :rst:dir:`automodapi` to serve as
:rst:dir:`toctree`'s, then specify this option with a directory path
``DIRNAME`` with respect to the location of your ``conf.py``.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:toctree: DIRNAME
If ``:toctree:`` is not set, then ``DIRNAME`` will default to what is set
by :confval:`automodapi_default_toctree_dir`. If no :rst:dir:`toctree`
is desired, then use option :rst:dir:`automodapi:no-toctree`.
.. rst:directive:option:: no-toctree
Use this option if you do not want the tables generated by
:rst:dir:`automodapi` to serve as :rst:dir:`toctree`'s.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-toctree:
.. rst:directive:option:: no-main-docstring
By default the module level docstring will be rendered and displayed, but
setting this option will omit the module level docstring and leave just
the :rst:dir:`autosummary` tables for each collected group of objects.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-main-docstring:
.. rst:directive:option:: inheritance-diagram
Set this option to generate inheritance diagrams (using the directive
:rst:dir:`inheritance-diagram`) for the groups listed in the configuration
value :confval:`automodapi_groups_with_inheritance_diagrams`. Default
behavior is controlled by the configuration value
:confval:`automodapi_include_inheritance_diagram`. The option
:rst:dir:`automodapi:no-inheritance-diagram` will supersede this option.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:inheritance-diagram:
.. rst:directive:option:: no-inheritance-diagram
Set this option to not generate inheritance diagrams. This option will
take precedence over the :rst:dir:`automodapi:inheritance-diagram` option.
.. code-block:: rst
.. automodapi:: plasmapy_sphinx.autodoc.automodapi
:no-inheritance-diagram:
.. _automodapi-confvals:
`automodapi` Configuration Values
---------------------------------
A configuration value is a variable that can be defined in ``conf.py`` to configure
the default behavior of related `sphinx` directives. The configuration values
below relate to the behavior of the :rst:dir:`automodapi` directive.
.. confval:: automodapi_default_toctree_dir
(Default ``"api"``) The default directory name, with respect to ``conf.py``,
for :rst:dir:`automodapi` to write stub files to. This is the default
value for :rst:dir:`automodapi:toctree`.
.. confval:: automodapi_group_order
(Default ``("modules", "classes", "exceptions", "warnings", "functions",
"variables")``) A tuple defining the order :rst:dir:`automodapi` should
display the collected groups. If :rst:dir:`automodapi` identifies groups
that are not identified here (e.g. unlisted custom groups), then those
groups will be displayed alphabetically after the groups defined in
:confval:`automodapi_group_order`. *This configuration value should be
defined if custom groups are defined by* :confval:`automodapi_custom_groups` *.*
.. confval:: automodapi_groups_with_inheritance_diagrams
(Default ``["classes", "exceptions", "warnings"]``) A list defining which
groups should have inheritance diagrams associated with them when displayed
by :rst:dir:`automodapi`.
.. confval:: automodapi_include_inheritance_diagram
(Default `True`) Controls if :rst:dir:`automodapi` will by default generated
inheritance diagrams (see directive :rst:dir:`inheritance-diagram`) for a
given group. The groups that should get inheritance diagrams are defined by
the configuration value :confval:`automodapi_groups_with_inheritance_diagrams`.
"""
__all__ = ["AutomodapiOptions", "ModAPIDocumenter", "setup"]
import inspect
import re
import sys
import warnings
from collections import OrderedDict
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx.application import Sphinx
try:
from sphinx.deprecation import RemovedInSphinx50Warning
except ImportError:
class RemovedInSphinx50Warning(PendingDeprecationWarning):
pass
from sphinx.ext.autodoc import bool_option, ModuleDocumenter
from sphinx.locale import __
from sphinx.util import logging
from typing import Any, Callable, Dict, List, Optional, Union
from ..automodsumm.core import AutomodsummOptions, option_str_list
from ..utils import default_grouping_info
if sys.version_info >= (3, 0):
text_type = str
else:
text_type = unicode # noqa
logger = logging.getLogger(__name__)
_option_spec = {
**ModuleDocumenter.option_spec,
"groups": option_str_list,
"exclude-groups": option_str_list,
"no-groups": bool_option,
# "group-order": option_str_list,
# "merge-groups": bool_option,
"skip": option_str_list,
"include-heading": bool_option,
# "members": lambda x: None,
"heading-chars": directives.unchanged,
"toctree": directives.unchanged,
"no-toctree": bool_option,
"no-main-docstring": bool_option,
"inheritance-diagram": bool_option,
"no-inheritance-diagram": bool_option,
} # type: Dict[str, Callable]
for option_name in list(_option_spec):
if "member" in option_name:
del _option_spec[option_name]
del _option_spec["ignore-module-all"]
del option_name
class AutomodapiOptions(AutomodsummOptions):
"""
Class for advanced conditioning and manipulation of option arguments of
`plasmapy_sphinx.autodoc.automodapi.ModAPIDocumenter`.
"""
option_spec = _option_spec
logger = logger
def condition_options(self):
super().condition_options()
self.condition_heading_chars_option()
self.condition_include_heading_option()
self.condition_inheritance_diagram_option()
def condition_toctree_option(self):
"""
Additional conditioning of the ``:toctree:`` option. (See options
:rst:dir:`automodapi:toctree` and :rst:dir:`automodapi:no-toctree`
for additional details.)
"""
if "no-toctree" in self.options and self.options["no-toctree"]:
if "toctree" in self.options:
del self.options["toctree"]
elif "toctree" not in self.options:
self.options["toctree"] = self.app.config.automodapi_default_toctree_dir
super().condition_toctree_option()
def condition_heading_chars_option(self):
"""
Additional conditioning of the ``:heading-chars:`` option. (See option
:rst:dir:`automodapi:heading-chars` for additional details.)
"""
non_alphanumerics = re.compile("[^0-9a-zA-Z]]+")
heading_chars = self.options.get("heading-chars", None)
if (
heading_chars is None
or heading_chars == ""
or len(heading_chars) < 2
or non_alphanumerics.fullmatch(heading_chars) is None
):
self.options["heading-chars"] = "-^"
def condition_include_heading_option(self):
"""
Additional conditioning of the ``:include-heading:`` option. (See option
:rst:dir:`automodapi:include-heading` for additional details.)
"""
if "include-heading" not in self.options:
self.options["include-heading"] = False
def condition_inheritance_diagram_option(self):
"""
Additional conditioning of the ``:inheritance-diagram:`` option. (See options
:rst:dir:`automodapi:inheritance-diagram` and
:rst:dir:`automodapi:no-inheritance-diagram` for additional details.)
"""
if "no-inheritance-diagram" in self.options:
self.options["inheritance-diagram"] = False
del self.options["no-inheritance-diagram"]
elif "inheritance-diagram" in self.options:
self.options["inheritance-diagram"] = False
else:
self.options[
"inheritance-diagram"
] = self.app.config.automodapi_include_inheritance_diagram
def condition_group_options(self):
"""
Additional conditioning of the grouping options. (See options
:rst:dir:`automodapi:groups`, :rst:dir:`automodapi:exclude-groups`, and
:rst:dir:`automodapi:no-groups` for additional details.)
"""
if "no-groups" in self.options and self.options["no-groups"]:
self.options["groups"] = []
if "exclude-groups" in self.options:
del self.options["exclude-groups"]
return
super().condition_group_options()
@property
def options_for_automodsumm(self) -> Dict[str, Any]:
"""
A dictionary of options suitable for :rst:dir:`automodsumm` based on the
options given to :rst:dir:`automodapi`, and excluding the group options.
"""
options = {}
asumm_opts = list(AutomodsummOptions.option_spec)
for name in asumm_opts:
if name in self.options and name not in ("groups", "exclude-groups"):
val = self.options[name]
if isinstance(val, list):
val = ", ".join(val)
if name == "toctree" and self.toctree["original"] is not None:
# automodsumm requires path relative to the confdir but
# Automodsumm.review_toctree_option generates the path relative
# to the file location
options[name] = self.toctree["original"]
else:
options[name] = val
return options
class ModAPIDocumenter(ModuleDocumenter):
"""
The class that defines the `~sphinx.ext.autodoc` directive :rst:dir:`automodapi`.
"""
objtype = "modapi"
"""Defines the *auto* directive name. In this case ``automodapi``."""
directivetype = "module"
"""Defines the generated directive name. In this case ``.. :py:module::``."""
titles_allowed = True
content_indent = ""
logger = logger
"""
Instance of the `~sphinx.util.logging.SphinxLoggerAdapter` for report during
builds.
"""
option_spec = _option_spec
"""Mapping of option names to validator functions."""
# Templates used for generated the additional content associated with the
# directive (e.g. the automodsumm tables)
_templates = {
"mod-heading": "\n".join(["{modname} {pkg_or_mod}", "{underline}", ""]),
"heading": "\n".join(["{title}", "{underline}"]),
"automodsumm": "\n".join([".. automodsumm:: {modname}", " :groups: {group}"]),
"options": " :{option}: {opt_args}",
"inheritance-diagram": "\n".join(
[
".. inheritance-diagram:: {cls_list}",
" :private-bases:",
" :parts: 1",
],
),
}
@property
def grouping_info(self) -> Dict[str, Dict[str, Union[str, None]]]:
"""
Dictionary of :rst:dir:`automodapi` and :rst:dir:`automodsumm` group
information. The primary key is the group name, e.g. **modules**,
**classes**, etc. The value associated with the primary key is a
dictionary with the following keys:
+-------------+------------------------------------------------------------+
| title | Title used to head the :rst:dir:`automodsumm` table. |
+-------------+------------------------------------------------------------+
| description | Brief description to follow the title. |
+-------------+------------------------------------------------------------+
| dunder | Name of the dunder variable used to define a custom group. |
+-------------+------------------------------------------------------------+
"""
group_order = tuple(self.env.app.config.automodapi_group_order)
custom_group_info = self.env.app.config.automodapi_custom_groups
group_names = set(default_grouping_info) | set(custom_group_info)
remainder = list(group_names - set(group_order))
if len(remainder) > 0:
group_order += tuple(sorted(remainder))
_grouping_info = OrderedDict()
for name in group_order:
if name in default_grouping_info:
_info = default_grouping_info[name]
else:
_info = custom_group_info[name]
_grouping_info.update(
{
name: {
"title": _info.get("title", None),
"description": _info.get("description", None),
"dunder": _info.get("dunder", None),
},
},
)
return _grouping_info
def generate_more_content(self, modname: str) -> List[str]:
"""
Generate the "more content" associate with the :rst:dir:`automodsumm` tables
and inheritance diagrams.
Parameters
----------
modname : str
Name of the module being documented (i.e. that given to
:rst:dir:`automodapi`).
Returns
-------
List[str]
A list of strings to be added the to the directive's content.
"""
app = self.env.app
inheritance_groups = app.config.automodapi_groups_with_inheritance_diagrams
lines = []
option_processor = AutomodapiOptions(
app,
modname,
self.options,
_warn=self.logger.warning,
docname=self.env.docname,
)
asumm_options = option_processor.options_for_automodsumm
mod_objs = option_processor.mod_objs_option_filtered
heading_char = (
option_processor.options["heading-chars"][1]
if option_processor.options["include-heading"]
else option_processor.options["heading-chars"][0]
)
include_inheritance_diagram = option_processor.options["inheritance-diagram"]
# scan thru default groups first
for group, info in self.grouping_info.items():
if group not in mod_objs:
continue
title = info["title"]
description = info["description"] # type: str
underline = heading_char * len(title)
# sub-heading
lines.extend(
self._templates["heading"]
.format(title=title, underline=underline)
.splitlines()
)
lines.append("")
# add group description
if description is not None:
description = inspect.cleandoc(description)
descr_list = description.split("\n")
lines.extend(descr_list)
lines.append("")
# add automodsumm directive
lines.extend(
self._templates["automodsumm"]
.format(modname=modname, group=group)
.splitlines()
)
# add options for automodsumm directive
for name, val in asumm_options.items():
if name == "toctree" and group == "modules":
continue
lines.extend(
self._templates["options"]
.format(option=name, opt_args=val)
.splitlines()
)
lines.append("")
# add inheritance-diagram
if group in inheritance_groups and include_inheritance_diagram:
cls_list = " ".join(mod_objs[group]["qualnames"])
lines.extend(
self._templates["inheritance-diagram"]
.format(cls_list=cls_list)
.splitlines()
)
lines.append("")
return lines
def generate_heading(self, modname: str) -> None:
"""
Generate and place a heading at the top of the directive's content. If
``modname`` is a package then the title will be ``<modname> Package``;
and if a module (``.py`` file) then the title will be ``<modname> Module``.
Parameters
----------
modname : str
Name of the module being documented (i.e. that given to
:rst:dir:`automodapi`).
"""
app = self.env.app
sourcename = self.get_sourcename()
option_processor = AutomodapiOptions(
app,
modname,
self.options,
_warn=self.logger.warning,
docname=self.env.docname,
)
if not option_processor.options["include-heading"]:
return
modname = re.escape(modname)
if option_processor.pkg_or_module == "pkg":
pkg_or_mod = "Package"
else:
pkg_or_mod = "Module"
heading_char = option_processor.options["heading-chars"][0]
underline = heading_char * (len(modname) + 1 + len(pkg_or_mod))
heading_lines = (
self._templates["mod-heading"]
.format(modname=modname, pkg_or_mod=pkg_or_mod, underline=underline)
.splitlines()
)
for line in heading_lines:
self.add_line(line, source=sourcename)
def add_content(
self, more_content: Optional[StringList], no_docstring: bool = False
) -> None:
"""Add content from docstrings, attribute documentation and user."""
if no_docstring:
warnings.warn(
"The 'no_docstring' argument to %s.add_content() is deprecated."
% self.__class__.__name__,
RemovedInSphinx50Warning,
stacklevel=2,
)
no_docstring = self.options.get("no-main-docstring", False)
# set sourcename and add content from attribute documentation
sourcename = self.get_sourcename()
if self.analyzer:
attr_docs = self.analyzer.find_attr_docs()
if self.objpath:
key = (".".join(self.objpath[:-1]), self.objpath[-1])
if key in attr_docs:
no_docstring = True
# make a copy of docstring for attributes to avoid cache
# the change of autodoc-process-docstring event.
docstrings = [list(attr_docs[key])]
for i, line in enumerate(self.process_doc(docstrings)):
self.add_line(line, sourcename, i)
# add content from docstrings
if not no_docstring:
docstrings = self.get_doc()
if docstrings is None:
# Do not call autodoc-process-docstring on get_doc() returns None.
pass
else:
if not docstrings:
# append at least a dummy docstring, so that the event
# autodoc-process-docstring is fired and can add some
# content if desired
docstrings.append([])
for i, line in enumerate(self.process_doc(docstrings)):
self.add_line(line, sourcename, i)
# add additional content (e.g. from document), if present
if more_content:
for line, src in zip(more_content.data, more_content.items):
self.add_line(line, src[0], src[1])
def generate(
self,
more_content: Optional[StringList] = None,
real_modname: str = None,
check_module: bool = False,
all_members: bool = False,
) -> None:
"""
Generate reST for the object given by *self.name*, and possibly for
its members.
If *more_content* is given, include that content. If *real_modname* is
given, use that module name to find attribute docs. If *check_module* is
True, only generate if the object is defined in the module name it is
imported from. If *all_members* is True, document all members.
"""
docname = self.env.docname
if not docname.endswith(".rst"):
docname += ".rst"
if not self.parse_name():
# need a module to import
logger.warning(
__(
f"don't know which module to import for autodocumenting "
f"{self.name} (try placing a 'module' or 'currentmodule' "
f"directive in the document, or giving an explicit module name)"
),
type="autodoc",
)
return
# now, import the module and get object to document
if not self.import_object():
return
# If there is no real module defined, figure out which to use.
# The real module is used in the module analyzer to look up the module
# where the attribute documentation would actually be found in.
# This is used for situations where you have a module that collects the
# functions and classes of internal submodules.
real_modname = real_modname or self.get_real_modname() # type: str
# Generate heading
self.generate_heading(modname=real_modname)
# Generate the 'more_content' (automodsumm and inheritance diagrams)
more_content = StringList()
more_lines = self.generate_more_content(modname=real_modname)
for line in more_lines:
more_content.append(line, source=docname)
# generate
super().generate(
more_content=more_content,
real_modname=real_modname,
check_module=check_module,
all_members=all_members,
)
def setup(app: Sphinx):
"""Sphinx ``setup()`` function for the :rst:dir:`automodapi` functionality."""
from ..automodsumm.core import setup as setup_automodsumm
rtn = setup_automodsumm(app)
app.setup_extension("sphinx.ext.inheritance_diagram")
app.add_autodocumenter(ModAPIDocumenter)
app.add_config_value("automodapi_include_inheritance_diagram", True, True)
app.add_config_value("automodapi_default_toctree_dir", "api", True)
app.add_config_value(
"automodapi_group_order",
("modules", "classes", "exceptions", "warnings", "functions", "variables"),
True,
)
app.add_config_value(
"automodapi_groups_with_inheritance_diagrams",
["classes", "exceptions", "warnings"],
True,
)
return rtn