import sys assert sys.version_info[0] == 3, "This program requires Python 3" import re import doctest from io import StringIO import bitarray import bitarray.util BASE_URL = "https://github.com/ilanschnell/bitarray" sig_pat = re.compile(r'(\w+\([^()]*\))( -> (.+))?') def write_doc(fo, name): doc = eval('bitarray.%s.__doc__' % name) assert doc, name lines = doc.splitlines() m = sig_pat.match(lines[0]) if m is None: raise Exception("signature line invalid: %r" % lines[0]) s = '``%s``' % m.group(1) if m.group(3): s += ' -> %s' % m.group(3) fo.write('%s\n' % s) assert lines[1] == '' for line in lines[2:]: out = line.rstrip() fo.write(" %s\n" % out.replace('`', '``') if out else "\n") fo.write('\n\n') def write_reference(fo): fo.write("""\ Reference ========= bitarray version: %s -- `change log <%s>`__ In the following, ``item`` and ``value`` are usually a single bit - an integer 0 or 1. The bitarray object: -------------------- """ % (bitarray.__version__, "%s/blob/master/doc/changelog.rst" % BASE_URL)) write_doc(fo, 'bitarray') fo.write("**A bitarray object supports the following methods:**\n\n") for method in sorted(dir(bitarray.bitarray)): if method.startswith('_'): continue write_doc(fo, 'bitarray.%s' % method) fo.write("Other objects:\n" "--------------\n\n") write_doc(fo, 'frozenbitarray') write_doc(fo, 'decodetree') fo.write("Functions defined in the `bitarray` module:\n" "-------------------------------------------\n\n") for func in sorted(['test', 'bits2bytes', 'get_default_endian']): write_doc(fo, func) fo.write("Functions defined in `bitarray.util` module:\n" "--------------------------------------------\n\n") for func in bitarray.util.__all__: write_doc(fo, 'util.%s' % func) def update_readme(path): ver_pat = re.compile(r'(bitarray.+?)(\d+\.\d+\.\d+)') with open(path, 'r') as fi: data = fi.read() with StringIO() as fo: for line in data.splitlines(): if line == 'Reference': break line = ver_pat.sub(lambda m: m.group(1) + bitarray.__version__, line) fo.write("%s\n" % line.rstrip()) write_reference(fo) new_data = fo.getvalue() if new_data == data: print("already up-to-date") else: with open(path, 'w') as f: f.write(new_data) def write_changelog(fo): ver_pat = re.compile(r'(\d{4}-\d{2}-\d{2})\s+(\d+\.\d+\.\d+)') issue_pat = re.compile(r'#(\d+)') link_pat = re.compile(r'\[(.+)\]\((.+)\)') def issue_replace(match): url = "%s/issues/%s" % (BASE_URL, match.group(1)) return "`%s <%s>`__" % (match.group(0), url) fo.write("Change log\n" "==========\n\n") for line in open('./CHANGE_LOG'): line = line.rstrip() match = ver_pat.match(line) if match: line = match.expand(r'**\2** (\1):') elif line.startswith('-----'): line = '' elif line.startswith(' '): line = line[2:] line = line.replace('`', '``') line = issue_pat.sub(issue_replace, line) line = link_pat.sub( lambda m: "`%s <%s>`__" % (m.group(1), m.group(2)), line) fo.write(line + '\n') def main(): if len(sys.argv) > 1: sys.exit("no arguments expected") update_readme('./README.rst') with open('./doc/reference.rst', 'w') as fo: write_reference(fo) with open('./doc/changelog.rst', 'w') as fo: write_changelog(fo) doctest.testfile('./README.rst') doctest.testfile('./doc/represent.rst') if __name__ == '__main__': main()