Changeset 113

Show
Ignore:
Timestamp:
06/28/07 17:45:53 (1 year ago)
Author:
apdavison
Message:

Refactored wikidoc.py so that it can now be used as an imported module (e.g. ) as well as a command-line script.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/0.3/doc/wikidoc.py

    r76 r113  
    66import types, string, re, logging 
    77 
    8 #-- Set up logging ------------------------------------------------------------- 
    9 logging.basicConfig(level=logging.DEBUG, 
    10                     format='%(asctime)s %(levelname)-8s %(message)s', 
    11                     datefmt='%Y%m%d-%H%M%S', 
    12                     filename='wikidoc.log', 
    13                     filemode='w') 
    14 # define a Handler which writes WARNING messages or higher to the sys.stderr 
    15 console = logging.StreamHandler() 
    16 console.setLevel(logging.WARNING) 
    17 # set a format which is simpler for console use 
    18 formatter = logging.Formatter('%(message)s') 
    19 # tell the handler to use this format 
    20 console.setFormatter(formatter) 
    21 # add the handler to the root logger 
    22 logging.getLogger('').addHandler(console) 
     8 
    239 
    2410#-- Define global data --------------------------------------------------------- 
     
    3622camelcase = re.compile(r'(\b([A-Z][a-z]+){2,99})') 
    3723 
    38 classes = {} 
    39 functions = [] 
    40 data = [] 
    41  
    42 #-- Process command line parameters -------------------------------------------- 
    43 if len(sys.argv) > 1: 
    44     output = sys.argv[1] 
    45 else: 
    46     output = 'wiki' 
    47 logging.info('Generating API documentation in %s format' % output) 
    48  
    49 #-- Define templates ----------------------------------------------------------- 
    50 if output == 'wiki': 
    51     default_arg_fmt  = '%s<span style="color:grey;">=%s</span>' 
    52     func_sig_fmt     = '%s(<span style="font-weight:normal;">%s</span>)' 
    53     function_fmt     = '\n====<span style="color:#0066ff;">%s</span>====\n' 
    54     method_fmt       = '\n====<span style="color:#8888ff;">%s</span>====\n' 
    55     staticmethod_fmt = '\n====<span style="color:#0066ff;">%s</span> (static)====\n' 
    56     dict_fmt         = "\n\n'''%s''' = {\n" 
    57     dict_fmt_end     = '}\n' 
    58     data_element_fmt = "\n'''%s''' = %s\n" 
    59     table_begin      = "{|\n" 
    60     table_end        = "|}\n" 
    61     table_row_fmt    = "| &nbsp;&nbsp;&nbsp; || %s ||: %s\n|-\n" 
    62     category_fmt     = '\n==%s==\n' 
    63     class_fmt        = '\n===<span style="color:green">%s</span>===\n' 
    64     horiz_line       = '\n----\n' 
    65 elif output == 'trac': 
    66     default_arg_fmt  = '%s=%s' 
    67     func_sig_fmt     = '%s(%s)' 
    68     function_fmt     = '\n=== %s ===\n' 
    69     method_fmt       = '\n=== %s ===\n' 
    70     staticmethod_fmt = '\n=== %s ===\n' 
    71     dict_fmt         = "\n\n'''%s''' = {\n" 
    72     dict_fmt_end     = '}\n' 
    73     data_element_fmt = "\n'''%s''' = %s\n" 
    74     table_begin      = "\n" 
    75     table_end        = "\n" 
    76     table_row_fmt    = "|| %s ||: %s ||\n" 
    77     category_fmt     = '\n= %s =\n' 
    78     class_fmt        = '\n== %s ==\n' 
    79     horiz_line       = '\n----\n' 
    80 elif output == 'latex': 
    81     default_arg_fmt  = '%s{\\color{grey}=%s}' 
    82     func_sig_fmt     = '%s(\\mdseries %s)' 
    83     function_fmt     = '\n\\paragraph*{\\color{brightblue}{%s}}\n' 
    84     method_fmt       = '\n\\paragraph*{\\color{brightblue}{%s}}\n' 
    85     staticmethod_fmt = '\n\\paragraph*{\\color{brightblue}{%s} (static)}\n' 
    86     dict_fmt         = '\n\\textbf{%s} = $\\lbrace$\n\n' 
    87     dict_fmt_end     = '$\\rbrace$\n' 
    88     data_element_fmt = "\n\\textbf{%s} = %s\n" 
    89     table_begin      = "\\begin{tabular}{lll}\n" 
    90     table_end        = "\\end{tabular}\n" 
    91     table_row_fmt    = '& %s & :%s\\\\\n' 
    92     category_fmt     = '\n\\subsection{%s}\n' 
    93     class_fmt        = '\n\\subsubsection*{%s}\n' 
    94     horiz_line       = '' 
    95               
     24  
    9625#-- Define functions ----------------------------------------------------------- 
    9726 
     
    11241    return "%s(%s)" % (fname, string.join(args,', ')) 
    11342 
    114 def func_sig(func): 
     43def func_sig(func, default_arg_fmt, func_sig_fmt): 
    11544    """Adapted from http://www.lemburg.com/python/hack.py, by  Marc-André Lemburg 
    11645       Returns the signature of a Python function/method as string. 
     
    15887#-- Main block ----------------------------------------------------------------- 
    15988 
    160 # gather information from the common module 
    161 logging.info("Gathering information from the common module.") 
    162 for entry in dir(pyNN.common): 
    163     if entry not in exclude: 
    164         instance = eval('pyNN.common.%s' % entry) 
    165         entry_type = type(instance) 
    166         logging.info('  %-30s %s' % (entry,entry_type)) 
    167         if entry_type in [types.ClassType, types.TypeType]: 
    168             classes[entry] = { 'methods': [], 'data': [], 'staticmethods': [] } 
    169             for classentry in dir(instance): 
    170                 if classentry not in exclude and (classentry[0] != '_' or classentry[0:2] == '__'): # don't include private methods 
    171                     classentry_type = type(eval('pyNN.common.%s.%s' % (entry,classentry))) 
    172                     logging.info('    %-28s %s' % (classentry,classentry_type)) 
    173                     if classentry_type == types.MethodType: 
    174                         classes[entry]['methods'].append(classentry) 
    175                     elif classentry_type == types.FunctionType: 
    176                         classes[entry]['staticmethods'].append(classentry) 
     89def apidoc(output): 
     90    classes = {} 
     91    functions = [] 
     92    data = [] 
     93     
     94    #-- Define templates ----------------------------------------------------------- 
     95    if output == 'wiki': 
     96        default_arg_fmt  = '%s<span style="color:grey;">=%s</span>' 
     97        func_sig_fmt     = '%s(<span style="font-weight:normal;">%s</span>)' 
     98        function_fmt     = '\n====<span style="color:#0066ff;">%s</span>====\n' 
     99        method_fmt       = '\n====<span style="color:#8888ff;">%s</span>====\n' 
     100        staticmethod_fmt = '\n====<span style="color:#0066ff;">%s</span> (static)====\n' 
     101        dict_fmt         = "\n\n'''%s''' = {\n" 
     102        dict_fmt_end     = '}\n' 
     103        data_element_fmt = "\n'''%s''' = %s\n" 
     104        table_begin      = "{|\n" 
     105        table_end        = "|}\n" 
     106        table_row_fmt    = "| &nbsp;&nbsp;&nbsp; || %s ||: %s\n|-\n" 
     107        category_fmt     = '\n==%s==\n' 
     108        class_fmt        = '\n===<span style="color:green">%s</span>===\n' 
     109        horiz_line       = '\n----\n' 
     110    elif output == 'trac': 
     111        default_arg_fmt  = '%s=%s' 
     112        func_sig_fmt     = '%s(%s)' 
     113        function_fmt     = '\n=== %s ===\n' 
     114        method_fmt       = '\n=== %s ===\n' 
     115        staticmethod_fmt = '\n=== %s ===\n' 
     116        dict_fmt         = "\n\n'''%s''' = {\n" 
     117        dict_fmt_end     = '}\n' 
     118        data_element_fmt = "\n'''%s''' = %s\n" 
     119        table_begin      = "\n" 
     120        table_end        = "\n" 
     121        table_row_fmt    = "|| %s ||: %s ||\n" 
     122        category_fmt     = '\n= %s =\n' 
     123        class_fmt        = '\n== %s ==\n' 
     124        horiz_line       = '\n----\n' 
     125    elif output == 'latex': 
     126        default_arg_fmt  = '%s{\\color{grey}=%s}' 
     127        func_sig_fmt     = '%s(\\mdseries %s)' 
     128        function_fmt     = '\n\\paragraph*{\\color{brightblue}{%s}}\n' 
     129        method_fmt       = '\n\\paragraph*{\\color{brightblue}{%s}}\n' 
     130        staticmethod_fmt = '\n\\paragraph*{\\color{brightblue}{%s} (static)}\n' 
     131        dict_fmt         = '\n\\textbf{%s} = $\\lbrace$\n\n' 
     132        dict_fmt_end     = '$\\rbrace$\n' 
     133        data_element_fmt = "\n\\textbf{%s} = %s\n" 
     134        table_begin      = "\\begin{tabular}{lll}\n" 
     135        table_end        = "\\end{tabular}\n" 
     136        table_row_fmt    = '& %s & :%s\\\\\n' 
     137        category_fmt     = '\n\\subsection{%s}\n' 
     138        class_fmt        = '\n\\subsubsection*{%s}\n' 
     139        horiz_line       = '' 
     140     
     141    # gather information from the common module 
     142    logging.info("Gathering information from the common module.") 
     143    for entry in dir(pyNN.common): 
     144        if entry not in exclude: 
     145            instance = eval('pyNN.common.%s' % entry) 
     146            entry_type = type(instance) 
     147            logging.info('  %-30s %s' % (entry,entry_type)) 
     148            if entry_type in [types.ClassType, types.TypeType]: 
     149                classes[entry] = { 'methods': [], 'data': [], 'staticmethods': [] } 
     150                for classentry in dir(instance): 
     151                    if classentry not in exclude and (classentry[0] != '_' or classentry[0:2] == '__'): # don't include private methods 
     152                        classentry_type = type(eval('pyNN.common.%s.%s' % (entry,classentry))) 
     153                        logging.info('    %-28s %s' % (classentry,classentry_type)) 
     154                        if classentry_type == types.MethodType: 
     155                            classes[entry]['methods'].append(classentry) 
     156                        elif classentry_type == types.FunctionType: 
     157                            classes[entry]['staticmethods'].append(classentry) 
     158                        else: 
     159                            classes[entry]['data'].append(classentry) 
    177160                    else: 
    178                         classes[entry]['data'].append(classentry) 
     161                        logging.info('    %-28s excluded' % classentry) 
     162            elif  entry_type == types.FunctionType: 
     163                functions.append(entry) 
     164            elif entry_type == types.ModuleType: 
     165                pass 
     166            else: 
     167                data.append(entry) 
     168        else: 
     169            logging.info('  %-30s excluded' % entry) 
     170     
     171    # output starts here 
     172    outputStr = '' 
     173    if output == 'latex': 
     174        outputStr += '\definecolor{brightblue}{rgb}{0.0,0.38,1.0}\n' 
     175        outputStr += '\definecolor{paleblue}{rgb}{0.5,0.5,1.0}\n' 
     176        outputStr += '\definecolor{grey}{rgb}{0.5,0.5,0.5}\n' 
     177     
     178    logging.info("==== DATA ====") 
     179    outputStr += category_fmt % "Data" 
     180    for element in data: 
     181        instance = eval('pyNN.common.%s' % element) 
     182        if type(instance) == types.DictType: 
     183            outputStr += dict_fmt % element 
     184            outputStr += table_begin 
     185            for k,v in instance.items(): 
     186                if output == 'latex': 
     187                    v = str(v).replace('{',' $\\lbrace$').replace('}',' $\\rbrace$') 
     188                outputStr += table_row_fmt % (k,v) 
     189            outputStr += table_end 
     190            outputStr += dict_fmt_end 
     191        else: 
     192            outputStr +=  data_element_fmt % (element, instance) 
     193         
     194    logging.info("==== FUNCTIONS ====") 
     195    outputStr += category_fmt % "Functions" 
     196    for funcname in functions: 
     197        funcinst = eval('pyNN.common.%s' % funcname) 
     198        outputStr += function_fmt % func_sig(funcinst, default_arg_fmt, func_sig_fmt) 
     199        if funcinst.__doc__: 
     200            outputStr += _(funcinst.__doc__.strip()) 
     201        
     202    logging.info("==== CLASSES ====") 
     203    # sort classes by type: 
     204    error_classes = {} 
     205    celltype_classes = {} 
     206    other_classes = {} 
     207    for classname in classes.keys(): 
     208        if classname.find('Error') > -1: 
     209            error_classes[classname] = classes[classname] 
     210        elif issubclass(eval('pyNN.common.%s' % classname),pyNN.common.StandardCellType): 
     211            celltype_classes[classname] = classes[classname] 
     212        else: 
     213            other_classes[classname] = classes[classname] 
     214     
     215    logging.info('Sorting classes...') 
     216    logging.info('Error classes:    %s' % ', '.join(error_classes.keys())) 
     217    logging.info('Celltype classes: %s' % ', '.join(celltype_classes.keys())) 
     218    logging.info('Other classes:    %s' % ', '.join(other_classes.keys())) 
     219     
     220    # Now iterate through the classes 
     221    outputStr += category_fmt % "Classes" 
     222    for classes in [celltype_classes, other_classes, error_classes]: 
     223        classlist = classes.keys() 
     224        classlist.sort() 
     225        for classname in classlist: 
     226            outputStr += class_fmt % classname 
     227            docstr = eval('pyNN.common.%s.__doc__' % classname) 
     228            if docstr: 
     229                outputStr += _(docstr) 
     230            for methodname in classes[classname]['methods']: 
     231                methodinst = eval('pyNN.common.%s.%s' % (classname,methodname)) 
     232                fs = func_sig(methodinst, default_arg_fmt, func_sig_fmt) 
     233                if fs: 
     234                    outputStr += method_fmt % fs 
     235                    if methodinst.__doc__: 
     236                        outputStr += _(methodinst.__doc__.strip()) 
     237            for methodname in classes[classname]['staticmethods']: 
     238                methodinst = eval('pyNN.common.%s.%s' % (classname,methodname)) 
     239                fs = func_sig(methodinst, default_arg_fmt, func_sig_fmt) 
     240                if fs: 
     241                    outputStr += staticmethod_fmt % fs 
     242                    if methodinst.__doc__: 
     243                        outputStr += _(methodinst.__doc__.strip()) 
     244            for element in classes[classname]['data']: 
     245                instance = eval('pyNN.common.%s.%s' % (classname,element)) 
     246                if type(instance) == types.DictType: 
     247                    outputStr += dict_fmt % element 
     248                    if len(instance) > 0: 
     249                        outputStr += table_begin 
     250                        for k,v in instance.items(): 
     251                            if output == 'latex': 
     252                                v = str(v).replace('{',' $\\lbrace$').replace('}',' $\\rbrace$') 
     253                                outputStr += table_row_fmt % (k,v) 
     254                            elif output == 'wiki': 
     255                                outputStr += table_row_fmt % ('&quot;%s&quot;' % k,v) 
     256                            elif output == 'trac': 
     257                                outputStr += table_row_fmt % ("'%s'" % k,v) 
     258                        outputStr += table_end 
     259                    outputStr += dict_fmt_end 
    179260                else: 
    180                     logging.info('    %-28s excluded' % classentry) 
    181         elif  entry_type == types.FunctionType: 
    182             functions.append(entry) 
    183         elif entry_type == types.ModuleType: 
    184             pass 
    185         else: 
    186             data.append(entry) 
     261                    outputStr +=  data_element_fmt % (element, instance) 
     262                     
     263            outputStr += horiz_line 
     264         
     265    if output == 'latex': 
     266        outputStr = outputStr.replace('_','\_') 
     267        outputStr = outputStr.replace('>','$>$') 
     268        outputStr = outputStr.replace('<','$<$') 
     269        outputStr = leftquote.sub('`',outputStr) 
     270        outputStr = leftdblquote.sub('``',outputStr) 
     271    if output == 'trac': 
     272        outputStr = outputStr.replace('__','!__') 
     273        outputStr = camelcase.sub(r'!\1',outputStr) 
     274     
     275    return outputStr 
     276 
     277# ============================================================================== 
     278if __name__ == "__main__": 
     279     
     280    #-- Set up logging ------------------------------------------------------------- 
     281    logging.basicConfig(level=logging.DEBUG, 
     282                        format='%(asctime)s %(levelname)-8s %(message)s', 
     283                        datefmt='%Y%m%d-%H%M%S', 
     284                        filename='wikidoc.log', 
     285                        filemode='w') 
     286    # define a Handler which writes WARNING messages or higher to the sys.stderr 
     287    console = logging.StreamHandler() 
     288    console.setLevel(logging.WARNING) 
     289    # set a format which is simpler for console use 
     290    formatter = logging.Formatter('%(message)s') 
     291    # tell the handler to use this format 
     292    console.setFormatter(formatter) 
     293    # add the handler to the root logger 
     294    logging.getLogger('').addHandler(console) 
     295     
     296    #-- Process command line parameters -------------------------------------------- 
     297    if len(sys.argv) > 1: 
     298        output = sys.argv[1] 
    187299    else: 
    188         logging.info('  %-30s excluded' % entry) 
    189  
    190 # output starts here 
    191 outputStr = '' 
    192 if output == 'latex': 
    193     outputStr += '\definecolor{brightblue}{rgb}{0.0,0.38,1.0}\n' 
    194     outputStr += '\definecolor{paleblue}{rgb}{0.5,0.5,1.0}\n' 
    195     outputStr += '\definecolor{grey}{rgb}{0.5,0.5,0.5}\n' 
    196  
    197 logging.info("==== DATA ====") 
    198 outputStr += category_fmt % "Data" 
    199 for element in data: 
    200     instance = eval('pyNN.common.%s' % element) 
    201     if type(instance) == types.DictType: 
    202         outputStr += dict_fmt % element 
    203         outputStr += table_begin 
    204         for k,v in instance.items(): 
    205             if output == 'latex': 
    206                 v = str(v).replace('{',' $\\lbrace$').replace('}',' $\\rbrace$') 
    207             outputStr += table_row_fmt % (k,v) 
    208         outputStr += table_end 
    209         outputStr += dict_fmt_end 
    210     else: 
    211         outputStr +=  data_element_fmt % (element, instance) 
    212      
    213 logging.info("==== FUNCTIONS ====") 
    214 outputStr += category_fmt % "Functions" 
    215 for funcname in functions: 
    216     funcinst = eval('pyNN.common.%s' % funcname) 
    217     outputStr += function_fmt % func_sig(funcinst) 
    218     if funcinst.__doc__: 
    219         outputStr += _(funcinst.__doc__.strip()) 
    220     
    221 logging.info("==== CLASSES ====") 
    222 # sort classes by type: 
    223 error_classes = {} 
    224 celltype_classes = {} 
    225 other_classes = {} 
    226 for classname in classes.keys(): 
    227     if classname.find('Error') > -1: 
    228         error_classes[classname] = classes[classname] 
    229     elif issubclass(eval('pyNN.common.%s' % classname),pyNN.common.StandardCellType): 
    230         celltype_classes[classname] = classes[classname] 
    231     else: 
    232         other_classes[classname] = classes[classname] 
    233  
    234 logging.info('Sorting classes...') 
    235 logging.info('Error classes:    %s' % ', '.join(error_classes.keys())) 
    236 logging.info('Celltype classes: %s' % ', '.join(celltype_classes.keys())) 
    237 logging.info('Other classes:    %s' % ', '.join(other_classes.keys())) 
    238  
    239 # Now iterate through the classes 
    240 outputStr += category_fmt % "Classes" 
    241 for classes in [celltype_classes, other_classes, error_classes]: 
    242     classlist = classes.keys() 
    243     classlist.sort() 
    244     for classname in classlist: 
    245         outputStr += class_fmt % classname 
    246         docstr = eval('pyNN.common.%s.__doc__' % classname) 
    247         if docstr: 
    248             outputStr += _(docstr) 
    249         for methodname in classes[classname]['methods']: 
    250             methodinst = eval('pyNN.common.%s.%s' % (classname,methodname)) 
    251             fs = func_sig(methodinst) 
    252             if fs: 
    253                 outputStr += method_fmt % fs 
    254                 if methodinst.__doc__: 
    255                     outputStr += _(methodinst.__doc__.strip()) 
    256         for methodname in classes[classname]['staticmethods']: 
    257             methodinst = eval('pyNN.common.%s.%s' % (classname,methodname)) 
    258             fs = func_sig(methodinst) 
    259             if fs: 
    260                 outputStr += staticmethod_fmt % fs 
    261                 if methodinst.__doc__: 
    262                     outputStr += _(methodinst.__doc__.strip()) 
    263         for element in classes[classname]['data']: 
    264             instance = eval('pyNN.common.%s.%s' % (classname,element)) 
    265             if type(instance) == types.DictType: 
    266                 outputStr += dict_fmt % element 
    267                 if len(instance) > 0: 
    268                     outputStr += table_begin 
    269                     for k,v in instance.items(): 
    270                         if output == 'latex': 
    271                             v = str(v).replace('{',' $\\lbrace$').replace('}',' $\\rbrace$') 
    272                             outputStr += table_row_fmt % (k,v) 
    273                         elif output == 'wiki': 
    274                             outputStr += table_row_fmt % ('&quot;%s&quot;' % k,v) 
    275                         elif output == 'trac': 
    276                             outputStr += table_row_fmt % ("'%s'" % k,v) 
    277                     outputStr += table_end 
    278                 outputStr += dict_fmt_end 
    279             else: 
    280                 outputStr +=  data_element_fmt % (element, instance) 
    281                  
    282         outputStr += horiz_line 
    283      
    284 if output == 'latex': 
    285     outputStr = outputStr.replace('_','\_') 
    286     outputStr = outputStr.replace('>','$>$') 
    287     outputStr = outputStr.replace('<','$<$') 
    288     outputStr = leftquote.sub('`',outputStr) 
    289     outputStr = leftdblquote.sub('``',outputStr) 
    290 if output == 'trac': 
    291     outputStr = outputStr.replace('__','!__') 
    292     outputStr = camelcase.sub(r'!\1',outputStr) 
    293  
    294 print outputStr 
     300        output = 'wiki' 
     301    logging.info('Generating API documentation in %s format' % output) 
     302    print apidoc(output)