tyro icon indicating copy to clipboard operation
tyro copied to clipboard

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

Open emcd opened this issue 1 year ago • 1 comments

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.)

emcd avatar Sep 21 '24 18:09 emcd

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:

  • Add a new marker object here: https://github.com/brentyi/tyro/blob/main/src/tyro/conf/_markers.py
  • Take the new marker into account when we create the field instantiators: https://github.com/brentyi/tyro/blob/main/src/tyro/_instantiators.py
    • We'd need to update both the typing.Literal logic in _instantiator_from_literal and the standard enum logic in instantiator_base_case.
  • Add tests!

brentyi avatar Sep 21 '24 23:09 brentyi