#!/usr/bin/python3 # # Copyright(c) 2017 Daniel Knüttel # # This program is free software. # Anyways if you think this program is worth it # and we meet shout a drink for me. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # # Dieses Programm ist Freie Software: Sie können es unter den Bedingungen # der GNU Affero General Public License, wie von der Free Software Foundation, # Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren # veröffentlichten Version, weiterverbreiten und/oder modifizieren. # # Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber # OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite # Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. # Siehe die GNU Affero General Public License für weitere Details. # # Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem # Programm erhalten haben. Wenn nicht, siehe . """ alldoc -- extract reStructuredText docstrings from all sourcefiles. This does include non-python files/languages. Invoke alldoc using :: python3 alldoc.py {} """ import logging # logging.basicConfig(level = logging.DEBUG) logging.basicConfig() start_alldoc = [ "", "", "startdoc", "SDOC"] stop_alldoc = ["", "", "stopdoc", "EDOC"] def indexof(str_, substr): """ This is handy if you want to get the next substr. """ try: return str_.index(substr) except: return float("inf") def extract_docs(str_, start_alldoc = start_alldoc, stop_alldoc = stop_alldoc): """ Extract all docstrings starting with ``start_alldoc`` and stopping with ``stop_alldoc``. For instance: :: /* This is a docstring */ """ lines_done = 0 while(1): next_doc_start, start = min([(indexof(str_, start), start) for start in start_alldoc]) if(next_doc_start == float("inf")): logging.debug("no more docstrings found in line "+ str(lines_done)) break logging.debug("found docstart " + start) unused, str_ = str_[:next_doc_start], str_[next_doc_start + len(start):] lines_done += unused.count("\n") logging.debug("docstart is in " + str(lines_done)) doc_stop, token = min([(indexof(str_, stop), stop) for stop in stop_alldoc]) if(doc_stop == float("inf")): raise ExtractException("unterminated docstart: " + start + " in line " + str(lines_done)) doc, str_ = str_[:doc_stop], str_[doc_stop + len(token):] logging.debug("found docstop " + token) yield doc lines_done += doc.count("\n") logging.debug("docstop is in " + str(lines_done)) def docs_from_file(path, delim = "\n\n"): """ Read all docstrings from one file. """ with open(path) as f: logging.debug("reading file " + path) str_ = f.read() docs = delim.join(extract_docs(str_)) f.close() return docs def collect_docs(files, delim = "\n\n"): """ Read all docstrings from multiple files """ for file_ in files: yield docs_from_file(file_, delim) def generate_rst_head(str_, underscore = "="): """ Generate a rst Heading. """ return str_ + "\n" + underscore * len(str_) + "\n" def generate_docfile(fname, files, delim = "\n\n", add_rst_head = True): """ Read all docstrings and output one file. FIXME: try to spend less memory. """ f = open(fname, "w") f.write("".join(["".join(t) for t in zip([generate_rst_head(file) for file in files] , collect_docs(files))])) f.close() class ExtractException(Exception): def __init__(self, *args): Exception.__init__(self, *args) if __name__ == "__main__": import sys if(len(sys.argv) < 3): print("Usage:", sys.argv[0], "outfile infile {infile}") print("extract docstrings from non-python files") print("start tokens: ", start_alldoc) print("stop tokens: ", stop_alldoc) sys.exit(1) outfile = sys.argv[1] infiles = sys.argv[2:] try: generate_docfile(outfile, infiles) except Exception as e: print("Error:", e) sys.exit(1)