Skip to content

launch: reconsider Literal[discriminator]-with-default vs requiring type: #362

@gilesknap

Description

@gilesknap

Context

Follow-up from PR #360 (slice #354 — multi-class launch()).

_build_entry_model builds each entry's type field as Literal[discriminator] with a default value equal to the discriminator:

# src/fastcs/launch.py:217
fields["type"] = (Literal[discriminator], discriminator)

The default is what lets single-class configs omit type: from fastcs.yaml. But:

  • In single-class mode, _build_options_model uses the entry model directly. The type: default works — Pydantic falls through to it on omission.
  • In multi-class mode, _build_options_model wraps the entry models in Annotated[Union[...], Field(discriminator=\"type\")]. Pydantic's discriminated-union resolution does not consult field defaults to pick a branch; an entry without type: raises a discrimination error.

So the same line of code produces "optional" behaviour in one mode and "required" behaviour in the other. The asymmetry is small but the kind of thing that silently shifts the day someone registers a second class.

Options

  1. Status quo + comment: leave the asymmetry, add a one-line code comment at the fields[\"type\"] site noting "default takes effect only in single-class mode."
  2. Require type: always: drop the default. Single-class users gain a redundant type: MyController line in YAML; in exchange the rule is one rule (type: is mandatory) and the simple case looks the same as the multi-class case.

The user-facing trade-off is "redundant line in trivial configs" vs "one consistent rule and no mode-dependent behaviour."

What to decide

Pick option 1 or 2 and apply.

Acceptance criteria

  • Decision recorded (in code comment for option 1; in a short ADR or PR description for option 2)
  • If option 2: demo controller.yaml, tests/data/config.yaml, snippets, and any docs migrate to include type:
  • Full test suite stays green

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions