Skip to content

Recursion errors for self-referencing generic models #1345

@umvarma

Description

@umvarma

Question

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

pydantic version: 1.4
            pydantic compiled: False
                 install path: F:\Software\Miniconda3\Lib\site-packages\pydantic
               python version: 3.7.6 | packaged by conda-forge | (default, Jan  7 2020, 21:48:41) [MSC v.1916 64 bit (AMD64)]
                     platform: Windows-10-10.0.18362-SP0
     optional deps. installed: []

Issue

I wrote a generic model named Tree as shown in the following snippet.

from __future__ import annotations
from pydantic import BaseModel, Schema
from typing import List, Generic, TypeVar
from pydantic.generics import GenericModel

T = TypeVar('T')

class Node(GenericModel, Generic[T]):
    value: T = Schema(..., description = 'Node value')
    children: List[Node[T]] = Schema([], description = 'Node children')
        
Node.update_forward_refs()

class Tree(GenericModel, Generic[T]):
    nodes: List[Node[T]] = Schema([], description = 'Top level nodes')

I get the error "maximum recursion depth exceeded while calling a Python object" when I try to use it. Any suggestions on how I can fix this would be greatly appreciated.

If I modify the Node.children type from List[Node[T]] to List[Node], then the error disappers.

from __future__ import annotations
from pydantic import BaseModel, Schema
from typing import List, Generic, TypeVar
from pydantic.generics import GenericModel

T = TypeVar('T')

class Node(GenericModel, Generic[T]):
    value: T = Schema(..., description = 'Node value')
    children: List[Node] = Schema([], description = 'Node children')
        
Node.update_forward_refs()

class Tree(GenericModel, Generic[T]):
    nodes: List[Node[T]] = Schema([], description = 'Top level nodes')

The problem in this case is that, it accepts any Node type as the children as shown in the following code.

n1 = Node[str](value = "j")
n2 = Node[int](value = 2)
n0 = Node[int](value = 0, children = [n1, n2])
Tree[int](nodes = [n0]).dict()

I want it to support only Node[int] as children, and I want it throw a validation error in the above case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions