export.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. '''
  2. Created on 29/01/2013
  3. @author: konstaa
  4. '''
  5. import logging
  6. import time
  7. import re
  8. import core.log
  9. import core.db.loader
  10. import core.db.post
  11. import core.db.utils
  12. import core.cmdparser
  13. import core.export.convert
  14. def main():
  15. exit_code = 0
  16. log_plugin = core.log.Plugin()
  17. db_plugin = core.db.post.Plugin()
  18. parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- <path 1> ... <path N>")
  19. log_plugin.declare_configuration(parser)
  20. db_plugin.declare_configuration(parser)
  21. parser.add_option("--general.format", default='xml', choices=['txt', 'xml', 'python'], help="Format of the output data [default: %default]")
  22. parser.add_option("--general.namespaces", default=None, help="Allows to enumerate namespaces of interest."
  23. " If not defined all namespaces available in database file will be processed."
  24. " Separate several namespaces by comma, for example 'general,std.code.complexity'"
  25. " [default: %default]")
  26. (options, args) = parser.parse_args()
  27. log_plugin.configure(options)
  28. db_plugin.configure(options)
  29. out_format = options.__dict__['general.format']
  30. namespaces = None
  31. if options.__dict__['general.namespaces'] != None:
  32. namespaces = re.split(',', options.__dict__['general.namespaces'])
  33. loader_prev = core.db.loader.Loader()
  34. if db_plugin.dbfile_prev != None:
  35. loader_prev.open_database(db_plugin.dbfile_prev)
  36. loader = core.db.loader.Loader()
  37. loader.open_database(db_plugin.dbfile)
  38. paths = None
  39. if len(args) == 0:
  40. paths = [""]
  41. else:
  42. paths = args
  43. if out_format == 'txt':
  44. print "=" * 80 + "\n" + "Export" + "\n" + "_" * 80 + "\n"
  45. elif out_format == 'xml':
  46. print "<export>"
  47. elif out_format == 'python':
  48. print "{'export': ["
  49. for (ind, path) in enumerate(paths):
  50. logging.info("Processing: " + path)
  51. aggregated_data = loader.load_aggregated_data(path, namespaces=namespaces)
  52. aggregated_data_tree = {}
  53. subdirs = []
  54. subfiles = []
  55. if aggregated_data != None:
  56. aggregated_data_tree = aggregated_data.get_data_tree(namespaces=namespaces)
  57. subdirs = aggregated_data.get_subdirs()
  58. subfiles = aggregated_data.get_subfiles()
  59. else:
  60. logging.error("Specified path '" + path + "' is invalid (not found in the database records)")
  61. exit_code += 1
  62. aggregated_data_prev = loader_prev.load_aggregated_data(path, namespaces=namespaces)
  63. if aggregated_data_prev != None:
  64. aggregated_data_tree = append_diff(aggregated_data_tree,
  65. aggregated_data_prev.get_data_tree(namespaces=namespaces))
  66. file_data = loader.load_file_data(path)
  67. file_data_tree = {}
  68. if file_data != None:
  69. file_data_tree = file_data.get_data_tree(namespaces=namespaces)
  70. file_data_prev = loader_prev.load_file_data(path)
  71. regions_matcher = None
  72. if file_data_prev != None:
  73. file_data_tree = append_diff(file_data_tree,
  74. file_data_prev.get_data_tree(namespaces=namespaces))
  75. regions_matcher = core.db.utils.FileRegionsMatcher(file_data, file_data_prev)
  76. regions = []
  77. for each in file_data.iterate_regions():
  78. region_data_tree = each.get_data_tree(namespaces=namespaces)
  79. if regions_matcher != None and regions_matcher.is_matched(each.id):
  80. region_data_prev = file_data_prev.get_region(regions_matcher.get_prev_id(each.id))
  81. region_data_tree = append_diff(region_data_tree,
  82. region_data_prev.get_data_tree(namespaces=namespaces))
  83. regions.append({"info": {"name" : each.name,
  84. 'type' : file_data.get_region_types()().to_str(each.get_type()),
  85. "cursor" : each.cursor,
  86. 'line_begin': each.line_begin,
  87. 'line_end': each.line_end,
  88. 'offset_begin': each.begin,
  89. 'offset_end': each.end},
  90. "data": region_data_tree})
  91. file_data_tree['regions'] = regions
  92. data = {"info": {"path": path, "id": ind + 1},
  93. "aggregated-data": aggregated_data_tree,
  94. "file-data": file_data_tree,
  95. "subdirs": subdirs,
  96. "subfiles": subfiles}
  97. if out_format == 'txt':
  98. print core.export.convert.to_txt(data, root_name = "data")
  99. elif out_format == 'xml':
  100. print core.export.convert.to_xml(data, root_name = "data")
  101. elif out_format == 'python':
  102. postfix = ""
  103. if ind < len(paths) - 1:
  104. postfix = ", "
  105. print core.export.convert.to_python(data, root_name = "data") + postfix
  106. if out_format == 'txt':
  107. print "\n"
  108. elif out_format == 'xml':
  109. print "</export>"
  110. elif out_format == 'python':
  111. print "]}"
  112. return exit_code
  113. def append_diff(main_tree, prev_tree):
  114. assert(main_tree != None)
  115. assert(prev_tree != None)
  116. for name in main_tree.keys():
  117. if name not in prev_tree.keys():
  118. continue
  119. for field in main_tree[name].keys():
  120. if field not in prev_tree[name].keys():
  121. continue
  122. if isinstance(main_tree[name][field], dict) and isinstance(prev_tree[name][field], dict):
  123. diff = {}
  124. for key in main_tree[name][field].keys():
  125. if key not in prev_tree[name][field].keys():
  126. continue
  127. diff[key] = main_tree[name][field][key] - prev_tree[name][field][key]
  128. main_tree[name][field]['__diff__'] = diff
  129. elif (not isinstance(main_tree[name][field], dict)) and (not isinstance(prev_tree[name][field], dict)):
  130. if '__diff__' not in main_tree[name]:
  131. main_tree[name]['__diff__'] = {}
  132. main_tree[name]['__diff__'][field] = main_tree[name][field] - prev_tree[name][field]
  133. return main_tree
  134. if __name__ == '__main__':
  135. ts = time.time()
  136. core.log.set_default_format()
  137. exit_code = main()
  138. logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
  139. exit(exit_code)