Part of the reason why attrs is so appealing is that all validations are essentially just plain functions that are run at certain times. However, I find myself pining for a little bit more control on *how* those functions are run. Notably, I'm looking for the ability to collect a report of *all* exceptions/warnings issued from validators in some object returned to users, which can then be manipulated and optionally reissued (somewhat similar to how cattrs uses `ExceptionGroup`s, but on the attrs instance itself). In a trivial case, consider a toy example where two validators always raise an exception: ```py @attrs.define class Example: name: str = attrs.field() @name.validator def always_fails(self, attr, value): raise ValueError() @name.validator def would_never_run(self, attr, value): # In pure attrs this function will never even run because of the previous validator raise TypeError() ``` The simplest solution I can think of is to simply change the signature of `validate()` and validators to handle `kwargs`: ```py def attrs.validate(inst, **kwargs): ... def validator(self, attr, value, **kwargs): ... ``` This would allow you pass whatever values you wanted to `attrs.validate()` and they would be passed straight through to every evaluated function. In cases where no extra args are specified (such as during attribute setting) then they would either error (appropriately) or resolve to defaults: ```py @attrs.define class Example: name: str = attrs.field() @name.validator def only_when_strict(self, attr, value, strict: Optional[bool] = False): if strict: raise ValueError() e = Example(name="passes, because 'strict' defaults to 'False'") e.name = "same as above" attrs.validate(e) # Same as above attrs.validate(e, strict=True) # Raises ValueError ``` To achieve simple error collection, I could simply pass in an optional list into kwargs and have errors be collected there if a validator detects said list: ```py @attrs.define class Example: name: str = attrs.field() @name.validator def always_fails(self, attr, value, error_list: Optional[list] = None): if error_list: error_list.append(ValueError()) else: raise ValueError() @name.validator def would_never_run(self, attr, value, error_list: Optional[list] = None): if error_list: error_list.append(TypeError()) else: raise TypeError() with attrs.validators.disabled(): e = Example(name="something") # Normally raises because `error_list` defaults to `None` error_list = [] attrs.validate(e, error_list=error_list) # Collect errors in `error_list` print(error_list) # -> [ValueError(), TypeError()] ``` In essence, this works in the same way as [Pydantic's `context` argument](https://docs.pydantic.dev/latest/concepts/validators/#validation-context). Writing a decorator like `@collect_errors` to remove the boilerplate of the if statement would be trivial, while also preserving the notion that validators are just "regular" functions. This (to me) seems a very simple and unobtrusive way to expand the functionality of existing validators while also maintaining backwards compatibility, though it unfortunately is only limited to cases where you explicitly call `attrs.validate()`. I don't believe cattrs itself is a solution here, because from what I understand cattrs is only concerned with validation of the object as it is being converted to/from a "raw" format (such as a dictionary to an attrs instance). In my case, I want the validators to run on manipulation of the attrs class itself, which only attrs itself is in charge of.