Skip to main content

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.