Example #1
0
class Program:
    # Variables
    logger = logging.getLogger(__name__)

    # Methods
    def __init__(self, cwd, inputFilePath):
        """create utilities required by the program,
        i.e. a registry checker, reader and module list
        """
        self.cwd = cwd
        self.inputFilePath = inputFilePath

        self._registryChecker = RegistryChecker()
        self._inputReader = Reader()
        self.moduleList = ModuleList()

        self.__prepModuleResult = DataContainer()
        return

    def run(self):
        """Run the program and time the overall calculation time.
        Main steps: read input, build call stack, call modules according to call stack.
        """

        # read input, make logger, build call stack and retrieve data required
        self.__makeLogger(self.inputFilePath)
        self.__readInput()
        self.__buildCallStack()

        # run call stack
        self.__runCallStack()

        # display elapsed time
        if hasattr(cf, 'mode') and cf.mode == 'debug':
            print 'Elapsed time per module:'
            for i in self.moduleList.moduleList:
                i.timer.disp(i.getName() + ': ')
        return

    def __makeLogger(self, inputpath):
        # make console logger
        logConf = LogConfigurator(__package__)
        logConf.makeConsoleLog()

        # Make the path to the diag file
        path = self.inputFilePath.split('\\')
        path[-1] = '/'.join(path[-1].split('/')[:-1])
        path = '\\'.join(path)

        # check if the path exists
        if not os.path.exists(path):
            raise NoInputFileException(
                'ERROR: Could not find path to input file %s.\nPlease check if you have selected the correct working directory and path to the input file.'
                % (path))

        # make file logger using the input filepath
        logConf.makeDiagFile(inputpath)

    def __runCallStack(self):
        """Run all calculation modules in the call stack.
        This requires the input to be loaded and processed into a call stack in the class variable self.moduleList
        """
        self.moduleList.runCallStack()
        return

    def __readInput(self):
        """call other methods to read input file and initiate the requested modules.
        """
        # open file
        self._inputReader.open(self.inputFilePath)

        # load imports
        imports = self._inputReader.readline('import')
        importModulePackages(self.cwd, imports)

        # load output settings
        outputReq = self.__loadOutput()

        # load other modules specified in input file
        self.__loadModule(outputReq)

        # close file
        self._inputReader.close()

        return

    def __loadOutput(self):
        """Read output requirements under 'requirements' keyword

        Returns:
            DataContainer containing output requirements
        """
        # read data from config and input file (NB. input file data may overwrite config data)
        outputData = self._inputReader.read('requirements')

        # check if a block of output requirements was found
        # if nothing is specified, do require output
        # if more than one block is found, take the last one
        if len(outputData) > 0:
            outputData = outputData[-1]
        else:
            outputData = DataContainer()

        return outputData

    def __loadModule(self, outputReq):
        """Read data of modules from input file
        For all found modules, it reads the data from input, loads its registry record and instantiates it.
        Registry records containing placeholder '@' will be refactored here before instantiating a module.

        Parameters:
            outputReq - (DataContainer) with output requirements as read from input
        """
        # read data from config and input file (NB. input file data may overwrite config data)
        configData = self.__loadConfig()
        inputData = self._inputReader.read('module')
        for dataContainer in inputData:
            # for each tag 'module' in input:
            #   iterate over all module types specified
            moduleList = toList(dataContainer.v('module'))

            for moduleName in moduleList:
                # make a new copy of the data container so that each module has a unique data container
                data = DataContainer()
                data.merge(configData)
                data.merge(
                    dataContainer)  # input data may overwrite config data
                data.addData('module', moduleName)

                # load their registry
                registerData = self._registryChecker.readRegistryEntry(
                    moduleName)
                self._registryChecker.refactorRegistry(data,
                                                       registerData,
                                                       output=outputReq)

                # set different data set for output module
                if registerData.v('outputModule') == 'True':
                    data = DataContainer(
                    )  # do not include config data for output module; start a new one
                    data.merge(dataContainer)
                    data.addData('module', moduleName)
                    data.addData(
                        'inputFile', self.inputFilePath
                    )  # output needs the input file, add this to its data

                # make the module
                self.moduleList.addModule(data, registerData, outputReq)
        return

    def __buildCallStack(self):
        self.moduleList.buildCallStack()
        return

    def __loadConfig(self):
        import config
        configvars = [var for var in dir(config) if not var.startswith('__')]
        d = {}
        for var in configvars:
            exec('d[var] = config.' + var)
        return DataContainer(d)