예제 #1
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)
예제 #2
0
def main():
    """Implement "rose suite-shutdown"."""
    argv = sys.argv[1:]
    method_name = argv.pop(0)
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("name", "non_interactive")
    opts, args = opt_parser.parse_args(argv)
    event_handler = Reporter(opts.verbosity - opts.quietness)
    suite_control = SuiteControl(event_handler=event_handler)
    method = getattr(suite_control, method_name)
    confirm = None
    suite_names = []
    if not opts.non_interactive:
        confirm = prompt
    else:
        if opts.name:
            suite_names.append(opts.name)
        else:
            try:
                suite_name = get_suite_name(event_handler)
                suite_names.append(suite_name)
            except SuiteNotFoundError as exc:
                event_handler(exc)
                sys.exit(1)

    if opts.debug_mode:
        for sname in suite_names:
            method(sname, confirm, sys.stderr, sys.stdout, *args)
    else:
        for sname in suite_names:
            try:
                method(sname, confirm, sys.stderr, sys.stdout, *args)
            except Exception as exc:
                event_handler(exc)
                sys.exit(1)
예제 #3
0
def main():
    """Launcher for the CLI."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options('name')
    opts, args = opt_parser.parse_args(sys.argv[1:])
    event_handler = Reporter(opts.verbosity - opts.quietness)
    suite_vc_cmp = SuiteVCComparator(event_handler)
    suite_name = opts.name
    if not suite_name and args:
        suite_name = args[0]
    if not suite_name:
        suite_name = os.getenv(suite_vc_cmp.suite_engine_proc.SUITE_NAME_ENV)
    if not suite_name:
        opt_parser.print_usage(sys.stderr)
        sys.exit(2)
    try:
        lines = suite_vc_cmp.cmp_source_vc_info(suite_name=suite_name)
    except Exception as exc:
        event_handler(exc)
        traceback.print_exc()
        sys.exit(2)
    else:
        if lines is None:
            event_handler(
                '%s: rose-suite-run.version: VC info not found' % (
                    suite_name),
                kind=Reporter.KIND_ERR, level=Reporter.FAIL)
            sys.exit(2)
        lines = list(line for line in lines)
        for line in lines:
            event_handler('%s\n' % line, prefix='')
        if lines:
            sys.exit(1)
        else:
            sys.exit(0)
예제 #4
0
def main():
    """Implement "rose env-cat"."""
    opt_parser = RoseOptionParser(usage='rose env-cat [OPTIONS] [FILE ...]',
                                  description=r'''
Substitute environment variables in input files and print.

If no argument is specified, read from STDIN. One `FILE` argument may be
`-`, which means read from STDIN.

In `match-mode=default`, the command will look for `$NAME` or `${NAME}`
syntax and substitute them with the value of the environment variable
`NAME`. A backslash in front of the syntax, e.g. `\$NAME` or `\${NAME}`
will escape the substitution.

In `match-mode=brace`, the command will look for `${NAME}` syntax only.

EXAMPLES
    rose env-cat [OPTIONS] [FILE ...]
        ''')
    opt_parser.add_my_options("match_mode", "output_file", "unbound")
    opt_parser.modify_option(
        'output_file',
        help=("Specify an output file."
              "\nIf no output file is specified or if `FILE`"
              "is `-`, write output to STDOUT."),
    )
    opts, args = opt_parser.parse_args()
    rose_env_cat(args, opts)
예제 #5
0
def main():
    """Implement the "rose config-dump" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("conf_dir", "files", "no_pretty_mode")
    opts = opt_parser.parse_args()[0]
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    fs_util = FileSystemUtil(report)
    if opts.conf_dir:
        fs_util.chdir(opts.conf_dir)
    file_names = []
    if opts.files:
        file_names = opts.files
    else:
        for dirpath, _, filenames in os.walk("."):
            for filename in fnmatch.filter(filenames, "rose-*.conf"):
                path = os.path.join(dirpath, filename)[2:]  # remove leading ./
                file_names.append(path)
    for file_name in file_names:
        handle = NamedTemporaryFile()
        node = ConfigLoader()(file_name)
        if (not opts.no_pretty_mode
                and os.path.basename(file_name) != META_CONFIG_NAME):
            pretty_format_config(node, ignore_error=True)
        ConfigDumper()(node, handle)
        handle.seek(0)
        if not filecmp.cmp(handle.name, file_name, shallow=False):
            report(ConfigDumpEvent(file_name))
            ConfigDumper()(node, file_name)
예제 #6
0
def main():
    """Launcher for command line invokation of metomi.rose stem."""

    # Process options
    opt_parser = RoseOptionParser()

    option_keys = SuiteRunner.OPTIONS + OPTIONS
    opt_parser.add_my_options(*option_keys)
    opts, args = opt_parser.parse_args()

    # Set up a runner instance and process the options
    stem = StemRunner(opts)
    if opts.debug_mode:
        opts = stem.process()
    else:
        try:
            opts = stem.process()
        except Exception as exc:
            stem.reporter(exc)
            sys.exit(1)

    # Get the suiterunner object and execute
    runner = SuiteRunner(event_handler=stem.reporter,
                         popen=stem.popen,
                         fs_util=stem.fs_util)
    if opts.debug_mode:
        sys.exit(runner(opts, args))
    try:
        sys.exit(runner(opts, args))
    except Exception as exc:
        runner.handle_event(exc)
        if isinstance(exc, RosePopenError):
            sys.exit(exc.ret_code)
        else:
            sys.exit(1)
