Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions PQAnalysis/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,46 @@



_ROOT_OPTIONS = (
"--help",
"--version",
"--progress",
"--logging-level",
"--log-file",
)



def _match_root_option(option: str) -> str | None:
"""Resolve a possibly abbreviated long root option like argparse does."""
matches = [
root_option for root_option in _ROOT_OPTIONS
if root_option.startswith(option)
]
return matches[0] if len(matches) == 1 else None



def _detect_command(arguments: list[str]) -> str | None:
"""Scan root options to find the first positional CLI command."""
index = 0
while index < len(arguments):
argument = arguments[index]

if argument in {"-h", "--help", "--version"}:
option = argument.partition("=")[0]
matched = (
_match_root_option(option)
if option.startswith("--") else None
)

if argument == "-h" or matched in {"--help", "--version"}:
return None

if argument == "--logging-level":
if matched == "--logging-level" and option == argument:
index += 2
continue

if argument == "--log-file":
if matched == "--log-file" and option == argument:
index += 1
if (
index < len(arguments) and
Expand All @@ -125,10 +151,6 @@ def _detect_command(arguments: list[str]) -> str | None:
index += 1
continue

if argument.startswith(("--logging-level=", "--log-file=")):
index += 1
continue

if argument.startswith("-"):
index += 1
continue
Expand Down
44 changes: 44 additions & 0 deletions tests/cli/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@
(["--logging-level=INFO", "vacf", "input.in"], "vacf"),
(["--log-file", "off", "convert", "rdf.dat"], "convert"),
(["--log-file=run.log", "vibrations", "input.in"], "vibrations"),
(["--logging", "DEBUG", "rdf", "input.in"], "rdf"),
(["--logging-lev", "DEBUG", "msd", "input.in"], "msd"),
(["--logging=DEBUG", "vacf", "input.in"], "vacf"),
(["--log-fi", "off", "convert", "rdf.dat"], "convert"),
(["--log-fi=run.log", "vibrations", "input.in"], "vibrations"),
(["--pro", "check_momentum", "traj.vel"], "check_momentum"),
(["--help"], None),
(["--help", "rdf"], None),
(["--he", "rdf"], None),
(["--version", "msd"], None),
(["--vers", "msd"], None),
([], None),
],
)
Expand All @@ -33,6 +41,42 @@ def test_detect_command(arguments, expected):



def test_main_dispatches_with_abbreviated_root_option(monkeypatch):
main_module = import_module("PQAnalysis.cli.main")
received = {}

class _FakeCLI:

@classmethod
def add_arguments(cls, parser):
parser.add_argument("input_file")

@classmethod
def run(cls, args):
received["input_file"] = args.input_file

monkeypatch.setattr(
main_module, "_load_command", lambda command: _FakeCLI
)
monkeypatch.setattr(
sys,
"argv",
["pqanalysis", "--logging", "DEBUG", "--log-fi", "off", "rdf", "in"],
)
monkeypatch.setattr(argument_parser, "print_header", lambda: None)

root_logger = argument_parser.logging.getLogger()
original_level = root_logger.level

try:
main_module.main()
finally:
root_logger.setLevel(original_level)

assert received == {"input_file": "in"}



@pytest.mark.parametrize(
("command", "module_name", "class_name"),
[
Expand Down
Loading