Skip to content

Commit

Permalink
new approach to add short arguments by adding them to the parser obje…
Browse files Browse the repository at this point in the history
…ct immediately after parser creation
  • Loading branch information
donaldcampbelljr committed May 15, 2024
1 parent c35dcb0 commit 1cf1f9b
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 104 deletions.
114 changes: 10 additions & 104 deletions looper/cli_pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
from divvy import select_divvy_config

from . import __version__
from .command_models.commands import SUPPORTED_COMMANDS, TopLevelParser
from .command_models.commands import (
SUPPORTED_COMMANDS,
TopLevelParser,
add_short_arguments,
)
from .const import *
from .divvy import DEFAULT_COMPUTE_RESOURCES_NAME, select_divvy_config
from .exceptions import *
Expand All @@ -53,64 +57,6 @@
from typing import List, Tuple


run_arguments_dict = {
"-d": "--dry-run",
"-c": "--compute",
"-l": "--limit",
"-k": "--skip",
"-o": "--output-dir",
"-S": "--sample-pipeline-interfaces",
"-P": "--project-pipeline-interfaces",
"-p": "--piface",
"-i": "--ignore-flags",
"-t": "--time-delay",
"-x": "--command-extra",
"-y": "--command-extra-override",
"-f": "--skip-file-checks",
"-u": "--lump-s",
"-n": "--lump-n",
"-j": "--lump-j",
}

init_arguments_dict = {
"-d": "--dry-run",
"-c": "--compute",
"-l": "--limit",
"-k": "--skip",
"-o": "--output-dir",
"-S": "--sample-pipeline-interfaces",
"-P": "--project-pipeline-interfaces",
"-p": "--piface",
"-i": "--ignore-flags",
"-t": "--time-delay",
"-x": "--command-extra",
"-y": "--command-extra-override",
"-f": "--force",
"-u": "--lump-s",
"-n": "--lump-n",
"-j": "--lump-j",
}

check_arguments_dict = {
"-d": "--dry-run",
"-c": "--compute",
"-l": "--limit",
"-k": "--skip",
"-o": "--output-dir",
"-S": "--sample-pipeline-interfaces",
"-P": "--project-pipeline-interfaces",
"-p": "--piface",
"-i": "--ignore-flags",
"-t": "--time-delay",
"-x": "--command-extra",
"-y": "--command-extra-override",
"-f": "--flags",
"-u": "--lump-s",
"-n": "--lump-n",
"-j": "--lump-j",
}


def opt_attr_pair(name: str) -> Tuple[str, str]:
"""Takes argument as attribute and returns as tuple of top-level or subcommand used."""
return f"--{name}", name.replace("-", "_")
Expand Down Expand Up @@ -368,60 +314,20 @@ def run_looper(args: TopLevelParser, parser: ArgumentParser, test_args=None):
_LOGGER.warning("No looper configuration was supplied.")


def create_command_string(args: list[str], command: str):
"""
This is a workaround for short form arguments not being supported by the pydantic argparse package.
:param args: list[str] taken from test_args or sys.argv
:param command: str high level command
:return modified_command_string: list[str] that has been modified, replacing shortforms with longforms
"""
arguments_dict = {}

# Must determine argument dict based on command since there is overlap in shortform keys for a couple of commands
if command in [
"run",
"runp",
"rerun",
"table",
"report",
"destroy",
"clean",
"inspect",
"link",
]:
arguments_dict = run_arguments_dict
if command in ["init"]:
arguments_dict = init_arguments_dict
if command in ["check"]:
arguments_dict = check_arguments_dict

modified_command_string = []
for arg in args:
# Replace shortform with long form based on the dictionary
replacement = arguments_dict.get(arg)
modified_command_string.append(replacement if replacement else arg)

if command not in modified_command_string:
# required when using sys.argv during normal usage i.e. not test_args
modified_command_string.insert(command)

return modified_command_string


def main(test_args=None) -> None:
parser = pydantic2_argparse.ArgumentParser(
model=TopLevelParser,
prog="looper",
description="Looper Pydantic Argument Parser",
add_help=True,
)

parser = add_short_arguments(parser)

if test_args:
command_string = create_command_string(args=test_args, command=test_args[0])
args = parser.parse_typed_args(args=test_args)
else:
sys_args = sys.argv[1:]
command_string = create_command_string(args=sys_args, command=sys_args[0])

args = parser.parse_typed_args(args=command_string)
args = parser.parse_typed_args()

return run_looper(args, parser, test_args=test_args)

Expand Down
42 changes: 42 additions & 0 deletions looper/command_models/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,48 @@ def create_model(self) -> Type[pydantic.BaseModel]:
InitPifaceParserModel = InitPifaceParser.create_model()


def add_short_arguments(parser):
"""
This function takes a parser object created under pydantic argparse and adds the short arguments AFTER the initial creation.
This is a workaround as pydantic-argparse does not currently support this during initial parser creation.
"""
# Loop through commands, add relevant short arguments

short_arguments_dict = {
"--dry-run": "-d",
"--limit": "-l",
"--compute": "-c",
"--skip": "-k",
"--output-dir": "-o",
"--sample-pipeline-interfaces": "-S",
"--project-pipeline-interfaces": "-P",
"--piface": "-p",
"--ignore-flags": "-i",
"--time-delay": "-t",
"--command-extra": "-x",
"--command-extra-override": "-y",
"--lump-s": "-u",
"--lump-n": "-n",
"--lump-j": "-j",
"--skip-file-checks": "-f",
"--force": "-f",
"--flags": "-f",
}

for cmd in parser._subcommands.choices.keys():
for long_key, short_key in short_arguments_dict.items():
if long_key in parser._subcommands.choices[cmd]._option_string_actions:
argument = parser._subcommands.choices[cmd]._option_string_actions[
long_key
]
argument.option_strings = (short_key, long_key)
parser._subcommands.choices[cmd]._option_string_actions[
short_key
] = argument

return parser


SUPPORTED_COMMANDS = [
RunParser,
RerunParser,
Expand Down
13 changes: 13 additions & 0 deletions tests/smoketests/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ def test_cli_shortform(prep_temp_pep):
except Exception:
raise pytest.fail("DID RAISE {0}".format(Exception))

x = ["run", "--looper-config", tp, "-d", "-l", "2"]
try:
main(test_args=x)
except Exception:
raise pytest.fail("DID RAISE {0}".format(Exception))

tp = prep_temp_pep
x = ["run", "--looper-config", tp, "-d", "-n", "2"]
try:
main(test_args=x)
except Exception:
raise pytest.fail("DID RAISE {0}".format(Exception))


def test_running_csv_pep(prep_temp_pep_csv):
tp = prep_temp_pep_csv
Expand Down

0 comments on commit 1cf1f9b

Please sign in to comment.