Example #1
0
def _launch(name, event_handler=None, run_fg=False, *args, **kwargs):
    popen = RosePopener(event_handler)
    command = popen.get_cmd(name, *args)
    kwargs['stdin'] = sys.stdin
    if run_fg:
        return popen.run(*command, **kwargs)
    popen.run_bg(*command, **kwargs)
Example #2
0
 def __init__(self, opts, reporter=None, popen=None, fs_util=None):
     self.opts = opts
     if reporter is None:
         self.reporter = Reporter(opts.verbosity - opts.quietness)
     else:
         self.reporter = reporter
     if popen is None:
         self.popen = RosePopener(event_handler=self.reporter)
     else:
         self.popen = popen
     if fs_util is None:
         self.fs_util = FileSystemUtil(event_handler=self.reporter)
     else:
         self.fs_util = fs_util
Example #3
0
File: stem.py Project: csimag/rose
    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [ url ]
                self._add_define_option('SOURCE_' + project.upper() + '_REV', 
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE', 
                                        '"' + base + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            expanded_groups = []
            for i in self.opts.group:
                expanded_groups.extend(i.split(','))
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(expanded_groups))

        # Load the config file and return any automatic-options
        auto_opts = self._read_site_config_and_return_options()
        if auto_opts:
            automatic_options = auto_opts.split()
            for option in automatic_options:
                elements = option.split("=")
                if len(elements) == 2:
                    self._add_define_option(elements[0], 
                                      '"' + elements[1] + '"')

        # Change into the suite directory
        if self.opts.conf_dir:
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #4
0
File: vc.py Project: kaday/rose
 def __init__(self,
              event_handler=None,
              popen=None,
              fs_util=None,
              force_mode=False):
     if event_handler is None:
         event_handler = self._dummy
     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
     self.force_mode = force_mode
     self._work_dir = None
     atexit.register(self._delete_work_dir)
     self.subversion_servers_conf = None
     subversion_servers_conf = os.getenv("ROSIE_SUBVERSION_SERVERS_CONF")
     if subversion_servers_conf:
         self.subversion_servers_conf = subversion_servers_conf
     else:
         subversion_servers_conf = os.path.expanduser(
             self.SUBVERSION_SERVERS_CONF)
         if os.path.exists(subversion_servers_conf):
             self.subversion_servers_conf = subversion_servers_conf
Example #5
0
def main():
    """Implement "rose suite-hook" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options(
        "mail_cc", "mail", "retrieve_job_logs", "shutdown")
    opts, args = opt_parser.parse_args()
    for key in ["mail_cc"]:
        values = []
        if getattr(opts, key):
            for value in getattr(opts, key):
                values.extend(value.split(","))
        setattr(opts, key, values)
    report = Reporter(opts.verbosity - opts.quietness - 1)  # Reduced default
    popen = RosePopener(event_handler=report)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report, popen=popen)
    args = suite_engine_proc.process_suite_hook_args(*args, **vars(opts))
    hook = RoseSuiteHook(event_handler=report,
                         popen=popen,
                         suite_engine_proc=suite_engine_proc)
    hook(*args,
         should_mail=opts.mail,
         mail_cc_list=opts.mail_cc,
         should_shutdown=opts.shutdown,
         should_retrieve_job_logs=opts.retrieve_job_logs)
Example #6
0
 def __init__(self, prefixes=None, prompt_func=None, popen=None,
              event_handler=None):
     if not event_handler:
         event_handler = Reporter()
     if not popen:
         popen = RosePopener(event_handler=event_handler)
     self.event_handler = event_handler
     self.popen = popen
     self.prompt_func = prompt_func
     self.prefixes = []
     self.auth_managers = {}
     conf = ResourceLocator.default().get_conf()
     conf_rosie_id = conf.get(["rosie-id"], no_ignore=True)
     if conf_rosie_id is not None:
         for key, node in conf_rosie_id.value.items():
             if node.is_ignored() or not key.startswith("prefix-ws."):
                 continue
             prefix = key.replace("prefix-ws.", "")
             self.auth_managers[prefix] = RosieWSClientAuthManager(
                 prefix, popen=self.popen, prompt_func=self.prompt_func)
     if not prefixes:
         prefixes_str = conf_rosie_id.get_value(["prefixes-ws-default"])
         if prefixes_str:
             prefixes = shlex.split(prefixes_str)
         else:
             prefixes = sorted(self.auth_managers.keys())
     self.set_prefixes(prefixes)
Example #7
0
    def __init__(self, prefix, popen=None, prompt_func=None):
        self.prefix = prefix
        root = self._get_conf_value("ws")
        if root is None:
            raise UndefinedRosiePrefixWS(self.prefix)
        if not root.endswith("/"):
            root += "/"
        self.root = root
        urlparse_res = urlparse(self.root)
        self.scheme = urlparse_res[0]
        self.host = urlparse_res[1]
        self.password_orig = None
        self.username_orig = None
        self.password = None
        self.username = None
        if popen is None:
            popen = RosePopener()
        self.popen = popen
        self.prompt_func = prompt_func
        for password_store_name in self.PASSWORD_STORE_NAMES:
            password_store_cls = globals()[password_store_name]
            if password_store_cls.usable():
                self.password_store = password_store_cls()
                break
        else:
            self.password_store = None

        self.requests_kwargs = {}
        self._init_https_params()
Example #8
0
 def __init__(self, event_handler=None, popen=None):
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(event_handler=event_handler)
     self.popen = popen
     self.scorers = {}
     self.local_host_strs = None
Example #9
0
def write_source_vc_info(run_source_dir, output=None, popen=None):
    """Write version control information of sources used in run time.

    run_source_dir -- The source directory we are interested in.
    output -- An open file handle or a string containing a writable path.
              If not specified, use sys.stdout.
    popen -- A rose.popen.RosePopener instance for running vc commands.
             If not specified, use a new local instance.

    """
    if popen is None:
        popen = RosePopener()
    if output is None:
        handle = sys.stdout
    elif hasattr(output, "write"):
        handle = output
    else:
        handle = open(output, "wb")
    msg = "%s\n" % run_source_dir
    _write_safely(msg, handle)
    environ = dict(os.environ)
    environ["LANG"] = "C"
    for vcs, args_list in [
            ("svn", [
                ["info", "--non-interactive"],
                ["status", "--non-interactive"],
                ["diff", "--internal-diff", "--non-interactive"]]),
            ("git", [["describe"], ["status"], ["diff"]])]:
        if not popen.which(vcs):
            continue
        cwd = os.getcwd()
        os.chdir(run_source_dir)
        try:
            for args in args_list:
                cmd = [vcs] + args
                ret_code, out, _ = popen.run(*cmd, env=environ)
                if out:
                    _write_safely(("#" * 80 + "\n"), handle)
                    _write_safely(("# %s\n" % popen.list_to_shell_str(cmd)),
                                  handle)
                    _write_safely(("#" * 80 + "\n"), handle)
                    _write_safely(out, handle)
                if ret_code:  # If cmd fails once, it will likely fail again
                    break
        finally:
            os.chdir(cwd)
Example #10
0
 def __init__(self, event_handler=None, popen=None, suite_engine_proc=None):
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(event_handler)
     self.popen = popen
     if suite_engine_proc is None:
         suite_engine_proc = SuiteEngineProcessor.get_processor(
             event_handler=event_handler, popen=popen)
     self.suite_engine_proc = suite_engine_proc
Example #11
0
 def __init__(self, event_handler=None, popen=None, fs_util=None, **kwargs):
     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
     self.date_time_oper = RoseDateTimeOperator()
Example #12
0
def write_source_vc_info(run_source_dir, output=None, popen=None):
    """Write version control information of sources used in run time.

    run_source_dir -- The source directory we are interested in.
    output -- An open file handle or a string containing a writable path.
              If not specified, use sys.stdout.
    popen -- A rose.popen.RosePopener instance for running vc commands.
             If not specified, use a new local instance.

    """
    if popen is None:
        popen = RosePopener()
    if output is None:
        handle = sys.stdout
    elif hasattr(output, "write"):
        handle = output
    else:
        handle = open(output, "wb")
    handle.write("%s\n" % run_source_dir)
    environ = dict(os.environ)
    environ["LANG"] = "C"
    for vcs, args_list in [
            ("svn", [
                ["info", "--non-interactive"],
                ["status", "--non-interactive"],
                ["diff", "--internal-diff", "--non-interactive"]]),
            ("git", [["describe"], ["status"], ["diff"]])]:
        if not popen.which(vcs):
            continue
        cwd = os.getcwd()
        os.chdir(run_source_dir)
        try:
            for args in args_list:
                cmd = [vcs] + args
                ret_code, out, _ = popen.run(*cmd, env=environ)
                if out:
                    handle.write("#" * 80 + "\n")
                    handle.write(("# %s\n" % popen.list_to_shell_str(cmd)))
                    handle.write("#" * 80 + "\n")
                    handle.write(out)
                if ret_code:  # If cmd fails once, it will likely fail again
                    break
        finally:
            os.chdir(cwd)
Example #13
0
 def __init__(self, event_handler=None, popen=None):
     if event_handler is None:
         event_handler = Reporter()
     self.event_handler = event_handler
     if popen is None:
         popen = RosePopener(self.event_handler)
     self.popen = popen
     path = os.path.dirname(os.path.dirname(sys.modules["rosie"].__file__))
     self.usertools_manager = SchemeHandlersManager(
         [path], "rosie.usertools", ["verify_users"])
Example #14
0
 def __init__(self, event_handler=None, popen=None, fs_util=None):
     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
     path = os.path.dirname(os.path.dirname(sys.modules["rose"].__file__))
     SchemeHandlersManager.__init__(self, [path], "rose.config_processors",
                                    ["process"])
Example #15
0
 def __init__(self, event_handler=None):
     self.event_handler = event_handler
     self.popen = RosePopener(self.event_handler)
     self.fs_util = FileSystemUtil(self.event_handler)
     self.config_pm = ConfigProcessorsManager(self.event_handler,
                                              self.popen, self.fs_util)
     self.host_selector = HostSelector(self.event_handler, self.popen)
     self.suite_engine_proc = SuiteEngineProcessor.get_processor(
         event_handler=self.event_handler,
         popen=self.popen,
         fs_util=self.fs_util)
Example #16
0
 def __init__(self, event_handler=None, popen=None, fs_util=None):
     if event_handler is None:
         event_handler = self._dummy
     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
     self.post_commit_hook = RosieSvnPostCommitHook(
         event_handler=event_handler, popen=popen)
Example #17
0
 def __init__(self, event_handler=None, popen=None, fs_util=None):
     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
     path = os.path.dirname(os.path.dirname(sys.modules["rose"].__file__))
     SchemeHandlersManager.__init__(
         self, [path], ns="rose.loc_handlers", attrs=["parse", "pull"],
         can_handle="can_pull")
Example #18
0
def _launch(name, event_handler=None, run_fg=False, *args, **kwargs):
    popen = RosePopener(event_handler)
    command = popen.get_cmd(name, *args)
    kwargs['stdin'] = sys.stdin
    if run_fg:
        return popen.run(*command, **kwargs)
    popen.run_bg(*command, **kwargs)
Example #19
0
 def __init__(self, event_handler=None, popen=None, fs_util=None,
              host_selector=None, **_):
     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 host_selector is None:
         host_selector = HostSelector(event_handler, popen)
     self.host_selector = host_selector
     self.date_time_oper = RoseDateTimeOperator()
Example #20
0
def write_source_vc_info(run_source_dir, output=None, popen=None):
    """Write version control information of sources used in run time.

    run_source_dir -- The source directory we are interested in.
    output -- An open file handle or a string containing a writable path.
              If not specified, use sys.stdout.
    popen -- A rose.popen.RosePopener instance for running vc commands.
             If not specified, use a new local instance.

    """
    if popen is None:
        popen = RosePopener()
    if output is None:
        handle = sys.stdout
    elif hasattr(output, "write"):
        handle = output
    else:
        handle = open(output, "wb")
    environ = dict(os.environ)
    environ["LANG"] = "C"
    for vcs, cmds in [("svn", ["info", "status", "diff"]),
                      ("git", ["describe", "status", "diff"])]:
        if not popen.which(vcs):
            continue
        cwd = os.getcwd()
        os.chdir(run_source_dir)
        try:
            for cmd in cmds:
                rc, out, err = popen.run(vcs, cmd, env=environ)
                if out:
                    handle.write("#" * 80 + "\n")
                    handle.write(("# %s %s\n" % (vcs, cmd)).upper())
                    handle.write("#" * 80 + "\n")
                    handle.write(out)
                if rc: # If cmd fails once, chances are, it will fail again
                    break
        finally:
            os.chdir(cwd)
Example #21
0
 def __init__(self, opts, reporter=None, popen=None, fs_util=None):
     self.opts = opts
     if reporter is None:
         self.reporter = Reporter(opts.verbosity - opts.quietness)
     else:
         self.reporter = reporter
     if popen is None:
         self.popen = RosePopener(event_handler=self.reporter)
     else:
         self.popen = popen
     if fs_util is None:
         self.fs_util = FileSystemUtil(event_handler=self.reporter)
     else:
         self.fs_util = fs_util
Example #22
0
    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [ url ]
                self._add_define_option('SOURCE_' + project.upper() + '_REV', 
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE', 
                                        '"' + base + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(self.opts.group))

        # Change into the suite directory
        if self.opts.conf_dir:
            self.fs_util.chdir(self.opts.conf_dir)
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.opts.conf_dir = thissuite
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #23
0
 def __init__(self,
              config,
              opts,
              args,
              method_paths,
              reporter=None,
              popen=None):
     if reporter is None:
         self.reporter = Reporter(opts.verbosity - opts.quietness)
     else:
         self.reporter = reporter
     if popen is None:
         self.popen = RosePopener(event_handler=self.reporter)
     else:
         self.popen = popen
     self.opts = opts
     self.args = args
     self.config = config
     self.load_tasks()
     modules = []
     for path in method_paths:
         for filename in glob.glob(path + "/*.py"):
             modules.append(filename)
     self.load_user_comparison_modules(modules)
Example #24
0
def write_source_vc_info(run_source_dir, output=None, popen=None):
    """Write version control information of sources used in run time.

    run_source_dir -- The source directory we are interested in.
    output -- An open file handle or a string containing a writable path.
              If not specified, use sys.stdout.
    popen -- A rose.popen.RosePopener instance for running vc commands.
             If not specified, use a new local instance.

    """
    if popen is None:
        popen = RosePopener()
    if output is None:
        handle = sys.stdout
    elif hasattr(output, "write"):
        handle = output
    else:
        handle = open(output, "wb")
    for vcs, cmds in [("svn", ["info", "status", "diff"]),
                      ("git", ["describe", "status", "diff"])]:
        if not popen.which(vcs):
            continue
        cwd = os.getcwd()
        os.chdir(run_source_dir)
        try:
            for cmd in cmds:
                rc, out, err = popen.run(vcs, cmd)
                if out:
                    handle.write("#" * 80 + "\n")
                    handle.write(("# %s %s\n" % (vcs, cmd)).upper())
                    handle.write("#" * 80 + "\n")
                    handle.write(out)
                if rc: # If cmd fails once, chances are, it will fail again
                    break
        finally:
            os.chdir(cwd)
Example #25
0
 def __init__(self, config, opts, args, method_paths, reporter=None, popen=None):
     if reporter is None:
         self.reporter = Reporter(opts.verbosity - opts.quietness)
     else:
         self.reporter = reporter
     if popen is None:
         self.popen = RosePopener(event_handler=self.reporter)
     else:
         self.popen = popen
     self.opts = opts
     self.args = args
     self.config = config
     self.load_tasks()
     modules = []
     for path in method_paths:
         for filename in glob.glob(path + "/*.py"):
             modules.append(filename)
     self.load_user_comparison_modules(modules)
Example #26
0
 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()
Example #27
0
    def __init__(self,
                 prefix,
                 popen=None,
                 prompt_func=None,
                 event_handler=None):
        self.prefix = prefix
        root = self._get_conf_value("ws")
        if root is None:
            raise UndefinedRosiePrefixWS(self.prefix)
        if not root.endswith("/"):
            root += "/"
        self.root = root
        urlparse_res = urlparse(self.root)
        self.scheme = urlparse_res[0]
        self.host = urlparse_res[1]
        self.password_orig = None
        self.username_orig = None
        self.password = None
        self.username = None
        if popen is None:
            popen = RosePopener()
        self.popen = popen
        self.prompt_func = prompt_func
        if event_handler is None:
            self.event_handler = Reporter()
        else:
            self.event_handler = event_handler
        res_loc = ResourceLocator.default()
        password_stores_str = res_loc.default().get_conf().get_value(
            keys=["rosie-id", "prefix-password-store." + self.prefix],
            default=self.PASSWORD_STORES_STR)
        for password_store_name in shlex.split(password_stores_str):
            password_store_cls = self.PASSWORD_STORE_CLASSES.get(
                password_store_name)
            if password_store_cls is not None and password_store_cls.usable():
                self.password_store = password_store_cls()
                break
        else:
            self.password_store = None

        self.requests_kwargs = {}
        self._init_https_params()
Example #28
0
def main():
    """Implement the "rose host-select" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("choice", "rank_method", "thresholds", "timeout")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    popen = RosePopener(event_handler=report)
    select = HostSelector(event_handler=report, popen=popen)
    try:
        host_score_list = select(names=args,
                                 rank_method=opts.rank_method,
                                 thresholds=opts.thresholds,
                                 ssh_cmd_timeout=opts.timeout)
    except (NoHostError, NoHostSelectError) as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc(exc)
        sys.exit(1)
    opts.choice = int(opts.choice)
    report(choice(host_score_list[0:opts.choice])[0] + "\n", level=0)
Example #29
0
def _launch(name, event_handler=None, *args, **kwargs):
    popen = RosePopener(event_handler)
    command = popen.get_cmd(name, *args)
    return popen.run_bg(*command, **kwargs)
Example #30
0
class Analyse(object):
    """A comparison engine for Rose."""
    def __init__(self,
                 config,
                 opts,
                 args,
                 method_paths,
                 reporter=None,
                 popen=None):
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler=self.reporter)
        else:
            self.popen = popen
        self.opts = opts
        self.args = args
        self.config = config
        self.load_tasks()
        modules = []
        for path in method_paths:
            for filename in glob.glob(path + "/*.py"):
                modules.append(filename)
        self.load_user_comparison_modules(modules)

    def analyse(self):
        """Perform comparisons given a list of tasks."""
        rc = 0
        for task in self.tasks:

            if self.check_extract(task):
                # Internal AnalysisEngine extract+comparison test

                # Extract data from results and from kgoX
                task = self.do_extract(task, "result")

                for i in range(task.numkgofiles):
                    var = "kgo" + str(i + 1)
                    task = self.do_extract(task, var)

                task = self.do_comparison(task)
            else:
                # External program(s) doing test

                # Command to run
                command = task.extract

                result = re.search(r"\$file", command)
                # If the command contains $file, it is run separately for both
                # the KGO and the result files
                if result:
                    # Replace $file token with resultfile or kgofile
                    resultcommand = self._expand_tokens(
                        command, task, "result")
                    kgocommand = self._expand_tokens(command, task, "kgo1")

                    # Run the command on the resultfile
                    task.resultdata = self._run_command(resultcommand)

                    # Run the command on the KGO file
                    task.kgo1data = self._run_command(kgocommand)
                else:
                    # The command works on both files at the same time
                    # Replace tokens $kgofile and $resultfile for actual values
                    command = self._expand_tokens(command, task)

                    # Run the command
                    task.resultdata = self._run_command(command)

                # Run the comparison
                task = self.do_comparison(task)

            self.reporter(TaskCompletionEvent(task),
                          prefix="[%s]" % (task.userstatus))
            if task.numericstatus != PASS:
                rc += 1
        return rc, self.tasks

    def check_extract(self, task):
        """Check if an extract name is present in a user method."""
        for module_name, class_name, method, help in self.user_methods:
            if task.extract == class_name:
                return True
        return False

    def do_comparison(self, task):
        """Run the comparison."""
        for module_name, class_name, method, help in self.user_methods:
            comparison_name = ".".join([module_name, class_name])
            if task.comparison == class_name:
                for module in self.modules:
                    if module.__name__ == module_name:
                        comparison_inst = getattr(module, class_name)()
                        comparison_meth = getattr(comparison_inst, "run")(task)
        return task

    def do_extract(self, task, var):
        """Extract the specified data."""
        for module_name, class_name, method, help in self.user_methods:
            extract_name = ".".join([module_name, class_name])
            if task.extract == class_name:
                for module in self.modules:
                    if module.__name__ == module_name:
                        extract_inst = getattr(module, class_name)()
                        extract_meth = getattr(extract_inst, "run")(task, var)
        return task

    def _run_command(self, command):
        """Run an external command using rose.popen."""
        output, stderr = self.popen.run_ok(command, shell=True)
        output = "".join(output).splitlines()
        return output

    def _expand_tokens(self, inputstring, task, var=None):
        """Expands tokens $resultfile, $file and $kgoXfile."""
        filename = ''
        if var:
            filename = getattr(task, var + "file")
        expansions = {'resultfile': task.resultfile, 'file': filename}
        for i in range(1, task.numkgofiles + 1):
            key = "kgo" + str(i) + "file"
            value = getattr(task, key)
            expansions[key] = value
        inputstring = inputstring.format(**expansions)
        return inputstring

    def _find_file(self, var, task):
        """Finds a file given a variable name containing the filename.

        Given a variable name and task object, this returns the filename it
        points to, including expanding any * characters with glob.
        """

        filevar = var + "file"
        if hasattr(task, filevar):
            configvar = var + "fileconfig"
            setattr(task, configvar, getattr(task, filevar))
            filenames = glob.glob(env_var_process(getattr(task, filevar)))
            if len(filenames) > 0:
                setattr(task, filevar, os.path.abspath(filenames[0]))
        return task

    def load_tasks(self):
        """Loads AnalysisTasks from files.

        Given a list of files, return AnalysisTasks generated from those files.
        This also expands environment variables in filenames, but saves the
        original contents for use when writing out config files
        """

        tasks = []
        for task in self.config.value.keys():
            if task is "env":
                continue
            if task.startswith("file:"):
                continue
            newtask = AnalysisTask()
            newtask.name = task
            value = self.config.get_value([task, "resultfile"])

            # If the task is ignored, this will be None, so continue
            # on to the next task
            if value is None:
                continue

            if "{}" in value:
                newtask.resultfile = value.replace("{}", self.args[0])
            else:
                newtask.resultfile = value
            newtask = self._find_file("result", newtask)
            newtask.extract = self.config.get_value([task, "extract"])
            result = re.search(r":", newtask.extract)
            if result:
                newtask.subextract = ":".join(newtask.extract.split(":")[1:])
                newtask.extract = newtask.extract.split(":")[0]
            newtask.comparison = self.config.get_value([task, "comparison"])
            newtask.tolerance = env_var_process(
                self.config.get_value([task, "tolerance"]))
            newtask.warnonfail = (self.config.get_value([task, "warnonfail"])
                                  in ["yes", "true"])

            # Allow for multiple KGO, e.g. kgo1file, kgo2file, for
            # statistical comparisons of results
            newtask.numkgofiles = 0
            for i in range(1, MAX_KGO_FILES):
                kgovar = "kgo" + str(i)
                kgofilevar = kgovar + "file"
                if self.config.get([task, kgofilevar]):
                    value = self.config.get([task, kgofilevar])[:]
                    if "{}" in value:
                        setattr(newtask, kgofilevar,
                                value.replace("{}", self.args[0]))
                    else:
                        setattr(newtask, kgofilevar, value)
                    newtask.numkgofiles += 1
                    newtask = self._find_file(kgovar, newtask)
                else:
                    break
            tasks.append(newtask)
        self.tasks = tasks
        return tasks

    def load_user_comparison_modules(self, files):
        """Import comparison modules and store them."""
        modules = []
        for filename in files:
            directory = os.path.dirname(filename)
            if (not directory.endswith(USRCOMPARISON_DIRNAME)
                    or not filename.endswith(USRCOMPARISON_EXT)):
                continue
            comparison_name = os.path.basename(filename).rpartition(
                USRCOMPARISON_EXT)[0]
            sys.path.insert(0, os.path.abspath(directory))
            try:
                modules.append(__import__(comparison_name))
            except ImportError as e:
                self.reporter(e)
            sys.path.pop(0)
        modules.sort()
        self.modules = modules

        user_methods = []
        for module in modules:
            comparison_name = module.__name__
            contents = inspect.getmembers(module, inspect.isclass)
            for obj_name, obj in contents:
                att_name = "run"
                if hasattr(obj, att_name) and callable(getattr(obj, att_name)):
                    doc_string = obj.__doc__
                    user_methods.append(
                        (comparison_name, obj_name, att_name, doc_string))
        self.user_methods = user_methods
        return user_methods

    def write_config(self, filename, tasks):
        """Write an analysis config file based on a list of tasks provided"""
        config = rose.config.ConfigNode()

        for task in tasks:
            sectionname = task.name
            if task.resultfileconfig:
                config.set([sectionname, "resultfile"], task.resultfileconfig)
            for i in range(1, task.numkgofiles + 1):
                origvar = "kgo" + str(i) + "fileconfig"
                valvar = "kgo" + str(i) + "file"
                if hasattr(task, origvar):
                    config.set([sectionname, valvar], getattr(task, origvar))
            if task.extract:
                config.set([sectionname, "extract"], task.extract)
            if task.subextract:
                config.set([sectionname, "extract"],
                           task.extract + ":" + task.subextract)
            if task.comparison:
                config.set([sectionname, "comparison"], task.comparison)
            if task.tolerance:
                config.set([sectionname, "tolerance"], task.tolerance)
            if task.warnonfail:
                config.set([sectionname, "warnonfail"], "true")
        rose.config.dump(config, filename)
Example #31
0
    'auto_cli_doc',
    'cylc_lang',
    'minicylc',
    'practical',
    'rose_lang',
    'rose_domain',
    'script_include',
    'sub_lang'
]

# Select best available SVG image converter.
for svg_converter, extension in [
        ('rsvg', 'sphinxcontrib.rsvgconverter'),
        ('inkscape', 'sphinxcontrib.inkscapeconverter')]:
    try:
        assert RosePopener.which(svg_converter)
        __import__(extension)
    except (AssertionError, ImportError):
        # converter or extension not available
        pass
    else:
        extensions.append(extension)
        break
else:
    # no extensions or converters available, fall-back to default
    # vector graphics will be converted to bitmaps in all documents
    extensions.append('sphinx.ext.imgconverter')

# Slide (hieroglyph) settings.
slide_theme = 'single-level'
slide_link_to_html = True
Example #32
0
    'auto_cli_doc',
    'cylc_lang',
    'minicylc',
    'practical',
    'rose_lang',
    'rose_domain',
    'script_include',
    'sub_lang'
]

# Select best available SVG image converter.
for svg_converter, extension in [('rsvg', 'sphinxcontrib.rsvgconverter'),
                                 ('inkscape',
                                  'sphinxcontrib.inkscapeconverter')]:
    try:
        assert RosePopener.which(svg_converter)
        __import__(extension)
    except (AssertionError, ImportError):
        # converter or extension not available
        pass
    else:
        extensions.append(extension)
        break
else:
    # no extensions or converters available, fall-back to default
    # vector graphics will be converted to bitmaps in all documents
    extensions.append('sphinx.ext.imgconverter')

# Slide (hieroglyph) settings.
slide_theme = 'single-level'
slide_link_to_html = True
Example #33
0
class StemRunner(object):

    """Set up options for running a STEM job through Rose."""

    def __init__(self, opts, reporter=None, popen=None, fs_util=None):
        self.opts = opts
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler = self.reporter)
        else:
            self.popen = popen
        if fs_util is None:
            self.fs_util = FileSystemUtil(event_handler = self.reporter)
        else:
            self.fs_util = fs_util

    def _add_define_option(self, var, val):
        """Add a define option passed to the SuiteRunner."""

        if self.opts.defines:
            self.opts.defines.append(SUITE_RC_PREFIX + var + '=' + val )
        else:
            self.opts.defines= [ SUITE_RC_PREFIX + var + '=' + val ]
        self.reporter(ConfigVariableSetEvent(var, val))
        return

    def _ascertain_project(self, item):
        """Set the project name and top-level from 'fcm loc-layout'"""

        project = ''
        if re.search(r'^\.', item):
            item = os.path.abspath(os.path.join(os.getcwd(), item))
        result = re.search(r'\[(\w+)\]', item)
        if result:
            project = result.group(1)
            item = re.sub(r'\[\w+\]', r'', item)
            return project, item

        rc, output, stderr = self.popen.run('fcm', 'loc-layout', item)
        if rc != 0:
            raise ProjectNotFoundException(item, stderr)
        result = re.search(r'url:\s*(file|svn|https|http|svn\+ssh)(://.*)',
                           output)

        # Generate a unique name for this project based on fcm kp
        if result:
            urlstring = result.group(1) + result.group(2)
            rc, kpoutput, stderr = self.popen.run('fcm', 'kp', urlstring)
            kpresult = re.search(r'location{primary}\[(.*)\]\s*=', kpoutput)
            if kpresult:
                project = kpresult.group(1)
        if not project:
            raise ProjectNotFoundException(item)

        result = re.search(r'peg_rev:\s*(.*)', output)
        if '@' in item and result:
            revision = '@' + result.group(1)
            base = re.sub(r'@.*', r'', item)
        else:
            revision = ''
            base = item

        # If we're in a subdirectory of the source tree, find it and
        # remove it leaving the top-level location
        result = re.search(r'target:\s*(.*)', output)
        target=''
        if result:
            target = result.group(1)
            subtree=''
            result2 = re.search(r'sub_tree:\s*(.*)', output)
            if result2:
                subtree = result2.group(1)
                item = re.sub(subtree, r'', target)

        # Remove trailing forwards-slash
        item = re.sub(r'/$',r'',item)
        return project, item, base, revision

    def _generate_name(self):
        """Generate a suite name from the name of the first source tree."""
        dummy, basedir, dummy2, dummy3 = self._ascertain_project(os.getcwd())
        name = os.path.basename(basedir)
        return name

    def _this_suite(self):
        """Find the location of the suite in the first source tree."""

        # Get base of first source
        basedir = ''
        if self.opts.source:
            basedir = self.opts.source[0]
        else:
            dummy, basedir, dum2, dum3 = self._ascertain_project(os.getcwd())

        suitedir = os.path.join(basedir, DEFAULT_TEST_DIR)
        suitefile = os.path.join(suitedir, "rose-suite.conf")

        if not os.path.isfile(suitefile):
            raise RoseSuiteConfNotFoundException(suitedir)
        return suitedir

    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [ url ]
                self._add_define_option('SOURCE_' + project.upper() + '_REV', 
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE', 
                                        '"' + base + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(self.opts.group))

        # Change into the suite directory
        if self.opts.conf_dir:
            self.fs_util.chdir(self.opts.conf_dir)
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.opts.conf_dir = thissuite
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #34
0
class StemRunner(object):
    """Set up options for running a STEM job through Rose."""
    def __init__(self, opts, reporter=None, popen=None, fs_util=None):
        self.opts = opts
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler=self.reporter)
        else:
            self.popen = popen
        if fs_util is None:
            self.fs_util = FileSystemUtil(event_handler=self.reporter)
        else:
            self.fs_util = fs_util

    def _add_define_option(self, var, val):
        """Add a define option passed to the SuiteRunner."""

        if self.opts.defines:
            self.opts.defines.append(SUITE_RC_PREFIX + var + '=' + val)
        else:
            self.opts.defines = [SUITE_RC_PREFIX + var + '=' + val]
        self.reporter(ConfigVariableSetEvent(var, val))
        return

    def _get_base_dir(self, item):
        """Given a source tree return the following from 'fcm loc-layout':
           * url
           * sub_tree
           * peg_rev
           * root
           * project
        """

        rc, output, stderr = self.popen.run('fcm', 'loc-layout', item)
        if rc != 0:
            raise ProjectNotFoundException(item, stderr)

        ret = {}
        for line in output.splitlines():
            if not ":" in line:
                continue
            key, value = line.split(":", 1)
            if key:
                if value:
                    ret[key] = value.strip()

        return ret

    def _get_project_from_url(self, source_dict):
        """Run 'fcm keyword-print' to work out the project name."""

        repo = source_dict['root']
        if source_dict['project']:
            repo += '/' + source_dict['project']

        rc, kpoutput, stderr = self.popen.run('fcm', 'kp', source_dict['url'])

        project = None
        for line in kpoutput.splitlines():
            if line.rstrip().endswith(repo):
                kpresult = re.search(r'^location{primary}\[(.*)\]', line)
                if kpresult:
                    project = kpresult.group(1)
                    break
        return project

    def _deduce_mirror(self, source_dict, project):
        """Deduce the mirror location of this source tree."""

        # Root location for project
        proj_root = source_dict['root'] + '/' + source_dict['project']

        # Swap project to mirror
        project = re.sub(r'\.x$', r'.xm', project)
        mirror_repo = "fcm:" + project

        # Generate mirror location
        mirror = re.sub(proj_root, mirror_repo, source_dict['url'])

        # Add forwards slash after .xm if missing
        if '.xm/' not in mirror:
            mirror = re.sub(r'\.xm', r'.xm/', mirror)
        return mirror

    def _ascertain_project(self, item):
        """Set the project name and top-level from 'fcm loc-layout'.
        Returns:
            * project name
            * top-level location of the source tree with revision number
            * top-level location of the source tree without revision number
            * revision number
        """

        project = ''
        if re.search(r'^\.', item):
            item = os.path.abspath(os.path.join(os.getcwd(), item))

        source_dict = self._get_base_dir(item)
        project = self._get_project_from_url(source_dict)
        mirror = self._deduce_mirror(source_dict, project)

        if not project:
            raise ProjectNotFoundException(item)

        if 'peg_rev' in source_dict and '@' in item:
            revision = '@' + source_dict['peg_rev']
            base = re.sub(r'@.*', r'', item)
        else:
            revision = ''
            base = item

        # Remove subtree from base and item
        if 'sub_tree' in source_dict:
            item = re.sub(r'(.*)%s/?$' % (source_dict['sub_tree']),
                          r'\1',
                          item,
                          count=1)
            base = re.sub(r'(.*)%s/?$' % (source_dict['sub_tree']),
                          r'\1',
                          base,
                          count=1)

        # Remove trailing forwards-slash
        item = re.sub(r'/$', r'', item)
        base = re.sub(r'/$', r'', base)

        # Remove anything after a point
        project = re.sub(r'\..*', r'', project)
        return project, item, base, revision, mirror

    def _generate_name(self):
        """Generate a suite name from the name of the first source tree."""
        try:
            basedir = self._ascertain_project(os.getcwd())[1]
        except ProjectNotFoundException:
            if self.opts.conf_dir:
                basedir = os.path.abspath(self.opts.conf_dir)
            else:
                basedir = os.getcwd()
        name = os.path.basename(basedir)
        self.reporter(NameSetEvent(name))
        return name

    def _this_suite(self):
        """Find the location of the suite in the first source tree."""

        # Get base of first source
        basedir = ''
        if self.opts.source:
            basedir = self.opts.source[0]
        else:
            basedir = self._ascertain_project(os.getcwd())[1]

        suitedir = os.path.join(basedir, DEFAULT_TEST_DIR)
        suitefile = os.path.join(suitedir, "rose-suite.conf")

        if not os.path.isfile(suitefile):
            raise RoseSuiteConfNotFoundException(suitedir)

        self._check_suite_version(suitefile)

        return suitedir

    def _read_site_config_and_return_options(self):
        """Read the site rose.conf file."""
        return ResourceLocator.default().get_conf().get_value(
            ["rose-stem", "automatic-options"])

    def _check_suite_version(self, fname):
        """Check the suite is compatible with this version of rose-stem."""
        if not os.path.isfile(fname):
            raise RoseSuiteConfNotFoundException(os.path.dirname(fname))
        config = rose.config.load(fname)
        suite_rose_stem_version = config.get(['ROSE_STEM_VERSION'])
        if suite_rose_stem_version:
            suite_rose_stem_version = int(suite_rose_stem_version.value)
        else:
            suite_rose_stem_version = None
        if not suite_rose_stem_version == ROSE_STEM_VERSION:
            raise RoseStemVersionException(suite_rose_stem_version)

    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev, mirror = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [url]
                self._add_define_option('SOURCE_' + project.upper() + '_REV',
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE',
                                        '"' + base + '"')
                self._add_define_option(
                    'SOURCE_' + project.upper() + '_MIRROR',
                    '"' + mirror + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            expanded_groups = []
            for i in self.opts.group:
                expanded_groups.extend(i.split(','))
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(expanded_groups))

        # Load the config file and return any automatic-options
        auto_opts = self._read_site_config_and_return_options()
        if auto_opts:
            automatic_options = auto_opts.split()
            for option in automatic_options:
                elements = option.split("=")
                if len(elements) == 2:
                    self._add_define_option(elements[0],
                                            '"' + elements[1] + '"')

        # Change into the suite directory
        if self.opts.conf_dir:
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
            self._check_suite_version(
                os.path.join(self.opts.conf_dir, 'rose-suite.conf'))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #35
0
class StemRunner(object):

    """Set up options for running a STEM job through Rose."""

    def __init__(self, opts, reporter=None, popen=None, fs_util=None):
        self.opts = opts
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler=self.reporter)
        else:
            self.popen = popen
        if fs_util is None:
            self.fs_util = FileSystemUtil(event_handler=self.reporter)
        else:
            self.fs_util = fs_util

    def _add_define_option(self, var, val):
        """Add a define option passed to the SuiteRunner."""

        if self.opts.defines:
            self.opts.defines.append(SUITE_RC_PREFIX + var + '=' + val)
        else:
            self.opts.defines = [SUITE_RC_PREFIX + var + '=' + val]
        self.reporter(ConfigVariableSetEvent(var, val))
        return

    def _get_base_dir(self, item):
        """Given a source tree return the following from 'fcm loc-layout':
           * url
           * sub_tree
           * peg_rev
           * root
           * project
        """

        rc, output, stderr = self.popen.run('fcm', 'loc-layout', item)
        if rc != 0:
            raise ProjectNotFoundException(item, stderr)

        ret = {}
        for line in output.splitlines():
            if ":" not in line:
                continue
            key, value = line.split(":", 1)
            if key:
                if value:
                    ret[key] = value.strip()

        return ret

    def _get_project_from_url(self, source_dict):
        """Run 'fcm keyword-print' to work out the project name."""

        repo = source_dict['root']
        if source_dict['project']:
            repo += '/' + source_dict['project']

        rc, kpoutput, stderr = self.popen.run('fcm', 'kp', source_dict['url'])

        project = None
        for line in kpoutput.splitlines():
            if line.rstrip().endswith(repo):
                kpresult = re.search(r'^location{primary}\[(.*)\]', line)
                if kpresult:
                    project = kpresult.group(1)
                    break
        return project

    def _deduce_mirror(self, source_dict, project):
        """Deduce the mirror location of this source tree."""

        # Root location for project
        proj_root = source_dict['root'] + '/' + source_dict['project']

        # Swap project to mirror
        project = re.sub(r'\.x$', r'.xm', project)
        mirror_repo = "fcm:" + project

        # Generate mirror location
        mirror = re.sub(proj_root, mirror_repo, source_dict['url'])

        # Add forwards slash after .xm if missing
        if '.xm/' not in mirror:
            mirror = re.sub(r'\.xm', r'.xm/', mirror)
        return mirror

    def _ascertain_project(self, item):
        """Set the project name and top-level from 'fcm loc-layout'.
        Returns:
            * project name
            * top-level location of the source tree with revision number
            * top-level location of the source tree without revision number
            * revision number
        """

        project = None
        try:
            project, item = item.split("=", 1)
        except ValueError:
            pass

        if re.search(r'^\.', item):
            item = os.path.abspath(os.path.join(os.getcwd(), item))

        if project is not None:
            print "[WARN] Forcing project for '{0}' to be '{1}'".format(
                item, project)
            return project, item, item, '', ''

        source_dict = self._get_base_dir(item)
        project = self._get_project_from_url(source_dict)
        mirror = self._deduce_mirror(source_dict, project)

        if not project:
            raise ProjectNotFoundException(item)

        if 'peg_rev' in source_dict and '@' in item:
            revision = '@' + source_dict['peg_rev']
            base = re.sub(r'@.*', r'', item)
        else:
            revision = ''
            base = item

        # Remove subtree from base and item
        if 'sub_tree' in source_dict:
            item = re.sub(
                r'(.*)%s/?$' % (source_dict['sub_tree']), r'\1', item, count=1)
            base = re.sub(
                r'(.*)%s/?$' % (source_dict['sub_tree']), r'\1', base, count=1)

        # Remove trailing forwards-slash
        item = re.sub(r'/$', r'', item)
        base = re.sub(r'/$', r'', base)

        # Remove anything after a point
        project = re.sub(r'\..*', r'', project)
        return project, item, base, revision, mirror

    def _generate_name(self):
        """Generate a suite name from the name of the first source tree."""
        try:
            basedir = self._ascertain_project(os.getcwd())[1]
        except ProjectNotFoundException:
            if self.opts.conf_dir:
                basedir = os.path.abspath(self.opts.conf_dir)
            else:
                basedir = os.getcwd()
        name = os.path.basename(basedir)
        self.reporter(NameSetEvent(name))
        return name

    def _this_suite(self):
        """Find the location of the suite in the first source tree."""

        # Get base of first source
        basedir = ''
        if self.opts.source:
            basedir = self.opts.source[0]
        else:
            basedir = self._ascertain_project(os.getcwd())[1]

        suitedir = os.path.join(basedir, DEFAULT_TEST_DIR)
        suitefile = os.path.join(suitedir, "rose-suite.conf")

        if not os.path.isfile(suitefile):
            raise RoseSuiteConfNotFoundException(suitedir)

        self._check_suite_version(suitefile)

        return suitedir

    def _read_site_config_and_return_options(self):
        """Read the site rose.conf file."""
        return ResourceLocator.default().get_conf().get_value(
            ["rose-stem", "automatic-options"])

    def _check_suite_version(self, fname):
        """Check the suite is compatible with this version of rose-stem."""
        if not os.path.isfile(fname):
            raise RoseSuiteConfNotFoundException(os.path.dirname(fname))
        config = rose.config.load(fname)
        suite_rose_stem_version = config.get(['ROSE_STEM_VERSION'])
        if suite_rose_stem_version:
            suite_rose_stem_version = int(suite_rose_stem_version.value)
        else:
            suite_rose_stem_version = None
        if not suite_rose_stem_version == ROSE_STEM_VERSION:
            raise RoseStemVersionException(suite_rose_stem_version)

    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev, mirror = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [url]
                self._add_define_option('SOURCE_' + project.upper() + '_REV',
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE',
                                        '"' + base + '"')
                self._add_define_option('SOURCE_' + project.upper() +
                                        '_MIRROR', '"' + mirror + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            expanded_groups = []
            for i in self.opts.group:
                expanded_groups.extend(i.split(','))
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(expanded_groups))

        # Load the config file and return any automatic-options
        auto_opts = self._read_site_config_and_return_options()
        if auto_opts:
            automatic_options = auto_opts.split()
            for option in automatic_options:
                elements = option.split("=")
                if len(elements) == 2:
                    self._add_define_option(
                        elements[0], '"' + elements[1] + '"')

        # Change into the suite directory
        if self.opts.conf_dir:
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
            self._check_suite_version(
                os.path.join(self.opts.conf_dir, 'rose-suite.conf'))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #36
0
class StemRunner(object):

    """Set up options for running a STEM job through Rose."""

    def __init__(self, opts, reporter=None, popen=None, fs_util=None):
        self.opts = opts
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler = self.reporter)
        else:
            self.popen = popen
        if fs_util is None:
            self.fs_util = FileSystemUtil(event_handler = self.reporter)
        else:
            self.fs_util = fs_util

    def _add_define_option(self, var, val):
        """Add a define option passed to the SuiteRunner."""

        if self.opts.defines:
            self.opts.defines.append(SUITE_RC_PREFIX + var + '=' + val )
        else:
            self.opts.defines= [ SUITE_RC_PREFIX + var + '=' + val ]
        self.reporter(ConfigVariableSetEvent(var, val))
        return

    def _get_base_dir(self, item):
        """Given a source tree return the following from 'fcm loc-layout':
           * url
           * sub_tree
           * peg_rev
           * root
           * project
        """
        
        
        rc, output, stderr = self.popen.run('fcm', 'loc-layout', item)
        if rc != 0:
            raise ProjectNotFoundException(item, stderr)

        ret = {}
        for line in output.splitlines():
            if not ":" in line:
              continue
            key, value = line.split(":", 1)
            if key:
                if value:
                    ret[key] = value.strip()

        return ret

    def _get_project_from_url(self, source_dict):
        """Run 'fcm keyword-print' to work out the project name."""

        repo = source_dict['root']
        if source_dict['project']:
            repo += '/' + source_dict['project']

        rc, kpoutput, stderr = self.popen.run('fcm', 'kp', source_dict['url'])

        project = None
        for line in kpoutput.splitlines():
            if line.rstrip().endswith(repo):
                kpresult = re.search(r'^location{primary}\[(.*)\]', line)
                if kpresult:
                    project = kpresult.group(1)
                    break
        return project

    def _ascertain_project(self, item):
        """Set the project name and top-level from 'fcm loc-layout'.
        Returns:
            * project name
            * top-level location of the source tree with revision number
            * top-level location of the source tree without revision number
            * revision number
        """

        project = ''
        if re.search(r'^\.', item):
            item = os.path.abspath(os.path.join(os.getcwd(), item))

        source_dict =  self._get_base_dir(item)
        project = self._get_project_from_url(source_dict)

        if not project:
            raise ProjectNotFoundException(item)

        if 'peg_rev' in source_dict and '@' in item:
            revision = '@' + source_dict['peg_rev']
            base = re.sub(r'@.*', r'', item)
        else:
            revision = ''
            base = item    

        # Remove subtree from base and item
        if 'sub_tree' in source_dict:
            item = item.replace(source_dict['sub_tree'], '', 1)
            base = base.replace(source_dict['sub_tree'], '', 1)

        # Remove trailing forwards-slash
        item = re.sub(r'/$',r'',item)
        base = re.sub(r'/$',r'',base)

        return project, item, base, revision

    def _generate_name(self):
        """Generate a suite name from the name of the first source tree."""
        dummy, basedir, dummy2, dummy3 = self._ascertain_project(os.getcwd())
        name = os.path.basename(basedir)
        return name

    def _this_suite(self):
        """Find the location of the suite in the first source tree."""

        # Get base of first source
        basedir = ''
        if self.opts.source:
            basedir = self.opts.source[0]
        else:
            dummy, basedir, dum2, dum3 = self._ascertain_project(os.getcwd())

        suitedir = os.path.join(basedir, DEFAULT_TEST_DIR)
        suitefile = os.path.join(suitedir, "rose-suite.conf")

        if not os.path.isfile(suitefile):
            raise RoseSuiteConfNotFoundException(suitedir)
        return suitedir

    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [ url ]
                self._add_define_option('SOURCE_' + project.upper() + '_REV', 
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE', 
                                        '"' + base + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(self.opts.group))

        # Change into the suite directory
        if self.opts.conf_dir:
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts
Example #37
0
 def __init__(self, event_handler=None):
     self.event_handler = event_handler
     self.popen = RosePopener(self.event_handler)
     self.suite_engine_proc = SuiteEngineProcessor.get_processor(
         event_handler=self.event_handler, popen=self.popen)
Example #38
0
class Analyse(object):

    """A comparison engine for Rose."""

    def __init__(self, config, opts, args, method_paths, reporter=None,
                 popen=None):
        if reporter is None:
            self.reporter = Reporter(opts.verbosity - opts.quietness)
        else:
            self.reporter = reporter
        if popen is None:
            self.popen = RosePopener(event_handler=self.reporter)
        else:
            self.popen = popen
        self.opts = opts
        self.args = args
        self.config = config
        self.load_tasks()
        modules = []
        for path in method_paths:
            for filename in glob.glob(path + "/*.py"):
                modules.append(filename)
        self.load_user_comparison_modules(modules)

    def analyse(self):
        """Perform comparisons given a list of tasks."""
        rc = 0
        for task in self.tasks:

            if self.check_extract(task):
                # Internal AnalysisEngine extract+comparison test

                # Extract data from results and from kgoX
                task = self.do_extract(task, "result")

                for i in range(task.numkgofiles):
                    var = "kgo" + str(i + 1)
                    task = self.do_extract(task, var)

                task = self.do_comparison(task)
            else:
                # External program(s) doing test

                # Command to run
                command = task.extract

                result = re.search(r"\$file", command)
                # If the command contains $file, it is run separately for both
                # the KGO and the result files
                if result:
                    # Replace $file token with resultfile or kgofile
                    resultcommand = self._expand_tokens(command, task,
                                                        "result")
                    kgocommand = self._expand_tokens(command, task, "kgo1")

                    # Run the command on the resultfile
                    task.resultdata = self._run_command(resultcommand)

                    # Run the command on the KGO file
                    task.kgo1data = self._run_command(kgocommand)
                else:
                    # The command works on both files at the same time
                    # Replace tokens $kgofile and $resultfile for actual values
                    command = self._expand_tokens(command, task)

                    # Run the command
                    task.resultdata = self._run_command(command)

                # Run the comparison
                task = self.do_comparison(task)

            self.reporter(TaskCompletionEvent(task),
                          prefix="[%s]" % (task.userstatus))
            if task.numericstatus != PASS:
                rc += 1
        return rc, self.tasks

    def check_extract(self, task):
        """Check if an extract name is present in a user method."""
        for module_name, class_name, method, help in self.user_methods:
            if task.extract == class_name:
                return True
        return False

    def do_comparison(self, task):
        """Run the comparison."""
        for module_name, class_name, method, help in self.user_methods:
            comparison_name = ".".join([module_name, class_name])
            if task.comparison == class_name:
                for module in self.modules:
                    if module.__name__ == module_name:
                        comparison_inst = getattr(module, class_name)()
                        comparison_meth = getattr(comparison_inst, "run")(task)
        return task

    def do_extract(self, task, var):
        """Extract the specified data."""
        for module_name, class_name, method, help in self.user_methods:
            extract_name = ".".join([module_name, class_name])
            if task.extract == class_name:
                for module in self.modules:
                    if module.__name__ == module_name:
                        extract_inst = getattr(module, class_name)()
                        extract_meth = getattr(extract_inst, "run")(task, var)
        return task

    def _run_command(self, command):
        """Run an external command using rose.popen."""
        output, stderr = self.popen.run_ok(command, shell=True)
        output = "".join(output).splitlines()
        return output

    def _expand_tokens(self, inputstring, task, var=None):
        """Expands tokens $resultfile, $file and $kgoXfile."""
        filename = ''
        if var:
            filename = getattr(task, var + "file")
        expansions = {'resultfile': task.resultfile, 'file': filename}
        for i in range(1, task.numkgofiles + 1):
            key = "kgo" + str(i) + "file"
            value = getattr(task, key)
            expansions[key] = value
        inputstring = inputstring.format(**expansions)
        return inputstring

    def _find_file(self, var, task):
        """Finds a file given a variable name containing the filename.

        Given a variable name and task object, this returns the filename it
        points to, including expanding any * characters with glob.
        """

        filevar = var + "file"
        if hasattr(task, filevar):
            configvar = var + "fileconfig"
            setattr(task, configvar, getattr(task, filevar))
            filenames = glob.glob(env_var_process(getattr(task, filevar)))
            if len(filenames) > 0:
                setattr(task, filevar, os.path.abspath(filenames[0]))
        return task

    def load_tasks(self):
        """Loads AnalysisTasks from files.

        Given a list of files, return AnalysisTasks generated from those files.
        This also expands environment variables in filenames, but saves the
        original contents for use when writing out config files
        """

        tasks = []
        for task in self.config.value.keys():
            if task is "env":
                continue
            if task.startswith("file:"):
                continue
            newtask = AnalysisTask()
            newtask.name = task
            value = self.config.get_value([task, "resultfile"])

            # If the task is ignored, this will be None, so continue
            # on to the next task
            if value is None:
                continue

            if "{}" in value:
                newtask.resultfile = value.replace("{}", self.args[0])
            else:
                newtask.resultfile = value
            newtask = self._find_file("result", newtask)
            newtask.extract = self.config.get_value([task, "extract"])
            result = re.search(r":", newtask.extract)
            if result:
                newtask.subextract = ":".join(newtask.extract.split(":")[1:])
                newtask.extract = newtask.extract.split(":")[0]
            newtask.comparison = self.config.get_value([task, "comparison"])
            newtask.tolerance = env_var_process(self.config.get_value(
                                                [task, "tolerance"]))
            newtask.warnonfail = (
                self.config.get_value([task, "warnonfail"]) in ["yes", "true"])

            # Allow for multiple KGO, e.g. kgo1file, kgo2file, for
            # statistical comparisons of results
            newtask.numkgofiles = 0
            for i in range(1, MAX_KGO_FILES):
                kgovar = "kgo" + str(i)
                kgofilevar = kgovar + "file"
                if self.config.get([task, kgofilevar]):
                    value = self.config.get([task, kgofilevar])[:]
                    if "{}" in value:
                        setattr(
                            newtask, kgofilevar,
                            value.replace("{}", self.args[0]))
                    else:
                        setattr(newtask, kgofilevar, value)
                    newtask.numkgofiles += 1
                    newtask = self._find_file(kgovar, newtask)
                else:
                    break
            tasks.append(newtask)
        self.tasks = tasks
        return tasks

    def load_user_comparison_modules(self, files):
        """Import comparison modules and store them."""
        modules = []
        for filename in files:
            directory = os.path.dirname(filename)
            if (not directory.endswith(USRCOMPARISON_DIRNAME) or
                    not filename.endswith(USRCOMPARISON_EXT)):
                continue
            comparison_name = os.path.basename(filename).rpartition(
                USRCOMPARISON_EXT)[0]
            sys.path.insert(0, os.path.abspath(directory))
            try:
                modules.append(__import__(comparison_name))
            except ImportError as e:
                self.reporter(e)
            sys.path.pop(0)
        modules.sort()
        self.modules = modules

        user_methods = []
        for module in modules:
            comparison_name = module.__name__
            contents = inspect.getmembers(module, inspect.isclass)
            for obj_name, obj in contents:
                att_name = "run"
                if hasattr(obj, att_name) and callable(getattr(obj, att_name)):
                    doc_string = obj.__doc__
                    user_methods.append((comparison_name, obj_name, att_name,
                                        doc_string))
        self.user_methods = user_methods
        return user_methods

    def write_config(self, filename, tasks):
        """Write an analysis config file based on a list of tasks provided"""
        config = rose.config.ConfigNode()

        for task in tasks:
            sectionname = task.name
            if task.resultfileconfig:
                config.set([sectionname, "resultfile"], task.resultfileconfig)
            for i in range(1, task.numkgofiles + 1):
                origvar = "kgo" + str(i) + "fileconfig"
                valvar = "kgo" + str(i) + "file"
                if hasattr(task, origvar):
                    config.set([sectionname, valvar], getattr(task, origvar))
            if task.extract:
                config.set([sectionname, "extract"], task.extract)
            if task.subextract:
                config.set([sectionname, "extract"],
                           task.extract + ":" + task.subextract)
            if task.comparison:
                config.set([sectionname, "comparison"], task.comparison)
            if task.tolerance:
                config.set([sectionname, "tolerance"], task.tolerance)
            if task.warnonfail:
                config.set([sectionname, "warnonfail"], "true")
        rose.config.dump(config, filename)
Example #39
0
    def process(self):
        """Process STEM options into 'rose suite-run' options."""

        # Generate options for source trees
        repos = {}
        if not self.opts.source:
            self.opts.source = ['.']
        self.opts.project = list()

        for i, url in enumerate(self.opts.source):
            project, url, base, rev, mirror = self._ascertain_project(url)
            self.opts.source[i] = url
            self.opts.project.append(project)
            if project in repos:
                repos[project].append(url)
            else:
                repos[project] = [url]
                self._add_define_option('SOURCE_' + project.upper() + '_REV',
                                        '"' + rev + '"')
                self._add_define_option('SOURCE_' + project.upper() + '_BASE',
                                        '"' + base + '"')
                self._add_define_option(
                    'SOURCE_' + project.upper() + '_MIRROR',
                    '"' + mirror + '"')
            self.reporter(SourceTreeAddedAsBranchEvent(url))
        for project, branches in repos.iteritems():
            var = 'SOURCE_' + project.upper()
            branchstring = RosePopener.list_to_shell_str(branches)
            self._add_define_option(var, '"' + branchstring + '"')

        # Generate the variable containing tasks to run
        if self.opts.group:
            if not self.opts.defines:
                self.opts.defines = []
            expanded_groups = []
            for i in self.opts.group:
                expanded_groups.extend(i.split(','))
            self.opts.defines.append(SUITE_RC_PREFIX + 'RUN_NAMES=' +
                                     str(expanded_groups))

        # Load the config file and return any automatic-options
        auto_opts = self._read_site_config_and_return_options()
        if auto_opts:
            automatic_options = auto_opts.split()
            for option in automatic_options:
                elements = option.split("=")
                if len(elements) == 2:
                    self._add_define_option(elements[0],
                                            '"' + elements[1] + '"')

        # Change into the suite directory
        if self.opts.conf_dir:
            self.reporter(SuiteSelectionEvent(self.opts.conf_dir))
            self._check_suite_version(
                os.path.join(self.opts.conf_dir, 'rose-suite.conf'))
        else:
            thissuite = self._this_suite()
            self.fs_util.chdir(thissuite)
            self.reporter(SuiteSelectionEvent(thissuite))

        # Create a default name for the suite; allow override by user
        if not self.opts.name:
            self.opts.name = self._generate_name()

        return self.opts