예제 #7
0
def main():
    """rose task-env."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("cycle", "cycle_offsets", "path_globs",
                              "prefix_delim", "suffix_delim")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness - 1)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report)
    kwargs = dict(vars(opts))
    try:
        task_props = suite_engine_proc.get_task_props(*args, **kwargs)
        for key, value in task_props:
            report(str(EnvExportEvent(key, value)) + "\n", level=0)
        path_globs = opts.path_globs
        if path_globs is None:
            path_globs = []
        prepend_paths_map = get_prepend_paths(report,
                                              task_props.suite_dir,
                                              path_globs,
                                              full_mode=True)
        for key, prepend_paths in prepend_paths_map.items():
            orig_paths = []
            orig_v = os.getenv(key, "")
            if orig_v:
                orig_paths = orig_v.split(os.pathsep)
            path = os.pathsep.join(prepend_paths + orig_paths)
            report(str(EnvExportEvent(key, path)) + "\n", level=0)
    except Exception as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
예제 #8
0
def parse_cli(*args, **kwargs):
    """Parse command line, start/stop ad-hoc server.

    Return a CLI instruction tuple for a valid command instruction, else False:
        ("start", Boolean, port):
            start server on 'port', [2]==True indicating non_interactive mode.
        ("stop", Boolean):
            stop server, [2]==True indicating service_root_mode.
        None:
            bare command, requesting to print server status
    """
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("non_interactive", "service_root_mode")
    opts, args = opt_parser.parse_args()

    arg = None
    if args:
        arg = args[0]

    if arg == "start":
        port = DEFAULT_PORT
        if args[1:]:
            try:
                port = int(args[1])
            except ValueError:
                print("Invalid port specified. Using the default port.")
        return ("start", opts.service_root_mode, port)
    elif arg == "stop":
        return ("stop", opts.non_interactive)
    elif arg:  # unrecognised (invalid) argument, to ignore
        return False  # False to distinguish from None for no arguments given
예제 #9
0
def main():
    """Implement "rose env-cat"."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("match_mode", "output_file", "unbound")
    opts, args = opt_parser.parse_args()
    if not args:
        args = ["-"]
    if not opts.output_file or opts.output_file == "-":
        out_handle = sys.stdout
    else:
        out_handle = open(opts.output_file, "wb")
    for arg in args:
        if arg == "-":
            in_handle = sys.stdin
        else:
            in_handle = open(arg)
        line_num = 0
        while True:
            line_num += 1
            line = in_handle.readline()
            if not line:
                break
            try:
                out_handle.write(
                    env_var_process(line, opts.unbound, opts.match_mode))
            except UnboundEnvironmentVariableError as exc:
                name = arg
                if arg == "-":
                    name = "<STDIN>"
                sys.exit("%s:%s: %s" % (name, line_num, str(exc)))
        in_handle.close()
    out_handle.close()
예제 #10
0
파일: env_cat.py 프로젝트: wxtim/rose
def main():
    """Implement "rose env-cat"."""
    opt_parser = RoseOptionParser(usage='rose env-cat [OPTIONS] [FILE ...]',
                                  description=r'''
Substitute environment variables in input files and print.

If no argument is specified, read from STDIN. One `FILE` argument may be
`-`, which means read from STDIN.

In `match-mode=default`, the command will look for `$NAME` or `${NAME}`
syntax and substitute them with the value of the environment variable
`NAME`. A backslash in front of the syntax, e.g. `\$NAME` or `\${NAME}`
will escape the substitution.

In `match-mode=brace`, the command will look for `${NAME}` syntax only.

EXAMPLES
    rose env-cat [OPTIONS] [FILE ...]
        ''')
    opt_parser.add_my_options("match_mode", "output_file", "unbound")
    opt_parser.modify_option(
        'output_file',
        help=("Specify an output file."
              "\nIf no output file is specified or if `FILE`"
              "is `-`, write output to STDOUT."),
    )
    opts, args = opt_parser.parse_args()
    if not args:
        args = ["-"]
    if not opts.output_file or opts.output_file == "-":
        out_handle = sys.stdout
    else:
        out_handle = open(opts.output_file, "wb")
    for arg in args:
        if arg == "-":
            in_handle = sys.stdin
        else:
            in_handle = open(arg)
        line_num = 0
        while True:
            line_num += 1
            line = in_handle.readline()
            if not line:
                break
            try:
                out_handle.write(
                    env_var_process(line, opts.unbound, opts.match_mode))
            except UnboundEnvironmentVariableError as exc:
                name = arg
                if arg == "-":
                    name = "<STDIN>"
                sys.exit("%s:%s: %s" % (name, line_num, str(exc)))
        in_handle.close()
    out_handle.close()
예제 #11
0
def main():
    """Launcher for the CLI."""
    opt_parser = RoseOptionParser(
        usage='%prog [OPTIONS] [--] [COMMAND ...]',
        description='''
Run an application according to its configuration.

May run a builtin application (if the `mode` setting in the configuration
specifies the name of a builtin application) or a command.

Determine the command to run in this order:

1. If `COMMAND` is specified, invoke the command.
2. If the `--command-key=KEY` option is defined, invoke the command
   specified in `[command]KEY`.
3. If the `ROSE_APP_COMMAND_KEY` environment variable is set, the command
   specified in the `[command]KEY` setting in the application
   configuration whose `KEY` matches it is used.
4. If the environment variable `ROSE_TASK_NAME` is defined and a setting
   in the `[command]` section has a key matching the value of the
   environment variable, then the value of the setting is used as the
   command.
5. Invoke the command specified in `[command]default`.
        ''',
        epilog='''
ENVIRONMENT VARIABLES
    optional ROSE_APP_COMMAND_KEY
        Switch to a particular command specified in `[command]KEY`.
    optional ROSE_APP_MODE
        Specifies a builtin application to run.
    optional ROSE_APP_OPT_CONF_KEYS
        Each `KEY` in this space delimited list switches on an optional
        configuration. The configurations are applied first-to-last.
    optional ROSE_FILE_INSTALL_ROOT
        If specified, change to the specified directory to install files.
        '''
    )
    option_keys = AppRunner.OPTIONS
    opt_parser.add_my_options(*option_keys)
    opts, args = opt_parser.parse_args()
    event_handler = Reporter(opts.verbosity - opts.quietness)
    runner = AppRunner(event_handler)
    try:
        sys.exit(runner(opts, args))
    except Exception as exc:
        runner.handle_event(exc)
        if opts.debug_mode:
            traceback.print_exc()
        if isinstance(exc, RosePopenError):
            sys.exit(exc.ret_code)
        else:
            sys.exit(1)
