Skip to content

Commit 11b2f7c

Browse files
authored
Merge pull request #509 from hfhoffman1144/python-pydantic
Materials for Pydantic: Simplifying Data Validation in Python
2 parents 3f9c3ca + e1aab39 commit 11b2f7c

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

python-pydantic/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Pydantic: Simplifying Data Validation in Python
2+
3+
Supporting code for the Real Python tutorial [Pydantic: Simplifying Data Validation in Python](https://realpython.com/pydantic-simplifying-data-validation-in-python/).
4+
5+
To run the code in this tutorial, install Pydantic with its `email` dependency:
6+
7+
```console
8+
(venv) $ python -m pip install "pydantic[email]"
9+
```
10+
11+
Pydantic has a separate package for [settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/), which you'll also cover in this tutorial. To install this, run the following command:
12+
13+
```console
14+
(venv) $ python -m pip install pydantic-settings
15+
```

python-pydantic/pydantic_models.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from typing import Self
2+
from datetime import date
3+
from uuid import UUID, uuid4
4+
from enum import Enum
5+
from pydantic import (
6+
BaseModel,
7+
EmailStr,
8+
Field,
9+
field_validator,
10+
model_validator,
11+
)
12+
13+
14+
class Department(Enum):
15+
HR = "HR"
16+
SALES = "SALES"
17+
IT = "IT"
18+
ENGINEERING = "ENGINEERING"
19+
20+
21+
class Employee(BaseModel):
22+
employee_id: UUID = Field(default_factory=lambda: uuid4(), frozen=True)
23+
name: str = Field(min_length=1, frozen=True)
24+
email: EmailStr = Field(pattern=r".+@example\.com$")
25+
date_of_birth: date = Field(alias="birth_date", repr=False, frozen=True)
26+
salary: float = Field(alias="compensation", gt=0, repr=False)
27+
department: Department
28+
elected_benefits: bool
29+
30+
@field_validator("date_of_birth")
31+
@classmethod
32+
def check_valid_age(cls, date_of_birth: date) -> date:
33+
date_delta = date.today() - date_of_birth
34+
age = date_delta.days / 365
35+
36+
if age < 18:
37+
raise ValueError("Employees must be at least 18 years old.")
38+
39+
return date_of_birth
40+
41+
@model_validator(mode="after")
42+
def check_it_benefits(self) -> Self:
43+
department = self.department
44+
elected_benefits = self.elected_benefits
45+
46+
if department == Department.IT and elected_benefits:
47+
raise ValueError(
48+
"IT employees are contractors and don't qualify for benefits."
49+
)
50+
return self
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from pydantic import HttpUrl, Field
2+
from pydantic_settings import BaseSettings, SettingsConfigDict
3+
4+
5+
class AppConfig(BaseSettings):
6+
model_config = SettingsConfigDict(
7+
env_file=".env",
8+
env_file_encoding="utf-8",
9+
case_sensitive=True,
10+
extra="forbid",
11+
)
12+
13+
database_host: HttpUrl
14+
database_user: str = Field(min_length=5)
15+
database_password: str = Field(min_length=10)
16+
api_key: str = Field(min_length=20)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import time
2+
from typing import Annotated
3+
from pydantic import PositiveFloat, validate_call, Field, EmailStr
4+
5+
6+
@validate_call
7+
def send_invoice(
8+
client_name: Annotated[str, Field(min_length=1)],
9+
client_email: EmailStr,
10+
items_purchased: list[str],
11+
amount_owed: PositiveFloat,
12+
) -> str:
13+
email_str = f"""
14+
Dear {client_name}, \n
15+
Thank you for choosing xyz inc! You
16+
owe ${amount_owed:,.2f} for the following items: \n
17+
{items_purchased}
18+
"""
19+
20+
print(f"Sending email to {client_email}...")
21+
time.sleep(2)
22+
23+
return email_str

0 commit comments

Comments
 (0)