-
Notifications
You must be signed in to change notification settings - Fork 77
Docs: inaccurate claim on schema field ordering #228
Description
The documentation states you don't need to set ordered = True on a schema when using CPython 3.6+. Unfortunately that's currently not true, as the Marshmallow Schema._init_fields() implementation relies on sets, not dictionaries, to select fields. The default set implementation used is the Python stdlib set type, which does not preserve insertion order.
This is why the following example, on Python 3.9, lists fields in a different order from that used by the schema class:
>>> import sys
>>> from marshmallow import Schema, fields
>>> class FooSchema(Schema):
... bar = fields.String()
... spam = fields.Int()
... ham = fields.Boolean()
...
>>> sys.version_info
sys.version_info(major=3, minor=9, micro=0, releaselevel='final', serial=0)
>>> list(FooSchema().fields)
['spam', 'ham', 'bar']which makes the claim in the docs that passing ordered Meta attribute is not necessary when using a Python version for which dictionaries are always ordered (>= 3.7 or CPython 3.6) incorrect.
I've taken to create a custom base class that sets set_class to OrderedSet:
>>> from marshmallow.orderedset import OrderedSet
>>> class OrderedBaseSchema(Schema):
... set_class = OrderedSet
...
>>> class FooSchemaOrdered(OrderedBaseSchema):
... bar = fields.String()
... spam = fields.Int()
... ham = fields.Boolean()
...
>>> list(FooSchemaOrdered().fields)
['bar', 'spam', 'ham']This is sufficient to retain field ordering for Python versions with the new insertion-order-preserving dict implementation.