### Setup Development Environment and Run Tests Source: https://docs.pydantic.dev/1.10/contributing Follow these steps to clone the repository, set up a virtual environment, install dependencies, and run tests and linting. Ensure you have Python 3.7-3.11, virtualenv, git, pdm, and make installed. ```bash # 1. clone your fork and cd into the repo directory git clone git@github.com:/pydantic.git cd pydantic # 2. Set up a virtualenv for running tests virtualenv -p `which python3.8` env source env/bin/activate # Building docs requires 3.8. If you don't need to build docs you can use # whichever version; 3.7 will work too. # 3. Install pydantic, dependencies, test dependencies and doc dependencies make install # 4. Checkout a new branch and make your changes git checkout -b my-new-feature-branch # make your changes... # 5. Fix formatting and imports make format # Pydantic uses black to enforce formatting and isort to fix imports # (https://github.com/ambv/black, https://github.com/timothycrosley/isort) # 6. Run tests and linting make # there are a few sub-commands in Makefile like `test`, `testcov` and `lint` # which you might want to use, but generally just `make` should be all you need # 7. Build documentation make docs # if you have changed the documentation make sure it builds successfully # you can also use `make docs-serve` to serve the documentation at localhost:8000 # ... commit, push, and create your pull request ``` -------------------------------- ### Install Pydantic from repository Source: https://docs.pydantic.dev/1.10/install Install directly from the GitHub repository, optionally including extras. ```shell pip install git+https://github.com/pydantic/pydantic@1.10.X-fixes#egg=pydantic # or with extras pip install git+https://github.com/pydantic/pydantic@1.10.X-fixes#egg=pydantic[email,dotenv] ``` -------------------------------- ### Install Pydantic via pip or conda Source: https://docs.pydantic.dev/1.10/install Standard installation commands for Pydantic 1.x. ```shell pip install 'pydantic<2' ``` ```shell conda install 'pydantic<2' -c conda-forge ``` -------------------------------- ### Install Pydantic with optional dependencies Source: https://docs.pydantic.dev/1.10/install Install Pydantic along with email validation or dotenv support. ```shell pip install 'pydantic[email]<2' # or pip install 'pydantic[dotenv]<2' # or just pip install 'pydantic[email,dotenv]<2' ``` -------------------------------- ### Define .env file content Source: https://docs.pydantic.dev/1.10/usage/settings Example content for a .env file used to populate environment variables. ```text ENVIRONMENT="production" REDIS_ADDRESS=localhost:6379 MEANING_OF_LIFE=42 MY_VAR='Hello world' ``` -------------------------------- ### Install datamodel-code-generator Source: https://docs.pydantic.dev/1.10/datamodel_code_generator Install the datamodel-code-generator package using pip. This command is used to set up the tool for code generation. ```bash pip install datamodel-code-generator ``` -------------------------------- ### Customize Settings Sources Priority (Python 3.9+) Source: https://docs.pydantic.dev/1.10/usage/settings This example demonstrates customizing settings source priority using Python 3.9+ type hinting for the return value of `customise_sources`. ```python from pydantic import BaseSettings, PostgresDsn from pydantic.env_settings import SettingsSourceCallable class Settings(BaseSettings): database_dsn: PostgresDsn class Config: @classmethod def customise_sources( cls, init_settings: SettingsSourceCallable, env_settings: SettingsSourceCallable, file_secret_settings: SettingsSourceCallable, ) -> tuple[SettingsSourceCallable, ...]: return env_settings, init_settings, file_secret_settings print(Settings(database_dsn='postgres://postgres@localhost:5432/kwargs_db')) #> database_dsn=PostgresDsn('postgres://postgres@localhost:5432/env_db', ) ``` -------------------------------- ### Add Examples to JSON Schema via Config Source: https://docs.pydantic.dev/1.10/usage/schema Use the schema_extra attribute within the Config class to inject custom fields like examples into the generated schema. ```python from pydantic import BaseModel class Person(BaseModel): name: str age: int class Config: schema_extra = { 'examples': [ { 'name': 'John Doe', 'age': 25, } ] } print(Person.schema_json(indent=2)) ``` -------------------------------- ### Install Pydantic without binaries Source: https://docs.pydantic.dev/1.10/install Commands to install Pydantic without pre-compiled binaries, useful for reducing environment size or custom builds. ```shell SKIP_CYTHON=1 pip install --no-binary pydantic pydantic<2 ``` ```shell CFLAGS="-Os -g0 -s" pip install \ --no-binary pydantic \ --global-option=build_ext \ pydantic<2 ``` -------------------------------- ### Get Pydantic Version Info Source: https://docs.pydantic.dev/1.10/contributing Include the output of this command in issues to help diagnose problems. Ensure you have pydantic installed. ```python python -c "import pydantic.utils; print(pydantic.utils.version_info())" ``` -------------------------------- ### Install Pydantic V2 Alpha Source: https://docs.pydantic.dev/1.10/blog/pydantic-v2-alpha Install the Pydantic V2 alpha release using pip. It is recommended to use a virtual environment for isolation. ```bash pip install --pre -U "pydantic>=2.0a1" ``` -------------------------------- ### Customize Settings Sources Priority (Python 3.7+) Source: https://docs.pydantic.dev/1.10/usage/settings Override `customise_sources` to change the order of settings input sources. This example prioritizes environment variables over initializer arguments. ```python from typing import Tuple from pydantic import BaseSettings, PostgresDsn from pydantic.env_settings import SettingsSourceCallable class Settings(BaseSettings): database_dsn: PostgresDsn class Config: @classmethod def customise_sources( cls, init_settings: SettingsSourceCallable, env_settings: SettingsSourceCallable, file_secret_settings: SettingsSourceCallable, ) -> Tuple[SettingsSourceCallable, ...]: return env_settings, init_settings, file_secret_settings print(Settings(database_dsn='postgres://postgres@localhost:5432/kwargs_db')) #> database_dsn=PostgresDsn('postgres://postgres@localhost:5432/env_db', ) ``` -------------------------------- ### Basic HttpUrl Validation Example Source: https://docs.pydantic.dev/1.10/usage/types Demonstrates how to use `HttpUrl` for basic URL validation in a Pydantic model. ```APIDOC ## Basic HttpUrl Validation Example ### Method N/A (This is a Pydantic model definition and usage example) ### Endpoint N/A ### Parameters N/A ### Request Body N/A ### Request Example ```python from pydantic import BaseModel, HttpUrl, ValidationError class MyModel(BaseModel): url: HttpUrl m = MyModel(url='http://www.example.com') print(m.url) ``` ### Response #### Success Response (200) - `url` (HttpUrl): The validated URL. #### Response Example ``` http://www.example.com ``` ### Error Handling Example ```python try: MyModel(url='ftp://invalid.url') except ValidationError as e: print(e) """ 1 validation error for MyModel url URL scheme not permitted (type=value_error.url.scheme; allowed_schemes={'http', 'https'}) """ try: MyModel(url='not a url') except ValidationError as e: print(e) """ 1 validation error for MyModel url invalid or missing URL scheme (type=value_error.url.scheme) """ ``` ``` -------------------------------- ### Customize schema with __modify_schema__ Source: https://docs.pydantic.dev/1.10/usage/schema Demonstrates implementing __modify_schema__ to inject custom examples into the field schema based on field metadata. ```python from typing import Any, Callable, Dict, Generator, Optional from pydantic import BaseModel, Field from pydantic.fields import ModelField class RestrictedAlphabetStr(str): @classmethod def __get_validators__(cls) -> Generator[Callable, None, None]: yield cls.validate @classmethod def validate(cls, value: str, field: ModelField): alphabet = field.field_info.extra['alphabet'] if any(c not in alphabet for c in value): raise ValueError(f'{value!r} is not restricted to {alphabet!r}') return cls(value) @classmethod def __modify_schema__( cls, field_schema: Dict[str, Any], field: Optional[ModelField] ): if field: alphabet = field.field_info.extra['alphabet'] field_schema['examples'] = [c * 3 for c in alphabet] class MyModel(BaseModel): value: RestrictedAlphabetStr = Field(alphabet='ABC') print(MyModel.schema_json(indent=2)) ``` ```python from typing import Any, Callable, Optional from collections.abc import Generator from pydantic import BaseModel, Field from pydantic.fields import ModelField class RestrictedAlphabetStr(str): @classmethod def __get_validators__(cls) -> Generator[Callable, None, None]: yield cls.validate @classmethod def validate(cls, value: str, field: ModelField): alphabet = field.field_info.extra['alphabet'] if any(c not in alphabet for c in value): raise ValueError(f'{value!r} is not restricted to {alphabet!r}') return cls(value) @classmethod def __modify_schema__( cls, field_schema: dict[str, Any], field: Optional[ModelField] ): if field: alphabet = field.field_info.extra['alphabet'] field_schema['examples'] = [c * 3 for c in alphabet] class MyModel(BaseModel): value: RestrictedAlphabetStr = Field(alphabet='ABC') print(MyModel.schema_json(indent=2)) ``` ```python from typing import Any from collections.abc import Callable, Generator from pydantic import BaseModel, Field from pydantic.fields import ModelField class RestrictedAlphabetStr(str): @classmethod def __get_validators__(cls) -> Generator[Callable, None, None]: yield cls.validate @classmethod def validate(cls, value: str, field: ModelField): alphabet = field.field_info.extra['alphabet'] if any(c not in alphabet for c in value): raise ValueError(f'{value!r} is not restricted to {alphabet!r}') return cls(value) @classmethod def __modify_schema__( cls, field_schema: dict[str, Any], field: ModelField | None ): if field: alphabet = field.field_info.extra['alphabet'] field_schema['examples'] = [c * 3 for c in alphabet] class MyModel(BaseModel): value: RestrictedAlphabetStr = Field(alphabet='ABC') print(MyModel.schema_json(indent=2)) ``` -------------------------------- ### Constrained Types Example Source: https://docs.pydantic.dev/1.10/usage/types Demonstrates the usage of various constrained types in Pydantic models. ```APIDOC ## Constrained Types The value of numerous common types can be restricted using `con*` type functions: Python 3.7 and above ```python from decimal import Decimal from pydantic import ( BaseModel, NegativeFloat, NegativeInt, PositiveFloat, PositiveInt, NonNegativeFloat, NonNegativeInt, NonPositiveFloat, NonPositiveInt, conbytes, condecimal, confloat, conint, conlist, conset, constr, Field, ) class Model(BaseModel): upper_bytes: conbytes(to_upper=True) lower_bytes: conbytes(to_lower=True) short_bytes: conbytes(min_length=2, max_length=10) strip_bytes: conbytes(strip_whitespace=True) upper_str: constr(to_upper=True) lower_str: constr(to_lower=True) short_str: constr(min_length=2, max_length=10) regex_str: constr(regex=r'^apple (pie|tart|sandwich)$') strip_str: constr(strip_whitespace=True) big_int: conint(gt=1000, lt=1024) mod_int: conint(multiple_of=5) pos_int: PositiveInt neg_int: NegativeInt non_neg_int: NonNegativeInt non_pos_int: NonPositiveInt big_float: confloat(gt=1000, lt=1024) unit_interval: confloat(ge=0, le=1) mod_float: confloat(multiple_of=0.5) pos_float: PositiveFloat neg_float: NegativeFloat non_neg_float: NonNegativeFloat non_pos_float: NonPositiveFloat short_list: conlist(int, min_items=1, max_items=4) short_set: conset(int, min_items=1, max_items=4) decimal_positive: condecimal(gt=0) decimal_negative: condecimal(lt=0) decimal_max_digits_and_places: condecimal(max_digits=2, decimal_places=2) mod_decimal: condecimal(multiple_of=Decimal('0.25')) bigger_int: int = Field(..., gt=10000) ``` _(This script is complete, it should run "as is")_ Where `Field` refers to the field function. ``` -------------------------------- ### Create a Generic HTTP Response Wrapper Source: https://docs.pydantic.dev/1.10/usage/models Demonstrates using GenericModel to create a reusable response wrapper that handles data or error states. The examples show variations for different Python versions. ```python from typing import Generic, TypeVar, Optional, List from pydantic import BaseModel, validator, ValidationError from pydantic.generics import GenericModel DataT = TypeVar('DataT') class Error(BaseModel): code: int message: str class DataModel(BaseModel): numbers: List[int] people: List[str] class Response(GenericModel, Generic[DataT]): data: Optional[DataT] error: Optional[Error] @validator('error', always=True) def check_consistency(cls, v, values): if v is not None and values['data'] is not None: raise ValueError('must not provide both data and error') if v is None and values.get('data') is None: raise ValueError('must provide data or error') return v data = DataModel(numbers=[1, 2, 3], people=[]) error = Error(code=404, message='Not found') print(Response[int](data=1)) #> data=1 error=None print(Response[str](data='value')) #> data='value' error=None print(Response[str](data='value').dict()) #> {'data': 'value', 'error': None} print(Response[DataModel](data=data).dict()) """ { 'data': {'numbers': [1, 2, 3], 'people': []}, 'error': None, } """ print(Response[DataModel](error=error).dict()) """ { 'data': None, 'error': {'code': 404, 'message': 'Not found'}, } """ try: Response[int](data='value') except ValidationError as e: print(e) """ 2 validation errors for Response[int] data value is not a valid integer (type=type_error.integer) error must provide data or error (type=value_error) """ ``` ```python from typing import Generic, Optional, TypeVar from pydantic import BaseModel, validator, ValidationError from pydantic.generics import GenericModel DataT = TypeVar('DataT') class Error(BaseModel): code: int message: str class DataModel(BaseModel): numbers: list[int] people: list[str] class Response(GenericModel, Generic[DataT]): data: Optional[DataT] error: Optional[Error] @validator('error', always=True) def check_consistency(cls, v, values): if v is not None and values['data'] is not None: raise ValueError('must not provide both data and error') if v is None and values.get('data') is None: raise ValueError('must provide data or error') return v data = DataModel(numbers=[1, 2, 3], people=[]) error = Error(code=404, message='Not found') print(Response[int](data=1)) #> data=1 error=None print(Response[str](data='value')) #> data='value' error=None print(Response[str](data='value').dict()) #> {'data': 'value', 'error': None} print(Response[DataModel](data=data).dict()) """ { 'data': {'numbers': [1, 2, 3], 'people': []}, 'error': None, } """ print(Response[DataModel](error=error).dict()) """ { 'data': None, 'error': {'code': 404, 'message': 'Not found'}, } """ try: Response[int](data='value') except ValidationError as e: print(e) """ 2 validation errors for Response[int] data value is not a valid integer (type=type_error.integer) error must provide data or error (type=value_error) """ ``` ```python from typing import Generic, TypeVar from pydantic import BaseModel, validator, ValidationError from pydantic.generics import GenericModel DataT = TypeVar('DataT') class Error(BaseModel): code: int message: str class DataModel(BaseModel): numbers: list[int] people: list[str] class Response(GenericModel, Generic[DataT]): data: DataT | None error: Error | None @validator('error', always=True) def check_consistency(cls, v, values): if v is not None and values['data'] is not None: raise ValueError('must not provide both data and error') if v is None and values.get('data') is None: raise ValueError('must provide data or error') return v data = DataModel(numbers=[1, 2, 3], people=[]) error = Error(code=404, message='Not found') print(Response[int](data=1)) #> data=1 error=None print(Response[str](data='value')) #> data='value' error=None print(Response[str](data='value').dict()) #> {'data': 'value', 'error': None} print(Response[DataModel](data=data).dict()) """ { 'data': {'numbers': [1, 2, 3], 'people': []}, 'error': None, } """ ``` -------------------------------- ### Define Pydantic models for type checking Source: https://docs.pydantic.dev/1.10/mypy_plugin Example models demonstrating field definitions and initialization, provided for different Python versions. ```python from datetime import datetime from typing import List, Optional from pydantic import BaseModel, NoneStr class Model(BaseModel): age: int first_name = 'John' last_name: NoneStr = None signup_ts: Optional[datetime] = None list_of_ints: List[int] m = Model(age=42, list_of_ints=[1, '2', b'3']) print(m.middle_name) # not a model field! Model() # will raise a validation error for age and list_of_ints ``` ```python from datetime import datetime from typing import Optional from pydantic import BaseModel, NoneStr class Model(BaseModel): age: int first_name = 'John' last_name: NoneStr = None signup_ts: Optional[datetime] = None list_of_ints: list[int] m = Model(age=42, list_of_ints=[1, '2', b'3']) print(m.middle_name) # not a model field! Model() # will raise a validation error for age and list_of_ints ``` ```python from datetime import datetime from pydantic import BaseModel, NoneStr class Model(BaseModel): age: int first_name = 'John' last_name: NoneStr = None signup_ts: datetime | None = None list_of_ints: list[int] m = Model(age=42, list_of_ints=[1, '2', b'3']) print(m.middle_name) # not a model field! Model() # will raise a validation error for age and list_of_ints ``` -------------------------------- ### Use stdlib dataclasses with BaseModel (Python 3.10+) Source: https://docs.pydantic.dev/1.10/usage/dataclasses This example demonstrates the use of Python 3.10+ type hinting syntax (`|`) with Pydantic and dataclasses. The behavior regarding automatic conversion and validation remains consistent with earlier Python versions. ```python import dataclasses from datetime import datetime from pydantic import BaseModel, ValidationError @dataclasses.dataclass(frozen=True) class User: name: str @dataclasses.dataclass class File: filename: str last_modification_time: datetime | None = None class Foo(BaseModel): file: File user: User | None = None file = File( filename=['not', 'a', 'string'], last_modification_time='2020-01-01T00:00', ) # nothing is validated as expected print(file) #> File(filename=['not', #> last_modification_time='2020-01-01T00:00') try: Foo(file=file) except ValidationError as e: print(e) """ 1 validation error for Foo file -> filename str type expected (type=type_error.str) """ foo = Foo(file=File(filename='myfile'), user=User(name='pika')) try: foo.user.name = 'bulbi' except dataclasses.FrozenInstanceError as e: print(e) #> cannot assign to field 'name' ``` -------------------------------- ### InitVar with Post-Initialization Hooks Source: https://docs.pydantic.dev/1.10/usage/dataclasses Fields annotated with `dataclasses.InitVar` are passed to both `__post_init__` and `__post_init_post_parse__` in Pydantic dataclasses. This example shows how `base_path` is used in both methods. ```python from dataclasses import InitVar from pathlib import Path from typing import Optional from pydantic.dataclasses import dataclass @dataclass class PathData: path: Path base_path: InitVar[Optional[Path]] def __post_init__(self, base_path): print(f'Received path={self.path!r}, base_path={base_path!r}') #> Received path='world', base_path='/hello' def __post_init_post_parse__(self, base_path): if base_path is not None: self.path = base_path / self.path path_data = PathData('world', base_path='/hello') # Received path='world', base_path='/hello' assert path_data.path == Path('/hello/world') ``` ```python from dataclasses import InitVar from pathlib import Path from pydantic.dataclasses import dataclass @dataclass class PathData: path: Path base_path: InitVar[Path | None] def __post_init__(self, base_path): print(f'Received path={self.path!r}, base_path={base_path!r}') #> Received path='world', base_path='/hello' def __post_init_post_parse__(self, base_path): if base_path is not None: self.path = base_path / self.path path_data = PathData('world', base_path='/hello') # Received path='world', base_path='/hello' assert path_data.path == Path('/hello/world') ``` -------------------------------- ### Nested Dataclasses with Pydantic Source: https://docs.pydantic.dev/1.10/usage/dataclasses Shows how to define and use nested dataclasses with Pydantic, including type hints for URLs. The example demonstrates instantiation and printing of a nested structure. ```python from pydantic import AnyUrl from pydantic.dataclasses import dataclass @dataclass class NavbarButton: href: AnyUrl @dataclass class Navbar: button: NavbarButton navbar = Navbar(button=('https://example.com',)) print(navbar) #> Navbar(button=NavbarButton(href=AnyUrl('https://example.com', scheme='https', #> host='example.com', tld='com', host_type='domain'))) ``` -------------------------------- ### Define and Validate Data Models Source: https://docs.pydantic.dev/1.10 Demonstrates defining a Pydantic model and validating external data. The examples show syntax variations for different Python versions. ```python from datetime import datetime from typing import List, Optional from pydantic import BaseModel class User(BaseModel): id: int name = 'John Doe' signup_ts: Optional[datetime] = None friends: List[int] = [] external_data = { 'id': '123', 'signup_ts': '2019-06-01 12:22', 'friends': [1, 2, '3'], } user = User(**external_data) print(user.id) #> 123 print(repr(user.signup_ts)) #> datetime.datetime(2019, 6, 1, 12, 22) print(user.friends) #> [1, 2, 3] print(user.dict()) """ { 'id': 123, 'signup_ts': datetime.datetime(2019, 6, 1, 12, 22), 'friends': [1, 2, 3], 'name': 'John Doe', } """ ``` ```python from datetime import datetime from typing import Optional from pydantic import BaseModel class User(BaseModel): id: int name = 'John Doe' signup_ts: Optional[datetime] = None friends: list[int] = [] external_data = { 'id': '123', 'signup_ts': '2019-06-01 12:22', 'friends': [1, 2, '3'], } user = User(**external_data) print(user.id) #> 123 print(repr(user.signup_ts)) #> datetime.datetime(2019, 6, 1, 12, 22) print(user.friends) #> [1, 2, 3] print(user.dict()) """ { 'id': 123, 'signup_ts': datetime.datetime(2019, 6, 1, 12, 22), 'friends': [1, 2, 3], 'name': 'John Doe', } """ ``` ```python from datetime import datetime from pydantic import BaseModel class User(BaseModel): id: int name = 'John Doe' signup_ts: datetime | None = None friends: list[int] = [] external_data = { 'id': '123', 'signup_ts': '2019-06-01 12:22', 'friends': [1, 2, '3'], } user = User(**external_data) print(user.id) #> 123 print(repr(user.signup_ts)) #> datetime.datetime(2019, 6, 1, 12, 22) print(user.friends) #> [1, 2, 3] print(user.dict()) """ { 'id': 123, 'signup_ts': datetime.datetime(2019, 6, 1, 12, 22), 'friends': [1, 2, 3], 'name': 'John Doe', } """ ``` -------------------------------- ### Define and use BaseSettings for configuration Source: https://docs.pydantic.dev/1.10/usage/settings Demonstrates defining a configuration model with environment variable mapping and complex types, compatible with Python 3.7+ and 3.9+ syntax. ```python from typing import Set from pydantic import ( BaseModel, BaseSettings, PyObject, RedisDsn, PostgresDsn, AmqpDsn, Field, ) class SubModel(BaseModel): foo = 'bar' apple = 1 class Settings(BaseSettings): auth_key: str api_key: str = Field(..., env='my_api_key') redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1' pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar' amqp_dsn: AmqpDsn = 'amqp://user:pass@localhost:5672/' special_function: PyObject = 'math.cos' # to override domains: # export my_prefix_domains='["foo.com", "bar.com"]' domains: Set[str] = set() # to override more_settings: # export my_prefix_more_settings='{"foo": "x", "apple": 1}' more_settings: SubModel = SubModel() class Config: env_prefix = 'my_prefix_' # defaults to no prefix, i.e. "" fields = { 'auth_key': { 'env': 'my_auth_key', }, 'redis_dsn': { 'env': ['service_redis_dsn', 'redis_url'] } } print(Settings().dict()) """ { 'auth_key': 'xxx', 'api_key': 'xxx', 'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1', ), 'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar', ), 'amqp_dsn': AmqpDsn('amqp://user:pass@localhost:5672/', scheme='amqp', user='user', password='pass', host='localhost', host_type='int_domain', port='5672', path='/'), 'special_function': , 'domains': set(), 'more_settings': {'foo': 'bar', 'apple': 1}, } """ ``` ```python from pydantic import ( BaseModel, BaseSettings, PyObject, RedisDsn, PostgresDsn, AmqpDsn, Field, ) class SubModel(BaseModel): foo = 'bar' apple = 1 class Settings(BaseSettings): auth_key: str api_key: str = Field(..., env='my_api_key') redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1' pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar' amqp_dsn: AmqpDsn = 'amqp://user:pass@localhost:5672/' special_function: PyObject = 'math.cos' # to override domains: # export my_prefix_domains='["foo.com", "bar.com"]' domains: set[str] = set() # to override more_settings: # export my_prefix_more_settings='{"foo": "x", "apple": 1}' more_settings: SubModel = SubModel() class Config: env_prefix = 'my_prefix_' # defaults to no prefix, i.e. "" fields = { 'auth_key': { 'env': 'my_auth_key', }, 'redis_dsn': { 'env': ['service_redis_dsn', 'redis_url'] } } print(Settings().dict()) """ { 'auth_key': 'xxx', 'api_key': 'xxx', 'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1', ), 'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar', ), 'amqp_dsn': AmqpDsn('amqp://user:pass@localhost:5672/', scheme='amqp', user='user', password='pass', host='localhost', host_type='int_domain', port='5672', path='/'), 'special_function': , 'domains': set(), 'more_settings': {'foo': 'bar', 'apple': 1}, } """ ``` -------------------------------- ### Enable Pydantic MyPy Plugin in mypy.ini Source: https://docs.pydantic.dev/1.10/mypy_plugin Add 'pydantic.mypy' to the plugins list in your mypy.ini file to enable the plugin. This is the basic setup required to start using the plugin. ```ini [mypy] plugins = pydantic.mypy ``` -------------------------------- ### Basic GenericModel Usage Source: https://docs.pydantic.dev/1.10/usage/models Demonstrates creating a generic response model and instantiating it with specific data types. Shows how to handle both successful responses and validation errors. ```python from typing import TypeVar, Generic from pydantic import BaseModel, ValidationError TypeX = TypeVar('TypeX') class Response(BaseModel, Generic[TypeX]): data: TypeX | None = None error: dict | None = None # Example usage with data print(Response[dict](data={'key': 'value'}).dict()) # Example usage with error print(Response[dict](error={'code': 404, 'message': 'Not found'}).dict()) # Example of validation error try: Response[int](data='value') except ValidationError as e: print(e) ``` -------------------------------- ### Create dynamic models with create_model Source: https://docs.pydantic.dev/1.10/usage/models Demonstrates creating a model dynamically that is equivalent to a statically defined BaseModel. ```python from pydantic import BaseModel, create_model DynamicFoobarModel = create_model('DynamicFoobarModel', foo=(str, ...), bar=123) class StaticFoobarModel(BaseModel): foo: str bar: int = 123 ``` -------------------------------- ### Instantiating models with construct() Source: https://docs.pydantic.dev/1.10/usage/models Demonstrates creating a model instance using construct() to skip validation, including the optional use of _fields_set to track initialized fields. ```python from pydantic import BaseModel class User(BaseModel): id: int age: int name: str = 'John Doe' original_user = User(id=123, age=32) user_data = original_user.dict() print(user_data) #> {'id': 123, 'age': 32, 'name': 'John Doe'} fields_set = original_user.__fields_set__ print(fields_set) #> {'id', 'age'} # ... # pass user_data and fields_set to RPC or save to the database etc. # ... # you can then create a new instance of User without # re-running validation which would be unnecessary at this point: new_user = User.construct(_fields_set=fields_set, **user_data) print(repr(new_user)) #> User(id=123, age=32, name='John Doe') print(new_user.__fields_set__) #> {'id', 'age'} # construct can be dangerous, only use it with validated data!: bad_user = User.construct(id='dog') print(repr(bad_user)) #> User(id='dog', name='John Doe') ``` -------------------------------- ### Load multiple .env files Source: https://docs.pydantic.dev/1.10/usage/settings Provide a list or tuple of files to the env_file configuration, where later files take precedence. ```python from pydantic import BaseSettings class Settings(BaseSettings): ... class Config: # `.env.prod` takes priority over `.env` env_file = '.env', '.env.prod' ``` -------------------------------- ### Pydantic Dataclass Validation Example Source: https://docs.pydantic.dev/1.10/usage/dataclasses This example shows how a Pydantic dataclass validates input data. It demonstrates successful validation and how `ValidationError` is raised for incorrect types. ```python import pydantic @pydantic.dataclasses.dataclass class ValidatedFile: filename: str modified_date: datetime.datetime seen_count: int validated_file = ValidatedFile( filename=b'thefilename', modified_date='2020-01-01T00:00', seen_count='7', ) print(validated_file) ``` ```python try: ValidatedFile( filename=['not', 'a', 'string'], modified_date=None, seen_count=3, ) except pydantic.ValidationError as e: print(e) ``` ```python # `File` is not altered and still does no validation by default print(File( filename=['not', 'a', 'string'], modified_date=None, seen_count=3, )) ``` -------------------------------- ### Use Color data type Source: https://docs.pydantic.dev/1.10/usage/types Demonstrates initializing Color objects from various formats and using them within a Pydantic model. ```python from pydantic import BaseModel, ValidationError from pydantic.color import Color c = Color('ff00ff') print(c.as_named()) #> magenta print(c.as_hex()) #> #f0f c2 = Color('green') print(c2.as_rgb_tuple()) #> (0, 128, 0) print(c2.original()) #> green print(repr(Color('hsl(180, 100%, 50%)'))) #> Color('cyan', rgb=(0, 255, 255)) class Model(BaseModel): color: Color print(Model(color='purple')) #> color=Color('purple', rgb=(128, 0, 128)) try: Model(color='hello') except ValidationError as e: print(e) """ 1 validation error for Model color value is not a valid color: string not recognised as a valid color (type=value_error.color; reason=string not recognised as a valid color) """ ``` -------------------------------- ### Initialize Pydantic Models from ORM Objects Source: https://docs.pydantic.dev/1.10/usage/models Shows how to enable orm_mode in a Pydantic model and use from_orm to instantiate it from an arbitrary class instance. ```python from typing import List from sqlalchemy import Column, Integer, String from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.ext.declarative import declarative_base from pydantic import BaseModel, constr Base = declarative_base() class CompanyOrm(Base): __tablename__ = 'companies' id = Column(Integer, primary_key=True, nullable=False) public_key = Column(String(20), index=True, nullable=False, unique=True) name = Column(String(63), unique=True) domains = Column(ARRAY(String(255))) class CompanyModel(BaseModel): id: int public_key: constr(max_length=20) name: constr(max_length=63) domains: List[constr(max_length=255)] class Config: orm_mode = True co_orm = CompanyOrm( id=123, public_key='foobar', name='Testing', domains=['example.com', 'foobar.com'], ) print(co_orm) #> co_model = CompanyModel.from_orm(co_orm) print(co_model) #> id=123 public_key='foobar' name='Testing' domains=['example.com', #> 'foobar.com'] ``` ```python from sqlalchemy import Column, Integer, String from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.ext.declarative import declarative_base from pydantic import BaseModel, constr Base = declarative_base() class CompanyOrm(Base): __tablename__ = 'companies' id = Column(Integer, primary_key=True, nullable=False) public_key = Column(String(20), index=True, nullable=False, unique=True) name = Column(String(63), unique=True) domains = Column(ARRAY(String(255))) class CompanyModel(BaseModel): id: int public_key: constr(max_length=20) name: constr(max_length=63) domains: list[constr(max_length=255)] class Config: orm_mode = True co_orm = CompanyOrm( id=123, public_key='foobar', name='Testing', domains=['example.com', 'foobar.com'], ) print(co_orm) #> co_model = CompanyModel.from_orm(co_orm) print(co_model) #> id=123 public_key='foobar' name='Testing' domains=['example.com', #> 'foobar.com'] ``` -------------------------------- ### Alias Precedence Example Source: https://docs.pydantic.dev/1.10/usage/model_config Demonstrates Pydantic's alias precedence rules, showing how aliases defined directly on a model field take priority over those defined in `Config.fields` or generated by `alias_generator`. This example highlights that `alias_generator` on a child model does not override aliases on parent models. ```python from pydantic import BaseModel, Field class Voice(BaseModel): name: str = Field(None, alias='ActorName') language_code: str = None mood: str = None class Character(Voice): act: int = 1 class Config: fields = {'language_code': 'lang'} @classmethod def alias_generator(cls, string: str) -> str: # this is the same as `alias_generator = to_camel` above return ''.join(word.capitalize() for word in string.split('_')) print(Character.schema(by_alias=True)) ``` -------------------------------- ### Initialize Model Instances Source: https://docs.pydantic.dev/1.10/usage/models Instantiate models with input data; Pydantic automatically parses and validates the provided values. ```python user = User(id='123') user_x = User(id='123.45') ``` -------------------------------- ### Validation Error JSON Output Source: https://docs.pydantic.dev/1.10 Example of the JSON structure returned by a ValidationError. ```json [ { "loc": [ "id" ], "msg": "field required", "type": "value_error.missing" }, { "loc": [ "signup_ts" ], "msg": "invalid datetime format", "type": "value_error.datetime" }, { "loc": [ "friends", 2 ], "msg": "value is not a valid integer", "type": "type_error.integer" } ] ``` -------------------------------- ### Verify Cython compilation Source: https://docs.pydantic.dev/1.10/install Check if the installed Pydantic package is using Cython-compiled binaries. ```python import pydantic print('compiled:', pydantic.compiled) ``` -------------------------------- ### Override environment variable with prefix Source: https://docs.pydantic.dev/1.10/usage/settings Example of setting an environment variable using a prefix to override a field value. ```bash export my_prefix_special_function='foo.bar' ``` -------------------------------- ### ValidationError Line Errors Structure Source: https://docs.pydantic.dev/1.10/blog/pydantic-v2 Example of the structured error list returned by Pydantic V2, including documentation links. ```python [ { 'kind': 'greater_than_equal', 'loc': ['age'], 'message': 'Value must be greater than or equal to 18', 'input_value': 11, 'context': {'ge': 18}, 'documentation': 'https://pydantic.dev/errors/#greater_than_equal', }, { 'kind': 'bool_parsing', 'loc': ['is_developer'], 'message': 'Value must be a valid boolean, unable to interpret input', 'input_value': 'foobar', 'documentation': 'https://pydantic.dev/errors/#bool_parsing', }, ] ```