提取python项目中的类关系

来源:互联网 发布:人口普查数据 编辑:程序博客网 时间:2024/05/18 21:41

代码对对python项目中的父子类关系进行提取。当然目前只做到了简单的提取工作,具体的分析并没有做。由于python中支持多继承,因此当有非常多的类以后,这个图不知道怎么画比较合适,等以后有时间想出了好的解决方案再来实施。下面是具体的python代码

#!/bin/python3import reimport osclass InfoCollector(object):def __init__(self):self.match_table = self._build_match_table()#class_relation store the known class relationself.class_relation = []#module_table used to map the short module name with full nameself.module_table = {}self.classs = []def _build_match_table(self):''' lines match in the keys order '''keys = ['class', 'import_as', 'import', 'from_import_as', 'from_import']match_table = []for key in keys:regex = self.__getattribute__('_PATTERN_STR_' + key.upper())proc = self.__getattribute__('_proc_' + key + '_match')match_table.append((key, regex, proc, re.compile(regex)))return match_table_PATTERN_STR_CLASS = r"^class (.*)\((.*)\):$"def _proc_class_match(self, match):child_class = match.groups()[0].strip()parents_class = match.groups()[1].strip()print("child_class:%s parent_class:%s" % (child_class, parents_class))parents = parents_class.split(',')for parent in parents:parent = parent.strip()if '.' in parent:path, sp, klass = parent.rpartition('.')abs_path = self.module_table.get(path, path)parent_class = ':'.join([abs_path, klass])else:if parent in self.classs:parent_class = ':' + parentprint(parent_class)else:parent_class = parentself.classs.append(child_class)self.class_relation.append((child_class, parent_class))_PATTERN_STR_IMPORT = r"^import (.*)"def _proc_import_match(self, match):module = match.groups()[0].strip()self.module_table[module] = moduleprint("module name: %s" % module)_PATTERN_STR_IMPORT_AS = r"^import (.*) as (.*)"def _proc_import_as_match(self, match):module = match.groups()[0]module = module.strip()alias = match.groups()[1]alias = alias.strip()self.module_table[alias] = moduleprint("module name: %s alias: %s" % (module, alias))_PATTERN_STR_FROM_IMPORT = r"^from (.*) import (.*)"def _proc_from_import_match(self, match):path = match.groups()[0]path = path.strip()module = match.groups()[1]module.strip()self.module_table[module] = '.'.join([path, module])print("path:%s module: %s" % (path, module))_PATTERN_STR_FROM_IMPORT_AS = r"^from (.*) import (.*) as (.*)"def _proc_from_import_as_match(self, match):path = match.groups()[0]path = path.strip()module = match.groups()[1]module = module.strip()alias = match.groups()[2]alias = alias.strip()self.module_table[alias] = '.'.join([path, module])print("path:%s module: %s alias: %s" % (path, module, alias))def update_with_single_line(self, line):for key, regex, proc, pattern in self.match_table:match = re.search(pattern, line)if match:proc(match)returnreturndef update_with_full_file(self, file_name):self.reset()with open(file_name) as in_file:for line in in_file:self.update_with_single_line(line)def reset(self):self.module_table = {}self.class_relation = []self.classs = []def present_relations(self):print(self.class_relation)class classFinder(object):def __init__(self, collector, dir_name):self._collector = collectorself._dir = dir_nameself.relations = []def update_with_file(self, full_file_name):module_name = full_file_name[len(self._dir):]module_name = module_name.replace(os.path.sep, '.')module_name = module_name.strip('.')self._collector.reset()with open(full_file_name) as in_file:for line in in_file:self._collector.update_with_single_line(line)for child, parent in self._collector.class_relation:if parent.startswith(':'):parent = module_name + parentself.relations.append((':'.join([module_name, child]), parent))self._collector.reset()def run(self):for path, dirs, files in os.walk(self._dir):files = [x for x in files if x.endswith('.py')]for _file in files:full_file_name = os.path.join(path, _file)self.update_with_file(full_file_name)def output_to_file(self, file_name):with open(file_name, 'w') as output_file:for pair in self.relations:output_file.write(str(pair) + '\n')if __name__ == '__main__':DIR= 'abspath/to/cinder'collector = InfoCollector()finder = classFinder(collector, DIR)finder.run()finder.output_to_file('class_of_cinder')

该代码还有很多需要完善的地方,当前只是把代码的大体结构给完成了。

0 0
原创粉丝点击