Document dataclass caveats for Declarative Dataclass Mapping - #13470
ArockiaRajamanickam wants to merge 1 commit into
Conversation
Adds a Dataclass Caveats section covering field ordering, kw_only inheritance vs type checkers, asdict() recursion across back_populates, and how dataclass defaults interact with ORM operations including the 2.1 change. References sqlalchemy#9410
|
I like that idea of doing docs and having the LLM independently confirm each bullet. I'm away this week so I can't look closely yet but I would imagine we'd backport to 2.0 as well , we usually do that from our gerrit review server. |
|
Thanks, and no rush at all. Understood on the backport, I'll leave that to your gerrit process and won't open anything against the 2.0 docs branch. One thing that might be worth a look when you're back. The base class ordering report from 2023 in the issue list doesn't reproduce for me on either 2.0.51 or 2.1.0b3. Both |
Adds a Dataclass Caveats section to
doc/build/orm/dataclasses.rst, addressing #9410. It sits at the end of the Declarative Dataclass Mapping material, just before the Pydantic section.Rather than transcribing the 2023 checklist in the issue, I ran each item against 2.0.51 and 2.1.0b3 and documented what those versions actually do. That changed the content in several places, so the notes below explain what is in the PR and what deliberately is not.
Documented (four items, each reproduced on both versions):
InvalidRequestErrorwrapping the stdlibTypeError("non-default argument 'email' follows default argument 'name'"). Both fixes are shown and both were tested: reorder the fields, or usekw_only=True.kw_onlyand type checkers — reframed from the issue's wording.kw_only=Trueon a superclass is applied to subclasses at runtime (idlands inkwonlyargson both 2.0 and 2.1), so this is not a runtime bug. The mismatch is with PEP 681 checkers, which scope the argument to the declaring class. Links to MappedAsDataclass inherits dataclasses attributes, while the spec says they don't #9493.asdict()recursion — aback_populatespair makes the object graph cyclic andasdict()has no cycle detection. ConfirmedRecursionErroron both versions and in all three states (unloaded, eagerly loaded, transient);astuple()behaves the same. Links to dataclasses astuple and asdict crash on recursive dataclass structures / dont support deepcopy memo python/cpython#94345, still open.Session.mergecase. On 2.0 a collection withdefault_factoryis treated as loaded-and-empty, and merging an object built by__init__()disassociates rows the database already holds; in my test both child rows had their foreign key set to NULL. On 2.1 the same test leaves them intact, so this carries a.. versionchanged:: 2.1pointing at:ref:change_12168`` rather than re-explaining the mechanism.Deliberately not included:
declared_attron a mixin (item 2) — already covered by :ref:orm_declarative_dc_mixins, which has a tip on this and links to :ref:error_dcmx. On 2.1 the error message itself names the fix. Linked instead of duplicated.DeclarativeBase, MappedAsDataclassfails where the reverse order works. It does not reproduce: both orders produce a working dataclass on 2.0.51 and 2.1.0b3. Left out rather than documenting a limitation that no longer exists — worth a look if it was fixed silently.__init__is not called on load #9930 / non-mapped field defaults on load — tracked separately, and it seemed out of scope for a caveats section on the mapping feature itself.Open questions for you:
rel_2_0doc branch? The field-ordering andasdict()items apply there unchanged, and the merge item is arguably most useful to 2.0 readers.Verification: full
sphinx -b htmlbuild adds no new warnings (the section previously tripped four "title underline too short" warnings, now fixed; the four remaining warnings in the build are pre-existing inchangelog_07.rst,migration_21.rstand ambiguous Python xrefs). Every cross-reference resolves, checked in the built HTML — including:ref:change_12168``,:paramref:targets and the two stdlib links. Note that `conf.py` has no `intersphinx_mapping`, so I used the file's existing `dataclasses_` named target and explicit URLs instead of `:mod:`/`:func:` roles, which render unlinked here. `tools/format_docs_code.py --check` passes.I used an AI assistant while working on this. The prose is my own and every behaviour claim above was verified by running it against both versions rather than taken from the issue text.