-
Notifications
You must be signed in to change notification settings - Fork 3
Description
If we want to allow sequences of pydantic models, things get unreadable quite fast.
Let's look at an example of a nested pydantic model with a sequence of another model:
pets.py
from typing import Optional, List
import typer
import pydantic
class Pet(pydantic.BaseModel):
name: str
species: str
class Person(pydantic.BaseModel):
name: str
age: Optional[float] = None
pets: List[Pet]
def main(person: Person):
print(person, type(person))
if __name__ == "__main__":
typer.run(main)The script could be called like this:
$ python pets.py --person.name Jeff --person.pets.name Lassie --person.pets.species dogIf we want to add multiple pets, we can just supply --person.pets.name and person.pets.species multiple times.
$ python pets.py --person.name Jeff --person.pets.name Lassie --person.pets.species dog --person.pets.name Nala --person.pets.species catWe don't explicitly state which pet names and species belong together and have to rely on the correct order of parameters. In my opinion this is potentially confusing for the CLI user and may lead to bugs.
Potential Solution
To make the mapping more explicit, we could allow to enable typer.Option lists to be indexed.
Like for nested pydantic models, I suggest sticking to the syntax traefik uses for lists. I.e. entrypoints.<name>.http.tls.domains[n].main
Indexed lists could be implemented independently of this PR and should work for all lists.
I suggest adding an indexed flag on typer.Option like shown in the example below.
indexed_list.py
from typing import List
import typer
def main(indexed_list: List[int] = typer.Option(..., indexed=True)):
print(indexed_list)
if __name__ == "__main__":
typer.run(main)This would then produce the following help text:
$ python indexed_list.py --help
Usage: indexed_list.py [OPTIONS]
╭─ Options ────────────────────────────────────────────────────────╮
│ * --indexed-list[n] INTEGER [default: None] [required] │
│ --help Show this message and │
│ exit. │
╰──────────────────────────────────────────────────────────────────╯And could be used like this:
$ python indexed_list.py --indexed-list[1] 0 --indexed-list[0] 1 --indexed-list[2] 2
[1, 0, 2]Note how the order of the input parameters doesn't matter anymore because the indices are given explicitly.
Notes on Implementation
Implementing this might not be trivial, but I think it could be possible by forwarding unknown options as described in the click docs.
Edit: This might actually be easier using token normalization.
Originally posted by @pypae in fastapi/typer#803 (comment)