Index: python-Levenshtein-0.10.1/genextdoc.py
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ python-Levenshtein-0.10.1/genextdoc.py	2008-03-29 19:00:28.182765776 +0100
@@ -0,0 +1,214 @@
+#!/usr/bin/python
+# Simple Python extension module doc generator.
+# @(#) $Id: genextdoc.py,v 1.1 2004/05/25 11:13:23 carlo Exp $
+# Written by Yeti <yeti@physics.muni.cz>
+# This program is in the public domain.
+import re, sys, types, inspect
+from cgi import escape as q
+
+args = sys.argv
+args.pop(0)
+if not args: sys.exit(0)
+
+selfcontained = False
+if args[0].startswith('-') and 'selfcontained'.startswith(args[0].strip('-')):
+    selfcontained = True
+    args.pop(0)
+if not args: sys.exit(0)
+modname = args.pop(0)
+plain_docs = args
+
+html_head = """\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head><title>%s %s</title></head>
+<body>
+"""
+
+html_foot = """\
+</body>
+</html>
+"""
+
+def split_para(doc):
+    p = []
+    for x in doc.split('\n\n'):
+        x = x.strip()
+        if x.find('\n>>>') > -1:
+            h, t = x.split('\n>>>', 1)
+            p.append(h)
+            p.append('>>>' + t)
+        else:
+            p.append(x)
+    return p
+
+def get_doc(members):
+    try: doc = members['__doc__']
+    except KeyError: pass
+    if doc: return doc
+    try: doc = 'Python module %s' % members['__name__']
+    except KeyError: pass
+    if doc: return doc
+    else: return 'A Python module'
+
+def format_synopsis(synopsis, link=False, classname=None):
+    lst = synopsis.split('\n')
+    for i, s in zip(range(len(lst)), lst):
+        m = re.match(r'(?P<func>\w+)(?P<args>.*)', s)
+        args = re.sub(r'([a-zA-Z]\w+)', r'<var>\1</var>', m.group('args'))
+        func = m.group('func')
+        if link:
+            if classname:
+                func = '<a href="#%s-%s">%s</a>' % (classname, func, func)
+            else:
+                func = '<a href="#%s">%s</a>' % (func, func)
+        lst[i] = func + args
+    return '<br/>\n'.join(lst)
+
+def format_para(p):
+    if not p: return ''
+    doc = ''
+    if p.startswith('>>>'): doc += '<pre>\n%s\n</pre>\n' % q(p)
+    else:
+        if not re.search('^- ', p, re.M): doc += '<p>%s</p>\n' % q(p)
+        else:
+            p = re.split('(?m)^- ', p)
+            if p[0]: doc += '<p>%s</p>\n' % q(p[0].strip())
+            del p[0]
+            doc += ('<ul>%s</ul>\n'
+                    % '\n'.join(['<li>%s</li>' % q(p.strip()) for p in p]))
+    return doc
+
+def preprocess_routine(name, doc):
+    parts = split_para(doc)
+    if parts: summary = parts.pop(0)
+    else: summary = 'FIXME'
+    if parts and re.match(r'\w+\(.*\)', parts[0]): synopsis = parts.pop(0)
+    else: synopsis = name + '()'
+    return {'synopsis': synopsis, 'summary': summary, 'details': parts}
+
+def analyse(obj):
+    members = obj.__dict__
+    if inspect.isclass(obj):
+        main_doc = preprocess_routine(obj.__name__, get_doc(members))
+        bases = [x.__name__ for x in obj.__bases__]
+    else:
+        main_doc = split_para(get_doc(members))
+        bases = []
+    routines = {}
+    classes = {}
+    data = {}
+    for name, m in members.items():
+        if name.startswith('__'): continue
+        try:
+            mro = list(inspect.getmro(m))
+            if mro[0] != m: continue
+        except AttributeError: pass
+        if inspect.isroutine(m):
+            try: doc = m.__doc__
+            except KeyError: pass
+            if not doc: doc = 'FIXME'
+            routines[name] = preprocess_routine(name, doc)
+            continue
+        if inspect.isclass(m):
+            classes[name] = analyse(m)
+            continue
+        t = type(m)
+        if t == types.IntType or t == types.StringType:
+            data[name] = repr(m)
+        else:
+            data[name] = m.__doc__
+    return {'name': obj.__name__, 'doc': main_doc, 'routines': routines,
+            'classes': classes, 'data': data, 'bases': bases}
+
+def format(tree, level, prefix=''):
+    name = tree['name']
+    if prefix: fullname = '%s-%s' % (prefix, name)
+    else: fullname = name
+    ##### Main doc
+    doc = []
+    if level > 1:
+        doc = ['<h%d id="%s">' % (level, fullname)]
+        try: doc.append(format_synopsis(tree['doc']['synopsis']))
+        except TypeError:
+            doc.append(name)
+        doc.append('</h%d>\n' % level)
+        if tree.has_key('bases'):
+            doc.append('<p>Bases: %s.</p>\n' % ', '.join(tree['bases']))
+    try: lst = [tree['doc']['summary']] + tree['doc']['details']
+    except TypeError: lst = tree['doc']
+    for p in lst: doc.append(format_para(p))
+    ##### Table of contents
+    routines = tree['routines'].keys()
+    classes = tree['classes'].keys()
+    data = tree['data'].keys()
+    if routines:
+        routines.sort()
+        if level == 1: doc.append('<p><b>Functions:</b></p>\n')
+        else: doc.append('<p><b>Methods:</b></p>\n')
+        doc.append('<ul class="ltoc">\n')
+        for r in routines:
+            synopsis = tree['routines'][r]['synopsis']
+            doc.append('<li>%s</li>\n' % format_synopsis(synopsis, True,
+                                                         fullname))
+        doc.append('</ul>\n')
+    if classes:
+        classes.sort()
+        doc.append('<p><b>Classes:</b></p>\n')
+        doc.append('<ul class="ltoc">\n')
+        for r in classes:
+            synopsis = tree['classes'][r]['doc']['synopsis']
+            doc.append('<li>%s</li>\n' % format_synopsis(synopsis, True,
+                                                         fullname))
+        doc.append('</ul>\n')
+    if data:
+        data.sort()
+        doc.append('<p><b>Data:</b></p>\n')
+        doc.append('<ul class="ltoc">\n')
+        for r in data:
+            doc.append('<li>%s = %s</li>\n' % (r, q(tree['data'][r])))
+        doc.append('</ul>\n')
+    ##### Functions
+    if routines:
+        if level == 1: doc.append('<hr/>\n')
+        doc.append('<dl>\n')
+        for r in routines:
+            doc.append('<dt id="%s-%s">' % (fullname, r))
+            rt = tree['routines'][r]
+            doc.append('%s</dt>\n<dd>' % format_synopsis(rt['synopsis']))
+            for p in [rt['summary']] + rt['details']:
+                doc.append(format_para(p))
+            doc.append('</dd>\n')
+        doc.append('</dl>\n')
+    ##### Classes
+    if classes:
+        for r in classes:
+            doc.append('<hr/>\n')
+            doc.append(format(tree['classes'][r], level+1, fullname))
+    return ''.join(doc)
+
+exec 'import %s as __test__' % modname
+doctree = analyse(__test__)
+document = format(doctree, 1)
+print modname + '.html'
+fh = file(modname + '.html', 'w')
+if selfcontained: fh.write(html_head % (modname, 'module API'))
+fh.write(document)
+if selfcontained: fh.write(html_foot)
+fh.close()
+for f in plain_docs:
+    try: fh = file(f, 'r')
+    except: continue
+    document = fh.read()
+    fh.close()
+    print f + '.xhtml'
+    fh = file(f + '.xhtml', 'w')
+    if selfcontained: fh.write(html_head % (modname, f))
+    fh.write('<h1>%s %s</h1>\n\n' % (modname, f))
+    fh.write('<pre class="main">\n')
+    fh.write(document)
+    fh.write('</pre>\n')
+    if selfcontained: fh.write(html_foot)
+    fh.close()
