Orb/python/doxygen/component_map_creator.py
changeset 1 82f11024044a
parent 0 42188c7ea2d9
equal deleted inserted replaced
0:42188c7ea2d9 1:82f11024044a
    12 #
    12 #
    13 import unittest
    13 import unittest
    14 import os
    14 import os
    15 import shutil
    15 import shutil
    16 import sys
    16 import sys
       
    17 import xml
       
    18 import logging
    17 from optparse import OptionParser
    19 from optparse import OptionParser
    18 from xml.etree import ElementTree as etree
    20 from xml.etree import ElementTree as etree
    19 from lib import scan, xml_decl, doctype_identifier
    21 from lib import scan, xml_decl, doctype_identifier
    20 
    22 
    21 __version__ = "0.1"
    23 __version__ = "0.1"
    36     def _get_component_names(self):
    38     def _get_component_names(self):
    37         component_names = [d for d in os.listdir(self.build_dir) if os.path.isdir(os.path.join(self.build_dir, d))]
    39         component_names = [d for d in os.listdir(self.build_dir) if os.path.isdir(os.path.join(self.build_dir, d))]
    38         component_names.sort()
    40         component_names.sort()
    39         return component_names 
    41         return component_names 
    40     
    42     
    41     def _get_ditamap_names_for_component_dir(self, component_dir):
    43     def _get_ditamaps_for_component(self, component_name):
    42         self._check_dir_exists(component_dir)
    44         component_dir = self._get_component_dir_for_component(component_name)
    43         ditamap_names = []
    45         ditamaps = []
    44         for root, dirs, files in os.walk(component_dir):
    46         for root, dirs, files in os.walk(component_dir):
    45             ditamap_names.extend([os.path.splitext(f)[0] for f in files if f.lower().endswith(".ditamap")])
    47             for filename in (filename for filename in files if filename.lower().endswith(".ditamap")):
    46         ditamap_names.sort()
    48                 ditamaps.append(os.path.join(root, filename))
    47         return ditamap_names
    49         return ditamaps
    48     
    50     
    49     def _get_component_dir_for_component(self, component):
    51     def _get_component_dir_for_component(self, component):
    50         return os.path.join(self.build_dir, component)
    52         return os.path.join(self.build_dir, component)
    51     
    53     
    52     def _create_topicref(self, target_name):
    54     def _create_topicref(self, target_name):
    53         return etree.Element("topicref", href=target_name+".ditamap", type="ditamap")
    55         return etree.Element("topicref", href=target_name+".ditamap", format="ditamap")
    54     
    56     
    55     def _create_topichead(self, target_name):
    57     def _get_topicrefs_from_map(self, ditamap):
    56         topichead = etree.Element("topichead", navtitle=target_name)
    58         try:
    57         topichead.append(self._create_topicref(target_name))
    59             root = etree.parse(ditamap).getroot()
    58         return topichead
    60         except xml.parsers.expat.ExpatError, e:
    59     
    61             logging.error("Could not parse ditamap: %s, error was: %s " % (ditamap, e))
    60     def _create_map(self, component_name):
    62             return None
    61         return etree.Element("map", title=component_name, id="cmp_"+component_name)
    63         else:
    62     
    64             return root.getchildren()
    63     def _create_ditamap(self, component_name):
    65     
    64         root = self._create_map(component_name)
    66     def _get_topicrefs_for_component(self, component_name):
    65         for topichead in self._get_topicheads_for_component(component_name):
    67         topicrefs = []
    66             root.append(topichead)
    68         seen = []
    67         return root
    69         for ditamap in self._get_ditamaps_for_component(component_name):
    68     
    70             target_topicrefs = self._get_topicrefs_from_map(ditamap)
    69     def _get_topicheads_for_component(self, component_name):
    71             if target_topicrefs is not None:
    70         topicheads = []
    72                 for topicref in target_topicrefs:
    71         for ditamap_name in self._get_ditamap_names_for_component_dir(self._get_component_dir_for_component(component_name)):
    73                     if not topicref.attrib['navtitle'] in seen:
    72             topicheads.append(self._create_topichead(ditamap_name))
    74                         seen.append(topicref.attrib['navtitle'])
    73         topicheads.sort()
    75                         topicrefs.append(topicref)
    74         return topicheads
    76         topicrefs.sort()
    75     
    77         return topicrefs
    76     def _write_ditamap_for_component(self, component_name):
    78     
    77         f = open(os.path.join(self.output_dir, "cmp_"+component_name+".ditamap"), "w")
    79     def _create_map_root(self, component_name):
    78         f.write(xml_decl()+"\n")
    80         return etree.Element("cxxAPIMap", title=component_name, id='cmp_'+component_name)    
    79         f.write(doctype_identifier("map")+"\n")
    81 
    80         map = self._create_ditamap(component_name)
    82     def _get_ditamap(self, component_name):
    81         f.write(etree.tostring(map))
    83         root = self._create_map_root(component_name)
    82         f.close()
    84         for topicref in self._get_topicrefs_for_component(component_name):
       
    85             root.append(topicref)
       
    86         if len(root.getchildren()) > 0: # If the component does not link to anything 
       
    87             return root                 # return None (instead of an empty map)
       
    88         else:
       
    89             return None    
       
    90     
       
    91     def _handle_component(self, component_name):
       
    92         map = self._get_ditamap(component_name)
       
    93         if map is not None:
       
    94             f = open(os.path.join(self.output_dir, 'cmp_'+component_name+".ditamap"), "w")
       
    95             f.write(xml_decl()+"\n")
       
    96             f.write(doctype_identifier("cxxAPIMap")+"\n")
       
    97             f.write(etree.tostring(map))
       
    98             f.close()
       
    99         else:
       
   100             logging.info("No component ditamap needed to be generated for component \"%s\"" % component_name)
    83                 
   101                 
    84     def create_component_maps(self):
   102     def create_component_maps(self):
    85         components = self._get_component_names()
   103         components = self._get_component_names()
    86         for component in components:
   104         for component in components:
    87             self._write_ditamap_for_component(component)     
   105             self._handle_component(component)     
       
   106             
    88             
   107             
    89 def create_component_maps(build_dir, output_dir):
   108 def create_component_maps(build_dir, output_dir):
    90     cmp = ComponentMapCreator(build_dir, output_dir)
   109     cmp = ComponentMapCreator(build_dir, output_dir)
    91     cmp.create_component_maps()
   110     cmp.create_component_maps()
    92             
   111             
   104 if __name__ == '__main__':
   123 if __name__ == '__main__':
   105     sys.exit(main(func=create_component_maps))
   124     sys.exit(main(func=create_component_maps))
   106     
   125     
   107                 
   126                 
   108 cmp_audiomsg_ditamap = """<?xml version="1.0" encoding="UTF-8"?>
   127 cmp_audiomsg_ditamap = """<?xml version="1.0" encoding="UTF-8"?>
   109 <!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
   128 <!DOCTYPE cxxAPIMap PUBLIC "-//NOKIA//DTD DITA C++ API Map Reference Type v0.5.0//EN" "dtd/cxxAPIMap.dtd" >
   110 <map id="cmp_audiomsg" title="audiomsg"><topichead navtitle="audiomessage"><topicref href="audiomessage.ditamap" type="ditamap" /></topichead></map>"""
   129 <cxxAPIMap id="cmp_audiomsg" title="audiomsg"><cxxStructRef href="struct___array_util.xml#_ArrayUtil" navtitle="_ArrayUtil" />
   111 
   130     </cxxAPIMap>"""
   112 audiomessage_ditamap = """
   131 
   113 <?xml version='1.0' encoding='UTF-8' standalone='no'?>
   132 audiomessage_ditamap = """<?xml version='1.0' encoding='UTF-8' standalone='no'?>
   114 <!DOCTYPE cxxAPIMap PUBLIC "-//NOKIA//DTD DITA C++ API Map Reference Type v0.1.0//EN" "dtd/cxxAPIMap.dtd" >
   133 <!DOCTYPE cxxAPIMap PUBLIC "-//NOKIA//DTD DITA C++ API Map Reference Type v0.1.0//EN" "dtd/cxxAPIMap.dtd" >
   115 <cxxAPIMap id="audiomessage" title="audiomessage">
   134 <cxxAPIMap id="audiomessage" title="audiomessage">
   116     <cxxStructRef href="struct___array_util.xml#_ArrayUtil" navtitle="_ArrayUtil"/>
   135     <cxxStructRef href="struct___array_util.xml#_ArrayUtil" navtitle="_ArrayUtil"/>
       
   136     <cxxStructRef href="struct___array_util.xml#_ArrayUtil" navtitle="_ArrayUtil"/>
   117 </cxxAPIMap>
   137 </cxxAPIMap>
   118 """
   138 """
       
   139 
       
   140 empty_target_ditamap = """<?xml version='1.0' encoding='UTF-8' standalone='no'?>
       
   141 <!DOCTYPE cxxAPIMap PUBLIC "-//NOKIA//DTD DITA C++ API Map Reference Type v0.1.0//EN" "dtd/cxxAPIMap.dtd" >
       
   142 <cxxAPIMap id="empty_target" title="empty_target">
       
   143 </cxxAPIMap>
       
   144 """
       
   145 
   119 
   146 
   120 class TestComponentCreator(unittest.TestCase):
   147 class TestComponentCreator(unittest.TestCase):
   121     def setUp(self):
   148     def setUp(self):
   122         self.test_build_dir = os.path.join(os.getcwd(), "test_build_dir")
   149         self.test_build_dir = os.path.join(os.getcwd(), "test_build_dir")
   123         self._create_test_build_dir()
   150         self._create_test_build_dir()
   128     def tearDown(self):
   155     def tearDown(self):
   129         self._clean_test_build_dir()
   156         self._clean_test_build_dir()
   130         self._clean_output_dir()
   157         self._clean_output_dir()
   131         
   158         
   132     def _create_test_build_dir(self):
   159     def _create_test_build_dir(self):
   133         # Create 3 components
   160         # Create 2 components
   134         for comp_name in ("audiomsg", "console", "autotest"):
   161         for comp_name in ("audiomsg", "component_with_no_dita_in_it"):
   135             os.makedirs(os.path.join(self.test_build_dir, comp_name))
   162             os.makedirs(os.path.join(self.test_build_dir, comp_name))
   136         # Create logfiles
   163         # Create logfiles
   137         makefile = open(os.path.join(self.test_build_dir, "Makefile"), "w")
   164         makefile = open(os.path.join(self.test_build_dir, "Makefile"), "w")
   138         logfile = open(os.path.join(self.test_build_dir, "logfile.log"), "w")
   165         logfile = open(os.path.join(self.test_build_dir, "logfile.log"), "w")
   139         # Create target ditamap
   166         # Create target ditamaps
   140         audiomessage_ditamap_dir = os.path.join(self.test_build_dir, "audiomsg", "c_96422b786aab3b96", "audiomessage_exe", "dox", "dita")
   167         audiomessage_ditamap_dir = os.path.join(self.test_build_dir, "audiomsg", "c_96422b786aab3b96", "audiomessage_exe", "dox", "dita")
   141         audiomessage_ditamap_path = os.path.join(audiomessage_ditamap_dir, "audiomessage.ditamap") 
   168         empty_target_ditamap_dir = os.path.join(self.test_build_dir, "audiomsg", "c_96422b786aab3b96", "empty_target_exe", "dox", "dita")
       
   169         self.audiomessage_ditamap_path = os.path.join(audiomessage_ditamap_dir, "audiomessage.ditamap")
       
   170         self.empty_target_ditamap_path = os.path.join(empty_target_ditamap_dir, "empty_target.ditamap") 
   142         os.makedirs(audiomessage_ditamap_dir)
   171         os.makedirs(audiomessage_ditamap_dir)
   143         audiomessage_ditamap_handle = open(audiomessage_ditamap_path, "w")
   172         os.makedirs(empty_target_ditamap_dir)
       
   173         audiomessage_ditamap_handle = open(self.audiomessage_ditamap_path, "w")
   144         audiomessage_ditamap_handle.write(audiomessage_ditamap)
   174         audiomessage_ditamap_handle.write(audiomessage_ditamap)
   145         audiomessage_ditamap_handle.close()
   175         audiomessage_ditamap_handle.close()
   146 
   176         empty_target_ditamap_handle = open(self.empty_target_ditamap_path, "w")
       
   177         empty_target_ditamap_handle.write(empty_target_ditamap)
       
   178         empty_target_ditamap_handle.close()
       
   179         
   147     def _create_output_dir(self):
   180     def _create_output_dir(self):
   148         os.mkdir(self.output_dir)    
   181         os.mkdir(self.output_dir)    
   149             
   182             
   150     def _clean_test_build_dir(self):
   183     def _clean_test_build_dir(self):
   151         shutil.rmtree(self.test_build_dir)
   184         shutil.rmtree(self.test_build_dir)
   153     def _clean_output_dir(self):
   186     def _clean_output_dir(self):
   154         shutil.rmtree(self.output_dir)    
   187         shutil.rmtree(self.output_dir)    
   155                     
   188                     
   156     def test_i_return_all_the_component_names_when_passed_a_dir(self):
   189     def test_i_return_all_the_component_names_when_passed_a_dir(self):
   157         component_names = self.cmp._get_component_names()
   190         component_names = self.cmp._get_component_names()
   158         self.assertEquals(component_names, ["audiomsg", "autotest", "console"])
   191         self.assertEquals(component_names, ["audiomsg", "component_with_no_dita_in_it"])
   159             
   192             
   160     def test_i_return_all_target_ditamap_names_for_a_component(self):
   193     def test_i_return_all_target_ditamaps_for_a_component(self):
   161         target_ditamap_names = self.cmp._get_ditamap_names_for_component_dir(os.path.join(self.test_build_dir, "audiomsg"))
   194         target_ditamaps = self.cmp._get_ditamaps_for_component("audiomsg")
   162         self.assertEquals(target_ditamap_names, ["audiomessage"])
   195         self.assertEquals(target_ditamaps, [self.audiomessage_ditamap_path, self.empty_target_ditamap_path])
   163         
   196         
   164     def test_i_return_a_component_directory_for_a_component(self):
   197     def test_i_return_a_component_directory_for_a_component(self):
   165         component_dir = self.cmp._get_component_dir_for_component("audiomsg")
   198         component_dir = self.cmp._get_component_dir_for_component("audiomsg")
   166         self.assertEquals(component_dir, os.path.join(self.test_build_dir, "audiomsg"))
   199         self.assertEquals(component_dir, os.path.join(self.test_build_dir, "audiomsg"))
   167         
   200         
   168     def test_i_return_a_topicref_element_for_a_target(self):
       
   169         topicref = self.cmp._create_topicref("audiomessage")
       
   170         self.assertEquals(topicref.attrib["href"], "audiomessage.ditamap")
       
   171         self.assertEquals(topicref.attrib["type"], "ditamap")
       
   172         
       
   173     def test_i_return_a_list_of_topicheads_for_a_component(self):
       
   174         topicheads = self.cmp._get_topicheads_for_component("audiomsg")
       
   175         self.assertEquals(len(topicheads), 1)
       
   176         
       
   177         
       
   178     def test_i_create_a_ditamap_for_a_component(self):
   201     def test_i_create_a_ditamap_for_a_component(self):
   179         ditamap = self.cmp._create_ditamap("audiomsg")
   202         ditamap = self.cmp._get_ditamap("audiomsg")
   180         self.assertEquals(ditamap.tag, "map") 
   203         self.assertEquals(ditamap.tag, "cxxAPIMap") 
   181         self.assertEquals(ditamap.attrib.get("title", ""), "audiomsg")
   204         self.assertEquals(ditamap.attrib.get("title", ""), "audiomsg")
   182         self.assertEquals(ditamap.attrib.get("id", ""), "cmp_audiomsg")
   205         self.assertEquals(ditamap.attrib.get("id", ""), "cmp_audiomsg")
   183         
   206         
       
   207     def test_i_dont_create_a_ditamap_for_a_component_with_no_dita(self):
       
   208         ditamap = self.cmp._get_ditamap("component_with_no_dita_in_it")
       
   209         self.assertEquals(ditamap, None)
       
   210         
   184     def test_i_can_write_out_a_ditamap_file_for_a_component(self): 
   211     def test_i_can_write_out_a_ditamap_file_for_a_component(self): 
   185         self.cmp._write_ditamap_for_component("audiomsg")
   212         self.cmp._handle_component("audiomsg")
   186         self.assertTrue(os.path.exists(os.path.join(self.output_dir,"cmp_audiomsg.ditamap")))
   213         self.assertTrue(os.path.exists(os.path.join(self.output_dir,"cmp_audiomsg.ditamap")))
   187         map = open(os.path.join(self.output_dir,"cmp_audiomsg.ditamap"),"r").read()
   214         map = open(os.path.join(self.output_dir,"cmp_audiomsg.ditamap"),"r").read()        
   188         print map
       
   189         print cmp_audiomsg_ditamap
       
   190         self.assertEquals(map, cmp_audiomsg_ditamap)
   215         self.assertEquals(map, cmp_audiomsg_ditamap)
   191         
   216         
   192     def test_i_write_component_maps(self):
   217     def test_i_write_component_maps(self):
   193         self.cmp.create_component_maps()
   218         self.cmp.create_component_maps()
   194         file_list = os.listdir(self.output_dir)
   219         file_list = os.listdir(self.output_dir)
   195         file_list.sort()
   220         file_list.sort()
   196         self.assertEquals(file_list, ["cmp_audiomsg.ditamap", "cmp_autotest.ditamap", "cmp_console.ditamap"])    
   221         self.assertEquals(file_list, ["cmp_audiomsg.ditamap"])