diff --git a/docs/known_issues.md b/docs/known_issues.md new file mode 100644 index 0000000..aaaa7fa --- /dev/null +++ b/docs/known_issues.md @@ -0,0 +1,55 @@ +# Known Issues + +This is a collection of known issues and workarounds to address them. + +## Argument list in config + +> Related GitHub issues: [typer-config#117](https://github.com/maxb2/typer-config/issues/117), [typer-config#124](https://github.com/maxb2/typer-config/issues/124). + +Providing values for a list argument in a config file doesn't work out of the box. +You must use a custom callback for list arguments to extract the values from the config. +Thanks to [@jlwhelan28](https://github.com/jlwhelan28) for the inital solution to this problem. +Below is a working example of how to deal with an argument list: + +```{.python title="arg_list.py" test="true"} +from typing import List +import typer +from typer_config import use_yaml_config +from typer_config.callbacks import argument_list_callback + +app = typer.Typer() + + +@app.command() +@use_yaml_config() +def main( + arg1: str, + arg2: List[str] = typer.Argument(default=None, callback=argument_list_callback), + opt1: str = typer.Option(...), + opt2: str = typer.Option("hello"), +): + typer.echo(f"{opt1} {opt2} {arg1}") + typer.echo(f"{arg2}") + + +if __name__ == "__main__": + app() +``` + +```yaml title="config.yml" +# config.yml +opt1: "apple" +opt2: "pear" +arg1: "lemon" +arg2: ["oak", "aspen", "maple"] +``` + +```{.bash title="Terminal"} +$ python arg_list.py --config config.yml +apple pear lemon +['oak', 'aspen', 'maple'] + +$ python arg_list.py strawberry bear wolf snake tiger --config config.yml +apple pear strawberry +['bear', 'wolf', 'snake', 'tiger'] +``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 09dd941..5732749 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,6 +33,7 @@ nav: - 'examples/schema.md' - 'examples/explicit_config.md' - 'examples/save_config.md' + - Known Issues: known_issues.md - API Reference: api.md - Changelog: changelog.md diff --git a/tests/doc_examples.py b/tests/doc_examples.py index b2fd10d..3ce507e 100644 --- a/tests/doc_examples.py +++ b/tests/doc_examples.py @@ -304,7 +304,12 @@ def exec_bash_fence(fence: Fence, **kwargs): for command in commands: result = run(command["input"], shell=True, check=True, capture_output=True) - assert result.stdout.decode().strip() == command["output"].strip() + assert ( + result.stdout.decode() + .strip() + .replace("\r", "") # NOTE: fixing windows line ends + == command["output"].strip() + ) register_executor("bash", exec_bash_fence) diff --git a/tests/test_docs.py b/tests/test_docs.py index b1a5934..e5b7b38 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -6,7 +6,11 @@ from .doc_examples import check_typer_md_file -@pytest.mark.parametrize("fpath", Path("docs/examples").glob("*.md"), ids=str) +@pytest.mark.parametrize( + "fpath", + [*list(Path("docs/examples").glob("*.md")), Path("docs/known_issues.md")], + ids=str, +) def test_doc_examples(fpath: Path): """Test doc file. diff --git a/typer_config/callbacks.py b/typer_config/callbacks.py index 9f39866..0e46c52 100644 --- a/typer_config/callbacks.py +++ b/typer_config/callbacks.py @@ -1,8 +1,18 @@ """Typer Configuration Parameter Callbacks.""" +from __future__ import annotations + +from typing import List, Optional + from typer import BadParameter, CallbackParam, Context -from .__typing import ConfigLoader, ConfigParameterCallback, TyperParameterValue +# NOTE: I'm not sure why, but these types must be imported at runtime +# for the tests to pass... +from .__typing import ( # noqa: TCH001 + ConfigLoader, + ConfigParameterCallback, + TyperParameterValue, +) from .loaders import ( dotenv_loader, json_loader, @@ -126,3 +136,25 @@ def _callback( Returns: TyperParameterValue: must return back the given parameter """ + + +def argument_list_callback( + ctx: Context, param: CallbackParam, param_value: Optional[List[str]] +) -> List[str]: + """Argument list callback. + + Note: + This is a shim to fix list arguments in a config. + See [maxb2/typer-config#124](https://github.com/maxb2/typer-config/issues/124). + + Args: + ctx (typer.Context): typer context + param (typer.CallbackParam): typer parameter + param_value (Optional[List[str]]): typer parameter value + + Returns: + List[str]: argument list + """ + ctx.default_map = ctx.default_map or {} + default = ctx.default_map.get(param.name, []) if param.name else [] + return param_value if param_value else default