def _convert(self, src_path): """return converted all lines of one source file""" results = [] line_generator = LineGenerator(src_path) self.next_rules = [] self.indent_level = 0 try: while not line_generator.is_end(): prev_line = line_generator.get_prev_line() line = line_generator.get_current_line() next_line = line_generator.get_next_line() result_line = '' if re.search('^\s*\$', line): result_line = self._get_result_by_template(line_generator, src_path) else: result_line = self._get_result_by_define(prev_line, line, next_line) #print result_line ##### debug results.append(result_line + '\n') line_generator.proceed() except: prev_line = line_generator.get_prev_line() line = line_generator.get_current_line() next_line = line_generator.get_next_line() cprint('<red:Convert Error: />line %d' % line_generator.get_line_number()) cprint(' <lred:%s/>\n> <lred:%s/>\n <lred:%s/>' % (prev_line, line, next_line)) raise return results
def go(self): """convert all source files according to defines and templates""" for i, src_path in enumerate(self.src_files): length = len(self.src_files) rate = (i + 1.0) / length * 100 cprint('%d / %d <yellow:(%5.1f %%)/> ::: %s' % (i+1, length, rate, src_path)) convert_result = self._convert(src_path) self._write_file(convert_result, src_path, self.build_path, self.ext_map)
def _get_output_path(self, src_path, build_dir, ext_map): groups = re.search('^.*?/(.*)(\..+)', src_path).groups() src_file_name = groups[0] src_file_ext = groups[1] try: build_file_ext = ext_map[src_file_ext] except: cprint('<red:key of extension table not found: /><purple:%s/>' % src_file_ext) cprint('<lred: * check your tkgen.cfg file./>\n') raise build_file_name = build_dir + src_file_name + build_file_ext return build_file_name
def _write_file(self, text_list, src_path, build_dir, ext_map): if not re.search('^(.*)/', src_path): return build_file_name = self._get_output_path(src_path, build_dir, ext_map) dir_to_build_file = re.search('^(.*)/', build_file_name).group(1) if not os.path.isdir(dir_to_build_file): os.makedirs(dir_to_build_file) file_obj = codecs.open(build_file_name, 'w', 'utf-8') file_obj.writelines(text_list) file_obj.close() cprint((' ' * 17) + '-> <blue:%s/>' % build_file_name)
def run_postprocess(module_path, opts, config): try: module = __import__( module_path, globals(), locals(), [''], -1 ) except ImportError: cprint("<red:Import Error: module file for postprocess not found: %s/>" % (module_path)) sys.exit() entry_func_name = 'postprocess' try: func = getattr(module, entry_func_name) func(opts, config) except AttributeError: cprint("<red:Attribute Error: postprocess function <%s.%s> not found/>" \ % (module_path, entry_func_name)) sys.exit()
def _import_modules(self, module_files): """モジュール名のキーにモジュールオブジェクトを入れた辞書を返す""" result = {} for file_path in module_files: # 'package/module.py' -> 'package.module' groups = re.search('^(.*)/(.*)\.py$', file_path).groups() package = groups[0] module_name = groups[1] module_path = (package + '.' + module_name) try: result[module_name] = __import__( module_path, globals(), locals(), [''], -1 # これまだ引数完全に理解してない ) except ImportError: cprint("<red:Import Error: module file not found: %s/>" % (module_path)) sys.exit() # print result return result
def get_updated_src_files(src_files, last_update_timestamps, option_all=False): updated_src_files = [] # return copy of all source file paths if option_all: cprint('<purple:option "all" is True: update all source files./>') return [path for path in src_files] # return only updated source file paths for path in src_files: t = tkutil.file.get_timestamp(path) color = 'white' tag = ' ' * 10 if path in last_update_timestamps: last_update = last_update_timestamps[path] if t > last_update: updated_src_files.append(path) last_update_timestamps[path] = t color = 'yellow' tag = '[ updated]' else: updated_src_files.append(path) last_update_timestamps[path] = t color = 'green' tag = '[new file]' cprint ('<%s:%s %s %s-%s %s:%s:%s ::: %s/>' % (color, tag, t[:4], t[4:6], t[6:8], t[8:10], t[10:12], t[12:], path) ) cprint('<cyan:number of updated files: %d/>' % len(updated_src_files)) return updated_src_files
def main(args, opts): print('arguments: %s' % args) print('options : %s' % opts) print '' #--- check output path if not opts.output_path: cprint('<red:[USAGE] ./setup.py -o path/to/skeleton />\n') return 1 outpath = opts.output_path if not (outpath.endswith('/')): outpath += '/' (status, stdout) = commands.getstatusoutput('cd ' + outpath) if (status != 0): cprint('<red:[Error] output_path not found: /><yellow:%s/>\n' % outpath) return 1 #--- load config file config_path = DEFAULT_CONFIG_PATH if (opts.config_path): config_path = opts.config_path cprint('<yellow:load config file:/> %s' % config_path) config = Config(config_path) config.describe() #--- dryrun? if opts.dryrun: cprint('<red:DRY RUN MODE./>') return 1 #--- execute shell commands print '' shell_cmds = get_shell_commands(outpath, config) for cmd in shell_cmds: cprint('<cyan:$ %s/>' % cmd) cprint('<blue:' + '-' * len(cmd) + '/>') (status, stdout) = commands.getstatusoutput(cmd) print stdout if (status != 0): cprint('<red:[Error]/>') return 1 print 'completed.' return 0
def _get_result_by_template(self, line_generator, src_path): result_lines = '' #----- テンプレート呼び出し全体を1つの文字列に # 閉じ括弧が現れるまでをまとめる template_unit = line_generator.get_current_line() while not re.search('\)', template_unit): template_unit += ('\n' + line_generator.proceed_and_get_line()) # <<< があれば >>> があるまでもまとめる if re.search('<<', template_unit) or re.search('<<', line_generator.get_next_line()): while not re.search('\n>>', template_unit): template_unit += ('\n' + line_generator.proceed_and_get_line()) if line_generator.is_end(): cprint("<red:Error: >> is not found/>") print "processing data:\n" + template_unit sys.exit() module_name = '' func_name = '' arguments_yaml = '' source_strings = '' p1 = re.compile('\$(.*?)\.(.*?)\((.*?)\)', re.DOTALL) # ドットを改行文字にもマッチさせる if re.search(p1, template_unit): groups = re.search(p1, template_unit).groups() module_name = groups[0] func_name = groups[1] arguments_yaml = groups[2] p2 = re.compile('<<(.*)>>', re.DOTALL) if re.search(p2, template_unit): source_strings = re.search(p2, template_unit).group(1) # 関数に渡す引数を YAML で解釈して辞書オブジェクトに args = yaml.load(arguments_yaml) # define での変換用 def convert(src): converter = RegConverter(src, self.defines) converter.convert() return converter.get_result() # 安全なアクセス用 getter def data_getter(key): try: return args[key] except: return '' return None # 指定されたモジュール内の関数を呼んでテンプレート処理の結果を得る module = self.template_modules[module_name] func = getattr(module, func_name) arg_dict = MyDict({ 'CONVERTER': convert, 'DATA' : args, 'data' : SafetyGetter(args), 'SOURCE' : source_strings, 'SRC_PATH' : src_path, 'OUT_PATH' : self._get_output_path(src_path, self.build_path, self.ext_map) }) result_lines = func(arg_dict) return result_lines
def main(opts={}, config_path='tkgen.cfg'): # initial time start_time = time.time() # load config file cprint('<lred:load config file:/> %s' % config_path) config = Config(config_path) config.describe() # list rule file paths rule_file_pattern = config.file_pattern.rule cprint('\n\n<lred:target rule files:/> %s%s' % (config.path.rule, rule_file_pattern)) put_line() rule_files = [] for path in tkutil.file.get_all_files(config.path.rule, rule_file_pattern): print path rule_files.append(path) # list source file paths src_file_pattern = config.file_pattern.src cprint('\n\n<lred:target source files:/> %s%s' % (config.path.src, src_file_pattern)) put_line() src_files = [] for path in tkutil.file.get_all_files(config.path.src, src_file_pattern): print path src_files.append(path) # compare timestamp of files and erase not-updated file path cprint('\n\n<lred:compare timestamp of files with last update time/>') put_line() last_update_timestamps = tkutil.file.load_obj_from_file(config.path.last_update) or {} updated_src_files = get_updated_src_files( src_files, last_update_timestamps, opts.all ) # list python module file path for template processing cprint('\n\n<lred:target template module files:/> %s*.py' % config.path.module) put_line() module_files = [] for path in tkutil.file.get_all_files(config.path.module, '*.py'): if not path == (config.path.module + '__init__.py'): print path module_files.append(path) # load rules, sources, and modules template_engine = TemplateEngine( rule_files, updated_src_files, module_files, config.path.build, config.extension_map ) # convert sources cprint('\n\n<lred:start converting.../>') put_line() template_engine.go() # save timestamps tkutil.file.save_obj_to_file(last_update_timestamps, config.path.last_update) # post process cprint('\n\n<lred:start post process:/> %s' % config.module.postprocess) put_line() run_postprocess(config.module.postprocess, opts, config) # print processing time end_time = time.time() print '\n\nprocessing time: %.3f [sec]' % (end_time - start_time) cprint('<lred:tkgen completed./>') return 0