From 9376bb5411af48444166573ace4b364026251967 Mon Sep 17 00:00:00 2001 From: PrettyWood Date: Tue, 12 Jan 2021 18:48:19 +0100 Subject: [PATCH] feat: pass down config to created models --- docs/examples/annotated_types_typed_dict.py | 16 +++++++++++++++- pydantic/validators.py | 6 +++--- tests/test_annotated_types.py | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/examples/annotated_types_typed_dict.py b/docs/examples/annotated_types_typed_dict.py index 1ae1c6cdb94..382ba65f369 100644 --- a/docs/examples/annotated_types_typed_dict.py +++ b/docs/examples/annotated_types_typed_dict.py @@ -1,6 +1,6 @@ from typing import TypedDict -from pydantic import BaseModel, ValidationError +from pydantic import BaseModel, Extra, ValidationError # `total=False` means keys are non-required @@ -17,6 +17,9 @@ class User(TypedDict): class Model(BaseModel): u: User + class Config: + extra = Extra.forbid + print(Model(u={'identity': {'name': 'Smith', 'surname': 'John'}, 'age': '37'})) @@ -29,3 +32,14 @@ class Model(BaseModel): Model(u={'identity': {'name': ['Smith'], 'surname': 'John'}, 'age': '24'}) except ValidationError as e: print(e) + +try: + Model( + u={ + 'identity': {'name': 'Smith', 'surname': 'John'}, + 'age': '37', + 'email': 'john.smith@me.com', + } + ) +except ValidationError as e: + print(e) diff --git a/pydantic/validators.py b/pydantic/validators.py index a8303f84010..6bfc2058093 100644 --- a/pydantic/validators.py +++ b/pydantic/validators.py @@ -568,7 +568,7 @@ def named_tuple_validator(values: Tuple[Any, ...]) -> NamedTupleT: return named_tuple_validator -def make_typed_dict_validator(type_: Type['TypedDict']) -> Callable[[Any], Dict[str, Any]]: +def make_typed_dict_validator(type_: Type['TypedDict'], config: Type['BaseConfig']) -> Callable[[Any], Dict[str, Any]]: from .main import create_model field_definitions: Dict[str, Any] @@ -593,7 +593,7 @@ def make_typed_dict_validator(type_: Type['TypedDict']) -> Callable[[Any], Dict[ field_name: (field_type, default_value) for field_name, field_type in type_.__annotations__.items() } - TypedDictModel: Type['BaseModel'] = create_model('TypedDictModel', **field_definitions) + TypedDictModel: Type['BaseModel'] = create_model('TypedDictModel', __config__=config, **field_definitions) def typed_dict_validator(values: 'TypedDict') -> Dict[str, Any]: return TypedDictModel(**values).dict(exclude_unset=True) @@ -696,7 +696,7 @@ def find_validators( # noqa: C901 (ignore complexity) yield make_named_tuple_validator(type_) return if is_typed_dict_type(type_): - yield make_typed_dict_validator(type_) + yield make_typed_dict_validator(type_, config) return class_ = get_class(type_) diff --git a/tests/test_annotated_types.py b/tests/test_annotated_types.py index a84e4efb522..e3b74155dee 100644 --- a/tests/test_annotated_types.py +++ b/tests/test_annotated_types.py @@ -154,3 +154,21 @@ class Model(BaseModel): 'type': 'value_error.missing', } ] + + +def test_typed_dict_extra(): + class User(TypedDict): + name: str + age: int + + class Model(BaseModel): + u: User + + class Config: + extra = 'forbid' + + with pytest.raises(ValidationError) as exc_info: + Model(u={'name': 'pika', 'age': 7, 'rank': 1}) + assert exc_info.value.errors() == [ + {'loc': ('u', 'rank'), 'msg': 'extra fields not permitted', 'type': 'value_error.extra'}, + ]