This commit is contained in:
enkore 2014-10-12 02:47:49 +02:00
parent b9662d62db
commit 9841cc65f8
4 changed files with 88 additions and 29 deletions

View File

@ -23,10 +23,11 @@ import mock
MOCK_MODULES = [ MOCK_MODULES = [
"alsaaudio", "alsaaudio",
"netifaces", "psutil", "netifaces", "psutil",
"lxml", "lxml.html", "lxml.cssselect", "lxml.html", "lxml.cssselect", "lxml",
"praw", "praw",
"gi.repository", "dbus", "gi.repository", "dbus.mainloop.glib", "dbus",
"pywapi", "basiciw" "pywapi", "basiciw",
"i3pystatus.pulseaudio.pulse"
] ]
for mod_name in MOCK_MODULES: for mod_name in MOCK_MODULES:

View File

@ -1,10 +1,15 @@
Module reference Module reference
================ ================
.. The contents of this file are automatically extended in-memory by .. autogen:: i3pystatus Module
the module_docs extension (see docs/module_docs.py).
Do not change the whitespace after the following directive.
Sincerely, your past self.
.. note:: List of all modules; .. note:: List of all modules:
.. _mailbackends:
Mail Backends
-------------
.. autogen:: i3pystatus.mail SettingsBase
.. nothin'

View File

@ -1,9 +1,17 @@
import pkgutil import pkgutil
import importlib
import sphinx.application import sphinx.application
from docutils.parsers.rst import Directive
from docutils.nodes import paragraph
from docutils.statemachine import StringList
import i3pystatus.core.settings import i3pystatus.core.settings
import i3pystatus.core.modules
from i3pystatus.core.imputil import ClassFinder
IGNORE_MODULES = ("__main__", "core")
def is_module(obj): def is_module(obj):
@ -12,7 +20,6 @@ def is_module(obj):
and not obj.__module__.startswith("i3pystatus.core.") and not obj.__module__.startswith("i3pystatus.core.")
def process_docstring(app, what, name, obj, options, lines): def process_docstring(app, what, name, obj, options, lines):
class Setting: class Setting:
doc = "" doc = ""
@ -51,8 +58,7 @@ def process_docstring(app, what, name, obj, options, lines):
return formatted return formatted
if is_module(obj) and obj.settings:
if is_module(obj):
lines.append(".. rubric:: Settings") lines.append(".. rubric:: Settings")
lines.append("") lines.append("")
@ -65,29 +71,76 @@ def process_signature(app, what, name, obj, options, signature, return_annotatio
return ("", return_annotation) return ("", return_annotation)
def source_read(app, docname, source):
ignore_modules = ("__main__", "mkdocs", "core")
def get_modules(path): def get_modules(path):
modules = [] modules = []
for finder, modname, is_pkg in pkgutil.iter_modules(path): for finder, modname, is_package in pkgutil.iter_modules(path):
if modname not in ignore_modules: if modname not in IGNORE_MODULES:
modules.append("i3pystatus." + modname) modules.append(get_module(finder, modname))
return modules return modules
if docname == "i3pystatus":
modules = sorted(get_modules(i3pystatus.__path__)) def get_module(finder, modname):
fullname = "i3pystatus.{modname}".format(modname=modname)
return (modname, finder.find_loader(fullname)[0].load_module(fullname))
def get_all(module_path, basecls):
mods = []
finder = ClassFinder(basecls)
for name, module in get_modules(module_path):
classes = finder.get_matching_classes(module)
found = []
for cls in classes:
if cls.__name__ not in found:
found.append(cls.__name__)
mods.append((module.__name__, cls.__name__))
return sorted(mods, key=lambda module: module[0])
def generate_automodules(path, basecls):
modules = get_all(path, basecls)
contents = []
for mod in modules: for mod in modules:
# sphinx seems to discard .append()ed items contents.append(" * :py:mod:`~{}`".format(mod[0]))
source[0] += " * :py:class:`~{}`\n".format(mod) contents.append("")
for mod in modules: for mod in modules:
source[0] += (".. automodule:: " + mod + "\n" + contents.append(".. automodule:: {}".format(mod[0]))
" :members:\n\n") contents.append(" :members: {}\n".format(mod[1]))
return contents
class AutogenDirective(Directive):
required_arguments = 2
has_content = True
def run(self):
# Raise an error if the directive does not have contents.
self.assert_has_content()
modname = self.arguments[0]
modpath = importlib.import_module(modname).__path__
basecls = getattr(i3pystatus.core.modules, self.arguments[1])
contents = []
for e in self.content:
contents.append(e)
contents.append("")
contents.extend(generate_automodules(modpath, basecls))
node = paragraph()
self.state.nested_parse(StringList(contents), 0, node)
return [node]
def setup(app: sphinx.application.Sphinx): def setup(app: sphinx.application.Sphinx):
app.connect("source-read", source_read)
app.add_directive("autogen", AutogenDirective)
app.connect("autodoc-process-docstring", process_docstring) app.connect("autodoc-process-docstring", process_docstring)
app.connect("autodoc-process-signature", process_signature) app.connect("autodoc-process-signature", process_signature)

View File

@ -17,7 +17,7 @@ class Mail(IntervalModule):
""" """
Generic mail checker Generic mail checker
The `backends` setting determines the backends to use. The `backends` setting determines the backends to use. For available backends see :ref:`mailbackends`
""" """
_endstring = """!!i3pystatus.mail!!""" _endstring = """!!i3pystatus.mail!!"""