﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37431	MigrationWriter silently serializes Python 3.15 frozendict values as tuples of keys	amanjain		"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 instead of serializing it as a tuple of keys.

This affects field defaults:

{{{#!python
models.JSONField(default=frozendict(answer=42))
}}}

The generated migration contains:

{{{#!python
models.JSONField(default=('answer',))
}}}

The database consequence was reproduced on SQLite: executing a generated AddField migration against an existing row stores {{{[""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 serializer, regression tests in the migration writer and operation suites, and documentation noting that generated migrations containing frozendict require Python 3.15+.

Validation:
 * Python 3.15: 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."	Uncategorized	new	Migrations	dev	Normal				Unreviewed	0	0	0	0	0	0
