def __init__( self, event_handler=None, popen=None, config_pm=None, fs_util=None, suite_engine_proc=None, ): if not self.CONF_NAME: self.CONF_NAME = self.NAME self.event_handler = event_handler if popen is None: popen = RosePopener(event_handler) self.popen = popen if fs_util is None: fs_util = FileSystemUtil(event_handler) self.fs_util = fs_util if config_pm is None: config_pm = ConfigProcessorsManager(event_handler, popen, fs_util) self.config_pm = config_pm if suite_engine_proc is None: suite_engine_proc = SuiteEngineProcessor.get_processor( event_handler=event_handler, popen=popen, fs_util=fs_util ) self.suite_engine_proc = suite_engine_proc self.conf_tree_loader = ConfigTreeLoader()
def rose_config_tree_loader(srcdir=None, opts=None): """Get a rose config tree from srcdir. Args: srcdir(string or Pathlib.path object): Search for a ``rose-suite.conf`` file in this location. opts: Options namespace: To be used to allow CLI specification of optional configuarations. Returns: A Rose ConfigTree object. """ opt_conf_keys = [] # get optional config key set as environment variable: opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS") if opt_conf_keys_env: opt_conf_keys += shlex.split(opt_conf_keys_env) # ... or as command line options if opts and 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys: if isinstance(opts.opt_conf_keys, str): opt_conf_keys += opts.opt_conf_keys.split() elif isinstance(opts.opt_conf_keys, list): opt_conf_keys += opts.opt_conf_keys # Optional definitions redefinitions = [] if opts and 'defines' in dir(opts) and opts.defines: redefinitions = opts.defines # Load the config tree from metomi.rose.config_tree import ConfigTreeLoader config_tree = ConfigTreeLoader().load( str(srcdir), 'rose-suite.conf', opt_keys=opt_conf_keys, defines=redefinitions, ) # Reload the Config using the suite_ variables. # (we can't do this first time around because we have no idea what the # templating section is.) if getattr(opts, 'rose_template_vars', None): template_section = identify_templating_section(config_tree.node) for template_var in opts.rose_template_vars: redefinitions.append(f'[{template_section}]{template_var}') # Reload the config config_tree = ConfigTreeLoader().load( str(srcdir), 'rose-suite.conf', opt_keys=opt_conf_keys, defines=redefinitions, ) return config_tree
def rose_config_tree_loader(srcdir=None, opts=None): """Get a rose config tree from srcdir. Args: srcdir(string or Pathlib.path object): Search for a ``rose-suite.conf`` file in this location. opts: Options namespace: To be used to allow CLI specification of optional configuarations. Returns: A Rose ConfigTree object. """ opt_conf_keys = [] # get optional config key set as environment variable: opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS") if opt_conf_keys_env: opt_conf_keys += shlex.split(opt_conf_keys_env) # ... or as command line options if opts and 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys: if isinstance(opts.opt_conf_keys, str): opt_conf_keys += opts.opt_conf_keys.split() elif isinstance(opts.opt_conf_keys, list): opt_conf_keys += opts.opt_conf_keys # Optional definitions redefinitions = [] if opts and 'defines' in dir(opts) and opts.defines: redefinitions = opts.defines # Load the config tree from metomi.rose.config_tree import ConfigTreeLoader config_tree = ConfigTreeLoader().load( str(srcdir), 'rose-suite.conf', opt_keys=opt_conf_keys, defines=redefinitions, ) return config_tree
def rose_config_tree_loader(dir_=None, opts=None): """Get a rose config tree from a given dir Args: dir_(string or Pathlib.path object): Search for a ``rose-suite.conf`` file in this location. opts: Some sort of options object or string - To be used to allow CLI specification of optional configuaration. Returns: A Rose ConfigTree object. """ from metomi.rose.config_tree import ConfigTreeLoader opt_conf_keys = [] # get optional config key set as environment variable: opt_conf_keys_env = os.getenv("ROSE_SUITE_OPT_CONF_KEYS") if opt_conf_keys_env: opt_conf_keys += shlex.split(opt_conf_keys_env) # ... or as command line options if 'opt_conf_keys' in dir(opts) and opts.opt_conf_keys: opt_conf_keys += opts.opt_conf_keys # Optional definitions redefinitions = [] if 'defines' in dir(opts) and opts.defines: redefinitions = opts.defines # Load the actual config tree config_tree = ConfigTreeLoader().load( str(dir_), 'rose-suite.conf', opt_keys=opt_conf_keys, defines=redefinitions ) return config_tree
class Runner: """Invoke a Rose application.""" CONF_NAME = None NAME = None OPTIONS = [] def __init__(self, event_handler=None, popen=None, config_pm=None, fs_util=None, suite_engine_proc=None): if not self.CONF_NAME: self.CONF_NAME = self.NAME self.event_handler = event_handler if popen is None: popen = RosePopener(event_handler) self.popen = popen if fs_util is None: fs_util = FileSystemUtil(event_handler) self.fs_util = fs_util if config_pm is None: config_pm = ConfigProcessorsManager(event_handler, popen, fs_util) self.config_pm = config_pm if suite_engine_proc is None: suite_engine_proc = SuiteEngineProcessor.get_processor( event_handler=event_handler, popen=popen, fs_util=fs_util) self.suite_engine_proc = suite_engine_proc self.conf_tree_loader = ConfigTreeLoader() def handle_event(self, *args, **kwargs): """Handle an event using the runner's event handler.""" if callable(self.event_handler): return self.event_handler(*args, **kwargs) def config_load(self, opts): """Combine main config file with optional ones and defined ones. Return an instance of metomi.rose.config_tree.ConfigTree. """ # Main configuration file conf_dir = opts.conf_dir if conf_dir is None: conf_dir = os.getcwd() conf_dir_orig = conf_dir conf_name = "rose-" + self.CONF_NAME + ".conf" while not os.access(os.path.join(conf_dir, conf_name), os.F_OK | os.R_OK): conf_dir = self.fs_util.dirname(conf_dir) if conf_dir == self.fs_util.dirname(conf_dir): # is root raise ConfigNotFoundError(conf_dir_orig, conf_name) # Optional configuration files opt_conf_keys = [] opt_conf_keys_env = os.getenv("ROSE_%s_OPT_CONF_KEYS" % self.CONF_NAME.upper()) if opt_conf_keys_env: opt_conf_keys += shlex.split(opt_conf_keys_env) if opts.opt_conf_keys: opt_conf_keys += opts.opt_conf_keys self.handle_event(RunConfigLoadEvent( conf_dir, conf_name, opt_conf_keys, opts.defines, getattr(opts, 'defines_suite', []))) conf_tree = self.conf_tree_loader.load(conf_dir, conf_name, opt_keys=opt_conf_keys, defines=opts.defines) return conf_tree def run(self, opts, args): """Initiates a run with this runner, using the options and arguments. opts is a dict or object with relevant flags args is a list of strings. """ if isinstance(opts, dict): opts = Dummy(**opts) cwd = os.getcwd() environ = dict(os.environ) uuid = str(uuid4()) work_files = [] try: return self.run_impl(opts, args, uuid, work_files) finally: # Close handle on specific log file try: self.event_handler.contexts[uuid].handle.close() except (KeyError, IOError, AttributeError): pass # Remove work files for work_file in work_files: try: if os.path.isfile(work_file) or os.path.islink(work_file): os.unlink(work_file) elif os.path.isdir(work_file): shutil.rmtree(work_file) except OSError: pass # Change back to original working directory try: os.chdir(cwd) except OSError: pass # Reset os.environ os.environ = dict(environ) __call__ = run def run_impl(self, opts, args, uuid, work_files): """Sub-class should implement the actual logic for a run. uuid is a unique identifier for a run. work_files is a list of files, which are removed at the end of a run. """ raise NotImplementedError()