feat(core): advance options/state handling and workflow execution integration
- extend OptionsManager to support multi-namespace option resolution and toggling - integrate OptionsManager more deeply across Action, ChainedAction, and ActionGroup - propagate shared runtime configuration through execution layers - refine action composition model (sequential + parallel execution semantics) - improve lifecycle consistency across BaseAction, Action, ChainedAction, and ActionGroup - begin aligning execution flow with centralized context and options handling wip: routing and root option parsing behavior still in progress
This commit is contained in:
1011
tests/test_parsers/test_command_argument_parser.py
Normal file
1011
tests/test_parsers/test_command_argument_parser.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,21 @@ def test_enable_execution_options_registers_retry_flags():
|
||||
assert "retry_backoff" in parser._execution_dests
|
||||
|
||||
|
||||
def test_enable_execution_options_invalid_double_registration_raises():
|
||||
parser = CommandArgumentParser()
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
|
||||
with pytest.raises(
|
||||
CommandArgumentError,
|
||||
match="destination 'summary' is already registered as an execution argument",
|
||||
):
|
||||
parser._register_execution_dest("summary")
|
||||
|
||||
|
||||
def test_enable_execution_options_registers_confirm_flags():
|
||||
parser = CommandArgumentParser()
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.CONFIRM}))
|
||||
@@ -48,12 +63,12 @@ def test_register_execution_dest_rejects_duplicates():
|
||||
parser = CommandArgumentParser()
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="Destination 'summary' is already defined"
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
parser.add_argument("--summary", action="store_true")
|
||||
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="Destination 'summary' is already defined"
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
|
||||
@@ -138,6 +153,6 @@ async def test_parse_args_split_with_conflicting_execution_option_raises():
|
||||
parser = CommandArgumentParser()
|
||||
parser.add_argument("--summary", action="store_true", help="A conflicting argument.")
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="Destination 'summary' is already defined"
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
|
||||
96
tests/test_parsers/test_group_builder.py
Normal file
96
tests/test_parsers/test_group_builder.py
Normal file
@@ -0,0 +1,96 @@
|
||||
import pytest
|
||||
|
||||
from falyx.exceptions import CommandArgumentError
|
||||
from falyx.parser import CommandArgumentParser
|
||||
from falyx.parser.command_argument_parser import _GroupBuilder
|
||||
|
||||
|
||||
def test_group_builder():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
group_builder = _GroupBuilder(parser, group_name="test_group")
|
||||
assert group_builder.group_name == "test_group"
|
||||
assert "group='test_group'" in str(group_builder)
|
||||
|
||||
group_builder = _GroupBuilder(
|
||||
parser,
|
||||
mutex_name="test_group",
|
||||
)
|
||||
assert group_builder.mutex_name == "test_group"
|
||||
assert "mutex_group='test_group'" in str(group_builder)
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
_GroupBuilder(parser, group_name="test_group", mutex_name="test_group")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
_GroupBuilder(parser)
|
||||
|
||||
with pytest.raises(AssertionError):
|
||||
builder = _GroupBuilder(parser, group_name="test_group")
|
||||
builder.group_name = None
|
||||
builder.mutex_name = None
|
||||
str(builder)
|
||||
|
||||
|
||||
def test_adding_arguments_to_group():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
|
||||
group = parser.add_argument_group("test_group")
|
||||
assert group.group_name == "test_group"
|
||||
|
||||
group.add_argument("--foo", type=str, help="Foo argument")
|
||||
group.add_argument("--bar", type=int, help="Bar argument")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
parser.add_argument_group("test_group")
|
||||
|
||||
|
||||
def test_adding_arguments_to_mutex_group():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
|
||||
mutex_group = parser.add_mutually_exclusive_group("test_mutex_group")
|
||||
assert mutex_group.mutex_name == "test_mutex_group"
|
||||
|
||||
mutex_group.add_argument("--foo", type=str, help="Foo argument")
|
||||
mutex_group.add_argument("--bar", type=int, help="Bar argument")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
parser.add_mutually_exclusive_group("test_mutex_group")
|
||||
|
||||
|
||||
def test_adding_arguments_to_group_with_invalid_group():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
parser.add_argument(
|
||||
"--foo", type=str, help="Foo argument", group="non_existent_group"
|
||||
)
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
parser.add_argument(
|
||||
"--bar", type=int, help="Bar argument", mutex_group="non_existent_group"
|
||||
)
|
||||
|
||||
|
||||
def test_adding_positional_arguments_to_mutex_group():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
|
||||
group = parser.add_mutually_exclusive_group("test_group")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
group.add_argument(
|
||||
"positional_arg", type=str, help="This should fail because it's positional"
|
||||
)
|
||||
|
||||
|
||||
def test_adding_required_arguments_to_mutex_group():
|
||||
parser = CommandArgumentParser(program="test_program")
|
||||
|
||||
group = parser.add_mutually_exclusive_group("test_group")
|
||||
|
||||
with pytest.raises(CommandArgumentError):
|
||||
group.add_argument(
|
||||
"--foo",
|
||||
type=str,
|
||||
help="This should fail because it's required",
|
||||
required=True,
|
||||
)
|
||||
@@ -69,14 +69,14 @@ async def test_resolve_args_raises_on_conflicting_execution_option():
|
||||
execution_options=["summary"],
|
||||
)
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="Destination 'summary' is already defined"
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
command.arg_parser.add_argument(
|
||||
"--summary", action="store_true", help="A conflicting argument."
|
||||
)
|
||||
|
||||
with pytest.raises(
|
||||
CommandArgumentError, match="Destination 'summary' is already defined"
|
||||
CommandArgumentError, match="destination 'summary' is already defined"
|
||||
):
|
||||
command.arg_parser.enable_execution_options(frozenset({ExecutionOption.SUMMARY}))
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import pytest
|
||||
|
||||
from falyx.exceptions import CommandArgumentError
|
||||
from falyx.parser.command_argument_parser import CommandArgumentParser
|
||||
from falyx.parser.parser_types import TLDRExample
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -45,3 +46,27 @@ async def test_add_tldr_examples_in_init():
|
||||
assert parser._tldr_examples[0].description == "This is the first example."
|
||||
assert parser._tldr_examples[1].usage == "example2"
|
||||
assert parser._tldr_examples[1].description == "This is the second example."
|
||||
|
||||
|
||||
def test_add_tldr_example():
|
||||
parser = CommandArgumentParser()
|
||||
parser.add_tldr_example("example1", "This is the first example.")
|
||||
assert len(parser._tldr_examples) == 1
|
||||
assert parser._tldr_examples[0].usage == "example1"
|
||||
assert parser._tldr_examples[0].description == "This is the first example."
|
||||
|
||||
|
||||
def test_add_tldr_example_bad_args():
|
||||
parser = CommandArgumentParser()
|
||||
with pytest.raises(TypeError):
|
||||
parser.add_tldr_example("example1", "This is the first example.", "extra_arg")
|
||||
|
||||
|
||||
def test_add_tldr_examples_with_tldr_example_objects():
|
||||
parser = CommandArgumentParser()
|
||||
example1 = TLDRExample(usage="example1", description="This is the first example.")
|
||||
example2 = TLDRExample(usage="example2", description="This is the second example.")
|
||||
parser.add_tldr_examples([example1, example2])
|
||||
assert len(parser._tldr_examples) == 2
|
||||
assert parser._tldr_examples[0] == example1
|
||||
assert parser._tldr_examples[1] == example2
|
||||
|
||||
Reference in New Issue
Block a user