Skip to content

Commit

Permalink
Add hook to update and read argv before parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
pvandyken committed Apr 29, 2024
1 parent f9c43db commit 1298061
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 13 deletions.
5 changes: 5 additions & 0 deletions snakebids/bidsapp/hookspecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 7 additions & 1 deletion snakebids/bidsapp/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 39 additions & 12 deletions snakebids/tests/test_bidsapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"]
Expand All @@ -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"]
Expand All @@ -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"]
Expand All @@ -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:
Expand Down

0 comments on commit 1298061

Please sign in to comment.