Opened 4 hours ago

Last modified 4 hours ago

#37431 new Uncategorized

MigrationWriter silently serializes Python 3.15 frozendict values as tuples of keys — at Initial Version

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

Description

Ticket title:

`
MigrationWriter silently serializes Python 3.15 frozendict values as tuples of keys
`

Ticket description:


On Python 3.15.0, Django's migration serializer treats built-in frozendict instances as generic iterables, preserving only their keys and silently discarding their values.

Reproduced against Django main at d430084791.

Minimal reproducer:

`python
from django.db.migrations.writer import MigrationWriter

MigrationWriter.serialize(frozendict(answer=42))
`

Actual result:

`python
("('answer',)", set())
`

Expected behavior: preserve the mapping's keys and values, rather than serialize it as a tuple of keys.

This affects field defaults. For example:

`python
models.JSONField(default=frozendict(answer=42))
`

is written into a migration as:

`python
models.JSONField(default=('answer',))
`

I reproduced the database consequence on SQLite: after executing a generated AddField migration against a table containing an existing row, the new JSON field contains answer instead of {"answer": 42}.

The serializer registry handles dict explicitly, but frozendict is not a dict subclass and falls through to IterableSerializer.

A proposed patch adds a dedicated frozendict serializer, regression tests in the existing migration writer and operation suites, and documentation noting that generated migrations containing frozendict require Python 3.15+.

Validation:

  • Python 3.15: all 75 writer/regression tests passed.
  • Python 3.15: 181 migration operation tests ran successfully, with 2 skipped.
  • Python 3.14: 75 writer/regression tests ran successfully, with 3 skipped.
  • Formatting and whitespace checks passed.
  • The full Django test suite has not been run.

AI disclosure: OpenAI Codex (GPT-6) assisted with investigation, implementation, regression tests, documentation, and commit preparation.

Change History (0)

Note: See TracTickets for help on using tickets.
Back to Top