예제 #12
0
파일: task_run.py 프로젝트: wxtim/rose
def main():
    """Launcher for the CLI."""
    opt_parser = RoseOptionParser(
        usage='rose task-run [OPTIONS] [--] [APP-COMMAND ...]',
        description='''
Provide an environment to run a suite task.

Provides environment variables documented in `rose task-env`. It is worth
noting that if the environment variables are already provided by
`rose task-env`, this command will not override them.

Normally, the suite task will select a Rose application configuration
that has the same name as the task. This can be overridden by the
`--app-key=KEY` option or the `ROSE_TASK_APP` environment variable.

SHORT OPTIONS
    All options of `rose app-run` and `rose task-env` are supported.
    Additional options are:

    --app-key=KEY
        Specify a named application configuration.
        ''',
        epilog='''
ENVIRONMENT VARIABLES
    All environment variables of `rose app-run` and `rose task-env` are
    supported. All environment variables documented in `rose task-env` are
    passed to the application `rose task-run` runs.
    The following environment variables are used by `rose task-run`:

    ROSE_TASK_APP
        Specify a named application configuration.

SEE ALSO
    * `rose app-run`
    * `rose task-env`
        ''',
    )
    option_keys = TaskRunner.OPTIONS
    opt_parser.add_my_options(*option_keys)
    opts, args = opt_parser.parse_args()
    event_handler = Reporter(opts.verbosity - opts.quietness)
    runner = TaskRunner(event_handler)
    try:
        sys.exit(runner(opts, args))
    except Exception as exc:
        runner.handle_event(exc)
        if opts.debug_mode:
            traceback.print_exc()
        if isinstance(exc, RosePopenError):
            sys.exit(exc.ret_code)
        else:
            sys.exit(1)
예제 #13
0
파일: date.py 프로젝트: MartinDix/rose
def main():
    """Implement "rose date"."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options(
        "calendar",
        "diff",
        "offsets1",
        "offsets2",
        "parse_format",
        "print_format",
        "task_cycle_time_mode",
        "as_total",
        "utc_mode",
    )
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)

    ref_point_str = None
    if opts.task_cycle_time_mode:
        ref_point_str = os.getenv(RoseDateTimeOperator.TASK_CYCLE_TIME_ENV)
        if ref_point_str is None:
            exc = UnboundEnvironmentVariableError(
                RoseDateTimeOperator.TASK_CYCLE_TIME_ENV)
            report(exc)
            if opts.debug_mode:
                raise exc
            sys.exit(1)

    date_time_oper = RoseDateTimeOperator(
        parse_format=opts.parse_format,
        utc_mode=opts.utc_mode,
        calendar_mode=opts.calendar,
        ref_point_str=ref_point_str,
    )

    try:
        if len(args) < 2:
            if opts.duration_print_format:
                _convert_duration(date_time_oper, opts, args)
            else:
                _print_time_point(date_time_oper, opts, args)
        else:
            _print_duration(date_time_oper, opts, args)
    except OffsetValueError as exc:
        report(exc)
        if opts.debug_mode:
            raise exc
        sys.exit(1)
예제 #14
0
def main():
    """Implement "rose suite-log" CLI."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("archive_mode", "force_mode", "name",
                              "non_interactive", "prune_remote_mode",
                              "update_mode", "user", "view_mode")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)

    try:
        suite_log_view(opts, args, report)
    except Exception as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
예제 #15
0
def main():
    """CLI for "rose namelist-dump"."""
    opt_parser = RoseOptionParser(
        usage='rose-namelist-dump [OPTIONS] [FILE ...]',
        description='''
Convert namelist files into a Rose application configuration snippet.
Each argument should be the path to an empty file or a file containing
Fortran namelist groups. A `-` can be used once in the argument list to
specify the standard input. If no argument is given, it assumes the
standard input is specified. Where possible, use relative path for file
names, as the file names appear as-specified in the generated
configuration.
        ''',
    )
    opt_parser.add_my_options("case_mode", "lower", "output_file", "upper")
    opts, args = opt_parser.parse_args()
    return namelist_dump(args, opts.output_file, opts.case_mode)
예제 #16
0
def main():
    """Launcher for the CLI."""
    opt_parser = RoseOptionParser()
    option_keys = AppRunner.OPTIONS
    opt_parser.add_my_options(*option_keys)
    opts, args = opt_parser.parse_args(sys.argv[1:])
    event_handler = Reporter(opts.verbosity - opts.quietness)
    runner = AppRunner(event_handler)
    try:
        sys.exit(runner(opts, args))
    except Exception as exc:
        runner.handle_event(exc)
        if opts.debug_mode:
            traceback.print_exc()
        if isinstance(exc, RosePopenError):
            sys.exit(exc.ret_code)
        else:
            sys.exit(1)
예제 #17
0
def main():
    """Implement the "rose suite-id" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("latest", "next", "to_local_copy", "to_origin",
                              "to_output", "to_web")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    SuiteId.svn.event_handler = report  # FIXME: ugly?
    arg = None
    if args:
        arg = args[0]

    try:
        if opts.to_origin:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_origin()) + "\n", level=0)
        elif opts.to_local_copy:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_local_copy()) + "\n",
                       level=0)
        elif opts.to_output:
            for arg in args:
                url = SuiteId(id_text=arg).to_output()
                report(str(url) + "\n", level=0)
        elif opts.to_web:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_web()) + "\n", level=0)
        elif opts.latest:
            suite_id = SuiteId.get_latest(prefix=arg)
            if suite_id is not None:
                report(str(suite_id) + "\n", level=0)
        elif opts.next:
            suite_id = SuiteId.get_next(prefix=arg)
            if suite_id is not None:
                report(str(suite_id) + "\n", level=0)
        else:
            if not arg:
                arg = os.getcwd()
            report(str(SuiteId(location=arg)) + "\n", level=0)
    except (NoSuiteLogError, SuiteIdError) as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
예제 #18
0
파일: config_dump.py 프로젝트: wxtim/rose
def main():
    """Implement the "rose config-dump" command."""
    opt_parser = RoseOptionParser(description='''
Re-dump Rose configuration files in the common format.

Load and dump `"rose-*.conf"` files in place. Apply format-specific
pretty-printing.

By default, it recursively loads and dumps all `rose-*.conf` files in the
current working directory.

EXAMPLES
    rose config-dump
    rose config-dump -C /path/to/conf/dir
    rose config-dump -f /path/to/file1 -f /path/to/file2
        ''')
    opt_parser.add_my_options("conf_dir", "files", "no_pretty_mode")
    opts = opt_parser.parse_args()[0]
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    fs_util = FileSystemUtil(report)
    if opts.conf_dir:
        fs_util.chdir(opts.conf_dir)
    file_names = []
    if opts.files:
        file_names = opts.files
    else:
        for dirpath, _, filenames in os.walk("."):
            for filename in fnmatch.filter(filenames, "rose-*.conf"):
                path = os.path.join(dirpath, filename)[2:]  # remove leading ./
                file_names.append(path)
    for file_name in file_names:
        handle = NamedTemporaryFile()
        node = ConfigLoader()(file_name)
        if (not opts.no_pretty_mode
                and os.path.basename(file_name) != META_CONFIG_NAME):
            pretty_format_config(node, ignore_error=True)
        ConfigDumper()(node, handle)
        handle.seek(0)
        if not filecmp.cmp(handle.name, file_name, shallow=False):
            report(ConfigDumpEvent(file_name))
            ConfigDumper()(node, file_name)
예제 #19
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()
        sys.exit(1)
    opts.choice = int(opts.choice)
    report(choice(host_score_list[0:opts.choice])[0] + "\n", level=0)
예제 #20
0
def main():
    """Launcher for the CLI."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("host", "name")
    opts, args = opt_parser.parse_args(sys.argv[1:])
    event_handler = Reporter(opts.verbosity - opts.quietness)
    suite_restarter = SuiteRestarter(event_handler)
    try:
        sys.exit(suite_restarter.restart(
            suite_name=opts.name,
            host=opts.host,
            args=args))
    except Exception as exc:
        event_handler(exc)
        if opts.debug_mode:
            traceback.print_exc()
        if isinstance(exc, RosePopenError):
            sys.exit(exc.ret_code)
        else:
            sys.exit(1)
예제 #21
0
파일: ws.py 프로젝트: wxtim/rose
def parse_cli(*args, **kwargs):
    """Parse command line, start/stop ad-hoc server.

    Return a CLI instruction tuple for a valid command instruction, else False:
        ("start", Boolean, port):
            start server on 'port', [2]==True indicating non_interactive mode.
        ("stop", Boolean):
            stop server, [2]==True indicating service_root_mode.
        None:
            bare command, requesting to print server status
    """
    opt_parser = RoseOptionParser(description='''
Start/stop ad-hoc Rosie suite discovery web service server.

For `rosie disco start`, if `PORT` is not specified, use port 8080.

Examples:
    rosie disco start [PORT] # start ad-hoc web service server (on PORT)
    rosie disco stop         # stop ad-hoc web service server
    rosie disco stop -y      # stop ad-hoc web service server w/o prompting
    rosie disco              # print status of ad-hoc web service server
        ''', )
    opt_parser.add_my_options("non_interactive", "service_root_mode")
    opts, args = opt_parser.parse_args()

    arg = None
    if args:
        arg = args[0]

    if arg == "start":
        port = DEFAULT_PORT
        if args[1:]:
            try:
                port = int(args[1])
            except ValueError:
                print("Invalid port specified. Using the default port.")
        return ("start", opts.service_root_mode, port)
    elif arg == "stop":
        return ("stop", opts.non_interactive)
    elif arg:  # unrecognised (invalid) argument, to ignore
        return False  # False to distinguish from None for no arguments given
예제 #22
0
def main():
    """Implement the "rose suite-clean" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("name", "non_interactive", "only_items")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    cleaner = SuiteRunCleaner(event_handler=report)
    if opts.name:
        args.append(opts.name)
    if not args:
        args = [os.path.basename(os.getcwd())]
    os.chdir(os.path.expanduser('~'))
    n_done = 0
    for arg in args:
        if not opts.non_interactive:
            try:
                answer = input("Clean %s? y/n (default n) " % arg)
            except EOFError:
                sys.exit(1)
            if answer not in ["Y", "y"]:
                continue
        try:
            cleaner.clean(arg, opts.only_items)
        except (
                OSError,
                IOError,
                ConfigSyntaxError,
                RosePopenError,
                SuiteStillRunningError,
        ) as exc:
            report(exc)
            if opts.debug_mode:
                traceback.print_exc()
        else:
            n_done += 1
    sys.exit(len(args) - n_done)  # Return 0 if everything done
예제 #23
0
파일: suite_id.py 프로젝트: wxtim/rose
def main():
    """Implement the "rose suite-id" command."""
    opt_parser = RoseOptionParser(description='''
Utility for working with suite IDs.

EXAMPLES:
    # Print the repository URL of a given suite ID
    rosie id --to-origin mo1-abc45

    # Print the local location of a given suite ID
    rosie id --to-local-copy mo1-abc45

    # Print the web URL of a given suite ID
    rosie id --to-web mo1-abc45

    # Print suite ID of working copy in $PWD
    rosie id

    # Print suite ID of working copy in a directory
    rosie id /path/to/working/copy

    # Print suite ID of a given URL
    rosie id svn://fcm1/rose_mo1_svn/a/b/c/4/5

    # Print latest suite ID in the default repository
    rosie id --latest

    # Print latest suite ID in the given repository
    rosie id --latest mot

    # Print next suite ID in the default repository
    rosie id --next
        ''', )
    opt_parser.add_my_options("latest", "next", "to_local_copy", "to_origin",
                              "to_web")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    SuiteId.svn.event_handler = report  # FIXME: ugly?
    arg = None
    if args:
        arg = args[0]

    try:
        if opts.to_origin:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_origin()) + "\n", level=0)
        elif opts.to_local_copy:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_local_copy()) + "\n",
                       level=0)
        elif opts.to_web:
            for arg in args:
                report(str(SuiteId(id_text=arg).to_web()) + "\n", level=0)
        elif opts.latest:
            suite_id = SuiteId.get_latest(prefix=arg)
            if suite_id is not None:
                report(str(suite_id) + "\n", level=0)
        elif opts.next:
            suite_id = SuiteId.get_next(prefix=arg)
            if suite_id is not None:
                report(str(suite_id) + "\n", level=0)
        else:
            if not arg:
                arg = os.getcwd()
            report(str(SuiteId(location=arg)) + "\n", level=0)
    except (NoSuiteLogError, SuiteIdError) as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
예제 #24
0
파일: config_cli.py 프로젝트: rolinzcy/rose
def main():
    """Implement the "rose config" command."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("default", "env_var_process_mode", "files",
                              "keys", "meta", "meta_key", "no_ignore",
                              "no_opts", "print_conf_mode")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)

    metomi.rose.macro.add_meta_paths()

    if opts.meta_key:
        opts.meta = True

    if opts.files and opts.meta_key:
        report(Exception("Cannot specify both a file and meta key."))
        sys.exit(1)

    config_loader = ConfigLoader()
    sources = []
    if opts.files:
        root_node = ConfigNode()
        for fname in opts.files:
            if fname == "-":
                sources.append(sys.stdin)
            else:
                if opts.meta:
                    try:
                        root_node = config_loader.load(fname)
                    except ConfigSyntaxError as exc:
                        report(exc)
                        sys.exit(1)
                    rel_path = os.sep.join(fname.split(os.sep)[:-1])
                    fpath = get_meta_path(root_node, rel_path)
                    if fpath is None:
                        report(MetadataNotFoundEvent(fname))
                    else:
                        sources.append(fpath)
                else:
                    sources.append(fname)
    elif opts.meta:
        root_node = ConfigNode()
        if opts.meta_key:
            root_node.set(["meta"], opts.meta_key)
        else:
            fname = os.path.join(os.getcwd(), metomi.rose.SUB_CONFIG_NAME)
            try:
                root_node = config_loader.load(fname)
            except ConfigSyntaxError as exc:
                report(exc)
                sys.exit(1)
        fpath = get_meta_path(root_node, meta_key=opts.meta_key)
        root_node.unset(["meta"])
        if fpath is None:
            report(Exception("Metadata not found"))
            sys.exit(1)
        else:
            sources.append(fpath)
    else:
        root_node = ResourceLocator.default().get_conf()

    for source in sources:
        try:
            if opts.meta or opts.no_opts:
                config_loader.load(source, root_node)
            else:
                config_loader.load_with_opts(source, root_node)
        except (ConfigSyntaxError, IOError) as exc:
            report(exc)
            sys.exit(1)
        if source is sys.stdin:
            source.close()

    if opts.quietness:
        sys.exit(root_node.get(args, opts.no_ignore) is None)

    if opts.keys_mode:
        try:
            keys = list(root_node.get(args, opts.no_ignore).value)
        except AttributeError:
            sys.exit(1)
        keys.sort()
        for key in keys:
            print(key)
        sys.exit()

    conf_dump = ConfigDumper()
    if len(args) == 0:
        conf_dump(root_node, concat_mode=opts.print_conf_mode)
        sys.exit()

    node = root_node.get(args, opts.no_ignore)

    if node is not None and isinstance(node.value, dict):
        if opts.print_conf_mode:
            conf_dump(ConfigNode().set(args, node.value), concat_mode=True)
            sys.exit()

        keys = list(node.value)
        keys.sort()
        for key in keys:
            node_of_key = node.get([key], opts.no_ignore)
            if node_of_key:
                value = node_of_key.value
                state = node_of_key.state
                string = "%s%s=%s" % (state, key, value)
                lines = string.splitlines()
                print(lines[0])
                i_equal = len(state + key) + 1
                for line in lines[1:]:
                    print(" " * i_equal + line)
        sys.exit()

    if node is None:
        if opts.default is None:
            sys.exit(1)
        value = opts.default
    elif opts.env_var_process_mode:
        value = env_var_process(node.value)
    else:
        value = node.value
    if opts.print_conf_mode:
        conf_dump(ConfigNode().set(args, value), concat_mode=True)
    else:
        print(value)
    sys.exit()
예제 #25
0
def main():
    """Implement the "rose host-select" command."""
    opt_parser = RoseOptionParser(
        usage='rose host-select [OPTIONS] [GROUP/HOST ...]',
        description='''
Select a host from a set of groups or names by load, by free memory
or by random.

Print the selected host name.
        ''',
        epilog='''
RANKING METHODS IN DETAIL (--rank-method):
    `load`
        Rank by average load as reported by `uptime` divided by
        number of virtual processors.

        If `METHOD-ARG` is specified, it must be `1`, `5` or `15`.
        The default is to use the 15 minute load.
    `fs`
        Rank by % usage of a file system as reported by `df`.

        `METHOD-ARG` must be a valid file system in all the given
        hosts and host groups. The default is to use the `~`
        directory.
    `mem`
        Rank by largest amount of free memory. Uses `free -m` to
        return memory in Mb
    `random`
        No ranking is used.

CONFIGURATION
    The command reads its settings from the `[rose-host-select]` section in
    the Rose configuration. All settings are optional. Type
    `rose config rose-host-select` to print settings.

    Valid settings are:

    default = GROUP/HOST ...
       The default arguments to use for this command.
    group{NAME} = GROUP/HOST ...
       Declare a named group of hosts.
    method{NAME} = METHOD[:METHOD-ARG]
       Declare the default ranking method for a group of hosts.
    thresholds{NAME} = [METHOD[:METHOD-ARG]:]VALUE ...
       Declare the default threshold(s) for a group of hosts.
    timeout = FLOAT
       Set the timeout in seconds of SSH commands to hosts.
       (default=10.0)
        '''
    )
    opt_parser.add_my_options("choice", "rank_method", "thresholds", "timeout")
    opt_parser.modify_option(
        'timeout',
        help='Set the timeout in seconds of SSH commands to hosts.',
    )
    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()
        sys.exit(1)
    opts.choice = int(opts.choice)
    report(choice(host_score_list[0 : opts.choice])[0] + "\n", level=0)
예제 #26
0
def create(argv):
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("checkout_mode", "info_file", "meta_suite_mode",
                              "non_interactive", "prefix", "project")
    opts, args = opt_parser.parse_args(argv)
    verbosity = opts.verbosity - opts.quietness
    client = RosieVCClient(event_handler=Reporter(verbosity))
    SuiteId.svn.event_handler = client.event_handler
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    interactive_mode = not opts.non_interactive
    if opts.info_file is None:
        info_config = client.generate_info_config(from_id, opts.prefix,
                                                  opts.project)
        if from_id is not None:
            meta_config = load_meta_config(
                info_config,
                directory=None,
                config_type=metomi.rose.INFO_CONFIG_NAME,
                error_handler=None,
                ignore_meta_error=False)
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.replace("=", "")
                if key == "copy-mode" and value == "clear":
                    info_config.set([sect], "")
                if key == "copy-mode" and value == "never":
                    info_config.unset([sect])

        info_config = _edit_info_config(opts, client, info_config)
    else:
        file_ = opts.info_file
        if opts.info_file == "-":
            file_ = sys.stdin
        info_config = metomi.rose.config.load(file_)
    info_config = _validate_info_config(opts, client, info_config)
    if interactive_mode:
        prefix = opts.prefix
        if from_id:
            if not prefix:
                prefix = from_id.prefix
            question = PROMPT_COPY % (from_id.to_string_with_version(), prefix)
        else:
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = PROMPT_CREATE % prefix
        try:
            response = input(question)
        except EOFError:
            sys.exit(1)
        if response != YES:
            sys.exit(1)
    try:
        id_ = client.create(info_config, from_id, opts.prefix,
                            opts.meta_suite_mode)
    except (RosePopenError, SuiteIdOverflowError) as exc:
        client.event_handler(exc)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id_)
        except (FileExistError, RosePopenError) as exc:
            client.event_handler(exc)
            sys.exit(1)
