Package mvpa :: Package base :: Module dochelpers
[hide private]
[frames] | no frames]

Source Code for Module mvpa.base.dochelpers

  1  #emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*- 
  2  #ex: set sts=4 ts=4 sw=4 et: 
  3  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## 
  4  # 
  5  #   See COPYING file distributed along with the PyMVPA package for the 
  6  #   copyright and license terms. 
  7  # 
  8  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ## 
  9  """""" 
 10   
 11  __docformat__ = 'restructuredtext' 
 12   
 13  import re, textwrap 
 14   
 15  # for table2string 
 16  import numpy as N 
 17  from math import ceil 
 18  from StringIO import StringIO 
 19   
20 -def rstUnderline(text, markup):
21 """Add and underline RsT string matching the length of the given string. 22 """ 23 return text + '\n' + markup * len(text)
24 25
26 -def handleDocString(text):
27 """Take care of empty and non existing doc strings.""" 28 if text == None or not len(text): 29 return 'No documentation found. Sorry!' 30 else: 31 # TODO: remove common empty prefix, so we don't offset 32 # documentation too much 33 # to see starts/ends of the lines use 34 # return '\n'.join(['>%s<' % x for x in text.split('\n')]) 35 # function posixpath.commonprefix might be used to detect 36 # common prefix, or just textwrap.dedent 37 # Problem is that first line might often have no offset, so might 38 # need to be ignored from dedent call 39 if not text.startswith(' '): 40 lines = text.split('\n') 41 text2 = '\n'.join(lines[1:]) 42 return lines[0] + "\n" + textwrap.dedent(text2) 43 else: 44 return textwrap.dedent(text)
45 46
47 -def enhancedDocString(name, lcl, *args):
48 """Generate enhanced doc strings.""" 49 return lcl['__doc__'] 50 rst_lvlmarkup = ["=", "-", "_"] 51 52 docs = [] 53 docs += [ handleDocString(lcl['__doc__']), 54 rstUnderline('Constructor information for `%s` class' % name, 55 rst_lvlmarkup[2]), 56 handleDocString(lcl['__init__'].__doc__) ] 57 58 if len(args): 59 docs.append(rstUnderline('\nDocumentation for base classes of `%s`' \ 60 % name, rst_lvlmarkup[0])) 61 for i in args: 62 docs += [ rstUnderline('Documentation for class `%s`' % i.__name__, 63 rst_lvlmarkup[1]), 64 handleDocString(i.__doc__) ] 65 66 return '\n\n'.join(docs)
67 68
69 -def enhancedClassDocString(cls, *args):
70 """Generate enhanced doc strings but given a class, not just a name. 71 72 It is to be used from a collector, ie whenever class is already created 73 """ 74 name = cls.__name__ 75 lcl = cls.__dict__ 76 return lcl['__doc__'] 77 rst_lvlmarkup = ["=", "-", "_"] 78 79 initdoc = None 80 if lcl.has_key('__init__'): 81 initdoc = lcl['__init__'].__doc__ 82 83 if lcl.has_key('_paramsdoc'): 84 if initdoc is None: 85 initdoc = "Initialize instance of %s" % name 86 87 # collector provided us with documentation for the parameters 88 if not (":Parameters:" in initdoc): 89 initdoc += "\n\n:Parameters:\n" 90 91 92 # where new line is after :Parameters: 93 nl_index = initdoc.index('\n', initdoc.index(':Parameters:')+1) 94 # how many spaces preceed next line 95 initdoc_therest = initdoc[nl_index+1:] 96 nspaces = len(initdoc_therest) - len(initdoc_therest.lstrip()) 97 initdoc = initdoc[:nl_index+1] + '\n'.join( 98 [' '*(nspaces-2) + x for x in cls._paramsdoc.rstrip().split('\n')]) + \ 99 initdoc[nl_index:] 100 101 docs = [] 102 docs += [ handleDocString(lcl['__doc__']), 103 rstUnderline('Constructor information for `%s` class' % name, 104 rst_lvlmarkup[2]), 105 handleDocString(initdoc) ] 106 107 # Add information about the states if available 108 if lcl.has_key('_statesdoc'): 109 docs += [rstUnderline('Available state variables:', rst_lvlmarkup[1]), 110 handleDocString(cls._statesdoc)] 111 112 if len(args): 113 docs.append(rstUnderline('\nDocumentation for base classes of `%s`' \ 114 % name, rst_lvlmarkup[0])) 115 for i in args: 116 docs += [ rstUnderline('Documentation for class `%s`' % i.__name__, 117 rst_lvlmarkup[1]), 118 handleDocString(i.__doc__) ] 119 120 result = '\n\n'.join(docs) 121 # remove some bogus new lines -- never 3 empty lines in doc are useful 122 result = re.sub("\s*\n\s*\n\s*\n", "\n\n", result) 123 124 return result
125 126
127 -def table2string(table, out=None):
128 """Given list of lists figure out their common widths and print to out 129 130 :Parameters: 131 table : list of lists of strings 132 What is aimed to be printed 133 out : None or stream 134 Where to print. If None -- will print and return string 135 136 :Returns: 137 string if out was None 138 """ 139 140 print2string = out is None 141 if print2string: 142 out = StringIO() 143 144 # equalize number of elements in each row 145 Nelements_max = max(len(x) for x in table) 146 for i,table_ in enumerate(table): 147 table[i] += [''] * (Nelements_max - len(table_)) 148 149 # figure out lengths within each column 150 atable = N.asarray(table) 151 markup_strip = re.compile('^@[lrc]') 152 col_width = [ max( [len(markup_strip.sub('', x)) 153 for x in column] ) for column in atable.T ] 154 string = "" 155 for i, table_ in enumerate(table): 156 string_ = "" 157 for j, item in enumerate(table_): 158 item = str(item) 159 if item.startswith('@'): 160 align = item[1] 161 item = item[2:] 162 if not align in ['l', 'r', 'c']: 163 raise ValueError, 'Unknown alignment %s. Known are l,r,c' 164 else: 165 align = 'c' 166 167 NspacesL = ceil((col_width[j] - len(item))/2.0) 168 NspacesR = col_width[j] - NspacesL - len(item) 169 170 if align == 'c': 171 pass 172 elif align == 'l': 173 NspacesL, NspacesR = 0, NspacesL + NspacesR 174 elif align == 'r': 175 NspacesL, NspacesR = NspacesL + NspacesR, 0 176 else: 177 raise RuntimeError, 'Should not get here with align=%s' % align 178 179 string_ += "%%%ds%%s%%%ds " \ 180 % (NspacesL, NspacesR) % ('', item, '') 181 string += string_.rstrip() + '\n' 182 out.write(string) 183 184 if print2string: 185 value = out.getvalue() 186 out.close() 187 return value 188 189 pass
190