# epydoc -- Plaintext output generation # # Copyright (C) 2005 Edward Loper # Author: Edward Loper # URL: # # $Id: plaintext.py 1473 2007-02-13 19:46:05Z edloper $ """ Plaintext output generation. """ __docformat__ = 'epytext en' from epydoc.apidoc import * import re class PlaintextWriter: def write(self, api_doc, **options): result = [] out = result.append self._cols = options.get('cols', 75) try: if isinstance(api_doc, ModuleDoc): self.write_module(out, api_doc) elif isinstance(api_doc, ClassDoc): self.write_class(out, api_doc) elif isinstance(api_doc, RoutineDoc): self.write_function(out, api_doc) else: assert 0, ('%s not handled yet' % api_doc.__class__) except Exception, e: print '\n\n' print ''.join(result) raise return ''.join(result) def write_module(self, out, mod_doc): #for n,v in mod_doc.variables.items(): # print n, `v.value`, `v.value.value` # The cannonical name of the module. out(self.section('Module Name')) out(' %s\n\n' % mod_doc.canonical_name) # The module's description. if mod_doc.descr not in (None, '', UNKNOWN): out(self.section('Description')) out(mod_doc.descr.to_plaintext(None, indent=4)) #out('metadata: %s\n\n' % mod_doc.metadata) # [xx] testing self.write_list(out, 'Classes', mod_doc, value_type='class') self.write_list(out, 'Functions', mod_doc, value_type='function') self.write_list(out, 'Variables', mod_doc, value_type='other') # hmm.. do this as just a flat list?? #self.write_list(out, 'Imports', mod_doc, imported=True, verbose=False) def baselist(self, class_doc): if class_doc.bases is UNKNOWN: return '(unknown bases)' if len(class_doc.bases) == 0: return '' s = '(' class_parent = class_doc.canonical_name.container() for i, base in enumerate(class_doc.bases): if base.canonical_name is None: if base.parse_repr is not UNKNOWN: s += base.parse_repr else: s += '??' elif base.canonical_name.container() == class_parent: s += str(base.canonical_name[-1]) else: s += str(base.canonical_name) if i < len(class_doc.bases)-1: out(', ') return s+')' def write_class(self, out, class_doc, name=None, prefix='', verbose=True): baselist = self.baselist(class_doc) # If we're at the top level, then list the cannonical name of # the class; otherwise, our parent will have already printed # the name of the variable containing the class. if prefix == '': out(self.section('Class Name')) out(' %s%s\n\n' % (class_doc.canonical_name, baselist)) else: out(prefix + 'class %s' % self.bold(str(name)) + baselist+'\n') if not verbose: return # Indent the body if prefix != '': prefix += ' | ' # The class's description. if class_doc.descr not in (None, '', UNKNOWN): if prefix == '': out(self.section('Description', prefix)) out(self._descr(class_doc.descr, ' ')) else: out(self._descr(class_doc.descr, prefix)) # List of nested classes in this class. self.write_list(out, 'Methods', class_doc, value_type='instancemethod', prefix=prefix, noindent=len(prefix)>4) self.write_list(out, 'Class Methods', class_doc, value_type='classmethod', prefix=prefix) self.write_list(out, 'Static Methods', class_doc, value_type='staticmethod', prefix=prefix) self.write_list(out, 'Nested Classes', class_doc, value_type='class', prefix=prefix) self.write_list(out, 'Instance Variables', class_doc, value_type='instancevariable', prefix=prefix) self.write_list(out, 'Class Variables', class_doc, value_type='classvariable', prefix=prefix) self.write_list(out, 'Inherited Methods', class_doc, value_type='method', prefix=prefix, inherited=True, verbose=False) self.write_list(out, 'Inherited Instance Variables', class_doc, value_type='instancevariable', prefix=prefix, inherited=True, verbose=False) self.write_list(out, 'Inherited Class Variables', class_doc, value_type='classvariable', prefix=prefix, inherited=True, verbose=False) self.write_list(out, 'Inherited Nested Classes', class_doc, value_type='class', prefix=prefix, inherited=True, verbose=False) def write_variable(self, out, var_doc, name=None, prefix='', verbose=True): if name is None: name = var_doc.name out(prefix+self.bold(str(name))) if (var_doc.value not in (UNKNOWN, None) and var_doc.is_alias is True and var_doc.value.canonical_name not in (None, UNKNOWN)): out(' = %s' % var_doc.value.canonical_name) elif var_doc.value not in (UNKNOWN, None): val_repr = var_doc.value.summary_pyval_repr( max_len=self._cols-len(name)-len(prefix)-3) out(' = %s' % val_repr.to_plaintext(None)) out('\n') if not verbose: return prefix += ' ' # indent the body. if var_doc.descr not in (None, '', UNKNOWN): out(self._descr(var_doc.descr, prefix)) def write_property(self, out, prop_doc, name=None, prefix='', verbose=True): if name is None: name = prop_doc.canonical_name out(prefix+self.bold(str(name))) if not verbose: return prefix += ' ' # indent the body. if prop_doc.descr not in (None, '', UNKNOWN): out(self._descr(prop_doc.descr, prefix)) def write_function(self, out, func_doc, name=None, prefix='', verbose=True): if name is None: name = func_doc.canonical_name self.write_signature(out, func_doc, name, prefix) if not verbose: return prefix += ' ' # indent the body. if func_doc.descr not in (None, '', UNKNOWN): out(self._descr(func_doc.descr, prefix)) if func_doc.return_descr not in (None, '', UNKNOWN): out(self.section('Returns:', prefix)) out(self._descr(func_doc.return_descr, prefix+' ')) if func_doc.return_type not in (None, '', UNKNOWN): out(self.section('Return Type:', prefix)) out(self._descr(func_doc.return_type, prefix+' ')) def write_signature(self, out, func_doc, name, prefix): args = [self.fmt_arg(argname, default) for (argname, default) in zip(func_doc.posargs, func_doc.posarg_defaults)] if func_doc.vararg: args.append('*'+func_doc.vararg) if func_doc.kwarg: args.append('**'+func_doc.kwarg) out(prefix+self.bold(str(name))+'(') x = left = len(prefix) + len(name) + 1 for i, arg in enumerate(args): if x > left and x+len(arg) > 75: out('\n'+prefix + ' '*len(name) + ' ') x = left out(arg) x += len(arg) if i < len(args)-1: out(', ') x += 2 out(')\n') # [xx] tuple args! def fmt_arg(self, name, default): if default is None: return '%s' % name else: default_repr = default.summary_pyval_repr() return '%s=%s' % (name, default_repr.to_plaintext(None)) def write_list(self, out, heading, doc, value_type=None, imported=False, inherited=False, prefix='', noindent=False, verbose=True): # Get a list of the VarDocs we should describe. if isinstance(doc, ClassDoc): var_docs = doc.select_variables(value_type=value_type, imported=imported, inherited=inherited) else: var_docs = doc.select_variables(value_type=value_type, imported=imported) if not var_docs: return out(prefix+'\n') if not noindent: out(self.section(heading, prefix)) prefix += ' ' for i, var_doc in enumerate(var_docs): val_doc, name = var_doc.value, var_doc.name if verbose: out(prefix+'\n') # hmm: if not verbose: if isinstance(doc, ClassDoc): name = var_doc.canonical_name elif val_doc not in (None, UNKNOWN): name = val_doc.canonical_name if isinstance(val_doc, RoutineDoc): self.write_function(out, val_doc, name, prefix, verbose) elif isinstance(val_doc, PropertyDoc): self.write_property(out, val_doc, name, prefix, verbose) elif isinstance(val_doc, ClassDoc): self.write_class(out, val_doc, name, prefix, verbose) else: self.write_variable(out, var_doc, name, prefix, verbose) def _descr(self, descr, prefix): s = descr.to_plaintext(None, indent=len(prefix)).rstrip() s = '\n'.join([(prefix+l[len(prefix):]) for l in s.split('\n')]) return s+'\n'#+prefix+'\n' # def drawline(self, s, x): # s = re.sub(r'(?m)^(.{%s}) ' % x, r'\1|', s) # return re.sub(r'(?m)^( {,%s})$(?=\n)' % x, x*' '+'|', s) #//////////////////////////////////////////////////////////// # Helpers #//////////////////////////////////////////////////////////// def bold(self, text): """Write a string in bold by overstriking.""" return ''.join([ch+'\b'+ch for ch in text]) def title(self, text, indent): return ' '*indent + self.bold(text.capitalize()) + '\n\n' def section(self, text, indent=''): if indent == '': return indent + self.bold(text.upper()) + '\n' else: return indent + self.bold(text.capitalize()) + '\n'