From 1298061466357d7f8ef7546df90928a4547728cd Mon Sep 17 00:00:00 2001 From: Peter Van Dyken Date: Mon, 29 Apr 2024 15:46:28 -0400 Subject: [PATCH] Add hook to update and read argv before parsing --- snakebids/bidsapp/hookspecs.py | 5 ++++ snakebids/bidsapp/run.py | 8 +++++- snakebids/tests/test_bidsapp.py | 51 +++++++++++++++++++++++++-------- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/snakebids/bidsapp/hookspecs.py b/snakebids/bidsapp/hookspecs.py index b1b289ed..6b83242a 100644 --- a/snakebids/bidsapp/hookspecs.py +++ b/snakebids/bidsapp/hookspecs.py @@ -46,6 +46,11 @@ def add_cli_arguments( """ +@hookspec(firstresult=True) +def get_argv(argv: list[str], config: dict[str, Any]) -> list[str]: # type: ignore + """Set or modify the CLI parameters that will be parsed by the parser.""" + + @hookspec def handle_unknown_args(args: list[str], config: dict[str, Any]): """If ``parse_known_args`` enabled, handle unknown arguments. diff --git a/snakebids/bidsapp/run.py b/snakebids/bidsapp/run.py index 894da89f..44841ad6 100644 --- a/snakebids/bidsapp/run.py +++ b/snakebids/bidsapp/run.py @@ -182,7 +182,13 @@ def parse_args(self, args: list[str] | None = None): """Run all plugins and parse arguments.""" if not self._processed: self.build_parser() - namespace, unknown = self.parser.parse_known_args(args=args) + args = sys.argv[1:] if args is None else args + argv: list[str] | None = self.pm.hook.get_argv( + argv=args, config=self.config + ) + namespace, unknown = self.parser.parse_known_args( + args=args if argv is None else argv + ) self.pm.hook.handle_unknown_args(args=unknown, config=self.config) self.pm.hook.update_cli_namespace( namespace=namespace.__dict__, config=self.config diff --git a/snakebids/tests/test_bidsapp.py b/snakebids/tests/test_bidsapp.py index 6e2d0e1c..321ead2c 100644 --- a/snakebids/tests/test_bidsapp.py +++ b/snakebids/tests/test_bidsapp.py @@ -5,6 +5,7 @@ from typing import Any import pytest +from pytest_mock import MockerFixture from snakebids import bidsapp, plugins from snakebids.bidsapp.args import ArgumentGroups @@ -36,19 +37,28 @@ def add_cli_arguments( parser.add_argument("arg_one") parser.add_argument("--arg-two") + @bidsapp.hookimpl + def get_argv(self, argv: list[str], config: dict[str, Any]): + self.hooks_run += 1 + assert config["added_args"] + config["provided_args"] = argv + assert argv == ["default"] + return ["known", "--arg-two", "known", "unknown"] + @bidsapp.hookimpl def handle_unknown_args(self, args: list[str], config: dict[str, Any]): self.hooks_run += 1 assert args == ["unknown"] - assert len(config) == 2 + assert len(config) == 3 assert config["initialized"] assert config["added_args"] + assert config["provided_args"] == ["default"] config["unknown_args"] = args @bidsapp.hookimpl def update_cli_namespace(self, namespace: dict[str, Any], config: dict[str, Any]): self.hooks_run += 1 - assert len(config) == 3 + assert len(config) == 4 assert config["initialized"] assert config["added_args"] assert config["unknown_args"] == ["unknown"] @@ -60,7 +70,7 @@ def update_cli_namespace(self, namespace: dict[str, Any], config: dict[str, Any] @bidsapp.hookimpl def finalize_config(self, config: dict[str, Any]): self.hooks_run += 1 - assert len(config) == 5 + assert len(config) == 6 assert config["initialized"] assert config["added_args"] assert config["unknown_args"] == ["unknown"] @@ -71,7 +81,7 @@ def finalize_config(self, config: dict[str, Any]): @bidsapp.hookimpl def run(self, config: dict[str, Any]): self.hooks_run += 1 - assert len(config) == 6 + assert len(config) == 7 assert config["initialized"] assert config["added_args"] assert config["unknown_args"] == ["unknown"] @@ -89,17 +99,34 @@ def test_build_parser(self): def test_parse_args(self): app = bidsapp.app(plugins=[self]) - app.parse_args(args=["known", "--arg-two", "known", "unknown"]) - assert self.hooks_run == 5 - app.parse_args(args=["known", "--arg-two", "known", "unknown"]) - assert self.hooks_run == 5 + app.parse_args(args=["default"]) + assert self.hooks_run == 6 + app.parse_args(args=["default"]) + assert self.hooks_run == 6 def test_run(self): app = bidsapp.app(plugins=[self]) - app.run(args=["known", "--arg-two", "known", "unknown"]) - assert self.hooks_run == 6 - app.run(args=["known", "--arg-two", "known", "unknown"]) - assert self.hooks_run == 6 + app.run(args=["default"]) + assert self.hooks_run == 7 + app.run(args=["default"]) + assert self.hooks_run == 7 + + +class TestNoArgvHook: + @bidsapp.hookimpl + def handle_unknown_args(self, args: list[str]): + assert args == ["mocked", "args"] + + def test_with_mocked_args(self, mocker: MockerFixture): + from snakebids.bidsapp.run import sys + + mocker.patch.object(sys, "argv", ["program", "mocked", "args"]) + app = bidsapp.app(plugins=[self]) + app.parse_args() + + def test_with_provided_args(self): + app = bidsapp.app(plugins=[self]) + app.parse_args(args=["mocked", "args"]) class TestDependencies: