Opened 39 hours ago

Last modified 31 hours ago

#36695 assigned Bug

Model field validator with a generic parameter causes infinite recursion when making migrations — at Version 2

Reported by: Michal Dabski Owned by:
Component: Migrations Version: 4.2
Severity: Normal Keywords:
Cc: Michal Dabski Triage Stage: Accepted
Has patch: no Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by Michal Dabski)

Minimal code to reproduce (in models.py) in Django==4.2.25

from django.utils.deconstruct import deconstructible
from django.db import models

@deconstructible
class SchemaValidator:
    def __init__(self, expected_type: type):
        pass

    def __call__(self, *args, **kwargs):
        pass

class TestModel(models.Model):
    config: dict[str, float] = models.JSONField(validators=[SchemaValidator(dict[str, float])])

This triggers an error when running makemigrations:

$ ./manage.py makemigrations
Migrations for 'audit_builder':
  meg_forms\audit_builder\migrations\0083_alter_testmodel_config.py
    - Alter field config on testmodel
Traceback (most recent call last):
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 996 more times]
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 389, in serializer_factory
    if isinstance(value, type_):
       ^^^^^^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded

Debugging locally shows that:

  • removing generic parameters from the dict type passed to SchemaValidator does not trigger the error
  • The loop happens in django.db.migrations.serializer.IterableSerializer.serialize, it keeps recursively invoking serializer_factory(item).serialize() with item='*dict[str, float]' (GenericAlias)
  • the same behaviour is with similar generic types - list[str]
  • without the migration being created/applied, validation works as expected

Change History (2)

comment:1 by Michal Dabski, 39 hours ago

Description: modified (diff)

comment:2 by Michal Dabski, 39 hours ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top