Skip to content

feat: validate Literal[...] annotations as choices - #25

Merged
bhirsz merged 1 commit into
mainfrom
feat/literal-choices
Aug 30, 2026
Merged

feat: validate Literal[...] annotations as choices#25
bhirsz merged 1 commit into
mainfrom
feat/literal-choices

Conversation

@bhirsz

@bhirsz bhirsz commented Aug 30, 2026

Copy link
Copy Markdown
Member

Summary

Adds choice validation driven by typing.Literal[...] annotations.

Annotate an option (or argument) with Literal[...] to restrict it to a fixed
set of allowed values:

from typing import Literal
from confargs import ArgConfig, option

class Args(ArgConfig):
    console: Literal["verbose", "dotted", "quiet", "none"] = option(name="console", default="verbose")
    level: Literal[1, 2, 3] = option(name="level", default=1)
    langs: list[Literal["en", "pl"]] = option(name="langs", default=list)

Behaviour

  • The incoming value is coerced to the members' type (so Literal[1, 2, 3]
    accepts the string "2" from the CLI and yields 2), then checked for
    membership.
  • An out-of-set value raises OptionValueError listing the allowed choices.
  • Works for scalars, list[Literal[...]], Literal[...] | None, method value
    parameters, positional arguments, and TOML/env sources.
  • --help renders the allowed values as a {a,b,c} metavar.

Changes

  • coercion.py: ValueType.choices, Literal detection in _analyse,
    _analyse_literal, and membership enforcement in coerce_value.
  • help.py: choices metavar.
  • README.md: "Restricting a value to a set of choices" section.
  • tests/test_choices.py: 10 tests.

Refs #22

Part of the option-ergonomics stack: #23 (attribute typing) → #24 (default
factory) → this PR. Enables the PR #20 example to drop manual choice validation.

@bhirsz
bhirsz force-pushed the feat/literal-choices branch from 4d6d812 to 1b89db5 Compare August 30, 2026 12:59
Base automatically changed from feat/option-default-factory to main August 30, 2026 13:00
Constrain an option or argument to a fixed set of values by annotating it
with typing.Literal[...]. Values are coerced to the members' type and then
checked for membership, raising OptionValueError otherwise. The allowed
values are surfaced in --help as a {a,b,c} metavar.

Refs #22

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bhirsz
bhirsz force-pushed the feat/literal-choices branch from 1b89db5 to eeb4fb7 Compare August 30, 2026 13:00
@bhirsz
bhirsz merged commit 196464b into main Aug 30, 2026
8 checks passed
@bhirsz
bhirsz deleted the feat/literal-choices branch August 30, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant