Skip to content

Commit

Permalink
trace origin of commands
Browse files Browse the repository at this point in the history
  • Loading branch information
wxtim committed Oct 24, 2022
1 parent 01071f7 commit 26363e4
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 64 deletions.
76 changes: 64 additions & 12 deletions cylc/flow/option_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
ACTION = 'action'
STORE = 'store'
STORE_CONST = 'store_const'
SOURCES = 'sources'
DEFAULT = 'default'
DEST = 'dest'
METAVAR = 'metavar'
Expand Down Expand Up @@ -688,7 +689,7 @@ def appendif(list_, item):


def combine_options_pair(first_list, second_list):
"""Combine two option lists.
"""Combine two option lists recording where each came from.
Scenarios:
- Arguments are identical - return this argument.
Expand All @@ -700,18 +701,37 @@ def combine_options_pair(first_list, second_list):
`command-B has an option `-f` or `--fortran`` then
`command-A+B` will have options `--fortran` and `--file` but _not_
`-f`, which would be confusing.
- Arguments only apply to a single compnent of the compound CLI script.
"""
label1, first_list = first_list
label2, second_list = second_list

output = []

for first, second in product(first_list, second_list):
if first == second and first not in output:
if not first.get(SOURCES, ''):
first[SOURCES] = {*label1}
if not second.get(SOURCES, ''):
second[SOURCES] = {*label2}

# Two options are identical in both args and kwargs:
if (
first[KWARGS] == second[KWARGS]
and first[ARGS] == second[ARGS]
):
first[SOURCES] = {*label1, *label2}
output = appendif(output, first)

# If any of the argument name identical:
# If any of the argument names identical we must remove
# overlapping names (if we can)
# e.g. [-a, --aleph], [-a, --alpha-centuri] -> keep both options
# but neither should have the `-a` short version:
elif (
first != second
(
first[KWARGS] != second[KWARGS]
or first[ARGS] != second[ARGS]
)
and any(i[0] == i[1] for i in product(second[ARGS], first[ARGS]))
):
# if any of the args are different:
Expand All @@ -725,11 +745,42 @@ def combine_options_pair(first_list, second_list):
# if none of the arg names are different.
raise Exception(f'Clashing Options \n{first}\n{second}')
else:
# Neither option appears in the other list, so it can be appended:
if all(first[ARGS] != i[ARGS] for i in second_list):
output = appendif(output, first)
if all(second[ARGS] != i[ARGS] for i in first_list):
output = appendif(output, second)
return output
label = [*label1, *label2]
if not output:
for item in first_list:
item[SOURCES] = {*label1}
output = first_list
return (label, output)


def add_sources_to_helps(options: list[Dict]) -> list[Dict]:
"""Prettify format of list of CLI commands this option applies to
and prepend that list to the start of help.
examples:
>>> options = [
... {
... 'args': ['stuff'],
... 'kwargs': {'help': "Don't Panic!"},
... 'sources': {'foo', 'bar'}
... },
... {}
... ]
>>> assert add_sources_to_helps(options)[0]['kwargs']['help'] == \
"\x1b[36m[foo, bar]\x1b[0m Don't Panic!"
"""
for option in options:
if 'sources' in option:
option[KWARGS][HELP] = cparse(
f'<cyan>[{", ".join(option[SOURCES])}]</cyan>'
f' {option[KWARGS][HELP]}')
return options


def combine_options(*args):
Expand All @@ -741,11 +792,9 @@ def combine_options(*args):
list_ = list(args)
output = list_[0]
for arg in list_[1:]:
if arg and output:
output = combine_options_pair(arg, output)
elif arg:
output = arg
return output
output = combine_options_pair(arg, output)

return add_sources_to_helps(output[1])


def cleanup_sysargv(
Expand All @@ -769,7 +818,6 @@ def cleanup_sysargv(
x[KWARGS].get('dest', x[ARGS][0].strip(DOUBLEDASH)): x
for x in compound_script_opts
}

# Filter out non-cylc-play options.
for unwanted_opt in (set(options.__dict__)) - set(script_opts_by_dest):
for arg in compound_opts_by_dest[unwanted_opt][ARGS]:
Expand All @@ -780,7 +828,7 @@ def cleanup_sysargv(
compound_opts_by_dest[unwanted_opt][KWARGS][ACTION]
not in ['store_true', 'store_false']
):
sys.argv.pop(index + 1)
sys.argv.pop(index)

# replace compound script name:
sys.argv[1] = script_name
Expand All @@ -790,6 +838,10 @@ def cleanup_sysargv(

def log_subcommand(command, workflow_id):
"""Log a command run as part of a sequence.
Example:
>>> log_subcommand('ruin', 'my_workflow')
\x1b[1m\x1b[36m$ cylc ruin my_workflow\x1b[0m\x1b[1m\x1b[0m\n
"""
print(cparse(
f'<b><cyan>$ cylc {command} {workflow_id}</cyan></b>'))
4 changes: 2 additions & 2 deletions cylc/flow/scripts/validate_install_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@

CYLC_ROSE_OPTIONS = COP.get_cylc_rose_options()
VIP_OPTIONS = combine_options(
VALIDATE_OPTIONS, INSTALL_OPTIONS,
PLAY_OPTIONS, CYLC_ROSE_OPTIONS
(['validate'], VALIDATE_OPTIONS), (['install'], INSTALL_OPTIONS),
(['play'], PLAY_OPTIONS), (['cylc-rose'], CYLC_ROSE_OPTIONS)
)


Expand Down
Loading

0 comments on commit 26363e4

Please sign in to comment.