1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
#!/usr/bin/python
import os,sys
def main(module_list):
options = {'target':None, 'modules':list(module_list), 'verbosity':1,
'prj_name':'', 'action':'html', 'tests':{'basic':1},
'show_imports':0, 'frames':1, 'private':None,
'list_classes_separately': 0, 'debug':0,
'docformat':None, 'top':None, 'inheritance': None,
'ignore_param_mismatch': 0, 'alphabetical': 1}
modules=_import(options['modules'],1)
# Record the order of the modules in options.
from epydoc.uid import make_uid
muids = []
for m in modules:
try:
muids.append(make_uid(m))
except:
raise
if sys.stderr.softspace: print >>sys.stderr
print >>sys.stderr, 'Failed to create a UID for %s' % m
# Build their documentation
docmap = _make_docmap(modules, options)
f=Formatter(docmap)
print f.format(module_list)
def escape(s):
return str(s).replace('&','&').replace('<','<').replace('>','>').replace('"','"').replace("'",''')
class _Progress:
"""
The progress meter that is used by C{cli} to report its progress.
It prints the status to C{stderrr}. Depending on the verbosity,
setting it will produce different outputs.
To update the progress meter, call C{report} with the name of the
object that is about to be processed.
"""
def __init__(self, action, verbosity, total_items, html_file=0):
"""
Create a new progress meter.
@param action: A string indicating what action is performed on
each objcet. Examples are C{"writing"} and C{"building
docs for"}.
@param verbosity: The verbosity level. This controls what the
progress meter output looks like.
@param total_items: The total number of items that will be
processed with this progress meter. This is used to let
the user know how much progress epydoc has made.
@param html_file: Whether to assume that arguments are html
file names, and munge them appropriately.
"""
self._action = action
self._verbosity = verbosity
self._total_items = total_items
self._item_num = 1
self._html_file = 0
def report(self, argument):
"""
Update the progress meter.
@param argument: The object that is about to be processed.
"""
if self._verbosity <= 0: return
if self._verbosity==1:
if self._item_num == 1 and self._total_items <= 70:
sys.stderr.write(' [')
if (self._item_num % 60) == 1 and self._total_items > 70:
sys.stderr.write(' [%3d%%] ' %
(100.0*self._item_num/self._total_items))
sys.stderr.write('.')
sys.stderr.softspace = 1
if (self._item_num % 60) == 0 and self._total_items > 70:
print >>sys.stderr
if self._item_num == self._total_items:
if self._total_items <= 70: sys.stderr.write(']')
print >>sys.stderr
elif self._verbosity>1:
TRACE_FORMAT = ((' [%%%dd/%d]' % (len(`self._total_items`),
self._total_items))+
' %s %%s' % self._action)
if self._html_file:
(dir, file) = os.path.split(argument)
(root, d) = os.path.split(dir)
if d in ('public', 'private'):
argument = os.path.join(d, file)
else:
fname = argument
print >>sys.stderr, TRACE_FORMAT % (self._item_num, argument)
self._item_num += 1
def _import(module_names, verbosity):
"""
@return: A list of the modules contained in the given files.
Duplicates are removed. Order is preserved.
@rtype: C{list} of C{module}
@param module_names: The list of module filenames.
@type module_names: C{list} of C{string}
@param verbosity: Verbosity level for tracing output.
@type verbosity: C{int}
"""
from epydoc.imports import import_module, find_modules
# First, expand packages.
for name in module_names[:]:
if os.path.isdir(name):
# In-place replacement.
index = module_names.index(name)
new_modules = find_modules(name)
if new_modules:
module_names[index:index+1] = new_modules
elif verbosity >= 0:
if sys.stderr.softspace: print >>sys.stderr
print >>sys.stderr, 'Error: %r is not a pacakge' % name
if verbosity > 0:
print >>sys.stderr, 'Importing %s modules.' % len(module_names)
modules = []
progress = _Progress('Importing', verbosity, len(module_names))
for name in module_names:
progress.report(name)
# Import the module, and add it to the list.
try:
module = import_module(name)
if module not in modules: modules.append(module)
elif verbosity > 2:
if sys.stderr.softspace: print >>sys.stderr
print >>sys.stderr, ' (duplicate)'
except ImportError, e:
if verbosity >= 0:
if sys.stderr.softspace: print >>sys.stderr
print >>sys.stderr, e
if len(modules) == 0:
print >>sys.stderr, '\nError: no modules successfully loaded!'
sys.exit(1)
return modules
def _make_docmap(modules, options):
"""
Construct the documentation map for the given modules.
@param modules: The modules that should be documented.
@type modules: C{list} of C{Module}
@param options: Options from the command-line arguments.
@type options: C{dict}
"""
from epydoc.objdoc import DocMap, report_param_mismatches
verbosity = options['verbosity']
document_bases = 1
document_autogen_vars = 1
inheritance_groups = (options['inheritance'] == 'grouped')
inherit_groups = (options['inheritance'] != 'grouped')
d = DocMap(verbosity, document_bases, document_autogen_vars,
inheritance_groups, inherit_groups)
if options['verbosity'] > 0:
print >>sys.stderr, ('Building API documentation for %d modules.'
% len(modules))
progress = _Progress('Building docs for', verbosity, len(modules))
for module in modules:
progress.report(module.__name__)
# Add the module. Catch any exceptions that get generated.
try: d.add(module)
except Exception, e:
if options['debug']: raise
else: _internal_error(e)
except:
if options['debug']: raise
else: _internal_error()
if not options['ignore_param_mismatch']:
if not report_param_mismatches(d):
estr = ' (To supress these warnings, '
estr += 'use --ignore-param-mismatch)'
print >>sys.stderr, estr
return d
HEADER="""<?xml version="1.0" encoding="utf-8" ?>
<XMI xmi.version="1.1" xmlns:UML="org.omg/standards/UML">
<XMI.header>
<XMI.metamodel name="UML" version="1.3" href="UML.xml"/>
<XMI.model name="PyXMPP" href="pyxmpp.xml"/>
</XMI.header>
<XMI.content>
<UML:Model>
<UML:Stereotype visibility="public" xmi.id="/Stereotype:classmethod" name="classmethod" />
<UML:Stereotype visibility="public" xmi.id="/Stereotype:staticmethod" name="staticmethod" />
"""
FOOTER="""
</UML:Model>
</XMI.content>
</XMI>"""
class Formatter:
def __init__(self,docmap):
self.docmap=docmap
def format(self,modules=None):
self.generalizations=[]
ret=HEADER
if modules:
from epydoc.uid import findUID
for m in modules:
uid=findUID(m)
if uid.is_module():
print >>sys.stderr,"Formatting: %s\n" % (uid,)
ret+=self.format_module(uid,True)
else:
print >>sys.stderr,"Skipping: %s (not a module)\n" % (uid,)
else:
decorated = [(u.name().lower(), u) for u in self.docmap.keys() if u.is_module()]
decorated.sort()
uids = [d[-1] for d in decorated]
for uid in uids:
if uid.is_module():
ret+=self.format_module(uid,False)
ret+="\n".join(self.generalizations)+"\n"
ret+=FOOTER
return ret
def format_module(self,uid,recursive):
if recursive:
name=uid.shortname()
else:
name=uid.name()
ret=" <UML:Package xmi.id='%s' name='%s'>\n" % (escape(uid),escape(name))
doc=self.docmap[uid]
classes=doc.classes()
for cls in classes:
ret+=self.format_class(cls)
if recursive and uid.is_package():
modules=doc.modules()
for mod in modules:
ret+=self.format_module(mod.target(),True)
ret+=" </UML:Package>\n"
return ret
def format_class(self,link):
name=link.name()
uid=link.target()
doc=self.docmap[uid]
descr=doc.descr()
ret=(" <UML:Class xmi.id='%s' name='%s' comment='%s'>\n"
% (escape(uid),escape(name),escape(descr.to_plaintext(None))))
for meth in doc.allmethods():
ret+=self.format_method(meth,doc)
for att in doc.ivariables():
ret+=self.format_attribute(att,doc)
ret+=" </UML:Class>\n"
for base in doc.bases():
buid=base.target()
g=(" <UML:Generalization xmi.id='%s(%s)'"
" child='%s' parent='%s' visibility='public'/>"
% (escape(uid),escape(buid),escape(uid),escape(buid)))
self.generalizations.append(g)
return ret
def format_attribute(self,var,container):
uid=var.uid()
name=var.name()
descr=var.descr()
cuid = container.uid()
inherited = (cuid.is_class() and uid.cls() != cuid)
if inherited:
return ""
if descr:
descr=" comment='%s'" % (escape(descr.to_plaintext(None)),)
else:
descr=""
if uid.is_public():
vis=" visibility='public'"
else:
vis=" visibility='private'"
return (" <UML:Attribute xmi.id='%s' name='%s' %s%s />\n" %
(escape(uid),escape(name),vis,descr))
def format_method(self,link,container):
uid=link.target()
name=link.name()
doc=self.docmap[uid]
descr=doc.descr()
cuid = container.uid()
inherited = (cuid.is_class() and uid.cls() != cuid)
if inherited:
return ""
if name.startswith("__") and not descr:
# ignore special/private methods without description
return ""
if doc is not None and uid.is_any_method() and not doc.has_docstring():
doc = self.docmap.documented_ancestor(uid) or doc
if descr:
descr=" comment='%s'" % (escape(descr.to_plaintext(None)),)
else:
descr=""
if uid.is_public():
vis=" visibility='public'"
else:
vis=" visibility='private'"
if uid.is_classmethod():
st=" stereotype='/Stereotype:classmethod'"
elif uid.is_staticmethod():
st=" stereotype='/Stereotype:staticmethod'"
else:
st=""
return (" <UML:Operation xmi.id='%s' name='%s' %s%s%s />\n" %
(escape(uid),escape(name),vis,descr,st))
main(sys.argv[1:])
# vi: sts=4 et sw=4
|