Source code for zsl.utils.deploy.apiari_doc_generator

"""
:mod:`zsl.utils.deploy.apiary_doc_generator`
--------------------------------------------

Generates the API documentation suitable for the apiary.io. It parses all the files and finds the apiary.io definitions
in the documentary comments. Then outputs it to a file.

.. moduleauthor:: Martin Babka
"""
import importlib
import inspect
import logging
import os
import pkgutil
import pydoc
import sys

from zsl import inject
from zsl.router.method import get_method_packages
from zsl.router.task import TaskRouter


[docs] class ApiaryDoc(pydoc.Doc): _API_DOC_STR = "API Documentation:" def __init__(self): self._docs = [] self._done = set() @staticmethod def _get_obj_id(obj): if hasattr(obj, '__path__'): return obj.__path__[0] if hasattr(obj, '__file__'): return obj.__file__ if hasattr(obj, '__name__'): return obj.__name__ else: return obj def _add_doc(self, obj): obj_id = self._get_obj_id(obj) if obj_id in self._done: return logging.debug('Adding {0}.'.format(obj_id)) self._done.add(obj_id) apistr = "" try: if obj.__doc__ is None: return start = obj.__doc__.find(self._API_DOC_STR) if start == -1: return apistr = obj.__doc__[start + len(self._API_DOC_STR):] except: # NOQA return apistr = apistr.splitlines() while apistr[0].isspace() or apistr[0] == "": apistr = apistr[1:] def white_space_at_beginning(l): c = 0 i = 0 length = len(l) while i < length: if l[i].isspace(): c += 1 else: return c i += 1 return c m = white_space_at_beginning(apistr[0]) for char in apistr: if char.isspace() or char == "": continue wl = white_space_at_beginning(char) if m > wl: m = wl apistr = [x[m:] for x in apistr] self._docs.append("\n".join(apistr))
[docs] def docmodule(self, obj, name=None, *args): if self._get_obj_id(obj) in self._done: return self._add_doc(obj) for _key, value in inspect.getmembers(obj, inspect.isclass): self._add_doc(value) for _key, value in inspect.getmembers(obj, lambda x: hasattr(x, '__call__')): self._add_doc(value) for _key, value in inspect.getmembers(obj, inspect.ismodule): self.docmodule(value) if not hasattr(obj, '__path__'): return if obj.__path__[0].startswith(os.path.dirname(sys.executable)): return for loader, module_name, _ispkg in pkgutil.iter_modules(obj.__path__): logging.debug("Loading module {0} in {1}.".format(module_name, obj.__path__)) try: module = loader.find_module(module_name).load_module(module_name) self.docmodule(module) except: # NOQA pass
[docs] def get_doc(self): return "FORMAT: 1A\n\n" + "\n\n".join(self._docs)
[docs] @inject(task_router=TaskRouter) def generate_apiary_doc(task_router): """Generate apiary documentation. Create a Apiary generator and add application packages to it. :param task_router: task router, injected :type task_router: TaskRouter :return: apiary generator :rtype: ApiaryDoc """ generator = ApiaryDoc() for m in task_router.get_task_packages() + get_method_packages(): m = importlib.import_module(m) generator.docmodule(m) return generator