Fix TypeError in type_info for mixed-type Literals#1019
Fix TypeError in type_info for mixed-type Literals#1019lawrence3699 wants to merge 1 commit intojcrist:mainfrom
Conversation
`type_info()` crashes with `TypeError` on `Literal` types that mix value types (e.g. `Literal[1, None]`) because `sorted()` in Python 3 cannot compare values of different types. Use a type-aware sort key that groups by type name, with `None` always sorting first. Also update the `LiteralType.values` annotation to reflect that mixed-type tuples are valid. Closes jcrist#1018
There was a problem hiding this comment.
Pull request overview
Fixes a TypeError in msgspec.inspect.type_info() when inspecting typing.Literal types containing mixed value types (e.g., Literal[1, None]) by introducing a type-aware sort, and expands LiteralType.values typing/docs to cover mixed literal value tuples.
Changes:
- Replace
sorted(args)forLiteral[...]handling with a type-aware sort key to avoid cross-type comparison errors. - Widen
LiteralType.valuesannotation and update its docstring to reflect supported mixed literal values. - Add regression tests covering
Noneand mixed(None, int, str)literal combinations.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/msgspec/inspect.py |
Makes Literal[...] translation robust to mixed-type literal args and updates LiteralType.values typing/docs. |
tests/unit/test_inspect.py |
Adds regression tests validating type_info() output ordering for mixed-type Literal values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| tuple( | ||
| sorted( | ||
| args, | ||
| key=lambda x: ("", 0) if x is None else (type(x).__name__, x), | ||
| ) |
There was a problem hiding this comment.
type_info() now returns mixed-type LiteralType.values by using a custom sort key, but msgspec.json.schema still does sorted(t.values) (see src/msgspec/_json_schema.py:367), which will continue to raise TypeError for mixed (None, int, str) enums. Consider either relying on the already-normalized ordering from type_info (no downstream re-sort), or factoring this sort key into a shared helper and reusing it in schema generation too.
Siyet
left a comment
There was a problem hiding this comment.
Tested on a Linux VPS (Python 3.12, Ubuntu): all 168 inspect tests green, including the 4 new ones. Also ran 12 extra edge-case scenarios (negative ints, single-element Literals, multi-type mixes), all pass.
Two things to address:
- +1 to Copilot's inline: confirmed on VPS that
msgspec.json.schema(Literal[1, None])crashes withTypeError. - Sort order (None first, then by type name, then by value) is not documented. A comment on the lambda would help.
Closes #1018
inspect.type_info()crashes withTypeErrorwhen called onLiteraltypes that mix value types:Cause:
sorted(args)on line 888 fails in Python 3 when args contain values of different types (e.g.intandNoneType).Fix: Use a type-aware sort key
("", 0) if x is None else (type(x).__name__, x)that groups values by type name, withNonealways sorting first. Also updates theLiteralType.valuesannotation toTuple[Union[None, int, str], ...]since mixed-type tuples are valid.Before:
type_info(Literal[1, None])raisesTypeErrorAfter:
type_info(Literal[1, None])returnsLiteralType(values=(None, 1))Existing behavior for same-type Literals is unchanged (e.g.
Literal[3, 1, 2]still produces(1, 2, 3)).Validation: all 168 inspect tests pass (including 4 new regression tests), ruff lint + format clean.