get_documentation.py

Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 # vin: sw=3 et:
00003 '''
00004 Copyright (C) 2012, Digium, Inc.
00005 Matt Jordan <mjordan@digium.com>
00006 
00007 This program is free software, distributed under the terms of
00008 the GNU General Public License Version 2.
00009 '''
00010 
00011 import sys
00012 import os
00013 import xml.dom.minidom
00014 
00015 from xml.dom.minidom import Element
00016 
00017 
00018 def get_manager_event_method_type(candidate_string):
00019     if "ast_manager_event_multichan" in candidate_string:
00020         return "multichan"
00021     elif "ast_manager_event" in candidate_string:
00022         return "ast_manager_event"
00023     elif "manager_event" in candidate_string:
00024         return "manager_event"
00025     return ""
00026 
00027 
00028 def parse_manager_event_instance(xml_fragment):
00029     ''' Parse the information for a manager event
00030 
00031     Keyword Arguments:
00032     xml_fragment    The XML fragment comment
00033 
00034     Returns:
00035     A well-formed XML fragment containing the comments passed in, as well as
00036     information obtained from the manager_event macro calls
00037     '''
00038 
00039     def __node_contains_parameter(node, parameter):
00040         ''' Return whether or not a node contains a given parameter name '''
00041         return any([n for n in node.getElementsByTagName("parameter")
00042                     if __node_contains_attribute(n, parameter)])
00043 
00044     def __node_contains_attribute(node, attribute_name):
00045         ''' Return whether or not a node contains a given attribute name '''
00046         return any([attr for attr in node.attributes.items()
00047                     if attr[1] == attribute_name])
00048 
00049     candidate_lines = []
00050     type = ""
00051 
00052     # Read the manager_event method call, which should occur after
00053     # the documentation block
00054     for line in sys.stdin:
00055         if len(line):
00056             candidate_lines.append(line)
00057         if ");" in line:
00058             break
00059 
00060     candidate_string = ''.join(candidate_lines)
00061     type = get_manager_event_method_type(candidate_string)
00062     if not type:
00063         # Unknown, return what we have
00064         return ''.join(xml_fragment)
00065 
00066     # strip off the macro name
00067     first_paren = candidate_string.index("(", 0)
00068     last_paren = candidate_string.rindex(");")
00069     candidate_string = candidate_string[first_paren + 1:last_paren]
00070 
00071     # split into parameter tokens
00072     func_parameter_tokens = candidate_string.split(',')
00073 
00074     if type == "manager_event" or type == "multichan":
00075         class_level = func_parameter_tokens[0].strip()
00076         event_type = func_parameter_tokens[1].strip()
00077     else:
00078         class_level = func_parameter_tokens[1].strip()
00079         event_type = func_parameter_tokens[2].strip()
00080 
00081     if type == "manager_event":
00082         event_parameters = func_parameter_tokens[2].strip()
00083     elif type == "ast_manager_event":
00084         event_parameters = func_parameter_tokens[3].strip()
00085     else:
00086         event_parameters = func_parameter_tokens[4].strip()
00087 
00088     parameter_tokens = event_parameters.replace("\"", "").split('\\r\\n')
00089 
00090     # Build the top level XML element information.  Note that we temporarily
00091     # add the xi namespace in case any includes are used
00092     node_text = '<managerEvent language=\"%s\" name=\"%s\" xmlns:xi=\"%s\">'
00093     xml_fragment.insert(0, node_text % ('en_US',
00094                                         event_type.strip().replace("\"", ""),
00095                                         'http://www.w3.org/2001/XInclude'))
00096     xml_fragment[1] = "<managerEventInstance class=\"%s\">" % (class_level)
00097     xml_fragment.insert(len(xml_fragment), "</managerEvent>")
00098 
00099     # Turn the XML into a DOM to manage the rest of the node manipulations
00100     dom = xml.dom.minidom.parseString(''.join(xml_fragment))
00101 
00102     # Get the syntax node if we have one; otherwise make one
00103     instance = dom.getElementsByTagName("managerEventInstance")[0]
00104     syntax = instance.getElementsByTagName("syntax")
00105     if not syntax:
00106         syntax = dom.createElement("syntax")
00107         instance.appendChild(syntax)
00108         # Move any existing parameter nodes over
00109         for node in instance.getElementsByTagName("parameter"):
00110             syntax.appendChild(node.cloneNode(True))
00111             instance.removeChild(node)
00112     else:
00113         syntax = syntax[0]
00114 
00115     # Add parameters found in the method invocation that were not previously
00116     # documented
00117     for parameter in parameter_tokens:
00118         if not len(parameter):
00119             continue
00120         index = parameter.find(':')
00121         if index < 0:
00122             index = len(parameter)
00123         parameter = (parameter[:index].strip().replace("\"", ""))
00124         if ('%s' not in parameter and
00125             not __node_contains_parameter(syntax, parameter)):
00126             e = dom.createElement("parameter")
00127             e.setAttribute('name', parameter)
00128             syntax.appendChild(e)
00129 
00130     return dom.toxml().replace("<?xml version=\"1.0\" ?>", "").replace(
00131                'xmlns:xi="http://www.w3.org/2001/XInclude"', '')
00132 
00133 
00134 def main(argv=None):
00135 
00136     if argv is None:
00137         argv = sys.argv
00138 
00139     in_doc = False
00140     xml_fragment = []
00141     xml = []
00142     line_number = 0
00143 
00144     for line in sys.stdin:
00145         # Note: multiple places may have to read a line, so iterating over
00146         # readlines isn't possible.  Break when a null line is returned
00147         line_number += 1
00148         if not line:
00149             break
00150 
00151         line = line.strip()
00152         if ("/*** DOCUMENTATION" in line):
00153             in_doc = True
00154         elif ("***/" in line and in_doc):
00155             # Depending on what we're processing, determine if we need to do
00156             # any additional work
00157             in_doc = False
00158             if not xml_fragment:
00159                 # Nothing read, move along
00160                 continue
00161 
00162             if "<managerEventInstance>" in xml_fragment[0]:
00163                 xml.append(parse_manager_event_instance(xml_fragment))
00164             else:
00165                 xml.append(''.join(xml_fragment))
00166 
00167             xml_fragment = []
00168         elif (in_doc):
00169             xml_fragment.append("%s\n" % line)
00170 
00171     sys.stdout.write(''.join(xml))
00172     return 0
00173 
00174 if __name__ == "__main__":
00175     sys.exit(main() or 0)

Generated on Thu Apr 16 06:27:36 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6