MCPcopy
hub / github.com/pydantic/pydantic / __setattr__

Method __setattr__

pydantic/v1/main.py:375–428  ·  view source on GitHub ↗
(self, name, value)

Source from the content-addressed store, hash-verified

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__)

Callers

nothing calls this directly

Calls 6

ValidationErrorClass · 0.90
ErrorWrapperClass · 0.90
validatorFunction · 0.70
getMethod · 0.45
itemsMethod · 0.45
validateMethod · 0.45

Tested by

no test coverage detected