!pip install pydantic
13 FastAPI, Pydantic
լուսանկարի հղումը, Հեղինակ՝ Aram Ramazyan
Song reference - ToDo
📌 Նկարագիր
📺 Տեսանյութեր
🏡 Տնային
📚 Pydantic Tutorial
What is Pydantic?
Pydantic is a Python library that provides data validation and settings management using Python type annotations. It’s designed to make data validation simple, fast, and reliable.
Key Features:
- Type Safety: Uses Python type hints for validation
- Fast: Written in Rust (v2) for performance
- Easy to Use: Intuitive API design
- Comprehensive: Supports complex data structures
- Integration: Works seamlessly with FastAPI
Why Use Pydantic?
- Data Validation: Automatically validates input data
- Type Conversion: Converts compatible types automatically
- Error Handling: Provides detailed error messages
- Documentation: Auto-generates JSON schemas
- IDE Support: Full type checking and autocomplete
Installation
pip install pydantic
For email validation and other extras:
pip install pydantic[email]
Reminder - dataclasses
from typing import Optional
from pydantic import BaseModel
Basic Pydantic Models
A Pydantic model is a class that inherits from BaseModel
. All attributes are defined with type annotations.
= {
user_data "id": 1,
"name": "Faylo Bobol",
"email": "faylo@bolol.am",
"age": 30, # optional
# is_active default = True
}
# Basic Pydantic Model
class User(BaseModel):
id: int
str
name: str
email: int] = None
age: Optional[bool = True
is_active:
= User(**user_data) # User(id=user_data["id"])
user
print(user)
print(f"User name: {user.name}")
print(f"User email: {user.email}")
id=1 name='Faylo Bobol' email='faylo@bolol.am' age=30 is_active=True
User name: Faylo Bobol
User email: faylo@bolol.am
# Convert to dictionary
print("\nAs dictionary:")
print(user.model_dump())
# Convert to JSON
print("\nAs JSON:")
print(user.model_dump_json(indent=4))
As dictionary:
{'id': 1, 'name': 'Faylo Bobol', 'email': 'faylo@bolol.am', 'age': 30, 'is_active': True}
As JSON:
{
"id": 1,
"name": "Faylo Bobol",
"email": "faylo@bolol.am",
"age": 30,
"is_active": true
}
print(user.model_dump(include={"id", "name"}))
print(user.model_dump(exclude={"id", "name"}))
{'id': 1, 'name': 'Faylo Bobol'}
{'email': 'faylo@bolol.am', 'age': 30, 'is_active': True}
Data Validation
Pydantic automatically validates data types and provides helpful error messages.
# Type conversion - Pydantic tries to convert compatible types
print("=== Type Conversion ===")
= User(id="123",
user_flexible ="Barxudarum",
name="barxudarum@panir.com",
email="25")
age
print(f"ID (converted from string): {user_flexible.id} (type: {type(user_flexible.id)})")
print(f"Age (converted from string): {user_flexible.age} (type: {type(user_flexible.age)})")
=== Type Conversion ===
ID (converted from string): 123 (type: <class 'int'>)
Age (converted from string): 25 (type: <class 'int'>)
= User(id="not_a_number", name="Spiridon", email="tervigen@xunk.am") invalid_user
--------------------------------------------------------------------------- ValidationError Traceback (most recent call last) Cell In[42], line 1 ----> 1 invalid_user = User(id="not_a_number", name="Spiridon", email="tervigen@xunk.am") File c:\Users\hayk_\.conda\envs\sl\lib\site-packages\pydantic\main.py:253, in BaseModel.__init__(self, **data) 251 # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 252 __tracebackhide__ = True --> 253 validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) 254 if self is not validated_self: 255 warnings.warn( 256 'A custom validator is returning a value other than `self`.\n' 257 "Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n" 258 'See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.', 259 stacklevel=2, 260 ) ValidationError: 1 validation error for User id Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='not_a_number', input_type=str] For further information visit https://errors.pydantic.dev/2.11/v/int_parsing
= User(id=509, email="tervigen@xunk.am") less_data
--------------------------------------------------------------------------- ValidationError Traceback (most recent call last) Cell In[43], line 1 ----> 1 less_data = User(id=509, email="tervigen@xunk.am") File c:\Users\hayk_\.conda\envs\sl\lib\site-packages\pydantic\main.py:253, in BaseModel.__init__(self, **data) 251 # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 252 __tracebackhide__ = True --> 253 validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) 254 if self is not validated_self: 255 warnings.warn( 256 'A custom validator is returning a value other than `self`.\n' 257 "Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n" 258 'See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.', 259 stacklevel=2, 260 ) ValidationError: 1 validation error for User name Field required [type=missing, input_value={'id': 509, 'email': 'tervigen@xunk.am'}, input_type=dict] For further information visit https://errors.pydantic.dev/2.11/v/missing
Field Constraints and Custom Validators
Pydantic provides Field constraints and custom validators for more sophisticated validation.
# Advanced model with Field constraints and custom validators
from pydantic import Field
from datetime import datetime
class AdvancedUser(BaseModel):
id: int = Field(gt=0, description="User ID must be positive") # greater than
str = Field(min_length=3, max_length=20, description="Username between 3-20 characters")
username: str = Field(description="Valid email address")
email: int] = Field(default=None, ge=0, le=100, description="Age between 0-100")
age: Optional[str = Field(min_length=8, description="Password minimum 8 characters")
password: str = Field(description="Password confirmation")
confirm_password: str = Field(description="Full name")
full_name:
= Field(default_factory=datetime.now) created_at: datetime
= AdvancedUser(
advanced_user id=1,
="Faylo509",
username="panir@hamov.am",
email=25,
age="hndkahav",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)print("✅ User created successfully!")
print(advanced_user.model_dump(exclude={'password', 'confirm_password'}))
✅ User created successfully!
{'id': 1, 'username': 'Faylo509', 'email': 'panir@hamov.am', 'age': 25, 'full_name': 'Faylo Bobolyan', 'created_at': datetime.datetime(2025, 8, 13, 18, 25, 25, 638385)}
= AdvancedUser(
advanced_user id=-3,
="Faylo509",
username="panir@hamov.am",
email=25,
age="hndkahav",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)print("✅ User created successfully!")
print(advanced_user.model_dump(exclude={'password', 'confirm_password'}))
--------------------------------------------------------------------------- ValidationError Traceback (most recent call last) Cell In[46], line 1 ----> 1 advanced_user = AdvancedUser( 2 id=-3, 3 username="Faylo509", 4 email="panir@hamov.am", 5 age=25, 6 password="hndkahav", 7 confirm_password="hndkahav", 8 full_name="Faylo Bobolyan" 9 ) 10 print("✅ User created successfully!") 11 print(advanced_user.model_dump(exclude={'password', 'confirm_password'})) File c:\Users\hayk_\.conda\envs\sl\lib\site-packages\pydantic\main.py:253, in BaseModel.__init__(self, **data) 251 # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 252 __tracebackhide__ = True --> 253 validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) 254 if self is not validated_self: 255 warnings.warn( 256 'A custom validator is returning a value other than `self`.\n' 257 "Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n" 258 'See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.', 259 stacklevel=2, 260 ) ValidationError: 1 validation error for AdvancedUser id Input should be greater than 0 [type=greater_than, input_value=-3, input_type=int] For further information visit https://errors.pydantic.dev/2.11/v/greater_than
from pydantic import ValidationError
try:
= AdvancedUser(
advanced_user id=-3,
="Faylo509",
username="panir@hamov.am",
email=123,
age="hndk",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)
except ValidationError as e:
print("❌ Validation failed:")
for error in e.errors():
print(f" {error['loc']}: {error['msg']}")
❌ Validation failed:
('id',): Input should be greater than 0
('age',): Input should be less than or equal to 100
('password',): String should have at least 8 characters
Custom validators
import re # regular expresstion
from pydantic import field_validator, model_validator
class AdvancedUser(BaseModel):
id: int = Field(gt=0, description="User ID must be positive") # greater than
str = Field(min_length=3, max_length=20, description="Username between 3-20 characters")
username: str = Field(description="Valid email address")
email: int] = Field(default=None, ge=0, le=100, description="Age between 0-100")
age: Optional[str = Field(min_length=8, description="Password minimum 8 characters")
password: str = Field(description="Password confirmation")
confirm_password: str = Field(description="Full name")
full_name:
# https://stackoverflow.com/questions/76972389/fastapi-pydantic-how-to-validate-email
@field_validator('email')
@classmethod
def validate_email(cls, v):
# Simple email validation
= r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
pattern if not re.match(pattern, v):
raise ValueError('Invalid email format')
return v
@field_validator('username')
@classmethod
def validate_username(cls, v):
if not v.isalnum():
raise ValueError('Username must be alphanumeric')
return v
@field_validator('password')
@classmethod
def validate_password(cls, v):
if not any(c.isupper() for c in v):
raise ValueError('Password must contain at least one uppercase letter')
if not any(c.islower() for c in v):
raise ValueError('Password must contain at least one lowercase letter')
if not any(c.isdigit() for c in v):
raise ValueError('Password must contain at least one digit')
return v
# # Validate that passwords match, after setting the values
@model_validator(mode='after')
def validate_passwords_match(self):
if self.password != self.confirm_password:
raise ValueError('Passwords do not match')
return self
try:
= AdvancedUser(
advanced_user id=3,
="Faylo509",
username="panir@hamov.am",
email=25,
age="Sovorakan_hav509",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)
except ValidationError as e:
print("❌ Validation failed:")
for error in e.errors():
print(f" {error['loc']}: {error['msg']}")
❌ Validation failed:
(): Value error, Passwords do not match
try:
= AdvancedUser(
advanced_user id=3,
="Faylo509",
username="panir@hamov.am",
email=25,
age="Sovorakan_hav509",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)
except ValidationError as e:
print("❌ Validation failed:")
for error in e.errors():
print(f" {error['loc']}: {error['msg']}")
❌ Validation failed:
(): Value error, Passwords do not match
Config
https://docs.pydantic.dev/latest/api/config/
class AdvancedUser(BaseModel):
id: int = Field(gt=0, description="User ID must be positive") # greater than
str = Field(min_length=3, max_length=20, description="Username between 3-20 characters")
username: str = Field(description="Valid email address")
email: int] = Field(default=None, ge=0, le=100, description="Age between 0-100")
age: Optional[str = Field(min_length=8, description="Password minimum 8 characters")
password: str = Field(description="Password confirmation")
confirm_password: str = Field(description="Full name")
full_name:
class Config: # https://docs.pydantic.dev/latest/api/config/
= True
str_to_upper # frozen = True
= AdvancedUser(
advanced_user id=3,
="Faylo509",
username="panir@hamov.am",
email=25,
age="Sovorakan_hav509",
password="hndkahav",
confirm_password="Faylo Bobolyan"
full_name
)
print(advanced_user)
id = 10
advanced_user.print(advanced_user)
id=3 username='FAYLO509' email='PANIR@HAMOV.AM' age=25 password='SOVORAKAN_HAV509' confirm_password='HNDKAHAV' full_name='FAYLO BOBOLYAN'
id=10 username='FAYLO509' email='PANIR@HAMOV.AM' age=25 password='SOVORAKAN_HAV509' confirm_password='HNDKAHAV' full_name='FAYLO BOBOLYAN'
Json Schema
advanced_user.model_json_schema()
{'properties': {'id': {'description': 'User ID must be positive',
'exclusiveMinimum': 0,
'title': 'Id',
'type': 'integer'},
'username': {'description': 'Username between 3-20 characters',
'maxLength': 20,
'minLength': 3,
'title': 'Username',
'type': 'string'},
'email': {'description': 'Valid email address',
'title': 'Email',
'type': 'string'},
'age': {'anyOf': [{'maximum': 100, 'minimum': 0, 'type': 'integer'},
{'type': 'null'}],
'default': None,
'description': 'Age between 0-100',
'title': 'Age'},
'password': {'description': 'Password minimum 8 characters',
'minLength': 8,
'title': 'Password',
'type': 'string'},
'confirm_password': {'description': 'Password confirmation',
'title': 'Confirm Password',
'type': 'string'},
'full_name': {'description': 'Full name',
'title': 'Full Name',
'type': 'string'}},
'required': ['id',
'username',
'email',
'password',
'confirm_password',
'full_name'],
'title': 'AdvancedUser',
'type': 'object'}
Enum
An Enum (Enumeration) is a way to create a set of symbolic names bound to unique, constant values. It provides a structured way to define a collection of related constants.
from enum import Enum
# Basic Enum example
class UserRole(str, Enum):
= "admin"
ADMIN = "user"
USER = "moderator"
MODERATOR
# Usage
= UserRole.ADMIN
role print(role)
print(f"Role: {role}") # Role: admin
print(f"Role value: {role.value}") # Role value: admin
print(f"Role name: {role.name}") # Role name: ADMIN
# # You can iterate over enum values
print("\nAll roles:")
for role in UserRole:
print(f" {role.name}: {role.value}")
UserRole.ADMIN
Role: admin
Role value: admin
Role name: ADMIN
All roles:
ADMIN: admin
USER: user
MODERATOR: moderator
Why enum?
- Type Safety and Validation
# Without Enum - prone to errors
def check_user_permission(role: str):
if role == "admin": # Typo risk: "admni", "Admin", etc.
return "Full access"
elif role == "user":
return "Limited access"
else:
return "No access"
# With Enum - type safe
def check_user_permission_safe(role: UserRole):
if role == UserRole.ADMIN: # IDE autocomplete, no typos
return "Full access"
elif role == UserRole.USER:
return "Limited access"
else:
return "No access"
# Demonstration
print("=== Type Safety Demo ===")
# print(f"{check_user_permission('admni') = }", "(Typo, but no error!)")
print(f"{check_user_permission_safe(UserRole.ADMIN) = }", "(Safe!)")
=== Type Safety Demo ===
check_user_permission_safe(UserRole.ADMIN) = 'Full access' (Safe!)
- Centralized Constants
class User(BaseModel):
str
role: str
status:
= User(role="admin", status="active")
user
# Bad: Magic strings scattered throughout code
if user.role == "admin": # Magic string
pass
if user.status == "active": # Another magic string
pass
# Good: Centralized in Enum
class UserStatus(str, Enum):
= "active"
ACTIVE = "inactive"
INACTIVE = "suspended"
SUSPENDED
if user.role == UserRole.ADMIN: # Clear, centralized
pass
if user.status == UserStatus.ACTIVE: # Clear, centralized
pass
- IDE Support and Autocomplete
# With Enum, your IDE provides:
# - Autocomplete for UserRole.
# - Error detection for invalid values
# - Refactoring support
= UserRole. # IDE shows: ADMIN, USER, MODERATOR role
Enum vs typing.Literal
from typing import Literal
# Using Literal
def process_with_literal(status: Literal["pending", "approved", "rejected"]):
return f"Processing {status}"
# Using Enum
class Status(str, Enum):
= "pending"
PENDING = "approved"
APPROVED = "rejected"
REJECTED
def process_with_enum(status: Status):
return f"Processing {status.value}"
# 1. Runtime Validation
def test_literal(value: Literal["a", "b", "c"]):
# No runtime validation - any string can be passed
return value
def test_enum(value: Status):
# Runtime validation when creating enum instance
return value
print("=== Runtime Validation ===")
print(test_literal("invalid")) # No error!
print(test_enum(Status("invalid"))) # Will raise ValueError
=== Runtime Validation ===
invalid
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[78], line 13 10 print("=== Runtime Validation ===") 11 print(test_literal("invalid")) # No error! ---> 13 print(test_enum(Status("invalid"))) # Will raise ValueError File c:\Users\hayk_\.conda\envs\sl\lib\enum.py:385, in EnumMeta.__call__(cls, value, names, module, qualname, type, start) 360 """ 361 Either returns an existing member, or creates a new enum class. 362 (...) 382 `type`, if set, will be mixed in as the first base class. 383 """ 384 if names is None: # simple value lookup --> 385 return cls.__new__(cls, value) 386 # otherwise, functional API: we're creating a new Enum type 387 return cls._create_( 388 value, 389 names, (...) 393 start=start, 394 ) File c:\Users\hayk_\.conda\envs\sl\lib\enum.py:710, in Enum.__new__(cls, value) 708 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__)) 709 if result is None and exc is None: --> 710 raise ve_exc 711 elif exc is None: 712 exc = TypeError( 713 'error in %s._missing_: returned %r instead of None or a valid member' 714 % (cls.__name__, result) 715 ) ValueError: 'invalid' is not a valid Status
# 2. Iteration and Introspection
print("\n=== Iteration ===")
# Literal - cannot iterate
# for item in Literal["a", "b", "c"]: # Not possible
# Enum - can iterate
for status in Status:
print(f"Status: {status.name} = {status.value}")
=== Iteration ===
Status: PENDING = pending
Status: APPROVED = approved
Status: REJECTED = rejected
# 3. Extensibility
class ExtendedStatus(str, Enum):
= "pending"
PENDING = "approved"
APPROVED = "rejected"
REJECTED
def is_final(self) -> bool:
"""Check if status is final (approved or rejected)"""
return self in (self.APPROVED, self.REJECTED)
@classmethod
def get_initial_status(cls):
"""Get the initial status for new items"""
return cls.PENDING
= ExtendedStatus.PENDING
status print(f"=== Extended Methods ===")
print(f"Is {status.value} final? {status.is_final()}")
print(f"Initial status: {ExtendedStatus.get_initial_status().value}")
=== Extended Methods ===
Is pending final? False
Initial status: pending
Enums with Pydantic
from enum import Enum
from pydantic import BaseModel, ValidationError
class UserRole(str, Enum):
= "admin"
ADMIN = "user"
USER = "moderator"
MODERATOR
try:
= UserRole("panir")
role except ValueError as e:
print(f"❌ Error: {e}")
# Correct usage:
= UserRole.MODERATOR
role print(f"✅ Correct: {role}")
❌ Error: 'panir' is not a valid UserRole
✅ Correct: moderator
# Pydantic Model with Enum
class UserWithRole(BaseModel):
id: int
role: UserRolestr
name:
# Valid creation
= UserWithRole(id=1, role="admin", name="Mavses") # hardcoded
user_with_role print(f"\n=== Pydantic with Enum ===")
print(f"User: {user_with_role}")
print(f"Role type: {type(user_with_role.role)}")
print(f"Role value: {user_with_role.role.value}")
# # Pydantic automatically validates enum values
= "panir"
wrong_role
try:
= UserWithRole(id=2, role=wrong_role, name="Goro")
invalid_user except ValidationError as e:
print(f"\n❌ Validation Error:")
for error in e.errors():
print(f" {error['loc']}: {error['msg']}")
=== Pydantic with Enum ===
User: id=1 role=<UserRole.ADMIN: 'admin'> name='Mavses'
Role type: <enum 'UserRole'>
Role value: admin
❌ Validation Error:
('role',): Input should be 'admin', 'user' or 'moderator'
We can also make it so it exports the value instead of the enum object itself
class UserWithRole(BaseModel):
id: int
role: UserRolestr
name:
# class Config:
# use_enum_values = True
= UserWithRole(id=509, role=UserRole.USER, name="DVD Gugo")
user
user.role
<UserRole.USER: 'user'>
We can add methods to enums
# Complex example with multiple enums
class Priority(str, Enum):
= "low"
LOW = "medium"
MEDIUM = "high"
HIGH = "critical"
CRITICAL
def __lt__(self, other):
"""Enable priority comparison"""
= {"low": 1, "medium": 2, "high": 3, "critical": 4}
order return order[self.value] < order[other.value]
class TaskStatus(str, Enum):
= "todo"
TODO = "in_progress"
IN_PROGRESS = "review"
REVIEW = "done"
DONE = "cancelled"
CANCELLED
def can_transition_to(self, new_status: 'TaskStatus') -> bool:
"""Define valid status transitions"""
= {
transitions self.TODO: [self.IN_PROGRESS, self.CANCELLED],
self.IN_PROGRESS: [self.REVIEW, self.CANCELLED],
self.REVIEW: [self.DONE, self.IN_PROGRESS],
self.DONE: [],
self.CANCELLED: [self.TODO]
}return new_status in transitions.get(self, [])
class Task(BaseModel):
id: int
str
title:
priority: Priority= TaskStatus.TODO
status: TaskStatus
def update_status(self, new_status: TaskStatus) -> bool:
"""Update status with validation"""
if self.status.can_transition_to(new_status):
self.status = new_status
return True
return False
# Usage example
print("\n=== Advanced Enum Example ===")
= Task(id=1, title="Fix bug", priority=Priority.HIGH)
task print(f"Initial task: {task}")
=== Advanced Enum Example ===
Initial task: id=1 title='Fix bug' priority=<Priority.HIGH: 'high'> status=<TaskStatus.TODO: 'todo'>
# Valid transition
if task.update_status(TaskStatus.IN_PROGRESS):
print(f"✅ Status updated: {task.status}")
else:
print("❌ Invalid status transition")
# Invalid transition
if task.update_status(TaskStatus.DONE):
print(f"✅ Status updated: {task.status}")
else:
print("❌ Invalid transition from IN_PROGRESS to DONE (must go through REVIEW)")
✅ Status updated: in_progress
❌ Invalid transition from IN_PROGRESS to DONE (must go through REVIEW)
# Priority comparison
= Priority.HIGH
high_priority = Priority.CRITICAL
critical_priority print(f"\nPriority comparison:")
print(f"High < Critical: {high_priority < critical_priority}")
Priority comparison:
High < Critical: True
# JSON serialization
print(f"\nJSON output: {task.model_dump_json(indent=2)}")
JSON output: {
"id": 1,
"title": "Fix bug",
"priority": "high",
"status": "in_progress"
}
Complex Data Structures and Nested Models
Pydantic can handle complex nested structures, lists, and enums.
from enum import Enum
from typing import Optional
from datetime import datetime
from pydantic import BaseModel, Field
class UserRole(str, Enum):
= "admin"
ADMIN = "user"
USER
class Status(str, Enum):
= "active"
ACTIVE = "inactive"
INACTIVE
# Simplified nested models
class Address(BaseModel):
str
street: str
city: str = Field(pattern=r'^\d{5}$') # 5-digit ZIP code
postal_code:
# Simplified complex user model
class ComplexUser(BaseModel):
id: int
role: UserRole= Status.ACTIVE
status: Status = None
address: Optional[Address] = Field(default_factory=datetime.now)
created_at: datetime
# Example data
= {
user_data "id": 1,
"role": "admin",
# no status -> default
"address": {
"street": "Padnijni Pskov",
"city": "Hervashen",
"postal_code": "0031"
},
}
# Create complex user
= ComplexUser(**user_data)
user print("=== Complex User Created ===")
print(f"Role: {user.role}")
print(f"Address: {user.address.street}, {user.address.city}")
# JSON output
print("\n=== JSON Representation ===")
print(user.model_dump_json(indent=2, exclude={'created_at'}))
--------------------------------------------------------------------------- ValidationError Traceback (most recent call last) Cell In[96], line 43 30 user_data = { 31 "id": 1, 32 "role": "admin", (...) 39 40 } 42 # Create complex user ---> 43 user = ComplexUser(**user_data) 44 print("=== Complex User Created ===") 45 print(f"Role: {user.role}") File c:\Users\hayk_\.conda\envs\sl\lib\site-packages\pydantic\main.py:253, in BaseModel.__init__(self, **data) 251 # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks 252 __tracebackhide__ = True --> 253 validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self) 254 if self is not validated_self: 255 warnings.warn( 256 'A custom validator is returning a value other than `self`.\n' 257 "Returning anything other than `self` from a top level model validator isn't supported when validating via `__init__`.\n" 258 'See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.', 259 stacklevel=2, 260 ) ValidationError: 1 validation error for ComplexUser address.postal_code String should match pattern '^\d{5}$' [type=string_pattern_mismatch, input_value='0031', input_type=str] For further information visit https://errors.pydantic.dev/2.11/v/string_pattern_mismatch
The Kernel crashed while executing code in the current cell or a previous cell. Please review the code in the cell(s) to identify a possible cause of the failure. Click <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details.