Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support variadic positional args when parsing from CLI #518

Open
jploskey opened this issue Jan 8, 2025 · 4 comments · May be fixed by #519
Open

Support variadic positional args when parsing from CLI #518

jploskey opened this issue Jan 8, 2025 · 4 comments · May be fixed by #519
Assignees

Comments

@jploskey
Copy link

jploskey commented Jan 8, 2025

Currently, it appears there's no way to take an arbitrary number of positional arguments when parsing settings from the command line. This is a blocker for me, migrating over from typer.

The closest you can get it by doing the following:

# test.py

from pydantic_settings import BaseSettings, CliPositionalArg, SettingsConfigDict


class Main(BaseSettings):
    model_config = SettingsConfigDict(
        cli_parse_args=True,
        cli_enforce_required=True,
    )

    values: CliPositionalArg[list[str]]


parsed = Main()
print(parsed.values)

However, this requires you to run it like python test.py a,b,c or python test.py '["a", "b", "c"]' rather than simply python test.py a b c, which usually makes more sense if the command only takes in a single list of values.

It would be nice to have something like a CliPositionalArgs type to support this:

# test.py

from pydantic_settings import BaseSettings, CliPositionalArgs, SettingsConfigDict


class Main(BaseSettings):
    model_config = SettingsConfigDict(
        cli_parse_args=True,
        cli_enforce_required=True,
    )

    values: CliPositionalArgs[list[str]]


parsed = Main()
print(parsed.values)
@jploskey jploskey changed the title Allow variadic positional args when parsing from CLI Support variadic positional args when parsing from CLI Jan 8, 2025
@hramezani
Copy link
Member

@kschwab can you take look?

@kschwab
Copy link
Contributor

kschwab commented Jan 10, 2025

@jploskey, thanks for the suggestion. I think the above is pretty straightforward to add. However, since internally we're based on argparse, it will likely run into issues for something like the below:

# test.py

from pydantic_settings import BaseSettings, CliPositionalArgs, SettingsConfigDict


class Main(BaseSettings):
    model_config = SettingsConfigDict(
        cli_parse_args=True,
        cli_enforce_required=True,
    )

    strings: CliPositionalArgs[list[str]]

    numbers: CliPositionalArg[list[int]]

#> test.py a b c 1 2 3

i.e., we could only support one variadic positional arg. Additionally, with a variadic positional, I think it also makes sense to reorder it to be the last positional, otherwise it will gobble up anything afterwards. e.g., if something like the below was provided, it would work with reordering:

# test.py

from pydantic_settings import BaseSettings, CliPositionalArgs, SettingsConfigDict


class Main(BaseSettings):
    model_config = SettingsConfigDict(
        cli_parse_args=True,
        cli_enforce_required=True,
    )

    strings: CliPositionalArgs[list[str]]

    number: CliPositionalArg[int]

#> test.py 1 a b c

If the above seems reasonable, we can head in that direction.

@jploskey
Copy link
Author

jploskey commented Jan 10, 2025

@kschwab That makes sense and looks reasonable to me.

I think most common use cases for this (including mine) would be supported within those constraints. It'd be pretty rare to need two different variadic argument lists in the same command. And the only time I can think of wanting a non-variadic argument at the end of a command would be something like a "move" command like mv file-0 file-1 dir. But both of these cases could be (mostly) solved by the user just taking in a single variadic argument list and parsing it into separate values themselves.

@kschwab kschwab linked a pull request Jan 11, 2025 that will close this issue
@kschwab
Copy link
Contributor

kschwab commented Jan 11, 2025

@jploskey @hramezani I've added support for the above onto #519.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants