(self, name, value)
| 373 | |
| 374 | @no_type_check |
| 375 | def __setattr__(self, name, value): # noqa: C901 (ignore complexity) |
| 376 | if name in self.__private_attributes__ or name in DUNDER_ATTRIBUTES: |
| 377 | return object_setattr(self, name, value) |
| 378 | |
| 379 | if self.__config__.extra is not Extra.allow and name not in self.__fields__: |
| 380 | raise ValueError(f'"{self.__class__.__name__}" object has no field "{name}"') |
| 381 | elif not self.__config__.allow_mutation or self.__config__.frozen: |
| 382 | raise TypeError(f'"{self.__class__.__name__}" is immutable and does not support item assignment') |
| 383 | elif name in self.__fields__ and self.__fields__[name].final: |
| 384 | raise TypeError( |
| 385 | f'"{self.__class__.__name__}" object "{name}" field is final and does not support reassignment' |
| 386 | ) |
| 387 | elif self.__config__.validate_assignment: |
| 388 | new_values = {**self.__dict__, name: value} |
| 389 | |
| 390 | for validator in self.__pre_root_validators__: |
| 391 | try: |
| 392 | new_values = validator(self.__class__, new_values) |
| 393 | except (ValueError, TypeError, AssertionError) as exc: |
| 394 | raise ValidationError([ErrorWrapper(exc, loc=ROOT_KEY)], self.__class__) |
| 395 | |
| 396 | known_field = self.__fields__.get(name, None) |
| 397 | if known_field: |
| 398 | # We want to |
| 399 | # - make sure validators are called without the current value for this field inside `values` |
| 400 | # - keep other values (e.g. submodels) untouched (using `BaseModel.dict()` will change them into dicts) |
| 401 | # - keep the order of the fields |
| 402 | if not known_field.field_info.allow_mutation: |
| 403 | raise TypeError(f'"{known_field.name}" has allow_mutation set to False and cannot be assigned') |
| 404 | dict_without_original_value = {k: v for k, v in self.__dict__.items() if k != name} |
| 405 | value, error_ = known_field.validate(value, dict_without_original_value, loc=name, cls=self.__class__) |
| 406 | if error_: |
| 407 | raise ValidationError([error_], self.__class__) |
| 408 | else: |
| 409 | new_values[name] = value |
| 410 | |
| 411 | errors = [] |
| 412 | for skip_on_failure, validator in self.__post_root_validators__: |
| 413 | if skip_on_failure and errors: |
| 414 | continue |
| 415 | try: |
| 416 | new_values = validator(self.__class__, new_values) |
| 417 | except (ValueError, TypeError, AssertionError) as exc: |
| 418 | errors.append(ErrorWrapper(exc, loc=ROOT_KEY)) |
| 419 | if errors: |
| 420 | raise ValidationError(errors, self.__class__) |
| 421 | |
| 422 | # update the whole __dict__ as other values than just `value` |
| 423 | # may be changed (e.g. with `root_validator`) |
| 424 | object_setattr(self, '__dict__', new_values) |
| 425 | else: |
| 426 | self.__dict__[name] = value |
| 427 | |
| 428 | self.__fields_set__.add(name) |
| 429 | |
| 430 | def __getstate__(self) -> 'DictAny': |
| 431 | private_attrs = ((k, getattr(self, k, Undefined)) for k in self.__private_attributes__) |
nothing calls this directly
no test coverage detected