00001
00002 '''
00003 Short auto-documentation for SLIMpy
00004 '''
00005
00006 __copyright__ = """
00007 Copyright 2008 Henryk Modzelewski
00008 """
00009 __license__ = """
00010 This file is part of SLIMpy .
00011
00012 SLIMpy is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as published by
00014 the Free Software Foundation, either version 3 of the License, or
00015 (at your option) any later version.
00016
00017 SLIMpy is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021
00022 You should have received a copy of the GNU Lesser General Public License
00023 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00024 """
00025
00026
00027 from string import Template
00028
00029 OPTIONS={
00030 'text':'generate quick and dirty text output (default)',
00031 'html':'generate HTML output to directory (dir-out must be specified)',
00032 'latex':'generate LaTeX output to file',
00033 'help':'this info'
00034 }
00035
00036
00037 import os
00038 import sys
00039 import getopt
00040 import time
00041 import pickle
00042
00043
00044 TITLE='SLIMpy methods and classes'
00045 HEADER={
00046 'LaTeX': '''\\maketitle''',
00047 'HTML': '''<HTML><HEAD><TITLE>'''+TITLE+'''</TITLE></HEAD><BODY>\n''',
00048 'TEXT': '''\n'''
00049 }
00050 FOOTER={
00051 'LaTeX': '''\n''',
00052 'HTML': '''<P><I>'''+time.asctime()+'''</I></BODY>\n''',
00053 'TEXT': '''\n'''+time.asctime()+'''\n'''
00054 }
00055 LINEEND={ 'LaTeX': '\n', 'HTML': '\n', 'TEXT': '\n' }
00056 LINEBREAK={ 'LaTeX': '\n', 'HTML': '<BR>\n', 'TEXT': '\n' }
00057 HLINE={ 'LaTeX': '\n', 'HTML': '<HR>\n', 'TEXT': '#'*30+'\n' }
00058 SECTION={ 'LaTeX': ['\\section*{','}\n'], 'HTML': ['<H3>','</H3>\n'], 'TEXT': ['# ','\n\n'] }
00059 SUBSECTION={ 'LaTeX': ['\\subsection*{','}\n'], 'HTML': ['<H4>','</H4>\n'], 'TEXT': ['### ','\n'] }
00060 ITEMIZE={ 'LaTeX': ['\\begin{itemize}\n','\\end{itemize}\n'], 'HTML': ['<UL>\n','</UL>\n'], 'TEXT': ['\n','\n'] }
00061 ITEM={ 'LaTeX': ['\\item ','\n'], 'HTML': ['<LI>','</LI>\n'], 'TEXT': [' || ','\n'] }
00062 PARAGRAPH={ 'LaTeX': ['\n','\n'], 'HTML': ['<P>','</P>\n'], 'TEXT': ['','\n'] }
00063
00064 def usage():
00065 """ print usage info """
00066 print __doc__
00067 print os.path.basename(sys.argv[0]), '[options] file-in [file/dir-out]'
00068 print '\tOptions:'
00069 options = OPTIONS.keys()
00070 options.sort()
00071 for option in options:
00072 print '\t--'+option,':',OPTIONS[option]
00073 print '\tNote: formating options are exclusive (last counts)'
00074 print COPYRIGHT
00075 sys.exit(2)
00076
00077 def makeSafe(format,text):
00078 ''' conversion of strings to LaTeX compliant'''
00079 if format!='LaTeX': return text
00080 texmap = [('\\','\\e '),('{','\\{'),('}','\\}'),('_','{\\_}'),('%','{\\%}')]
00081 for key,val in texmap:
00082 text = text.replace(key,val)
00083 return text
00084
00085 class l_Section(object):
00086
00087 sec = Template("""
00088 \\section*{${name}: ${perc}\\%}
00089 There are ${all} methods in ${name}: ${tested} tested methods and ${untested} untested
00090
00091
00092 ${perc}{\\%} of ${name} is tested.
00093
00094 ${subsections}
00095 """)
00096
00097 def __init__(self,name,dict):
00098
00099
00100 all_methods = dict['all_methods']
00101 tested_methods = dict['tested_methods']
00102 doc = dict['doc']
00103 assert tested_methods.issubset( all_methods ), (tested_methods,all_methods)
00104 untested = all_methods.difference( tested_methods )
00105
00106 if not len(all_methods):
00107 self.perc = 100
00108 else:
00109 self.perc = 100*len(tested_methods) / len(all_methods)
00110
00111 self.name = makeSafe('LaTeX', name)
00112 untested_sec = sub_section('untested methods: %d' %len(untested), untested, doc )
00113 tested_sec = sub_section('tested methods: %d' %len(tested_methods), tested_methods, doc )
00114
00115 self.subsections = str(tested_sec) + str( untested_sec )
00116 self.untested = len(untested)
00117 self.tested = len(tested_methods)
00118 self.all = len(all_methods)
00119
00120 def __str__(self):
00121
00122 return self.sec.substitute( **self.__dict__ )
00123
00124 class sub_section( object ):
00125
00126 subsec = Template("""
00127 \\subsection*{${name}}
00128 \\begin{itemize}
00129 ${items}
00130 \\end{itemize}
00131
00132 """)
00133 def __init__(self,name, uset, doc):
00134 self.name = name
00135 self.uset = uset
00136 if doc:
00137 print doc
00138 self.items = "\n".join([ "\\item[%s] %s" %(item,doc.get(item,"")) for item in self.uset])
00139
00140 def __str__(self):
00141 if self.uset:
00142 return self.subsec.substitute( **self.__dict__ )
00143 else:
00144 return ""
00145
00146
00147 def makeList(Document,Output,FORMAT):
00148
00149 if not Document:
00150 print "No Profiles were created"
00151 FileOut=open(Output,'w')
00152 FileOut.close()
00153 return
00154
00155 tu = [ (len(val['all_methods']),len(val['tested_methods'])) for val in Document.itervalues() ]
00156
00157 all,tested = zip(*tu)
00158
00159 all = sum(all)
00160 tested = sum(tested)
00161 untested = all - tested
00162 perc = 100* tested / all
00163
00164 keys = Document.keys()
00165 keys.sort()
00166 funcs = [ str(l_Section(key,Document[key] )) for key in keys ]
00167
00168 FileOut=open(Output,'w')
00169 print >> FileOut, """%(perc)s \\%% of all SLIMpy classes have been tested
00170
00171 There are a total of %(all)s class methods: %(tested)s tested and %(untested)s untested""" %vars()
00172
00173 lines = "\n".join(funcs)
00174 FileOut.write(lines)
00175
00176 FileOut.close()
00177
00178
00179 def _makeList(Document,Output,FORMAT):
00180 '''
00181 makeList creates the list of Classes and Methods in either
00182 TEXT, LaTeX, or HTML format.
00183
00184 Parameters:
00185 Document - hash of classes and methods
00186 Output - string with file/dir name or None
00187 file for TEXT/LaTeX
00188 directory for HTML
00189 None for TEXT/LaTeX to stdout
00190 FORMAT - either TEXT, LaTeX, or HTML
00191 '''
00192
00193 if FORMAT=='HTML':
00194 if not os.path.isdir(Output):
00195 print 'FATAL ERROR:', Output, 'does not exist or is not a directory'
00196 sys.exit(1)
00197 ContentOut = os.path.join(Output,'index.html')
00198 try: FileOut=open(ContentOut,'w')
00199 except:
00200 print 'FATAL ERROR: cannot open', ContentOut
00201 sys.exit()
00202 FileOut.write(HEADER[FORMAT])
00203 FileOut.write(SECTION[FORMAT][0])
00204 FileOut.write(TITLE)
00205 FileOut.write(SECTION[FORMAT][1])
00206 FileOut.write(HLINE[FORMAT])
00207 FileOut.write(SECTION[FORMAT][0])
00208 FileOut.write('Table of Contents:')
00209 FileOut.write(SECTION[FORMAT][1])
00210 LINKS={}
00211 names=Document.keys()
00212 names.sort()
00213 for name in names:
00214 LINKS[name]=str('node'+str(len(LINKS)+1000)+'.html')
00215 FileOut.write(ITEMIZE[FORMAT][0])
00216 FileOut.write(ITEM[FORMAT][0])
00217 FileOut.write(''.join(['<A href=\"',LINKS[name],'\">[',name,']</A>']))
00218 ntested = len(Document[name]['tested_methods'])
00219 nall = len(Document[name]['all_methods'])
00220 line = " %.0f%% tested" %(100.*ntested/nall)
00221 FileOut.write(line)
00222 FileOut.write(ITEM[FORMAT][1])
00223 FileOut.write(ITEMIZE[FORMAT][1])
00224 FileOut.write(FOOTER[FORMAT])
00225 FileOut.close()
00226 else:
00227 if Output:
00228 try: FileOut=open(Output,'w')
00229 except:
00230 'FATAL ERROR: cannot open', Output
00231 sys.exit(1)
00232 else: FileOut=sys.stdout
00233 FileOut.write(HEADER[FORMAT])
00234
00235 names=Document.keys()
00236 names.sort()
00237 for name in names:
00238 section = Document[name]
00239 used_in = section.setdefault('used in',{})
00240 doc = section['doc']
00241
00242 if FORMAT=='HTML':
00243 NodeOut=os.path.join(Output,LINKS[name])
00244 try: FileOut=open(NodeOut,'w')
00245 except:
00246 'FATAL ERROR: cannot open', NodeOut
00247 sys.exit(1)
00248 FileOut.write(HEADER[FORMAT])
00249 FileOut.write(SECTION[FORMAT][0])
00250 FileOut.write(TITLE)
00251 FileOut.write(SECTION[FORMAT][1])
00252 FileOut.write('<A href=\"index.html\">[Back]</A> to Table of Contents')
00253 FileOut.write(LINEEND[FORMAT])
00254
00255 FileOut.write(HLINE[FORMAT])
00256 FileOut.write(SECTION[FORMAT][0])
00257 if FORMAT=='HTML': line = ''.join(['<A name=\"',LINKS[name],'\">',name,'</A>'])
00258 else: line = makeSafe(FORMAT,name)
00259 FileOut.write(line)
00260 FileOut.write(SECTION[FORMAT][1])
00261
00262 ntested = len(Document[name]['tested_methods'])
00263 nall = len(Document[name]['all_methods'])
00264 line = "There are %s tested methods and %s untested methods in %s" %(ntested,nall-ntested,name)
00265 line = makeSafe(FORMAT,line)
00266 FileOut.write(PARAGRAPH[FORMAT][0]+line+PARAGRAPH[FORMAT][1])
00267
00268 if nall == 0:
00269 line = "0%% of the %s is tested" %( name )
00270 else:
00271 line = "%.0f%% of the %s is tested" %(100.*ntested/nall, name )
00272 line = makeSafe(FORMAT,line)
00273 FileOut.write(PARAGRAPH[FORMAT][0]+line+PARAGRAPH[FORMAT][1])
00274 FileOut.write(LINEEND[FORMAT])
00275
00276 FileOut.write(SUBSECTION[FORMAT][0]+"tested methods:"+SUBSECTION[FORMAT][1])
00277 FileOut.write(ITEMIZE[FORMAT][0])
00278 methods = list(section['tested_methods'])
00279 methods.sort()
00280 for method in methods:
00281 FileOut.write(ITEM[FORMAT][0])
00282 line = makeSafe(FORMAT,' '.join([method, doc.get(method ,'')]))
00283 FileOut.write(line)
00284 FileOut.write(LINEBREAK[FORMAT])
00285 line = makeSafe(FORMAT,' '.join([" used in the demos:", used_in.get(method,'')]))
00286 FileOut.write(line)
00287 FileOut.write(ITEM[FORMAT][1])
00288 FileOut.write(ITEMIZE[FORMAT][1])
00289
00290 FileOut.write(SUBSECTION[FORMAT][0]+"untested methods:"+SUBSECTION[FORMAT][1])
00291 untested_methods = section['all_methods'].difference(section['tested_methods'])
00292 FileOut.write(ITEMIZE[FORMAT][0])
00293 methods = list(untested_methods)
00294 methods.sort()
00295 for method in methods:
00296 FileOut.write(ITEM[FORMAT][0])
00297 line = makeSafe(FORMAT,' '.join([method, doc.get(method ,'')]))
00298 FileOut.write(line)
00299 FileOut.write(ITEM[FORMAT][1])
00300 FileOut.write(ITEMIZE[FORMAT][1])
00301 FileOut.write(LINEEND[FORMAT])
00302
00303 if FORMAT=='HTML':
00304 FileOut.write(''.join(['<A href=\"index.html\">[Back]</A> to Table of Contents']))
00305 FileOut.write(LINEEND[FORMAT])
00306 FileOut.write(FOOTER[FORMAT])
00307 FileOut.close()
00308
00309 if FORMAT!='HTML': FileOut.write(FOOTER[FORMAT])
00310
00311 return
00312
00313
00314 if __name__ == '__main__':
00315
00316 FORMAT='TEXT'
00317
00318
00319 try:
00320 opts, args = getopt.getopt(sys.argv[1:], '',OPTIONS.keys())
00321 except getopt.GetoptError:
00322 print OPTIONS.keys()
00323 usage()
00324
00325 for o, a in opts:
00326 if o == '--help': usage()
00327 if o == '--text': FORMAT='TEXT'
00328 if o == '--html': FORMAT='HTML'
00329 if o == '--latex': FORMAT='LaTeX'
00330
00331 if ( len(args) == 0 or len(args) >2):
00332 print 'FATAL ERROR: too few or too many arguments'
00333 usage()
00334 if len(args) > 0:
00335 FileIn = args[0]
00336 Output = None
00337 if len(args) <2 and FORMAT=='HTML':
00338 print 'FATAL ERROR: no directory for HTML output'
00339 usage()
00340 if len(args) > 1:
00341 Output = args[1]
00342
00343
00344 pickle_file = open(FileIn)
00345 Document = pickle.load( pickle_file )
00346 pickle_file.close()
00347
00348 makeList(Document,Output,FORMAT)
00349
00350 sys.exit(0)