MCPcopy
hub / github.com/pydantic/pydantic / __eq__

Method __eq__

pydantic/main.py:1164–1219  ·  view source on GitHub ↗
(self, other: Any)

Source from the content-addressed store, hash-verified

1162 if not TYPE_CHECKING:
1163
1164 def __eq__(self, other: Any) -> bool:
1165 if isinstance(other, BaseModel):
1166 # When comparing instances of generic types for equality, as long as all field values are equal,
1167 # only require their generic origin types to be equal, rather than exact type equality.
1168 # This prevents headaches like MyGeneric(x=1) != MyGeneric[Any](x=1).
1169 self_type = self.__pydantic_generic_metadata__['origin'] or self.__class__
1170 other_type = other.__pydantic_generic_metadata__['origin'] or other.__class__
1171
1172 # Perform common checks first
1173 if not (
1174 self_type is other_type
1175 and getattr(self, '__pydantic_private__', None) == getattr(other, '__pydantic_private__', None)
1176 # We need to assume `None` and `{}` are equivalent, because extra behavior
1177 # can be controlled at validation time:
1178 and (self.__pydantic_extra__ or {}) == (other.__pydantic_extra__ or {})
1179 ):
1180 return False
1181
1182 # We only want to compare pydantic fields but ignoring fields is costly.
1183 # We'll perform a fast check first, and fallback only when needed
1184 # See GH-7444 and GH-7825 for rationale and a performance benchmark
1185
1186 # First, do the fast (and sometimes faulty) __dict__ comparison
1187 if self.__dict__ == other.__dict__:
1188 # If the check above passes, then pydantic fields are equal, we can return early
1189 return True
1190
1191 # We don't want to trigger unnecessary costly filtering of __dict__ on all unequal objects, so we return
1192 # early if there are no keys to ignore (we would just return False later on anyway)
1193 model_fields = type(self).__pydantic_fields__.keys()
1194 if self.__dict__.keys() <= model_fields and other.__dict__.keys() <= model_fields:
1195 return False
1196
1197 # If we reach here, there are non-pydantic-fields keys, mapped to unequal values, that we need to ignore
1198 # Resort to costly filtering of the __dict__ objects
1199 # We use operator.itemgetter because it is much faster than dict comprehensions
1200 # NOTE: Contrary to standard python class and instances, when the Model class has a default value for an
1201 # attribute and the model instance doesn't have a corresponding attribute, accessing the missing attribute
1202 # raises an error in BaseModel.__getattr__ instead of returning the class attribute
1203 # So we can use operator.itemgetter() instead of operator.attrgetter()
1204 getter = operator.itemgetter(*model_fields) if model_fields else lambda _: _utils._SENTINEL
1205 try:
1206 return getter(self.__dict__) == getter(other.__dict__)
1207 except KeyError:
1208 # In rare cases (such as when using the deprecated BaseModel.copy() method),
1209 # the __dict__ may not contain all model fields, which is how we can get here.
1210 # getter(self.__dict__) is much faster than any 'safe' method that accounts
1211 # for missing keys, and wrapping it in a `try` doesn't slow things down much
1212 # in the common case.
1213 self_fields_proxy = _utils.SafeGetItemProxy(self.__dict__)
1214 other_fields_proxy = _utils.SafeGetItemProxy(other.__dict__)
1215 return getter(self_fields_proxy) == getter(other_fields_proxy)
1216
1217 # other instance is not a BaseModel
1218 else:
1219 return NotImplemented # delegate to the other item in the comparison
1220
1221 if TYPE_CHECKING:

Callers

nothing calls this directly

Calls 1

keysMethod · 0.80

Tested by

no test coverage detected