Skip to content

Commit

Permalink
Test: Add test for variadic generic (pydantic#5625)
Browse files Browse the repository at this point in the history
  • Loading branch information
caniko committed May 5, 2023
1 parent 517161d commit 3c4b58f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
1 change: 1 addition & 0 deletions changes/5626-caniko.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test: Variadic generic model definition, object instantiation, and method call
65 changes: 64 additions & 1 deletion tests/test_generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import pytest
from dirty_equals import HasRepr
from pydantic_core import core_schema
from typing_extensions import Annotated, Literal, OrderedDict
from typing_extensions import Annotated, Literal, OrderedDict, TypeVarTuple, Unpack

from pydantic import (
BaseModel,
Expand All @@ -42,6 +42,7 @@
PydanticUserError,
ValidationError,
ValidationInfo,
computed_field,
root_validator,
)
from pydantic._internal._core_utils import collect_invalid_schemas
Expand Down Expand Up @@ -2313,3 +2314,65 @@ class Model(BaseModel, Generic[T]):
'title': 'Model[test_generic_intenum_bound.<locals>.MyEnum]',
'type': 'object',
}


@pytest.mark.skipif(sys.version_info < (3, 11), reason='requires python 3.11 or higher')
@pytest.mark.xfail(reason='TODO: Variadic generic parametrization is not supported yet')
def test_variadic_generic_init():
class ComponentModel(BaseModel):
pass

class Wrench(ComponentModel):
pass

class Screwdriver(ComponentModel):
pass

ComponentVar = TypeVar('ComponentVar', bound=ComponentModel)
NumberOfComponents = TypeVarTuple('NumberOfComponents')

class VariadicToolbox(BaseModel, Generic[ComponentVar, Unpack[NumberOfComponents]]):
main_component: ComponentVar
left_component_pocket: Optional[list[ComponentVar]] = Field(default_factory=list)
right_component_pocket: Optional[list[ComponentVar]] = Field(default_factory=list)

@computed_field
@property
def all_components(self) -> tuple[ComponentVar, Unpack[NumberOfComponents]]:
return (self.main_component, *self.left_component_pocket, *self.right_component_pocket)

sa, sb, w = Screwdriver(), Screwdriver(), Wrench()
my_toolbox = VariadicToolbox[Screwdriver, Screwdriver, Wrench](
main_component=sa, left_component_pocket=[w], right_component_pocket=[sb]
)

assert my_toolbox.all_components == [sa, w, sb]


@pytest.mark.skipif(sys.version_info < (3, 11), reason='requires python 3.11 or higher')
@pytest.mark.xfail(reason='TODO: Variadic fields are not supported yet')
def test_variadic_generic_with_variadic_fields():
class ComponentModel(BaseModel):
pass

class Wrench(ComponentModel):
pass

class Screwdriver(ComponentModel):
pass

ComponentVar = TypeVar('ComponentVar', bound=ComponentModel)
NumberOfComponents = TypeVarTuple('NumberOfComponents')

class VariadicToolbox(BaseModel, Generic[ComponentVar, Unpack[NumberOfComponents]]):
toolbelt_cm_size: Optional[tuple[Unpack[NumberOfComponents]]] = Field(default_factory=tuple)
manual_toolset: Optional[tuple[ComponentVar, Unpack[NumberOfComponents]]] = Field(default_factory=tuple)

MyToolboxClass = VariadicToolbox[Screwdriver, Screwdriver, Wrench]

sa, sb, w = Screwdriver(), Screwdriver(), Wrench()
MyToolboxClass(toolbelt_cm_size=(5, 10.5, 4), manual_toolset=(sa, sb, w))

with pytest.raises(TypeError):
# Should raise error because integer 5 does not meet the bound requirements of ComponentVar
MyToolboxClass(manual_toolset=(sa, sb, 5))

0 comments on commit 3c4b58f

Please sign in to comment.