Convert other enums to int for Python 2.5 (Stephen Watson).
[rox-lib/lack.git] / python / make_docs.py
blob8bea2c285fc68fe8ce236a00aba11dd34373592f
1 #!/usr/bin/env python
3 import pydoc
4 from pydoc import *
5 import inspect
7 import sys, os
8 sys.path.insert(0, os.path.abspath(os.getcwd()))
10 try:
11 os.mkdir('../Help/python')
12 except OSError:
13 pass
15 # Ignore names starting with _
16 old_get = inspect.getmembers
17 def get(object, pred):
18 return [(n,v) for (n,v) in old_get(object, pred) if not n.startswith('_')]
19 inspect.getmembers = get
21 class MyHtml(pydoc.HTMLDoc):
22 def docmodule(self, object, name=None, mod=None, *ignored):
23 """Produce HTML documentation for a module object."""
24 name = object.__name__ # ignore the passed-in name
25 parts = split(name, '.')
26 links = []
27 for i in range(len(parts)-1):
28 links.append(
29 '<a href="%s.html"><font color="#ffffff">%s</font></a>' %
30 (join(parts[:i+1], '.'), parts[i]))
31 linkedname = join(links + parts[-1:], '.')
32 head = '<big><big><strong>%s</strong></big></big>' % linkedname
33 info = []
34 if hasattr(object, '__version__'):
35 version = str(object.__version__)
36 if version[:11] == '$' + 'Revision: ' and version[-1:] == '$':
37 version = strip(version[11:-1])
38 info.append('version %s' % self.escape(version))
39 if hasattr(object, '__date__'):
40 info.append(self.escape(str(object.__date__)))
41 if info:
42 head = head + ' (%s)' % join(info, ', ')
43 result = self.heading(
44 head, '#ffffff', '#7799ee', '<a href="rox.html">index</a><br>')
46 modules = inspect.getmembers(object, inspect.ismodule)
48 classes, cdict = [], {}
49 for key, value in inspect.getmembers(object, inspect.isclass):
50 if (inspect.getmodule(value) or object) is object:
51 classes.append((key, value))
52 cdict[key] = cdict[value] = '#' + key
53 for key, value in classes:
54 for base in value.__bases__:
55 key, modname = base.__name__, base.__module__
56 module = sys.modules.get(modname)
57 if modname != name and module and hasattr(module, key):
58 if getattr(module, key) is base:
59 if not cdict.has_key(key):
60 cdict[key] = cdict[base] = modname + '.html#' + key
61 funcs, fdict = [], {}
62 for key, value in inspect.getmembers(object, inspect.isroutine):
63 if inspect.isbuiltin(value) or inspect.getmodule(value) is object:
64 funcs.append((key, value))
65 fdict[key] = '#-' + key
66 if inspect.isfunction(value): fdict[value] = fdict[key]
68 doc = self.markup(getdoc(object), self.preformat, fdict, cdict)
69 doc = doc and '<tt>%s</tt>' % doc
70 result = result + '<p>%s</p>\n' % doc
72 if hasattr(object, '__path__'):
73 modpkgs = []
74 modnames = []
75 for file in os.listdir(object.__path__[0]):
76 if file.startswith('_'):
77 continue
78 path = os.path.join(object.__path__[0], file)
79 modname = inspect.getmodulename(file)
80 if modname and modname not in modnames:
81 modpkgs.append((modname, name, 0, 0))
82 modnames.append(modname)
83 elif ispackage(path):
84 modpkgs.append((file, name, 1, 0))
85 modpkgs.sort()
86 contents = self.multicolumn(modpkgs, self.modpkglink)
87 result = result + self.bigsection(
88 'Package Contents', '#ffffff', '#aa55cc', contents)
90 if classes:
91 classlist = map(lambda (key, value): value, classes)
92 contents = [
93 self.formattree(inspect.getclasstree(classlist, 1), name)]
94 for key, value in classes:
95 contents.append(self.document(value, key, name, fdict, cdict))
96 result = result + self.bigsection(
97 'Classes', '#ffffff', '#ee77aa', join(contents))
98 if funcs:
99 contents = []
100 for key, value in funcs:
101 contents.append(self.document(value, key, name, fdict, cdict))
102 result = result + self.bigsection(
103 'Functions', '#ffffff', '#eeaa77', join(contents))
104 if hasattr(object, '__author__'):
105 contents = self.markup(str(object.__author__), self.preformat)
106 result = result + self.bigsection(
107 'Author', '#ffffff', '#7799ee', contents)
108 if hasattr(object, '__credits__'):
109 contents = self.markup(str(object.__credits__), self.preformat)
110 result = result + self.bigsection(
111 'Credits', '#ffffff', '#7799ee', contents)
113 return result
115 def docclass(self, object, name=None, mod=None, funcs={}, classes={},
116 *ignored):
117 """Produce HTML documentation for a class object."""
118 realname = object.__name__
119 name = name or realname
120 bases = object.__bases__
122 contents = []
123 push = contents.append
125 # Cute little class to pump out a horizontal rule between sections.
126 class HorizontalRule:
127 def __init__(self):
128 self.needone = 0
129 def maybe(self):
130 if self.needone:
131 push('<hr>\n')
132 self.needone = 1
133 hr = HorizontalRule()
135 mro = list(inspect.getmro(object))
137 def spill(msg, attrs, predicate):
138 ok, attrs = pydoc._split_list(attrs, predicate)
139 if ok:
140 hr.maybe()
141 push(msg)
142 for name, kind, homecls, value in ok:
143 if name.startswith('_') and name is not '__init__':
144 continue
145 push(self.document(getattr(object, name), name, mod,
146 funcs, classes, mdict, object))
147 push('\n')
148 return attrs
150 def spillproperties(msg, attrs, predicate):
151 ok, attrs = pydoc._split_list(attrs, predicate)
152 if ok:
153 hr.maybe()
154 push(msg)
155 for name, kind, homecls, value in ok:
156 push('<dl><dt><strong>%s</strong></dt>\n' % name)
157 if value.__doc__ is not None:
158 doc = self.markup(value.__doc__, self.preformat,
159 funcs, classes, mdict)
160 push('<dd><tt>%s</tt></dd>\n' % doc)
161 for attr, tag in [("fget", " getter"),
162 ("fset", " setter"),
163 ("fdel", " deleter")]:
164 func = getattr(value, attr)
165 if func is not None:
166 base = self.document(func, name + tag, mod,
167 funcs, classes, mdict, object)
168 push('<dd>%s</dd>\n' % base)
169 push('</dl>\n')
170 return attrs
172 def spilldata(msg, attrs, predicate):
173 ok, attrs = pydoc._split_list(attrs, predicate)
174 if ok:
175 hr.maybe()
176 push(msg)
177 for name, kind, homecls, value in ok:
178 base = self.docother(getattr(object, name), name, mod)
179 doc = getattr(value, "__doc__", None)
180 if doc is None:
181 push('<dl><dt>%s</dl>\n' % base)
182 else:
183 doc = self.markup(getdoc(value), self.preformat,
184 funcs, classes, mdict)
185 doc = '<dd><tt>%s</tt>' % doc
186 push('<dl><dt>%s%s</dl>\n' % (base, doc))
187 push('\n')
188 return attrs
190 attrs = inspect.classify_class_attrs(object)
191 mdict = {}
192 for key, kind, homecls, value in attrs:
193 mdict[key] = anchor = '#' + name + '-' + key
194 value = getattr(object, key)
195 try:
196 # The value may not be hashable (e.g., a data attr with
197 # a dict or list value).
198 mdict[value] = anchor
199 except TypeError:
200 pass
202 while attrs:
203 if mro:
204 thisclass = mro.pop(0)
205 else:
206 thisclass = attrs[0][2]
207 attrs, inherited = pydoc._split_list(attrs, lambda t: t[2] is thisclass)
209 if thisclass is object:
210 tag = "defined here"
211 else:
212 tag = "inherited from %s" % self.classlink(thisclass,
213 object.__module__)
214 tag += ':<br>\n'
216 # Sort attrs by name.
217 attrs.sort(lambda t1, t2: cmp(t1[0], t2[0]))
219 # Pump out the attrs, segregated by kind.
220 attrs = spill("Methods %s" % tag, attrs,
221 lambda t: t[1] == 'method')
222 attrs = spill("Class methods %s" % tag, attrs,
223 lambda t: t[1] == 'class method')
224 attrs = spill("Static methods %s" % tag, attrs,
225 lambda t: t[1] == 'static method')
226 attrs = spillproperties("Properties %s" % tag, attrs,
227 lambda t: t[1] == 'property')
228 #attrs = spilldata("Data and non-method functions %s" % tag, attrs,
229 # lambda t: t[1] == 'data')
230 #assert attrs == []
231 attrs = None
233 contents = ''.join(contents)
235 if name == realname:
236 title = '<a name="%s">class <strong>%s</strong></a>' % (
237 name, realname)
238 else:
239 title = '<strong>%s</strong> = <a name="%s">class %s</a>' % (
240 name, name, realname)
241 if bases:
242 parents = []
243 for base in bases:
244 parents.append(self.classlink(base, object.__module__))
245 title = title + '(%s)' % join(parents, ', ')
246 doc = self.markup(getdoc(object), self.preformat, funcs, classes, mdict)
247 doc = doc and '<tt>%s<br>&nbsp;</tt>' % doc or '&nbsp;'
249 return self.section(title, '#000000', '#ffc8d8', contents, 5, doc)
252 pydoc.html = MyHtml()
254 files = os.listdir('rox')
255 os.chdir('../Help/python')
257 pydoc.writedoc('rox')
258 for file in files:
259 if not file.startswith('_') and file.endswith('.py'):
260 pydoc.writedoc('rox.' + file[:-3])