Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/attr/_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,13 +483,15 @@ def _transform_attrs(
# the end and can be mandatory or non-mandatory in any order, as they will
# be specified as keyword args anyway). Check the order of those attrs:
had_default = False
which_had_default = None
for a in (a for a in attrs if a.init is not False and a.kw_only is False):
if had_default is True and a.default is NOTHING:
msg = f"No mandatory attributes allowed after an attribute with a default value or factory. Attribute in question: {a!r}"
msg = f"No mandatory attributes allowed after an attribute with a default value or factory. Attribute in question: {a!r} appears after {which_had_default!r}"
raise ValueError(msg)

if had_default is False and a.default is not NOTHING:
had_default = True
which_had_default = a

# Resolve default field alias for any new attributes that the
# field_transformer may have added without setting an alias.
Expand Down
7 changes: 6 additions & 1 deletion tests/test_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,12 @@ class C:
"eq=True, eq_key=None, order=True, order_key=None, "
"hash=None, init=True, "
"metadata=mappingproxy({'field_order': 1}), type='int', converter=None, "
"kw_only=False, inherited=False, on_setattr=None, alias='x')"
"kw_only=False, inherited=False, on_setattr=None, alias='x') "
"appears after Attribute(name='y', default=0, validator=None, "
"repr=True, eq=True, eq_key=None, order=True, order_key=None, "
"hash=None, init=True, metadata=mappingproxy({'field_order': 0}), "
"type='int', converter=None, kw_only=False, inherited=False, "
"on_setattr=None, alias='y')"
),
) == e.value.args

Expand Down
7 changes: 6 additions & 1 deletion tests/test_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,12 @@ class C:
"eq=True, eq_key=None, order=True, order_key=None, "
"hash=None, init=True, "
"metadata=mappingproxy({}), type=None, converter=None, "
"kw_only=False, inherited=False, on_setattr=None, alias='y')"
"kw_only=False, inherited=False, on_setattr=None, alias='y') "
"appears after Attribute(name='x', default=None, validator=None, "
"repr=True, eq=True, eq_key=None, order=True, order_key=None, "
"hash=None, init=True, metadata=mappingproxy({}), type=None, "
"converter=None, kw_only=False, inherited=False, on_setattr=None, "
"alias='x')"
),
) == e.value.args

Expand Down
Loading