Skip to content

Commit f81147e

Browse files
authored
Merge pull request #104 from Chilipp/autoexception-support
Autoexception support
2 parents 811352b + db473cf commit f81147e

File tree

11 files changed

+156
-48
lines changed

11 files changed

+156
-48
lines changed

.github/workflows/python-app.yml

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -75,31 +75,3 @@ jobs:
7575
"sphinxcontrib-jsmath<1.0.1"
7676
"sphinxcontrib-qthelp<1.0.7"
7777
"sphinxcontrib-serializinghtml<1.1.10"'
78-
79-
80-
build-legacy-sphinx-30plus:
81-
name: Build
82-
83-
strategy:
84-
fail-fast: false
85-
matrix:
86-
python-version: [ "3.7", "3.8", "3.9" ]
87-
sphinx-version: [
88-
"3.0.*", # possible range: 3.0.0 - 3.5.4
89-
]
90-
include:
91-
- python-version: "3.7"
92-
sphinx-version: "3.5.*" # latest version that supports py3.7
93-
uses: ./.github/workflows/build.yml
94-
with:
95-
python-version: ${{ matrix.python-version }}
96-
extra-requirements: '\
97-
"sphinx==${{ matrix.sphinx-version }}"
98-
"jinja2<3.1"
99-
"alabaster<0.7.14"
100-
"sphinxcontrib-applehelp<1.0.8"
101-
"sphinxcontrib-devhelp<1.0.6"
102-
"sphinxcontrib-htmlhelp<2.0.5"
103-
"sphinxcontrib-jsmath<1.0.1"
104-
"sphinxcontrib-qthelp<1.0.7"
105-
"sphinxcontrib-serializinghtml<1.1.10"'

autodocsumm/__init__.py

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353

5454
from sphinx.ext.autodoc import (
5555
ClassDocumenter, ModuleDocumenter, ALL, PycodeError,
56-
ModuleAnalyzer, AttributeDocumenter, DataDocumenter, Options,
56+
ModuleAnalyzer, AttributeDocumenter, DataDocumenter, Options, ExceptionDocumenter,
5757
Documenter, prepare_docstring)
5858
import sphinx.ext.autodoc as ad
5959

@@ -349,7 +349,7 @@ class AutoSummModuleDocumenter(ModuleDocumenter, AutosummaryDocumenter):
349349

350350
#: slightly higher priority than
351351
#: :class:`sphinx.ext.autodoc.ModuleDocumenter`
352-
priority = ModuleDocumenter.priority + 0.1
352+
priority = ModuleDocumenter.priority + 0.1 # type: ignore[assignment]
353353

354354
#: original option_spec from :class:`sphinx.ext.autodoc.ModuleDocumenter`
355355
#: but with additional autosummary boolean option
@@ -399,7 +399,7 @@ class AutoSummClassDocumenter(ClassDocumenter, AutosummaryDocumenter):
399399

400400
#: slightly higher priority than
401401
#: :class:`sphinx.ext.autodoc.ClassDocumenter`
402-
priority = ClassDocumenter.priority + 0.1
402+
priority = ClassDocumenter.priority + 0.1 # type: ignore[assignment]
403403

404404
#: original option_spec from :class:`sphinx.ext.autodoc.ClassDocumenter`
405405
#: but with additional autosummary boolean option
@@ -437,11 +437,64 @@ def add_content(self, *args, **kwargs):
437437
self.add_autosummary(relative_ref_paths=True)
438438

439439

440+
class AutoSummExceptionDocumenter(ExceptionDocumenter, AutosummaryDocumenter):
441+
"""Exception Documenter with autosummary tables for its members.
442+
443+
This class has the same functionality as the base
444+
:class:`sphinx.ext.autodoc.ExceptionDocumenter` class but with an
445+
additional `autosummary` option to provide the ability to provide a summary
446+
of all methods and attributes.
447+
It's priority is slightly higher than the one of the ExceptionDocumenter
448+
"""
449+
450+
#: slightly higher priority than
451+
#: :class:`sphinx.ext.autodoc.ExceptionDocumenter`
452+
priority = ExceptionDocumenter.priority + 0.1 # type: ignore[assignment]
453+
454+
#: original option_spec from
455+
#: :class:`sphinx.ext.autodoc.ExceptionDocumenter` but with additional
456+
#: autosummary boolean option
457+
option_spec = ExceptionDocumenter.option_spec.copy()
458+
option_spec['autosummary'] = bool_option
459+
option_spec['autosummary-no-nesting'] = bool_option
460+
option_spec['autosummary-sections'] = list_option
461+
option_spec['autosummary-no-titles'] = bool_option
462+
option_spec['autosummary-force-inline'] = bool_option
463+
option_spec['autosummary-nosignatures'] = bool_option
464+
465+
#: Add options for members for the autosummary
466+
for _option in member_options.intersection(option_spec):
467+
option_spec['autosummary-' + _option] = option_spec[_option]
468+
del _option
469+
470+
member_sections = {
471+
ad.ExceptionDocumenter.member_order: 'Classes',
472+
ad.MethodDocumenter.member_order: 'Methods',
473+
ad.AttributeDocumenter.member_order: 'Attributes',
474+
}
475+
""":class:`dict` that includes the autosummary sections
476+
477+
This dictionary defines the sections for the autosummmary option. The
478+
values correspond to the :attr:`sphinx.ext.autodoc.Documenter.member_order`
479+
attribute that shall be used for each section."""
480+
481+
def add_content(self, *args, **kwargs):
482+
super().add_content(*args, **kwargs)
483+
484+
# If the class is already documented under another name, Sphinx
485+
# documents it as data/attribute. In this case, we do not want to
486+
# generate an autosummary of the class for the attribute (see #69).
487+
if not self.doc_as_attr:
488+
self.add_autosummary(relative_ref_paths=True)
489+
490+
440491
class CallableDataDocumenter(DataDocumenter):
441492
""":class:`sphinx.ext.autodoc.DataDocumenter` that uses the __call__ attr
442493
"""
443494

444-
priority = DataDocumenter.priority + 0.1
495+
#: slightly higher priority than
496+
#: :class:`sphinx.ext.autodoc.DataDocumenter`
497+
priority = DataDocumenter.priority + 0.1 # type: ignore[assignment]
445498

446499
def format_args(self):
447500
# for classes, the relevant signature is the __init__ method's
@@ -474,6 +527,8 @@ def get_doc(self, *args, **kwargs):
474527

475528
doc = []
476529
for docstring in docstrings:
530+
encoding = _get_arg("encoding", 0, None, *args, **kwargs)
531+
ignore = _get_arg("ignore", 1, 1, *args, **kwargs)
477532
if not isinstance(docstring, str):
478533
docstring = force_decode(docstring, encoding)
479534
doc.append(prepare_docstring(docstring, ignore))
@@ -486,7 +541,9 @@ class CallableAttributeDocumenter(AttributeDocumenter):
486541
attr
487542
"""
488543

489-
priority = AttributeDocumenter.priority + 0.1
544+
#: slightly higher priority than
545+
#: :class:`sphinx.ext.autodoc.AttributeDocumenter`
546+
priority = AttributeDocumenter.priority + 0.1 # type: ignore[assignment]
490547

491548
def format_args(self):
492549
# for classes, the relevant signature is the __init__ method's
@@ -565,7 +622,7 @@ class NoDataDataDocumenter(CallableDataDocumenter):
565622
"""DataDocumenter that prevents the displaying of large data"""
566623

567624
#: slightly higher priority as the one of the CallableDataDocumenter
568-
priority = CallableDataDocumenter.priority + 0.1
625+
priority = CallableDataDocumenter.priority + 0.1 # type: ignore[assignment]
569626

570627
def __init__(self, *args, **kwargs):
571628
super(NoDataDataDocumenter, self).__init__(*args, **kwargs)
@@ -580,7 +637,7 @@ class NoDataAttributeDocumenter(CallableAttributeDocumenter):
580637
"""AttributeDocumenter that prevents the displaying of large data"""
581638

582639
#: slightly higher priority as the one of the CallableAttributeDocumenter
583-
priority = CallableAttributeDocumenter.priority + 0.1
640+
priority = CallableAttributeDocumenter.priority + 0.1 # type: ignore[assignment]
584641

585642
def __init__(self, *args, **kwargs):
586643
super(NoDataAttributeDocumenter, self).__init__(*args, **kwargs)
@@ -596,13 +653,15 @@ class AutoDocSummDirective(SphinxDirective):
596653
597654
Usage::
598655
599-
.. autoclasssum:: <Class>
656+
.. autoclasssumm:: <Class>
657+
658+
.. automodsumm:: <module>
600659
601-
.. automodsum:: <module>
660+
.. autoexceptionsumm:: <ExceptionClass>
602661
603-
The directive additionally supports all options of the ``autoclass`` or
604-
``automod`` directive respectively. Sections can be a list of section titles
605-
to be included. If ommitted, all sections are used.
662+
The directive additionally supports all options of the ``autoclass``,
663+
``automod``, or ``autoexception`` directive respectively. Sections can be a
664+
list of section titles to be included. If ommitted, all sections are used.
606665
"""
607666

608667
has_content = False
@@ -616,9 +675,9 @@ def run(self):
616675
reporter = self.state.document.reporter
617676

618677
try:
619-
source, lineno = reporter.get_source_and_line(self.lineno)
678+
_, lineno = reporter.get_source_and_line(self.lineno)
620679
except AttributeError:
621-
source, lineno = (None, None)
680+
_, lineno = (None, None)
622681

623682
# look up target Documenter
624683
objtype = self.name[4:-4] # strip prefix (auto-) and suffix (-summ).
@@ -659,6 +718,7 @@ def setup(app):
659718
app.setup_extension('sphinx.ext.autosummary')
660719
app.setup_extension('sphinx.ext.autodoc')
661720
app.add_directive('autoclasssumm', AutoDocSummDirective)
721+
app.add_directive('autoexceptionsumm', AutoDocSummDirective)
662722
app.add_directive('automodulesumm', AutoDocSummDirective)
663723

664724
AUTODOC_DEFAULT_OPTIONS.extend(
@@ -673,7 +733,7 @@ def setup(app):
673733
registry = app.registry.documenters
674734
for cls in [AutoSummClassDocumenter, AutoSummModuleDocumenter,
675735
CallableAttributeDocumenter, NoDataDataDocumenter,
676-
NoDataAttributeDocumenter]:
736+
NoDataAttributeDocumenter, AutoSummExceptionDocumenter]:
677737
if not issubclass(registry.get(cls.objtype), cls):
678738
app.add_autodocumenter(cls, override=True)
679739

docs/conf_settings.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ Directives
7878
By default, this directives also sets the `:members:` option unless you
7979
specify `:no-members`.
8080

81+
.. rst:directive:: autoexceptionsumm
82+
83+
The same as the ``autoclasssumm`` directive, just for an ``Exception``
84+
subclass.
85+
8186
.. rst:directive:: automodulesumm
8287
8388
The same as the ``autoclasssumm`` directive, just for a module.

docs/demo_exception.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.. _demo_exception:
2+
3+
Demo Exception
4+
==============
5+
6+
.. autoexception:: dummy.MyException
7+
:members:
8+
:noindex:

docs/dummy.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,18 @@ def do_something(self):
2222
some_other_attr = None
2323

2424

25+
class MyException(object):
26+
"""Some Exception
27+
28+
With some description"""
29+
30+
def do_something_exceptional(self):
31+
"""Do something exceptional"""
32+
pass
33+
34+
#: Any instance attribute
35+
some_exception_attr = None
36+
37+
2538
#: Some module data
2639
large_data = 'Whatever'

docs/examples.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Examples
88

99
Demo Module <demo_module>
1010
Demo Class <demo_class>
11+
Demo Exception <demo_exception>
1112
Demo Grouper <demo_grouper>
1213

1314
Including a table of contents
@@ -24,11 +25,16 @@ The *autosummary* flag introduces a small table of contents. So::
2425

2526
produces :ref:`this <demo_module>`. And::
2627

27-
.. autoclass:: dummy.SomeClass
28+
.. autoclass:: dummy.MyClass
2829
:members:
2930
:autosummary:
3031

31-
produces :ref:`this <demo_class>`.
32+
produces :ref:`this <demo_class>`, and for exceptions::
33+
34+
.. autoexception:: dummy.MyException
35+
:members:
36+
:autosummary:
37+
produces :ref:`this <demo_exception>`.
3238

3339
By default, module members are (mainly) grouped according into *Functions*,
3440
*Classes* and *Data*, class members are grouped into *Methods* and
@@ -178,8 +184,8 @@ section of a class, you can specify::
178184
Multiple sections might be separated by `;;`, e.g.
179185
``:autosummary-sections: Methods ;; Attributes``.
180186

181-
This also works for the ``autoclasssumm`` and ``automodulesumm`` directives,
182-
e.g.::
187+
This also works for the ``autoclasssumm``, ``autoexceptionsumm`` and
188+
``automodulesumm`` directives, e.g.::
183189

184190
.. autoclasssumm:: dummy.SomeClass
185191
:autosummary-sections: Methods

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ classifiers = [
3333

3434
requires-python = '>= 3.7'
3535
dependencies = [
36-
'Sphinx >= 2.2, < 9.0',
36+
'Sphinx >= 4.0, < 9.0',
3737
]
3838

3939
[project.urls]

tests/test-root/dummy.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ class InnerClass(object):
6767
small_data = 'Should be skipped'
6868

6969

70+
class TestException(Exception):
71+
"""Exception test for autosummary"""
72+
73+
def __init__(self):
74+
#: This is an exception attribute
75+
self.exception_instance_attribute = 1
76+
77+
def test_exception_method(self):
78+
"""Test if the method is included"""
79+
pass
80+
81+
7082
class InheritedTestClass(TestClass):
7183
"""Class test for inherited attributes"""
7284

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Autoexceptionsumm of Dummy Exception
2+
====================================
3+
4+
.. autoexceptionsumm:: dummy.TestException

tests/test-root/test_exception.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Dummy Exception Doc
2+
===================
3+
4+
.. autoexception:: dummy.TestException

0 commit comments

Comments
 (0)