Skip to content

Instantly share code, notes, and snippets.

@samuelcolvin
Last active March 16, 2023 15:29

Revisions

  1. samuelcolvin revised this gist Mar 16, 2023. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions test_broken.py
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,8 @@
    """
    pydantic-core: 01fdec6d2242fdf7205663d566be5ba990d1d459 - the custom-dataclass-validator branch
    and pydantic: 519800fa5167a57681ba3b202503751aa0f17347 - the dataclasses-v2 branch
    """

    from typing import TypeVar

    import pytest
  2. samuelcolvin created this gist Mar 16, 2023.
    145 changes: 145 additions & 0 deletions test_broken.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,145 @@
    from typing import TypeVar

    import pytest

    from pydantic import BaseModel, ValidationError

    try:
    import email_validator
    except ImportError:
    email_validator = None

    T = TypeVar('T')


    def test_generic_recursive_models_triple(create_module):
    @create_module
    def module():
    from typing import Generic, TypeVar, Union

    from pydantic import BaseModel

    T1 = TypeVar('T1')
    T2 = TypeVar('T2')
    T3 = TypeVar('T3')

    class A1(BaseModel, Generic[T1]):
    a1: 'A2[T1]'

    model_config = dict(undefined_types_warning=False)

    class A2(BaseModel, Generic[T2]):
    a2: 'A3[T2]'

    model_config = dict(undefined_types_warning=False)

    class A3(BaseModel, Generic[T3]):
    a3: Union['A1[T3]', T3]

    model_config = dict(undefined_types_warning=False)

    A1.model_rebuild()

    A1 = module.A1

    with pytest.raises(ValidationError) as exc_info:
    A1[str].model_validate({'a1': {'a2': {'a3': 1}}})
    assert exc_info.value.errors() == [
    {
    'input': 1,
    'loc': ('a1', 'a2', 'a3', 'A1[str]'),
    'msg': 'Input should be a valid dictionary',
    'type': 'dict_type',
    },
    {'input': 1, 'loc': ('a1', 'a2', 'a3', 'str'), 'msg': 'Input should be a valid string', 'type': 'string_type'},
    ]

    A1[int].model_validate({'a1': {'a2': {'a3': 1}}})


    def test_generic_recursive_models_complicated(create_module):
    @create_module
    def module():
    from typing import Generic, TypeVar, Union

    from pydantic import BaseModel

    T1 = TypeVar('T1')
    T2 = TypeVar('T2')
    T3 = TypeVar('T3')

    class A1(BaseModel, Generic[T1]):
    a1: T1 # 'A2[T1]'

    model_config = dict(undefined_types_warning=False)

    class A2(BaseModel, Generic[T2]):
    a2: 'A3[T2]'

    model_config = dict(undefined_types_warning=False)

    class A3(BaseModel, Generic[T3]):
    a3: Union[A1[T3], T3]

    model_config = dict(undefined_types_warning=False)

    A1.model_rebuild()

    S1 = TypeVar('S1')
    S2 = TypeVar('S2')

    class B1(BaseModel, Generic[S1]):
    a1: 'B2[S1]'

    model_config = dict(undefined_types_warning=False)

    class B2(BaseModel, Generic[S2]):
    a2: 'B1[S2]'

    model_config = dict(undefined_types_warning=False)

    B1.model_rebuild()

    V1 = TypeVar('V1')
    V2 = TypeVar('V2')
    V3 = TypeVar('V3')

    class M1(BaseModel, Generic[V1, V2]):
    a: int
    b: B1[V2]
    m: 'M2[V1]'

    model_config = dict(undefined_types_warning=False)

    class M2(BaseModel, Generic[V3]):
    m: Union[M1[V3, int], V3]

    model_config = dict(undefined_types_warning=False)

    M1.model_rebuild()

    M1 = module.M1

    assert collect_invalid_schemas(M1.__pydantic_core_schema__) == []


    def test_key():
    class ApplePie(BaseModel):
    """
    This is a test.
    """

    a: float
    b: int = 10

    s = {
    'type': 'object',
    'properties': {'a': {'type': 'number', 'title': 'A'}, 'b': {'type': 'integer', 'title': 'B', 'default': 10}},
    'required': ['a'],
    'title': 'ApplePie',
    'description': 'This is a test.',
    }
    assert ApplePie.__schema_cache__.keys() == set()
    assert ApplePie.model_json_schema() == s
    assert ApplePie.__schema_cache__.keys() == {(True, '#/$defs/{model}')}
    assert ApplePie.model_json_schema() == s