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

Recursion error for self-references using type alias for a generic type #91

Closed
mishamsk opened this issue Jan 5, 2023 · 4 comments
Closed
Labels
bug Something isn't working

Comments

@mishamsk
Copy link
Contributor

mishamsk commented Jan 5, 2023

  • mashumaro version: 3.3
  • Python version: 3.11.1
  • Operating System: MacOS Ventura

Description

Using a combination of generic class with self-referenced attributes that in turn have a non-generic type alias causes RecursionError. The setup is similar to #90

What I Did

This code:

from __future__ import annotations
from dataclasses import dataclass
from typing import TypeVar, Generic, Any

from mashumaro.mixins.json import DataClassJSONMixin

T = TypeVar("T")


@dataclass
class Foo(Generic[T], DataClassJSONMixin):
    x: T
    y: Foo  # ok
    # z: AnyFoo  # Uncomment to get RecursionError: maximum recursion depth exceeded


AnyFoo = Foo[Any]


@dataclass
class Bar(Foo):
    ...

fails with RecursionError: maximum recursion depth exceeded

with this traceback (actually, traceback comes with recursion limit set to 100 to reduce number of repetitions):

Traceback (most recent call last):
  File "/Users/misha/Dev/mashumaro_test/m1.py", line 26, in <module>
    class Bar(Foo):
  File "/Users/misha/.asdf/installs/python/3.11.1/lib/python3.11/typing.py", line 1818, in __init_subclass__
    super().__init_subclass__(*args, **kwargs)
  File "/Users/misha/Dev/mashumaro/mashumaro/mixins/dict.py", line 24, in __init_subclass__
    compile_mixin_unpacker(cls, **builder_params["unpacker"])
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/mixin.py", line 49, in compile_mixin_unpacker
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 208, in unpack_dataclass_dict_mixin_subclass
    builder.add_unpack_method()
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 389, in add_unpack_method
    self._add_unpack_method_lines(method_name)
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 304, in _add_unpack_method_lines
    self._unpack_method_set_value(
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/code/builder.py", line 419, in _unpack_method_set_value
    unpacked_value = UnpackerRegistry.get(
                     ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/common.py", line 86, in get
    expr = packer(spec)
           ^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/types/unpack.py", line 186, in unpack_dataclass_dict_mixin_subclass
    if is_dataclass_dict_mixin_subclass(spec.origin_type):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/helpers.py", line 436, in is_dataclass_dict_mixin_subclass
    if is_dataclass_dict_mixin(cls):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/helpers.py", line 430, in is_dataclass_dict_mixin
    return type_name(typ) == DataClassDictMixinPath
           ^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/helpers.py", line 230, in type_name
    elif not is_type_origin and is_generic(typ):
                                ^^^^^^^^^^^^^^^
  File "/Users/misha/Dev/mashumaro/mashumaro/core/meta/helpers.py", line 294, in is_generic
    and type(typ[str]) is types.GenericAlias  # type: ignore
             ~~~^^^^^
  File "/Users/misha/.asdf/installs/python/3.11.1/lib/python3.11/typing.py", line 341, in inner
    return cached(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/.asdf/installs/python/3.11.1/lib/python3.11/typing.py", line 1791, in __class_getitem__
    if not all(_is_typevar_like(p) for p in params):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/misha/.asdf/installs/python/3.11.1/lib/python3.11/typing.py", line 1791, in <genexpr>
    if not all(_is_typevar_like(p) for p in params):
               ^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded
@Fatal1ty
Copy link
Owner

Fatal1ty commented Jan 9, 2023

Hi @mishamsk

This edge case wasn't properly covered. I fixed it in this branch. Could you check it with your real code?

@Fatal1ty Fatal1ty added the bug Something isn't working label Jan 9, 2023
@mishamsk
Copy link
Contributor Author

mishamsk commented Jan 9, 2023

@Fatal1ty hey, just tested. works like a charm, thanks a lot!

@Fatal1ty
Copy link
Owner

Merged and will be available in an upcoming release.

@Fatal1ty
Copy link
Owner

Fixed in 3.3.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants