#!/usr/local/bin/python2.3 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=""" """ FOOTER=""" """ 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=" \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+=" \n" return ret def format_class(self,link): name=link.name() uid=link.target() doc=self.docmap[uid] descr=doc.descr() ret=(" \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+=" \n" for base in doc.bases(): buid=base.target() g=(" " % (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 (" \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 (" \n" % (escape(uid),escape(name),vis,descr,st)) main(sys.argv[1:]) # vi: sts=4 et sw=4