Skip to content

Commit

Permalink
Merge pull request #509 from hfhoffman1144/python-pydantic
Browse files Browse the repository at this point in the history
Materials for Pydantic: Simplifying Data Validation in Python
  • Loading branch information
brendaweles authored Mar 24, 2024
2 parents 3f9c3ca + e1aab39 commit 11b2f7c
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
15 changes: 15 additions & 0 deletions python-pydantic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Pydantic: Simplifying Data Validation in Python

Supporting code for the Real Python tutorial [Pydantic: Simplifying Data Validation in Python](https://realpython.com/pydantic-simplifying-data-validation-in-python/).

To run the code in this tutorial, install Pydantic with its `email` dependency:

```console
(venv) $ python -m pip install "pydantic[email]"
```

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:

```console
(venv) $ python -m pip install pydantic-settings
```
50 changes: 50 additions & 0 deletions python-pydantic/pydantic_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from typing import Self
from datetime import date
from uuid import UUID, uuid4
from enum import Enum
from pydantic import (
BaseModel,
EmailStr,
Field,
field_validator,
model_validator,
)


class Department(Enum):
HR = "HR"
SALES = "SALES"
IT = "IT"
ENGINEERING = "ENGINEERING"


class Employee(BaseModel):
employee_id: UUID = Field(default_factory=lambda: uuid4(), frozen=True)
name: str = Field(min_length=1, frozen=True)
email: EmailStr = Field(pattern=r".+@example\.com$")
date_of_birth: date = Field(alias="birth_date", repr=False, frozen=True)
salary: float = Field(alias="compensation", gt=0, repr=False)
department: Department
elected_benefits: bool

@field_validator("date_of_birth")
@classmethod
def check_valid_age(cls, date_of_birth: date) -> date:
date_delta = date.today() - date_of_birth
age = date_delta.days / 365

if age < 18:
raise ValueError("Employees must be at least 18 years old.")

return date_of_birth

@model_validator(mode="after")
def check_it_benefits(self) -> Self:
department = self.department
elected_benefits = self.elected_benefits

if department == Department.IT and elected_benefits:
raise ValueError(
"IT employees are contractors and don't qualify for benefits."
)
return self
16 changes: 16 additions & 0 deletions python-pydantic/settings_management.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pydantic import HttpUrl, Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class AppConfig(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=True,
extra="forbid",
)

database_host: HttpUrl
database_user: str = Field(min_length=5)
database_password: str = Field(min_length=10)
api_key: str = Field(min_length=20)
23 changes: 23 additions & 0 deletions python-pydantic/validate_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import time
from typing import Annotated
from pydantic import PositiveFloat, validate_call, Field, EmailStr


@validate_call
def send_invoice(
client_name: Annotated[str, Field(min_length=1)],
client_email: EmailStr,
items_purchased: list[str],
amount_owed: PositiveFloat,
) -> str:
email_str = f"""
Dear {client_name}, \n
Thank you for choosing xyz inc! You
owe ${amount_owed:,.2f} for the following items: \n
{items_purchased}
"""

print(f"Sending email to {client_email}...")
time.sleep(2)

return email_str

0 comments on commit 11b2f7c

Please sign in to comment.