Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recursive model error in latest version #227

Closed
DenSinH opened this issue Nov 18, 2024 · 1 comment
Closed

Recursive model error in latest version #227

DenSinH opened this issue Nov 18, 2024 · 1 comment

Comments

@DenSinH
Copy link
Contributor

DenSinH commented Nov 18, 2024

It seems something broke between releases 2.12.1 and 2.13.0, which has not been fixed yet, regarding cyclic / self referential models. The following minimal example 'builds' in release 2.12.1 and fails in 2.13.0, 2.13.1 and 2.14.0:

from pydantic_xml import BaseXmlModel, element


class MyBaseClass(BaseXmlModel):
    name: str = element("Name")
    children: list['MyDerivedClass'] = element(tag="Derived", default_factory=list)


class MyDerivedClass(MyBaseClass, tag="Derived"):
    field: int = element("type")

Stack trace:

Traceback (most recent call last):
  File "C:\projects\playground\stuff.py", line 9, in <module>
    class MyDerivedClass(MyBaseClass, tag="Derived"):
  File "C:\projects\playground\venv\Lib\site-packages\pydantic_xml\model.py", line 373, in __new__
    cls = typing.cast(Type['BaseXmlModel'], super().__new__(mcls, name, bases, namespace, **kwargs))
                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 137, in __new__
    cls: type[BaseModel] = super().__new__(mcs, cls_name, bases, namespace, **kwargs)  # type: ignore
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen abc>", line 106, in __new__
  File "C:\projects\playground\venv\Lib\site-packages\pydantic_xml\model.py", line 433, in __init_subclass__
    if func := getattr(cls, attr_name, None):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_mock_val_ser.py", line 43, in __len__
    return self._get_built().__len__()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_mock_val_ser.py", line 43, in __len__
    return self._get_built().__len__()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_mock_val_ser.py", line 43, in __len__
    return self._get_built().__len__()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 965 more times]
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_mock_val_ser.py", line 53, in _get_built
    schema = self._attempt_rebuild()
             ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_mock_val_ser.py", line 126, in handler
    if cls.model_rebuild(raise_errors=False, _parent_namespace_depth=5) is not False:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic_xml\model.py", line 482, in model_rebuild
    super().model_rebuild(**kwargs)
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\main.py", line 563, in model_rebuild
    return _model_construction.complete_model_class(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 577, in complete_model_class
    schema = cls.__get_pydantic_core_schema__(cls, handler)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\main.py", line 671, in __get_pydantic_core_schema__
    return handler(source)
           ^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 83, in __call__
    schema = self._handler(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 655, in generate_schema
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 924, in _generate_schema_inner
    return self._model_schema(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 739, in _model_schema
    {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()},
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1115, in _generate_md_field_schema
    common_field = self._common_field_schema(name, field_info, decorators)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1308, in _common_field_schema
    schema = self._apply_annotations(
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2107, in _apply_annotations
    schema = get_inner_schema(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 83, in __call__
    schema = self._handler(source_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2088, in inner_handler
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 929, in _generate_schema_inner
    return self.match_type(obj)
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1029, in match_type
    return self._match_generic_type(obj, origin)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1062, in _match_generic_type
    return self._list_schema(self._get_first_arg_or_any(obj))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 431, in _list_schema
    return core_schema.list_schema(self.generate_schema(items_type))
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 655, in generate_schema
    schema = self._generate_schema_inner(obj)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 918, in _generate_schema_inner
    return self.generate_schema(self._resolve_forward_ref(obj))
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 864, in _resolve_forward_ref
    obj = _typing_extra.eval_type_backport(obj, globalns=self._types_namespace)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_typing_extra.py", line 279, in eval_type_backport
    return _eval_type_backport(value, globalns, localns, type_params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_typing_extra.py", line 303, in _eval_type_backport
    return _eval_type(value, globalns, localns, type_params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\projects\playground\venv\Lib\site-packages\pydantic\_internal\_typing_extra.py", line 332, in _eval_type
    return typing._eval_type(  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\programs\python\Lib\typing.py", line 415, in _eval_type
    return t._evaluate(globalns, localns, type_params, recursive_guard=recursive_guard)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\programs\python\Lib\typing.py", line 947, in _evaluate
    eval(self.__forward_code__, globalns, localns),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded

I was really hoping to use the (temporary) fix for CDATA fields from #201, but sadly I can't because of this issue.

@dapper91 dapper91 mentioned this issue Nov 28, 2024
Merged
dapper91 added a commit that referenced this issue Nov 28, 2024
- pydantic 2.10 mypy plugin compatibility fixed. See #232
- recursive model bug fixed. See #227.
@dapper91
Copy link
Owner

fixed in version 2.14.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants