brentyi / tyro

CLI interfaces & config objects, from types
https://brentyi.github.io/tyro
MIT License
487 stars 25 forks source link

Feature: Configuration option to use `Enum` values instead of names for choices. #166

Open emcd opened 2 weeks ago

emcd commented 2 weeks ago

A common convention for Python Enum classes is to use all-uppercase names for the members of the enum. (This is the style used in the standard library documentation, for example.) However, all-uppercase names can be somewhat visually-jarring if the rest of the CLI is all-lowercase, as is typical for CLI subcommands and option names. Furthermore, with the introduction of StrEnum in Python 3.11, the enum.auto values for each name are the all-lowercase transformation of the name.

To get around this problem, one could, of course, extract all of the enum values and use those as a literals list. But, that is dual maintenance if the enum is being used for more than just CLI options. Consider the use case of selecting output formats, for example. To use a selected output format (JSON (json), pretty text (pretty), TOML (toml), etc...), after CLI parsing, someone may want to match..case on the enum or even call a dispatcher method on the enum itself. Imo, an enum is more maintainable (and easier to validate) than a collection of literals in case like this.

To make Tyro friendlier to string enums, would you consider an enhancement to provide a configuration option which would populate choices by enum value rather than name?

--

(Tyro is great, btw. I just discovered it a couple days ago after messing around with Typer (no dataclasses support, no natural separation of parsing from execution) and SimpleParsing (no PEP 593 support). Thanks for making this. It is beautiful and works as advertised.)

brentyi commented 2 weeks ago

Hi @emcd! Thanks for your nice words, I've spent a lot of time on tyro and it's always nice to hear when it makes sense to people. 🙂

Yeah, your reasons make sense and I don't mind supporting this. Did you want to make a PR?

The steps would be: