[docs]defcmp_using(eq=None,lt=None,le=None,gt=None,ge=None,require_same_type=True,class_name="Comparable",):""" Create a class that can be passed into `attrs.field`'s ``eq``, ``order``, and ``cmp`` arguments to customize field comparison. The resulting class will have a full set of ordering methods if at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. Args: eq (typing.Callable | None): Callable used to evaluate equality of two objects. lt (typing.Callable | None): Callable used to evaluate whether one object is less than another object. le (typing.Callable | None): Callable used to evaluate whether one object is less than or equal to another object. gt (typing.Callable | None): Callable used to evaluate whether one object is greater than another object. ge (typing.Callable | None): Callable used to evaluate whether one object is greater than or equal to another object. require_same_type (bool): When `True`, equality and ordering methods will return `NotImplemented` if objects are not of the same type. class_name (str | None): Name of class. Defaults to "Comparable". See `comparison` for more details. .. versionadded:: 21.1.0 """body={"__slots__":["value"],"__init__":_make_init(),"_requirements":[],"_is_comparable_to":_is_comparable_to,}# Add operations.num_order_functions=0has_eq_function=FalseifeqisnotNone:has_eq_function=Truebody["__eq__"]=_make_operator("eq",eq)body["__ne__"]=__ne__ifltisnotNone:num_order_functions+=1body["__lt__"]=_make_operator("lt",lt)ifleisnotNone:num_order_functions+=1body["__le__"]=_make_operator("le",le)ifgtisnotNone:num_order_functions+=1body["__gt__"]=_make_operator("gt",gt)ifgeisnotNone:num_order_functions+=1body["__ge__"]=_make_operator("ge",ge)type_=types.new_class(class_name,(object,),{},lambdans:ns.update(body))# Add same type requirement.ifrequire_same_type:type_._requirements.append(_check_same_type)# Add total ordering if at least one operation was defined.if0<num_order_functions<4:ifnothas_eq_function:# functools.total_ordering requires __eq__ to be defined,# so raise early error here to keep a nice stack.msg="eq must be define is order to complete ordering from lt, le, gt, ge."raiseValueError(msg)type_=functools.total_ordering(type_)returntype_
def_make_init():""" Create __init__ method. """def__init__(self,value):""" Initialize object with *value*. """self.value=valuereturn__init__def_make_operator(name,func):""" Create operator method. """defmethod(self,other):ifnotself._is_comparable_to(other):returnNotImplementedresult=func(self.value,other.value)ifresultisNotImplemented:returnNotImplementedreturnresultmethod.__name__=f"__{name}__"method.__doc__=(f"Return a {_operation_names[name]} b. Computed by attrs.")returnmethoddef_is_comparable_to(self,other):""" Check whether `other` is comparable to `self`. """returnall(func(self,other)forfuncinself._requirements)def_check_same_type(self,other):""" Return True if *self* and *other* are of the same type, False otherwise. """returnother.value.__class__isself.value.__class__