fluksio run takes inputs after -- as name=value
So an input named like a flag of run, timeout or sync, can still be set. Flags before -- keep naming inputs as they did.
This commit is contained in:
@@ -807,9 +807,12 @@ def main(argv: list[str] | None = None) -> int:
|
||||
parser = _parser()
|
||||
if argv and argv[0] == "run":
|
||||
# A flow's inputs are its own, so `--lr 0.05` cannot be declared here:
|
||||
# whatever this parser does not know is typed against the flow.
|
||||
args, rest = parser.parse_known_args(argv)
|
||||
return int(args.func(args, rest))
|
||||
# whatever this parser does not know is typed against the flow. What
|
||||
# follows `--` is the flow's whatever its name, so an input called
|
||||
# `timeout` is set there rather than taken as `run --timeout`.
|
||||
cut = argv.index("--") if "--" in argv else len(argv)
|
||||
args, rest = parser.parse_known_args(argv[:cut])
|
||||
return int(args.func(args, rest + argv[cut:]))
|
||||
args = parser.parse_args(argv)
|
||||
result: int = args.func(args)
|
||||
return result
|
||||
|
||||
@@ -453,15 +453,20 @@ def _ask_params(definition: dict[str, Any]) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _params(definition: dict[str, Any], rest: list[str]) -> dict[str, Any]:
|
||||
"""Turn `--lr 0.05` into a typed parameter, using the flow's own inputs."""
|
||||
"""Turn `--lr 0.05` into a typed parameter, using the flow's own inputs.
|
||||
|
||||
After `--` every token is `name=value`, which is how an input that shares
|
||||
its name with a flag of `run` is set.
|
||||
"""
|
||||
types = _input_types(definition)
|
||||
cut = rest.index("--") if "--" in rest else len(rest)
|
||||
# Collected as written and typed afterwards, so a name this flow does not
|
||||
# have is refused by name rather than by whatever its value failed to parse
|
||||
# as: `--param lr=0.002` is a sweep's spelling, and said so it reads as an
|
||||
# input called `param` holding unparseable json.
|
||||
raw: dict[str, str | bool] = {}
|
||||
pending: str | None = None
|
||||
for token in rest:
|
||||
for token in rest[:cut]:
|
||||
if token.startswith("--"):
|
||||
if pending is not None:
|
||||
# A flag with no value is a flag: `--resume` means true.
|
||||
@@ -480,6 +485,11 @@ def _params(definition: dict[str, Any], rest: list[str]) -> dict[str, Any]:
|
||||
pending = None
|
||||
if pending is not None:
|
||||
raw[pending] = True
|
||||
for token in rest[cut + 1 :]:
|
||||
name, sep, value = token.partition("=")
|
||||
if not sep or not name:
|
||||
raise SyncError(f"after `--` an input is name=value, not '{token}'")
|
||||
raw[name.replace("-", "_")] = value
|
||||
unknown = sorted(set(raw) - set(types))
|
||||
if unknown:
|
||||
hint = ""
|
||||
|
||||
@@ -90,6 +90,31 @@ def test_run_arguments_are_typed_by_the_flow_they_are_for() -> None:
|
||||
_params(definition, ["--nonesuch", "1"])
|
||||
|
||||
|
||||
def test_inputs_after_a_double_dash_may_share_a_name_with_a_run_flag(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""`run --timeout` is the wait; `-- timeout=5` is the flow's input."""
|
||||
from fluksio import cli
|
||||
from fluksio.sdk import cli as sdk_cli
|
||||
|
||||
seen = []
|
||||
monkeypatch.setattr(
|
||||
sdk_cli, "cmd_run", lambda args, rest: seen.append((args.timeout, rest)) or 0
|
||||
)
|
||||
cli.main(["run", "train", "--timeout", "3", "--lr", "0.1", "--", "timeout=5"])
|
||||
assert seen == [(3.0, ["--lr", "0.1", "--", "timeout=5"])]
|
||||
|
||||
definition = {
|
||||
"inputs": [
|
||||
{"spec": {"name": "lr", "dtype": "float"}},
|
||||
{"spec": {"name": "timeout", "dtype": "int"}},
|
||||
]
|
||||
}
|
||||
assert sdk_cli._params(definition, seen[0][1]) == {"lr": 0.1, "timeout": 5}
|
||||
with pytest.raises(sdk_cli.SyncError, match="name=value"):
|
||||
sdk_cli._params(definition, ["--", "timeout"])
|
||||
|
||||
|
||||
def test_a_sweeps_param_spelling_is_refused_by_name() -> None:
|
||||
"""`run --param lr=0.002` is a name this flow has not got, and says so."""
|
||||
import pytest
|
||||
|
||||
@@ -190,6 +190,13 @@ Syncs local code, then submits a run. Flags such as `--lr` name the flow's
|
||||
declared inputs and are converted to their declared types. Unknown inputs are
|
||||
rejected. Use `--param name=a,b` with `sweep` for multiple values.
|
||||
|
||||
Everything after `--` is an input written as `name=value`. Use it for an input
|
||||
that shares its name with a flag of `run`, such as `timeout`:
|
||||
|
||||
```sh
|
||||
fluksio run train --wait --timeout 600 -- timeout=30 lr=0.05
|
||||
```
|
||||
|
||||
After the first sync, `run` imports the module that declared the flow. If no
|
||||
declaration is recorded, it searches the working directory and skips paths
|
||||
covered by `.gitignore`. Import errors in that fallback search produce
|
||||
|
||||
Reference in New Issue
Block a user