diff --git a/src/attr/_make.py b/src/attr/_make.py index 7f22b273b..e229a1e81 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -59,6 +59,8 @@ # Unique object for unequivocal getattr() defaults. _sentinel = object() +_ng_default_on_setattr = setters.pipe(setters.convert, setters.validate) + class _Nothing(object): """ @@ -722,13 +724,16 @@ def __init__( self._cls_dict["__delattr__"] = _frozen_delattrs self._wrote_own_setattr = True - elif on_setattr == setters.validate: + elif on_setattr == _ng_default_on_setattr: for a in attrs: if a.validator is not None: break + if a.converter is not None: + break else: - # If class-level on_setattr is set to validating, but there's - # no field to validate, pretend like there's no on_setattr. + # If class-level on_setattr is set to convert + validate, but + # there's no field to convert or validate, pretend like there's + # no on_setattr. self._on_setattr = None if getstate_setstate: diff --git a/src/attr/_next_gen.py b/src/attr/_next_gen.py index 6dd2ebc11..843447173 100644 --- a/src/attr/_next_gen.py +++ b/src/attr/_next_gen.py @@ -8,7 +8,13 @@ from attr.exceptions import UnannotatedAttributeError from . import setters -from ._make import NOTHING, _frozen_setattrs, attrib, attrs +from ._make import ( + NOTHING, + _frozen_setattrs, + _ng_default_on_setattr, + attrib, + attrs, +) def define( @@ -92,7 +98,7 @@ def wrap(cls): # By default, mutable classes convert & validate on setattr. if frozen is False and on_setattr is None: - on_setattr = [setters.convert, setters.validate] + on_setattr = _ng_default_on_setattr # However, if we subclass a frozen class, we inherit the immutability # and disable on_setattr.