How create an option with an optional argument (e.g. a flag with an optional value) #608
Replies: 7 comments 2 replies
-
|
some hints? how to do this? @app.command()
def test_flag(flag: Optional[str] = typer.Option(None, is_flag=False, flag_value='default')):
if flag is not None:
print(f"{flag=}")
else:
print("flag unset")calling what is the purpose of parameter |
Beta Was this translation helpful? Give feedback.
-
|
Any appropriate answers to this question? This kind of behavior is common in CLI programs, which is the reason why Click supports it. This kind of thing makes Typer inadequate for everything but the simplest CLI programs. Really sad given that the general concept of it is very good. |
Beta Was this translation helpful? Give feedback.
-
|
Also wondering how to do this. I've been trying different ways and none of them worked. |
Beta Was this translation helpful? Give feedback.
-
|
I am interested in this too. |
Beta Was this translation helpful? Give feedback.
-
|
Kinda a shame, I tried |
Beta Was this translation helpful? Give feedback.
-
|
Hey, Summary
Thanks @svlandeg for correction of newer events Example code:import typer
from typing import Optional
app = typer.Typer()
@app.command()
def test(
opt_1: bool = typer.Option(False, "--opt-1", help="Enable the option (defaults to 3.14)"),
opt_1_val: Optional[float] = typer.Option(None, "--opt-1-val", help="Explicitly override the 3.14 value")
):
# A more manual approach...
if opt_1_val is not None:
final_val = opt_1_val
elif opt_1:
final_val = 3.14
else:
final_val = None
print(f"Result: {final_val}")
if __name__ == "__main__":
app()This gives the following:
I must admit, this solution is not pretty, but it is somewhat the best I can provide for now in the meantime - as work is being done to handle it accordingly internally in the codebase(ses). As I see it, in the meantime, not so many solutions will work, since these things seem to be deprecating soon anyways... |
Beta Was this translation helpful? Give feedback.
-
|
Short version: on current Typer you can't do this as a single option anymore. "Optional value" is a Click feature, and the copy of Click that Typer now bundles has dropped the parser support for it. Here's what's actually going on, plus two things that do work today. Why That pattern is Click's "optional value" feature, and it still works in standalone Click 8.x: # pip install "click>=8,<9"
import click
@click.command()
@click.option("--opt-1", is_flag=False, flag_value=3.14, type=float, default=None)
def cli(opt_1):
click.echo(f"opt_1={opt_1!r}")Recent Typer (0.26.x here) bundles its own copy of Click, and that copy no longer has the machinery. If you introspect the Click option Typer builds from cmd = typer.main.get_command(app)
p = next(x for x in cmd.params if x.name == "opt_1")
# is_flag=False, nargs=1, no flag_value (it lands in a dead `_depr_flag_value` slot)In standalone Click, the parser decides "consume the next token, or not" from an internal attribute Option A: pure Typer, two options (works today) Not a single flag, but it reproduces the exact three-way behavior and doesn't lean on anything deprecated: from typing import Optional
import typer
app = typer.Typer()
DEFAULT = 3.14
@app.command()
def main(
opt_1: bool = typer.Option(False, "--opt-1", help=f"Use {DEFAULT} unless --opt-1-value is given"),
opt_1_value: Optional[float] = typer.Option(None, "--opt-1-value"),
):
value = opt_1_value if opt_1_value is not None else (DEFAULT if opt_1 else None)
typer.echo(f"value={value!r}")Option B: drop to raw Click for just this command (works today, single flag) If you specifically need the single-flag UX, define that one command in Click directly (the first snippet) and keep Typer for the rest of the app. They compose fine. Since the bundled Click has already dropped optional value, this relies on standalone Click, so pin Given the deprecation, Option A is the one I'd ship. Tested on Typer 0.26.8 / Click 8.4.2, Python 3.11. The outputs above are real. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
In
click, it is possible to create an option with an optional value: https://click.palletsprojects.com/en/8.1.x/options/#optional-valueI'm wondering if it is possible to do this in
typer?For the example given above, I would expect the following:
--opt-1flag passed:None--opt-1flag is passed with no value:3.14(default value)--opt-1flag is passed with a value (99):99(value that was passed)Operating System
macOS
Operating System Details
No response
Typer Version
0.9.0
Python Version
3.10.10
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions