Source code for crookbook
import six
[docs]def essence(attrs, mutable=True):
if isinstance(attrs, six.string_types):
attrs = attrs.split(' ')
def essence_maker(cls):
def __essence__(self):
return tuple(getattr(self, attr) for attr in attrs)
setattr(cls, '__essence__', __essence__)
def eq(self, other):
if isinstance(other, cls):
return self.__essence__() == cls.__essence__(other)
return NotImplemented
setattr(cls, '__eq__', eq)
if six.PY2:
# Taken from:
# https://stackoverflow.com/a/35781654
def ne(self, other):
equal = self.__eq__(other)
return equal if equal is NotImplemented else not equal
setattr(cls, '__ne__', ne)
def hash_(self):
return hash(self.__essence__())
setattr(cls, '__hash__', None if mutable else hash_)
# Would use total_ordering, but the recursive comparison issue is still present in
# Python 2.7, so have to work this way instead.
def lt(self, other):
if isinstance(other, cls):
return self.__essence__() < cls.__essence__(other)
return NotImplemented
def le(self, other):
if isinstance(other, cls):
return self.__essence__() <= cls.__essence__(other)
return NotImplemented
def gt(self, other):
if isinstance(other, cls):
return self.__essence__() > cls.__essence__(other)
return NotImplemented
def ge(self, other):
if isinstance(other, cls):
return self.__essence__() >= cls.__essence__(other)
return NotImplemented
setattr(cls, '__lt__', lt)
setattr(cls, '__le__', le)
setattr(cls, '__gt__', gt)
setattr(cls, '__ge__', ge)
return cls
return essence_maker
[docs]def described(inner):
def described_maker(cls):
def repr_(self):
return ('<{0.__class__.__name__} ' + inner + '>').format(self)
setattr(cls, '__repr__', repr_)
if '__str__' not in cls.__dict__:
def str_(self):
return repr(self)
setattr(cls, '__str__', str_)
return six.python_2_unicode_compatible(cls)
return described_maker