def __time(self, indent = 0, printTotal = False, totalIndent = 0): secFormat = '{:8.4f}' now = time.perf_counter() # @UndefinedVariable printLine('*** Duration: ' + secFormat.format(now - self.__lastTime) + ' Seconds ***', indent = indent) if printTotal: totalAsterisk = '******' if totalIndent < indent: totalAsterisk += (indent - totalIndent) * 2 * '*' printLine(totalAsterisk + ' Total: ' + secFormat.format(now - self.__startTime) + ' Seconds ***', indent = totalIndent) self.__lastTime = now
def addCode(self, subroutineFullName, typeArgumentReferences, typeResultReferences, globalsReferences, callgraph, types): assertType(subroutineFullName, 'subroutineFullName', SubroutineFullName) assertTypeAll(typeArgumentReferences, 'typeArgumentReferences', VariableReference) assertTypeAll(typeResultReferences, 'typeResultReferences', VariableReference) assertTypeAll(globalsReferences, 'globalsReferences', VariableReference) assertType(callgraph, 'callgraph', CallGraph) assertType(types, 'types', TypeCollection) printLine('Add Code to Used Modules', indent=1) self.__backupFinder.setBackupSuffixPrefix( self.__backupFinder.EXPORT_SUFFIX_PREFIX) refModules = list( self.__getModulesFromCallgraph(callgraph).union( self.__extractModulesFromVariableReferences( globalsReferences))) refModules.sort(reverse=True) for refModule in refModules: usedSourceFile = refModule.getSourceFile() usedSourceFilePath = usedSourceFile.getPath() if usedSourceFilePath.endswith( self.__backupFinder.getBackupSuffix()): usedSourceFilePath = usedSourceFilePath.replace( self.__backupFinder.getBackupSuffix(), CodeGenerator.DEFAULT_SUFFIX) usedSourceFile = SourceFile(usedSourceFilePath, usedSourceFile.isPreprocessed()) refModule = usedSourceFile.getModule(refModule.getName()) self.__backupFinder.setBackupSuffixPrefix( BackupFileFinder.EXPORT_SUFFIX_PREFIX) backup = self.__backupFinder.create(usedSourceFilePath) subroutine = self._findSubroutine(subroutineFullName) self._setTypesToSubroutineVariables(subroutine, types) exportTemplateNameSpace = ExportTemplatesNameSpace( refModule, typeArgumentReferences, typeResultReferences, globalsReferences, subroutine, callgraph, self._postProcessor) lastLine = refModule.getContainsLineNumber() if lastLine < 0: lastLine = refModule.getLastLineNumber() result = self._processTemplate(usedSourceFilePath, lastLine - 1, self.BEFORE_CONTAINS_TEMPLATE_PART, exportTemplateNameSpace) lastUseLineNumber = refModule.getLastUseLineNumber() lastUseLineNumber = self._shiftLineNumberByPreprocesserorEndifs( refModule, lastUseLineNumber) result = self._processTemplate(usedSourceFilePath, lastUseLineNumber, self.AFTER_USE_TEMPLATE_PART, exportTemplateNameSpace) or result if backup and not result: self.__backupFinder.remove(usedSourceFilePath)
def _processTemplate(self, sourceFilePath, lineNumber, part, templateNameSpace): printInline('Process Template ' + os.path.basename(self.__templatePath) + ' [' + part + ']' + ' on file ' + sourceFilePath, indent = 2) source = self._readFile(sourceFilePath) codeToAdd = self.__loadTemplate(part, templateNameSpace) if codeToAdd: source = source[:lineNumber] + ["\n"] + [codeToAdd] + ["\n", "\n"] + source[lineNumber:] self._writeFile(sourceFilePath, source) printLine() return True else: printLine(' >>> EMPTY') return False
def remove(self, originalPath): printInline('Remove File Backup of ' + originalPath, indent=2) backupPath = originalPath.replace(BackupFileFinder.DEFAULT_SUFFIX, self.getBackupSuffix()) backupPath = backupPath.replace( BackupFileFinder.DEFAULT_SUFFIX.upper(), self.getBackupSuffix()) if (backupPath == originalPath): backupPath = originalPath + self.getBackupSuffix() if os.path.exists(backupPath): os.remove(backupPath) printLine() return True else: printLine(' >>> NOT FOUND') return False
def addCode(self, subroutineFullName, typeArgumentReferences, typeResultReferences, globalsReferences, callgraph, types): assertType(subroutineFullName, 'subroutineFullName', SubroutineFullName) assertTypeAll(typeArgumentReferences, 'typeArgumentReferences', VariableReference) assertTypeAll(typeResultReferences, 'typeResultReferences', VariableReference) assertTypeAll(globalsReferences, 'globalsReferences', VariableReference) assertType(callgraph, 'callgraph', CallGraph) assertType(types, 'types', TypeCollection) printLine('Create code in new test source file', indent=1) tempTestFile = os.path.join(self.__testSourceDir, self.TEMP_TEST_FILE) printLine('Create file ' + tempTestFile, indent=2) self._writeFile(tempTestFile, []) subroutine = self._findSubroutine(subroutineFullName) self._setTypesToSubroutineVariables(subroutine, types) templateNameSpace = ReplayTemplatesNameSpace( subroutine, typeArgumentReferences, typeResultReferences, globalsReferences, self.__testDataDir, callgraph, self._postProcessor) self._processTemplate(tempTestFile, 0, self.TEST_TEMPLATE_PART, templateNameSpace) testModuleName = self.__findModuleNameInTestFile(tempTestFile) if testModuleName is not None: testFilePath = os.path.join(self.__testSourceDir, testModuleName + '.f90') printLine('Rename file to ' + testFilePath, indent=2) os.rename(tempTestFile, testFilePath)
def create(self, originalPath): printInline('Create File Backup of ' + originalPath, indent=2) backupPath = originalPath if not backupPath.endswith(self.getBackupSuffix()): backupPath = backupPath.replace(BackupFileFinder.DEFAULT_SUFFIX, self.getBackupSuffix()) backupPath = backupPath.replace( BackupFileFinder.DEFAULT_SUFFIX.upper(), self.getBackupSuffix()) if not os.path.exists(backupPath): shutil.copyfile(originalPath, backupPath) printLine() return True elif not os.path.exists(originalPath): shutil.copyfile(backupPath, originalPath) printLine() return True else: printLine(' >>> ALREADY EXISTS') return False
def restore(self): for backupFile in self.find(): restoreFile = self.__getOriginalFile(backupFile) printLine('Restore ' + restoreFile, indent=1) os.rename(backupFile, restoreFile)
def main(): argParser = argparse.ArgumentParser(description='Generate test code.'); args = parseArguments(argParser); if not (args.restore or args.restoreCapture or args.export or args.capture or args.replay): argParser.error('No action requested, add -a/--restoreCapture and/or -b/--restore and/or -c/--capture and/or -e/--export and/or -r/--replay') config = loadFortranTestGeneratorConfiguration(args.configFile) if config is None: exit(3) backupSuffix = '.' + config[CFG_BACKUP_SUFFIX].lstrip('.') ftgPrefix = config[CFG_FTG_PREFIX] templatePath = config[CFG_TEMPLATE] testSourceDir = config[CFG_TEST_SOURCE_DIR] testDataBaseDir = config[CFG_TEST_DATA_BASE_DIR] modifySourceDirs = config[CFG_MODIFY_SOURCE_DIRS] sys.path.append(config[CFG_FCG_DIR]) from fcgconfigurator import loadFortranCallGraphConfiguration, CFG_EXCLUDE_MODULES, CFG_IGNORE_GLOBALS_FROM_MODULES, CFG_IGNORE_DERIVED_TYPES, CFG_ASSEMBLER_DIRS,\ CFG_SPECIAL_MODULE_FILES, CFG_CACHE_DIR, CFG_SOURCE_DIRS, CFG_SOURCE_FILES_PREPROCESSED, CFG_ABSTRACT_TYPES, CFG_ALWAYS_FULL_TYPES from source import SubroutineFullName, SourceFiles from backup import BackupFileFinder from postprocessor import CodePostProcessor from generator import CodeGeneratorSettings from combined import CombinedCodeGenerator from assembler import GNUx86AssemblerCallGraphBuilder from treecache import CachedAssemblerCallGraphBuilder configFTG = {} if config[CFG_FCG_CONFIG_FILE] is not None: configFTG = loadFortranCallGraphConfiguration(config[CFG_FCG_CONFIG_FILE], incomplete=True) configFTG = loadFortranCallGraphConfiguration(config[CFG_FTG_CONFIG_FILE], baseConfig=configFTG) # Overwrite variables from FCG config file if configFTG is None: exit(3) config.update(configFTG) excludeModules = config[CFG_EXCLUDE_MODULES] ignoreGlobalsFromModuls = config[CFG_IGNORE_GLOBALS_FROM_MODULES] ignoreDerivedTypes = config[CFG_IGNORE_DERIVED_TYPES] alwaysFullTypes = config[CFG_ALWAYS_FULL_TYPES] abstractTypes = config[CFG_ABSTRACT_TYPES] sourceDirs = config[CFG_SOURCE_DIRS] graphBuilder = GNUx86AssemblerCallGraphBuilder(config[CFG_ASSEMBLER_DIRS], config[CFG_SPECIAL_MODULE_FILES]) if config[CFG_CACHE_DIR]: graphBuilder = CachedAssemblerCallGraphBuilder(config[CFG_CACHE_DIR], graphBuilder) sourceFiles = SourceFiles(sourceDirs, config[CFG_SPECIAL_MODULE_FILES], config[CFG_SOURCE_FILES_PREPROCESSED]) if modifySourceDirs is not None: modifySourceFiles = SourceFiles(modifySourceDirs, config[CFG_SPECIAL_MODULE_FILES]) backupFinder = BackupFileFinder(modifySourceDirs, backupSuffix) else: modifySourceFiles = sourceFiles backupFinder = BackupFileFinder(sourceDirs, backupSuffix) if args.export or args.capture or args.replay: moduleName = args.module; subroutineName = args.subroutine; subroutineFullName = None if not moduleName: argParser.error('Missing Module (and Subroutine) name!'); elif not subroutineName: if SubroutineFullName.validFullName(moduleName): subroutineFullName = SubroutineFullName(moduleName) else: argParser.error('Missing Subroutine name!'); elif SubroutineFullName.validParts(moduleName, subroutineName): subroutineFullName = SubroutineFullName.fromParts(moduleName, subroutineName) else: argParser.error('Invalid Module and/or Subroutine name!'); if subroutineFullName is not None and not sourceFiles.existsSubroutine(subroutineFullName): argParser.error('Subroutine ' + str(subroutineFullName) + ' not found!'); if args.restore: printLine('Restore all Backup Files') backupFinder.restore() sourceFiles.clearCache() elif args.restoreCapture: printLine('Restore Capture Backup Files') backupFinder.setBackupSuffixPrefix(BackupFileFinder.CAPTURE_SUFFIX_PREFIX) backupFinder.restore() sourceFiles.clearCache() elif modifySourceDirs is None or modifySourceDirs == sourceDirs: sourceFiles.setSpecialModuleFiles(backupFinder.extendSpecialModuleFiles(sourceFiles.getSpecialModuleFiles())) if args.export or args.capture or args.replay: printLine('Generate Code') postProcessor = CodePostProcessor() generatorSettings = CodeGeneratorSettings() generatorSettings.excludeModules = excludeModules generatorSettings.ignoreGlobalsFromModules = ignoreGlobalsFromModuls generatorSettings.fullTypes = alwaysFullTypes generatorSettings.ignoredTypes = ignoreDerivedTypes generatorSettings.ignorePrefix = ftgPrefix generatorSettings.abstractTypes = abstractTypes generatorSettings.measureTime = args.measure generatorSettings.clearCache = args.clearCache generator = CombinedCodeGenerator(args.capture, args.replay, sourceFiles, modifySourceFiles, templatePath, testSourceDir, testDataBaseDir, graphBuilder, postProcessor, backupFinder, generatorSettings) generator.generate(subroutineFullName)
def generate(self, subroutineFullName): assertType(subroutineFullName, 'subroutineFullName', SubroutineFullName) if self._settings.ignorePrefix != '': self._settings.ignoreSubroutinesRegex = re.compile('^' + self._settings.ignorePrefix + '.*$') else: self._settings.ignoreSubroutinesRegex = None subroutine = self._findSubroutine(subroutineFullName) if subroutine is None: raise LookupError("Subroutine not found: " + str(subroutineFullName)) if self._settings.measureTime: self.__initTime() printLine('Build Call Graph', indent = 1) callgraph = self.__graphBuilder.buildCallGraph(subroutineFullName, self._settings.clearCache) if self._settings.measureTime: self.__time(2) printLine('Find Interfaces and Types', indent = 1) useTraversal = UseTraversal(self._sourceFiles, self._settings.excludeModules, self._settings.abstractTypes) useTraversal.parseModules(callgraph.getRoot()) interfaces = useTraversal.getInterfaces() types = useTraversal.getTypes() if self._settings.measureTime: self.__time(2) printLine('Analyse Source Code', indent = 1) argumentTracker = VariableTracker(self._sourceFiles, self._settings, interfaces, types, callGraphBuilder = self.__graphBuilder) printLine('Find References to Type Argument Members', indent = 2) typeArgumentReferences = argumentTracker.trackDerivedTypeArguments(callgraph) subroutine = self._findSubroutine(subroutineFullName) if subroutine.isFunction() and subroutine.getResultVariable().hasDerivedType(): printLine('Find References to Type Result', indent = 2) typeResultReferences = argumentTracker.trackDerivedTypeResult(callgraph) else: typeResultReferences = [] printLine('Find References to Global Variables', indent = 2) globalsTracker = GlobalVariableTracker(self._sourceFiles, self._settings, interfaces, types, callGraphBuilder = self.__graphBuilder) globalsReferences = globalsTracker.trackGlobalVariables(callgraph) sourceFile = subroutine.getSourceFile() sourceFilePath = sourceFile.getPath() if not os.path.isfile(sourceFile.getPath()): raise IOError("File not found: " + sourceFilePath); if self._settings.measureTime: self.__time(2) self.addCode(subroutineFullName, typeArgumentReferences, typeResultReferences, globalsReferences, callgraph, types) if self._settings.measureTime: self.__time(2, True, 1)