Literal and Enum Constraints
To restrict data to a fixed set of values, this codebase provides LiteralSchema and EnumSchema. These allow you to validate that input matches specific literal values or members of a Python Enum.
Literal Constraints
You can restrict a field to a specific set of values using literal_schema. This is commonly used for status fields or as discriminators in unions.
from pydantic_core import SchemaValidator, core_schema
# Define a schema that only accepts 'apple' or 'orange'
schema = core_schema.literal_schema(['apple', 'orange'])
v = SchemaValidator(schema)
assert v.validate_python('apple') == 'apple'
# v.validate_python('banana') -> ValidationError: Input should be 'apple' or 'orange'
Mixed Types in Literals
Literals can contain values of different types, such as strings and integers simultaneously.
from pydantic_core import SchemaValidator, core_schema
schema = core_schema.literal_schema(['active', 1, 0])
v = SchemaValidator(schema)
assert v.validate_python('active') == 'active'
assert v.validate_python(1) == 1
Enum Constraints
The enum_schema allows you to validate input against a Python Enum class. You must provide both the Enum class and a list of its members.
from enum import Enum
from pydantic_core import SchemaValidator, core_schema
class Status(Enum):
PENDING = 'pending'
COMPLETED = 'completed'
# Initialize enum_schema with the class and its members
schema = core_schema.enum_schema(
Status,
list(Status.__members__.values())
)
v = SchemaValidator(schema)
assert v.validate_python('pending') is Status.PENDING
assert v.validate_python(Status.COMPLETED) is Status.COMPLETED
Coercion and Sub-types
By default, enum_schema can coerce raw values (like strings or integers) into Enum members if they match the member values. You can explicitly define the expected underlying type using the sub_type parameter.
from enum import IntEnum
from pydantic_core import SchemaValidator, core_schema
class Priority(IntEnum):
LOW = 1
HIGH = 2
# Use sub_type='int' to ensure integer coercion
schema = core_schema.enum_schema(
Priority,
list(Priority.__members__.values()),
sub_type='int'
)
v = SchemaValidator(schema)
# Coerces the integer 1 to Priority.LOW
assert v.validate_python(1) is Priority.LOW
Strict Validation
In strict mode, validation will fail if the input is not an instance of the expected Enum or an exact match for the Literal.
from enum import Enum
from pydantic_core import SchemaValidator, core_schema
class Color(Enum):
RED = 'red'
schema = core_schema.enum_schema(
Color,
list(Color.__members__.values()),
strict=True
)
v = SchemaValidator(schema)
# This works because it's the actual Enum member
assert v.validate_python(Color.RED) is Color.RED
# This fails in strict mode even though the value matches
# v.validate_python('red') -> ValidationError: Input should be an instance of Color
Custom Fallback Logic
The missing parameter in enum_schema allows you to provide a callable that handles values not found in the Enum's members. This is typically used to implement the behavior of an Enum's _missing_ method.
from enum import Enum
from pydantic_core import SchemaValidator, core_schema
class MyEnum(Enum):
A = 1
UNKNOWN = 0
@classmethod
def _missing_(cls, value):
return cls.UNKNOWN
schema = core_schema.enum_schema(
MyEnum,
list(MyEnum.__members__.values()),
missing=MyEnum._missing_
)
v = SchemaValidator(schema)
# Value 3 is not in MyEnum, so it falls back to UNKNOWN via the missing callable
assert v.validate_python(3) is MyEnum.UNKNOWN
Troubleshooting
Empty Expected Values
Both LiteralSchema and EnumSchema require at least one value in their respective expected or members lists. Providing an empty list will result in a SchemaError during validator initialization.
from pydantic_core import SchemaError, core_schema
try:
# This will raise a SchemaError
core_schema.literal_schema([])
except SchemaError as e:
print(e) # "SchemaError: `expected` should have length > 0"
Literal vs Enum Identity
LiteralSchema validation is strict by default regarding types. If you include an Enum member in a literal_schema, passing the raw value of that Enum member will fail unless the input is the Enum member itself (or vice versa, depending on the schema definition). For standard Enum support, always prefer enum_schema.