예제 #27
0
파일: vc.py 프로젝트: wxtim/rose
def create():
    """CLI function: create and copy."""
    opt_parser = RoseOptionParser(
        usage=('rosie create [OPTIONS]'
               '\n       rosie copy [OPTIONS] ID-OF-EXISTING-SUITE'),
        description='''
rosie create: Create a new suite
rosie copy  : Create a new suite and copy content from an existing one.

Assign a new `ID` and create the directory structure in the central
repository for a new suite.

The location of the repository for the new suite is determined in order
of preference:

1. `--prefix=PREFIX` option
2. prefix of the `ID-OF-EXISTING-SUITE`
3. `[rosie-id]prefix-default` option in the site/user configuration.

If `ID-OF-EXISTING-SUITE` is specified, copy items from the existing suite
`ID-OF-EXISTING-SUITE` when the suite is created. It is worth noting that
revision history of the copied items can only be preserved if
`ID-OF-EXISTING-SUITE` is in the same repository of the new suite

The syntax of the ID-OF-EXISTING-SUITE is PREFIX-xxNNN[/BRANCH][@REV]
(e.g. my-su173, my-su173/trunk, my-su173/trunk@HEAD). If REV is not specified,
the last changed revision of the branch is used. If BRANCH is not specified,
"trunk" is used.

NOTE: ID-OF-EXISTING-SUITE is _not_ a filepath.
        ''',
    )
    opt_parser.add_my_options(
        "checkout_mode",
        "info_file",
        "meta_suite_mode",
        "non_interactive",
        "prefix",
        "project",
    )
    opts, args = opt_parser.parse_args()
    verbosity = opts.verbosity - opts.quietness
    client = RosieVCClient(event_handler=Reporter(verbosity))
    SuiteId.svn.event_handler = client.event_handler
    from_id = None
    if args:
        from_id = SuiteId(id_text=args[0])
        if from_id.branch is None:
            from_id.branch = from_id.BRANCH_TRUNK
        if from_id.revision is None:
            from_id.revision = from_id.REV_HEAD
            from_id = SuiteId(id_text=from_id.to_string_with_version())
    interactive_mode = not opts.non_interactive
    if opts.info_file is None:
        info_config = client.generate_info_config(from_id, opts.prefix,
                                                  opts.project)
        if from_id is not None:
            meta_config = load_meta_config(
                info_config,
                directory=None,
                config_type=metomi.rose.INFO_CONFIG_NAME,
                error_handler=None,
                ignore_meta_error=False,
            )
            for node_keys, node in meta_config.walk(no_ignore=True):
                if isinstance(node.value, dict):
                    continue
                sect, key = node_keys
                value = node.value
                sect = sect.replace("=", "")
                if key == "copy-mode" and value == "clear":
                    info_config.set([sect], "")
                if key == "copy-mode" and value == "never":
                    info_config.unset([sect])

        info_config = _edit_info_config(opts, client, info_config)
    else:
        file_ = opts.info_file
        if opts.info_file == "-":
            file_ = sys.stdin
        info_config = metomi.rose.config.load(file_)
    info_config = _validate_info_config(opts, client, info_config)
    if interactive_mode:
        prefix = opts.prefix
        if from_id:
            if not prefix:
                prefix = from_id.prefix
            question = PROMPT_COPY % (from_id.to_string_with_version(), prefix)
        else:
            if not prefix:
                prefix = SuiteId.get_prefix_default()
            question = PROMPT_CREATE % prefix
        try:
            response = input(question)
        except EOFError:
            sys.exit(1)
        if response != YES:
            sys.exit(1)
    try:
        id_ = client.create(info_config, from_id, opts.prefix,
                            opts.meta_suite_mode)
    except (RosePopenError, SuiteIdOverflowError) as exc:
        client.event_handler(exc)
        sys.exit(1)
    if opts.checkout_mode:
        try:
            client.checkout(id_)
        except (FileExistError, RosePopenError) as exc:
            client.event_handler(exc)
            sys.exit(1)
예제 #28
0
def main():
    """CLI for "rose namelist-dump"."""
    opt_parser = RoseOptionParser()
    opt_parser.add_my_options("case_mode", "lower", "output_file", "upper")
    opts, args = opt_parser.parse_args()
    return namelist_dump(args, opts.output_file, opts.case_mode)
예제 #29
0
파일: config_cli.py 프로젝트: wxtim/rose
def main():
    """Implement the "rose config" command."""
    opt_parser = RoseOptionParser(description='''
Parse and print rose configuration files.

With no option and no argument, print the rose site + user configuration.

EXAMPLES
    # Print the value of OPTION in SECTION.
    rose config SECTION OPTION

    # Print the value of OPTION in SECTION in FILE.
    rose config --file=FILE SECTION OPTION

    # Print the value of OPTION in SECTION if exists, or VALUE otherwise.
    rose config --default=VALUE SECTION OPTION

    # Print the OPTION=VALUE pairs in SECTION.
    rose config SECTION

    # Print the value of a top level OPTION.
    rose config OPTION

    # Print the OPTION keys in SECTION.
    rose config --keys SECTION

    # Print the SECTION keys.
    rose config --keys

    # Exit with 0 if OPTION exists in SECTION, or 1 otherwise.
    rose config -q SECTION OPTION

    # Exit with 0 if SECTION exists, or 1 otherwise.
    rose config -q SECTION

    # Combine the configurations in FILE1 and FILE2, and dump the result.
    rose config --file=FILE1 --file=FILE2

    # Print the value of OPTION in SECTION of the metadata associated with
    # the specified config FILE
    rose config --file=FILE --meta SECTION OPTION

    # Print the value of a specified metadata KEY
    rose config --meta-key=KEY
        ''',
                                  epilog='''
ENVIRONMENT VARIABLES
    optional ROSE_META_PATH
        Prepend `$ROSE_META_PATH` to the metadata search path.
        ''')
    opt_parser.add_my_options(
        "default",
        "env_var_process_mode",
        "files",
        "keys",
        "meta",
        "meta_key",
        "no_ignore",
        "no_opts",
        "print_conf_mode",
    )
    # the quietness argument is non-standard for this command
    opt_parser.modify_option(
        'quietness',
        help=("Exit with 0 if the specified `SECTION` and/or `OPTION` exist in"
              " the configuration, or 1 otherwise."),
    )

    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    metomi.rose.macro.add_meta_paths()

    if opts.meta_key:
        opts.meta = True

    if opts.files and opts.meta_key:
        report(Exception("Cannot specify both a file and meta key."))
        sys.exit(1)

    config_loader = ConfigLoader()
    sources = []
    if opts.files:
        root_node = ConfigNode()
        for fname in opts.files:
            if fname == "-":
                sources.append(sys.stdin)
            else:
                if opts.meta:
                    try:
                        root_node = config_loader.load(fname)
                    except ConfigSyntaxError as exc:
                        report(exc)
                        sys.exit(1)
                    rel_path = os.sep.join(fname.split(os.sep)[:-1])
                    fpath = get_meta_path(root_node, rel_path)
                    if fpath is None:
                        report(MetadataNotFoundEvent(fname))
                    else:
                        sources.append(fpath)
                else:
                    sources.append(fname)
    elif opts.meta:
        root_node = ConfigNode()
        if opts.meta_key:
            root_node.set(["meta"], opts.meta_key)
        else:
            fname = os.path.join(os.getcwd(), metomi.rose.SUB_CONFIG_NAME)
            try:
                root_node = config_loader.load(fname)
            except ConfigSyntaxError as exc:
                report(exc)
                sys.exit(1)
        fpath = get_meta_path(root_node, meta_key=opts.meta_key)
        root_node.unset(["meta"])
        if fpath is None:
            report(Exception("Metadata not found"))
            sys.exit(1)
        else:
            sources.append(fpath)
    else:
        root_node = ResourceLocator.default().get_conf()

    for source in sources:
        try:
            if opts.meta or opts.no_opts:
                config_loader.load(source, root_node)
            else:
                config_loader.load_with_opts(source, root_node)
        except (ConfigSyntaxError, IOError) as exc:
            report(exc)
            sys.exit(1)
        if source is sys.stdin:
            source.close()

    if opts.quietness:
        sys.exit(root_node.get(args, opts.no_ignore) is None)

    if opts.keys_mode:
        try:
            keys = list(root_node.get(args, opts.no_ignore).value)
        except AttributeError:
            sys.exit(1)
        keys.sort()
        for key in keys:
            print(key)
        sys.exit()

    conf_dump = ConfigDumper()
    if len(args) == 0:
        conf_dump(root_node, concat_mode=opts.print_conf_mode)
        sys.exit()

    node = root_node.get(args, opts.no_ignore)

    if node is not None and isinstance(node.value, dict):
        if opts.print_conf_mode:
            conf_dump(ConfigNode().set(args, node.value), concat_mode=True)
            sys.exit()

        keys = list(node.value)
        keys.sort()
        for key in keys:
            node_of_key = node.get([key], opts.no_ignore)
            if node_of_key:
                value = node_of_key.value
                state = node_of_key.state
                string = "%s%s=%s" % (state, key, value)
                lines = string.splitlines()
                print(lines[0])
                i_equal = len(state + key) + 1
                for line in lines[1:]:
                    print(" " * i_equal + line)
        sys.exit()

    if node is None:
        if opts.default is None:
            sys.exit(1)
        value = opts.default
    elif opts.env_var_process_mode:
        value = env_var_process(node.value)
    else:
        value = node.value
    if opts.print_conf_mode:
        conf_dump(ConfigNode().set(args, value), concat_mode=True)
    else:
        print(value)
    sys.exit()
예제 #30
0
파일: task_env.py 프로젝트: wxtim/rose
def main():
    """rose task-env."""
    opt_parser = RoseOptionParser(
        description='''
STANDARD USAGE:
    eval $(rose task-env)

Provide an environment for cycling suite task.

Print `KEY=VALUE` of the following to the STDOUT:

`ROSE_SUITE_DIR`
    The path to the root directory of the running suite.
`ROSE_SUITE_DIR_REL`
    The path to the root directory of the running suite relative to
    `$HOME`.
`ROSE_SUITE_NAME`
    The name of the running suite.
`ROSE_TASK_NAME`
    The name of the suite task.
`ROSE_TASK_CYCLE_TIME`
    The cycle time of the suite task, if there is one.
`ROSE_CYCLING_MODE`
    The cycling mode of the running suite.
`ROSE_TASK_LOG_ROOT`
    The root path for log files of the suite task.
`ROSE_DATA`
    The path to the data directory of the running suite.
`ROSE_DATAC`
    The path to the data directory of this cycle
    time in the running suite.
`ROSE_DATAC????`
    The path to the data directory of the cycle time with an offset
    relative to the current cycle time. `????` is a duration:

    A `__` (double underscore) prefix denotes a cycle time in the
    future (because a minus sign cannot be used in an environment
    variable). Otherwise, it is a cycle time in the past.

    The rest should be either an ISO 8601 duration, such as:

    * `P2W` - 2 weeks
    * `PT12H` - 12 hours
    * `P1DT6H` - 1 day, 6 hours
    * `P4M` - 4 months
    * `PT5M` - 5 minutes

    Or, for the case of integer cycling suites:

    * `P1` - 1 cycle before the current cycle
    * `P5` - 5 cycles before the current cycle

    Deprecated syntax:

    * `nW` denotes `n` weeks.
    * `n` or `nD` denotes `n` days.
    * `Tn` or `TnH` denotes `n` hours.
    * `TnM` denotes `n` minutes.
    * `TnS` denotes `s` seconds.

    E.g. `ROSE_DATACPT6H` is the data directory of 6 hours before the
    current cycle time.

    E.g. `ROSE_DATACP1D` and `ROSE_DATACPT24H` are both the data
    directory of 1 day before the current cycle time.
`ROSE_ETC`
    The path to the etc directory of the running suite.
`ROSE_TASK_PREFIX`
    The prefix in the task name.
`ROSE_TASK_SUFFIX`
    The suffix in the task name.
        ''',
        epilog='''
USAGE IN SUITES
    rose `task-env` can be used to make environment variables available to a
    suite by defining its `flow.cylc` `env-script` option as
    `env-script = eval $(rose task-env)`.
        ''',
    )
    opt_parser.add_my_options("cycle", "cycle_offsets", "path_globs",
                              "prefix_delim", "suffix_delim")
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness - 1)
    suite_engine_proc = SuiteEngineProcessor.get_processor(
        event_handler=report)
    kwargs = dict(vars(opts))
    try:
        task_props = suite_engine_proc.get_task_props(*args, **kwargs)
        for key, value in task_props:
            report(str(EnvExportEvent(key, value)) + "\n", level=0)
        path_globs = opts.path_globs
        if path_globs is None:
            path_globs = []
        prepend_paths_map = get_prepend_paths(report,
                                              task_props.suite_dir,
                                              path_globs,
                                              full_mode=True)
        for key, prepend_paths in prepend_paths_map.items():
            orig_paths = []
            orig_v = os.getenv(key, "")
            if orig_v:
                orig_paths = orig_v.split(os.pathsep)
            path = os.pathsep.join(prepend_paths + orig_paths)
            report(str(EnvExportEvent(key, path)) + "\n", level=0)
    except Exception as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)