# # Generates the dynamic parts of the ZeekControl documentation. # import inspect def api(*deco_args): if len(deco_args) == 1 and callable(deco_args[0]): # No argument to decorator. method = deco_args[0] method._doc = "" return method else: # Tag argument. def _api(method): method._doc = deco_args[0] return method return _api def print_indented(text, level): out = "" if not isinstance(text, list): text = text.splitlines() for line in text: if line: out += "{} {}\n".format(" " * level, line) else: out += "\n" out += "\n" return out # Prints API documentation for a class. Includes all methods tagged with # @api(tag). (Use an unknown tag to not exclude all methods.) If header is # False, the class's name and doc string is not included. def print_class(cls, tag="", header=True): out = "" methods = {} for key, val in cls.__dict__.items(): if not inspect.isfunction(val): continue if not "_doc" in val.__dict__: continue if val.__dict__["_doc"] == tag: methods[key] = val if header: out += f".. _{cls.__name__}:\n\n" out += f"Class ``{cls.__name__}``\n" out += "~~~~~~~~%s~~" % ("~" * len(cls.__name__)) out += "\n\n" out += f"class **{cls.__name__}**\n" out += print_indented(inspect.getdoc(cls), 1) for name in sorted(methods.keys()): func = methods[name] spec = inspect.getfullargspec(func) out += print_indented(f".. _{cls.__name__}.{name}:", 1) out += print_indented("**{}** ({})".format(name, ", ".join(spec.args)), 1) out += print_indented(inspect.getdoc(func), 2) return out