Configuring Global Scalar Behavior
Global scalar behavior in pydantic-core is controlled via the CoreConfig TypedDict. This configuration allows you to define default validation and serialization rules for basic types like strings, floats, and temporal objects across an entire schema.
Setting Global String Constraints
You can enforce length limits and apply transformations to all string fields by passing a CoreConfig instance to the SchemaValidator.
from pydantic_core import CoreConfig, SchemaValidator, core_schema as cs
# Define global string length limits
config = CoreConfig(
str_max_length=5,
str_min_length=2,
str_strip_whitespace=True,
str_to_lower=True
)
v = SchemaValidator(cs.str_schema(), config=config)
# Valid input: length is 4, whitespace is stripped, converted to lower
assert v.validate_python(' TEST ') == 'test'
# Invalid input: exceeds str_max_length
try:
v.validate_python('too long')
except Exception as e:
print(e) # String should have at most 5 characters
Key string configuration attributes include:
str_max_length/str_min_length: Sets the global bounds for string length.str_strip_whitespace: WhenTrue, leading and trailing whitespace is removed during validation.str_to_lower/str_to_upper: Automatically converts strings to the specified case.
Controlling Float Validation and Serialization
CoreConfig manages how non-finite numbers (Infinity and NaN) are handled during both validation and JSON serialization.
Validation: allow_inf_nan
By default, pydantic-core allows non-finite floats. You can disable this globally using allow_inf_nan.
from pydantic_core import CoreConfig, SchemaValidator, core_schema as cs
# Disallow non-finite numbers globally
config = CoreConfig(allow_inf_nan=False)
v = SchemaValidator(cs.float_schema(), config=config)
# This will raise a ValidationError with type 'finite_number'
try:
v.validate_python(float('nan'))
except Exception as e:
print(e) # Input should be a finite number
Serialization: ser_json_inf_nan
JSON does not natively support NaN or Infinity. Use ser_json_inf_nan to define how these should be represented in JSON output.
from pydantic_core import CoreConfig, SchemaSerializer, core_schema as cs
# Options: 'null' (default), 'constants' (Infinity), 'strings' ("Infinity")
config = CoreConfig(ser_json_inf_nan='strings')
s = SchemaSerializer(cs.float_schema(), config=config)
assert s.to_json(float('inf')) == b'"Infinity"'
assert s.to_json(float('nan')) == b'"NaN"'
Defining Temporal Serialization Formats
Temporal types (datetime, date, time, timedelta) default to ISO 8601 serialization. You can change this globally to numeric timestamps using ser_json_temporal.
from pydantic_core import SchemaSerializer, core_schema as cs
from datetime import datetime
# Serialize all temporal types to Unix timestamps (seconds)
config = {'ser_json_temporal': 'seconds'}
s = SchemaSerializer(cs.datetime_schema(), config=config)
dt = datetime(2024, 1, 1)
# to_python with mode='json' simulates the JSON serialization process
assert s.to_python(dt, mode='json') == 1704067200.0
Available formats for ser_json_temporal:
'iso8601': Standard string format (e.g.,"2024-01-01T00:00:00").'seconds': Float representing Unix epoch seconds.'milliseconds': Float representing Unix epoch milliseconds.
Scoping and Precedence
Configuration settings follow a specific hierarchy. Understanding these rules is critical for troubleshooting unexpected behavior.
Field-Level Overrides
Specific constraints defined within a schema (e.g., cs.str_schema(max_length=2)) always take precedence over global CoreConfig settings.
from pydantic_core import CoreConfig, SchemaValidator, core_schema as cs
# Global max is 10, but field max is 5
config = CoreConfig(str_max_length=10)
v = SchemaValidator(cs.str_schema(max_length=5), config=config)
# This fails because the field-level constraint (5) is used
assert v.isinstance_python('123456') is False
Temporal Precedence
If both ser_json_temporal and ser_json_timedelta are provided in the configuration, ser_json_temporal takes precedence and is used for timedelta serialization as well.
# ser_json_temporal overrides ser_json_timedelta
config = {
'ser_json_temporal': 'seconds',
'ser_json_timedelta': 'iso8601'
}
# timedeltas will be serialized as seconds, not ISO 8601
Model-Specific Configuration
You can scope CoreConfig to a specific model by including it in the model_schema definition rather than passing it to the top-level validator.
v = SchemaValidator(
cs.model_schema(
cls=dict,
config=CoreConfig(str_max_length=5),
schema=cs.model_fields_schema(fields={
'name': cs.model_field(schema=cs.str_schema())
}),
)
)