PageRenderTime 42ms CodeModel.GetById 31ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/scripts/build_toolbox.py

https://bitbucket.org/cistrome/cistrome-harvard/
Python | 166 lines | 159 code | 4 blank | 3 comment | 7 complexity | 447e39b2bd05e8076e88f9a3746ddf9b MD5 | raw file
  1import os
  2import sys
  3from xml.etree import ElementTree as ET
  4
  5def prettify(elem):
  6    from xml.dom import minidom
  7    rough_string = ET.tostring(elem, 'utf-8')
  8    repaired = minidom.parseString(rough_string)
  9    return repaired.toprettyxml(indent='  ')
 10
 11# Build a list of all toolconf xml files in the tools directory
 12def getfilenamelist(startdir):
 13    filenamelist = []
 14    for root, dirs, files in os.walk(startdir):
 15        for fn in files:
 16            fullfn = os.path.join(root, fn)
 17            if fn.endswith('toolconf.xml'):
 18                filenamelist.append(fullfn)
 19            elif fn.endswith('.xml'):
 20                try:
 21                    doc = ET.parse(fullfn)
 22                except:
 23                    print "An OOPS on", fullfn
 24                    raise
 25                rootelement = doc.getroot()
 26                # Only interpret those 'tool' XML files that have
 27                # the 'section' element.
 28                if rootelement.tag == 'tool':
 29                    if rootelement.findall('toolboxposition'):
 30                        filenamelist.append(fullfn)
 31                    else:
 32                        print "DBG> tool config does not have a <section>:", fullfn
 33    return filenamelist
 34
 35class ToolBox(object):
 36    def __init__(self):
 37        from collections import defaultdict
 38        self.tools = defaultdict(list)
 39        self.sectionorders = {}
 40
 41    def add(self, toolelement, toolboxpositionelement):
 42        section = toolboxpositionelement.attrib.get('section','')
 43        label = toolboxpositionelement.attrib.get('label','')
 44        order = int(toolboxpositionelement.attrib.get('order', '0'))
 45        sectionorder = int(toolboxpositionelement.attrib.get('sectionorder', '0'))
 46
 47        # If this is the first time we encounter the section, store its order
 48        # number. If we have seen it before, ignore the given order and use
 49        # the stored one instead
 50        if not self.sectionorders.has_key(section):
 51            self.sectionorders[section] = sectionorder
 52        else:
 53            sectionorder = self.sectionorders[section]
 54
 55        # Sortorder: add intelligent mix to the front
 56        self.tools[("%05d-%s"%(sectionorder,section), label, order, section)].append(toolelement)
 57
 58    def addElementsTo(self, rootelement):
 59        toolkeys = self.tools.keys()
 60        toolkeys.sort()
 61
 62        # Initialize the loop: IDs to zero, current section and label to ''
 63        currentsection = ''
 64        sectionnumber = 0
 65        currentlabel = ''
 66        labelnumber = 0
 67        for toolkey in toolkeys:
 68            section = toolkey[3]
 69            # If we change sections, add the new section to the XML tree,
 70            # and start adding stuff to the new section. If the new section
 71            # is '', start adding stuff to the root again.
 72            if currentsection != section:
 73                currentsection = section
 74                # Start the section with empty label
 75                currentlabel = ''
 76                if section:
 77                    sectionnumber += 1
 78                    attrib = {'name': section,
 79                              'id': "section%d"% sectionnumber}
 80                    sectionelement = ET.Element('section', attrib)
 81                    rootelement.append(sectionelement)
 82                    currentelement = sectionelement
 83                else:
 84                    currentelement = rootelement
 85            label = toolkey[1]
 86
 87            # If we change labels, add the new label to the XML tree
 88            if currentlabel != label:
 89                currentlabel = label
 90                if label:
 91                    labelnumber += 1
 92                    attrib = {'text': label,
 93                              'id': "label%d"% labelnumber}
 94                    labelelement = ET.Element('label', attrib)
 95                    currentelement.append(labelelement)
 96
 97            # Add the tools that are in this place
 98            for toolelement in self.tools[toolkey]:
 99                currentelement.append(toolelement)
100        
101# Analyze all the toolconf xml files given in the filenamelist 
102# Build a list of all sections
103def scanfiles(filenamelist):
104    # Build an empty tool box
105    toolbox = ToolBox()
106
107    # Read each of the files in the list
108    for fn in filenamelist: 
109        doc = ET.parse(fn)
110        root = doc.getroot()
111        
112        if root.tag == 'tool':
113            toolelements = [root]
114        else:
115            toolelements = doc.findall('tool')
116            
117        for toolelement in toolelements:
118            # Figure out where the tool XML file is, absolute path.
119            if toolelement.attrib.has_key('file'):
120                # It is mentioned, we need to make it absolute
121                fileattrib = os.path.join(os.getcwd(),
122                                          os.path.dirname(fn),
123                                          toolelement.attrib['file'])
124            else:
125                # It is the current file
126                fileattrib = os.path.join(os.getcwd(), fn)
127
128            # Store the file in the attibutes of the new tool element
129            attrib = {'file': fileattrib}
130
131            # Add the tags into the attributes
132            tags = toolelement.find('tags')
133            if tags:
134                tagarray = []
135                for tag in tags.findall('tag'):
136                    tagarray.append(tag.text)
137                attrib['tags'] = ",".join(tagarray)
138            else:
139                print "DBG> No tags in",fn
140
141            # Build the tool element
142            newtoolelement = ET.Element('tool', attrib)
143            toolboxpositionelements = toolelement.findall('toolboxposition')
144            if not toolboxpositionelements:
145                print "DBG> %s has no toolboxposition" % fn
146            else:
147                for toolboxpositionelement in toolboxpositionelements:
148                    toolbox.add(newtoolelement, toolboxpositionelement)
149    return toolbox
150
151def assemble():
152    filenamelist = []
153    for directorytree in ['tools']:
154        filenamelist.extend(getfilenamelist('tools'))
155    filenamelist.sort()
156
157    toolbox = scanfiles(filenamelist)
158
159    toolboxelement = ET.Element('toolbox')
160
161    toolbox.addElementsTo(toolboxelement)
162    
163    print prettify(toolboxelement)
164    
165if __name__ == "__main__":
166    assemble()