limitations/dataclasses.md
dataclasses moduleNative, in-sandbox @dataclass: sandboxed code can define its own dataclasses,
executed entirely inside the sandbox (unlike host-supplied dataclasses, which
are passed in and dispatch back to the host — see classes.md).
Only the bare @dataclass decorator and is_dataclass exist. Everything below
raises at decoration time rather than producing a subtly wrong class, so a
class body Monty cannot honour never silently misbehaves.
Each raises NotImplementedError — a feature Monty has not built yet, not a
mistake in the calling code. CPython accepts all of them, so the exception type
is a divergence in its own right: code catching TypeError around a decoration
will not catch these.
@dataclass(...) keyword form — frozen, eq=False, order,
unsafe_hash, kw_only and the hashing/ordering they imply. Any keyword
raises NotImplementedError: dataclass() keyword options (eq, order, frozen, unsafe_hash, ...) are not yet supported. A dataclass is therefore always
eq=True, frozen=False: instances are unhashable and unordered.__post_init__ — raises NotImplementedError: dataclass() does not yet support __post_init__ in a class body, which would be silently skipped.InitVar[...] — raises NotImplementedError: dataclass() does not yet support InitVar (field <name>), which would become an ordinary field.
Detected textually, since annotations are never evaluated: the name need not
be imported to be rejected.field() / default_factory / MISSING — field(...) in a class body
raises NameError. There is no MISSING object, so the Field attributes
whose value would be one raise NotImplementedError: Field.default is not yet supported, dataclasses.MISSING is not implemented (likewise
default_factory, and default only for a field that has none).
Field.metadata and Field._field_type raise the same way, for
types.MappingProxyType and dataclasses._FIELD.fields, asdict, astuple, replace.Mutable defaults are rejected as CPython rejects them
(ValueError: mutable default <class 'list'> for field xs is not allowed: use default_factory), and so is a non-default field after a defaulted one
(TypeError: non-default argument 'b' follows default argument 'a').
__annotations__, which Monty stores as never-evaluated source text (always
PEP 563) — see typing.md. Field
discovery and the generated methods are unaffected, the field type being
inert metadata, but C.__dataclass_fields__['x'].type is the string 'int',
not the int type object.__dataclass_fields__ holds only real fields. CPython keeps ClassVar
(and InitVar) entries in the mapping, marked _FIELD_CLASSVAR, and filters
them in fields(). Monty has no field kinds — the mapping is the field
list — so class variables never appear in it.Field renders differently. repr(field) follows CPython's layout but
writes MISSING where CPython writes <dataclasses._MISSING_TYPE object at 0x..>, and the stringized type. repr(type(field)) is <class 'Field'>,
not <class 'dataclasses.Field'> (Field.__name__ matches either way, so
attribute errors read the same).__dataclass_fields__ un-marks the class. Every dunder reads
the mapping from the class namespace, so C.__dataclass_fields__ = 5 makes
is_dataclass(C) false and C(...) construct like a plain class. CPython
keeps its generated methods and still calls C a dataclass.ClassVar / InitVar detection is purely textual. Monty matches the
annotation text (bare, dotted, subscripted, or quoted) without checking that
the name is actually imported, where CPython resolves a string annotation
through the defining module's namespace. So c: "ClassVar[int]" without
ClassVar in scope is excluded by Monty but is an ordinary field to CPython.
Conversely any dotted spelling matches, so a same-named attribute on an
unrelated module (mymod.ClassVar) is treated as typing.ClassVar.repr for those differs (see classes.md). Only the
text differs; the value and its equality match CPython.__setattr__ never runs for the synthesized __init__,
which writes fields straight into the instance __dict__. Not a
dataclass-specific gap — the never-dispatched attribute hook of
classes.md — so @dataclass does not reject it.@dataclass on a non-class (e.g. dataclasses.dataclass(5)) raises
TypeError: dataclass() should be called on a class, not '<type>'. CPython
instead raises an incidental AttributeError about __module__ from its
implementation; Monty reports the misuse directly. (The @deco syntax only
ever targets a class, so this affects only direct calls.)slots=True / weakref_slot=True — no __slots__, no weakrefs.