Skip to content

Commit 08ac9fe

Browse files
committed
feat: allow config in command decorator
1 parent 1c5aac2 commit 08ac9fe

3 files changed

Lines changed: 79 additions & 2 deletions

File tree

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
# Pending
4+
5+
- Allow passing configuration(s) directly to `@app.command()`
6+
37
# v0.2.1 - 11-05-2023
48

59
- Fix un-allowed kwargs: accepted signatures are `fn(paramA, paramB=..., ... **kwargs)`

confit/cli.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import inspect
22
import sys
3+
import tempfile
34
from pathlib import Path
45
from typing import Any, Callable, Dict, List, Optional, Type, Union
56

@@ -76,6 +77,7 @@ def command( # noqa
7677
# Rich settings
7778
rich_help_panel: Union[str, None] = Default(None),
7879
registry: Any = None,
80+
config: Optional[Union[Config, List[Config]]] = None,
7981
) -> Callable[[CommandFunctionType], CommandFunctionType]:
8082
typer_command = super().command(
8183
name=name,
@@ -96,14 +98,35 @@ def command( # noqa
9698
},
9799
)
98100

101+
initial_config = config
102+
99103
def wrapper(fn):
100104
validated = validate_arguments(fn)
101105

102106
@typer_command
103107
def command(ctx: Context, config: Optional[List[Path]] = None):
104-
config_path = config
108+
config_path = config or []
105109

106110
has_meta = _fn_has_meta(fn)
111+
112+
if initial_config is not None:
113+
initial_configs = (
114+
[initial_config]
115+
if isinstance(initial_config, Config)
116+
else initial_config
117+
)
118+
119+
initial_config_path = []
120+
121+
for c in initial_configs:
122+
temp_file = tempfile.NamedTemporaryFile(delete=False)
123+
temp_file.write(
124+
c.to_str().encode()
125+
) # Write the string to the file
126+
temp_file.close()
127+
initial_config_path.append(Path(temp_file.name))
128+
config_path = initial_config_path + config_path
129+
107130
if config_path:
108131
config, name_from_file = merge_from_disk(config_path)
109132
else:

tests/test_cli.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typer.testing import CliRunner
44

5-
from confit import Cli, Registry
5+
from confit import Cli, Config, Registry
66
from confit.registry import RegistryCollection, set_default_registry
77

88
runner = CliRunner()
@@ -94,6 +94,56 @@ def test_cli_merge(change_test_dir):
9494
assert "Other: 99" in result.stdout
9595

9696

97+
app_with_initial_config = Cli(pretty_exceptions_show_locals=False)
98+
initial_config = [
99+
Config(
100+
{
101+
"modelA": {
102+
"submodel": {
103+
"value": 1,
104+
}
105+
},
106+
"script": {
107+
"other": 4,
108+
},
109+
}
110+
),
111+
Config(
112+
{
113+
"script": {
114+
"other": 5,
115+
},
116+
}
117+
),
118+
]
119+
120+
121+
@app_with_initial_config.command(name="script", config=initial_config)
122+
def app_with_initial_config_function(
123+
modelA: BigModel,
124+
modelB: BigModel,
125+
other: int,
126+
seed: int,
127+
):
128+
assert modelA.submodel is modelB.submodel
129+
assert modelA.submodel.value == 12 # --config has precedent over initial_config
130+
assert other == 5 # initial_config[-1] has precedent over initial_config[0]
131+
132+
133+
def test_cli_working_with_initial_config(change_test_dir):
134+
result = runner.invoke(
135+
app_with_initial_config,
136+
[
137+
"--config",
138+
"config.cfg",
139+
"--seed",
140+
"42",
141+
],
142+
)
143+
print(result.exit_code)
144+
assert result.exit_code == 0, result.stdout
145+
146+
97147
app_with_meta = Cli(pretty_exceptions_show_locals=False)
98148

99149

0 commit comments

Comments
 (0)