1"""
2cloud_sptheme.ext.autoattribute_search_bases -- monkeypatches autodoc so ``autoattribute`` searches base classes for attr doc.
3"""
4#=============================================================================
5# imports
6#=============================================================================
7# core
8import logging; log = logging.getLogger(__name__)
9# site
10# pkg
11from cloud_sptheme import __version__
12from cloud_sptheme.utils import patchapplier, monkeypatch
13# local
14__all__ = [
15    "setup",
16]
17
18#=============================================================================
19# patch
20#=============================================================================
21@patchapplier
22def _patch_autoattribute():
23    from sphinx.ext.autodoc import AttributeDocumenter, ModuleAnalyzer, PycodeError
24
25    @monkeypatch(AttributeDocumenter)
26    def add_content(_wrapped, self, *args, **kwds):
27        if not self._datadescriptor and self.analyzer and self.objpath:
28            attr_docs = self.analyzer.find_attr_docs()
29            key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
30            if key not in attr_docs:
31                # look for parent class w/ correct attr
32                if hasattr(self.parent, "__mro__"):
33                    for basecls in self.parent.__mro__[1:]:
34                        try:
35                            analyzer = ModuleAnalyzer.for_module(basecls.__module__)
36                            base_attr_docs = analyzer.find_attr_docs()
37                        except PycodeError as err:
38                            continue
39                        # FIXME: need qualname or equivalent for basecls
40                        base_key = (basecls.__name__, self.objpath[-1])
41                        if base_key in base_attr_docs:
42                            # insert data into existing analyzer
43                            # XXX: might be prettier way to handle this,
44                            #      (esp so actual source file was reported)
45                            #      but would have to duplicate much of add_content()
46                            attr_docs[key] = base_attr_docs[base_key]
47                            break
48        return _wrapped(self, *args, **kwds)
49
50#=============================================================================
51# sphinx entry point
52#=============================================================================
53def setup(app):
54    # don't apply our patch unless actually loaded by sphinx
55    _patch_autoattribute()
56
57    # identifies the version of our extension
58    return {'version': __version__}
59
60#=============================================================================
61# eoc
62#=============================================================================
63