Пример #1
0
def test_eq_():
    fp1 = Fingerprint(33)
    fp2 = Fingerprint(33)
    assert fp1 == fp1
    assert fp1 == fp2
    assert not (fp1 != fp2)
    fp2.touch(32)
    assert not (fp1 == fp2)
    assert fp1 != fp2
Пример #2
0
def test_equivalence():
    fp1 = Fingerprint(33)
    fp2 = Fingerprint(33)
    assert fp1.equivalent(fp1)
    assert fp1.equivalent(fp2)
    assert fp2.equivalent(fp1)
    fp1.touch(32)
    fp2.touch(31)
    fp2.touch(32)
    assert fp2.equivalent(fp1)
    assert not fp1.equivalent(fp2)
Пример #3
0
def test_accessors():
    fp = Fingerprint(65)
    with pytest.raises(ValueError):
        fp.get(-1)
        fp.get(65)
    for i in range(65):
        assert fp.get(i) == False
    for i in [0, 1, 31, 32, 63]:
        fp.touch(i)
        assert fp.get(i) == True
        fp.wipe(i)
        assert fp.get(i) == False
Пример #4
0
def test_serialization():
    fp1 = Fingerprint(33)
    fp1.touch(31)
    fp1.touch(32)

    s = Serializer()
    fp1.serialize(s)
    assert len(s.buffer) == fp1.get_length()

    fp2 = Fingerprint(33)
    assert fp1 != fp2
    fp2.deserialize(Deserializer(s.buffer))
    assert fp1 == fp2
Пример #5
0
def test_copy_creation():
    for n in [32, 33]:
        fp1 = Fingerprint(n)
        indices = [0, 1, n - 2, n - 1]
        for i in indices:
            fp1.touch(i)
        fp2 = Fingerprint(fp1)
        for i in indices:
            assert fp2.get(i) == True
        # Make sure that we have a deep copy
        for i in indices:
            fp2.wipe(i)
        for i in indices:
            assert fp1.get(i) == True
Пример #6
0
def test_lt_():
    fp1 = Fingerprint(32)
    fp2 = Fingerprint(33)
    fp3 = Fingerprint(33)
    assert not (fp1 < fp1)
    # with different lengths
    assert fp1 < fp2
    assert fp2 > fp1
    fp1.touch(0)
    assert fp1 < fp2
    # with same lengths
    assert not (fp2 < fp3)
    fp3.touch(31)
    assert fp2 < fp3
    fp2.touch(32)
    assert fp2 > fp3
Пример #7
0
def test_hash_():
    fp1 = Fingerprint(33)
    fp2 = Fingerprint(33)
    assert fp1.__hash__() == fp2.__hash__()
    fp2.touch(32)
    assert fp1.__hash__() != fp2.__hash__()
Пример #8
0
class Cell(object):
    """Common base class for all custom types."""
    class Tag(object):
        def __init__(self, base, type_name, props):
            self.base = base
            self.type_name = type_name
            self.props = props
            self.offset = 0
            if base is not None:
                self.offset = base.offset + len(base.props)

    tag = Tag(None, 'Cell', [])

    def __init__(self, length):
        self.fingerprint = Fingerprint(length)
        self.values = [None] * length  # property values

    def desc(self):
        prop_descs = []
        tag = self.type_tag()
        self._desc(tag, prop_descs)
        result = ', '.join(prop_descs)
        result = "{} {{ {} }}".format(tag.type_name, result)
        return result

    def _desc(self, tag, prop_descs):
        if tag.base is not None:
            self._desc(tag.base, prop_descs)
        if len(tag.props) == 0:
            return
        for index, prop in enumerate(tag.props):
            if prop.name.startswith('_'):
                continue
            value = self.values[tag.offset + index]
            if prop.type_index == MetaProperty.STRING:
                value = "'{}'".format(value.replace("'", "''"))
            elif prop.type_index == MetaProperty.BYTES:
                value = repr(value)
            prop_descs.append('{}:{}'.format(prop.name, value))

    def deserialize(self, deserializer):
        self.fingerprint.deserialize(deserializer)
        self._deserialize(self.type_tag(), deserializer)

    def _deserialize(self, tag, deserializer):
        if tag.base is not None:
            self._deserialize(tag.base, deserializer)
        if len(tag.props) == 0:
            return
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if prop.name.startswith('_'):
                if prop.name == '_Handle':
                    continue
            if self.fingerprint.get(base + index):
                self.values[base + index] = deserializer.read(prop)

    def get_length(self, target_type=None):
        result = self.fingerprint.get_length()
        length, _ = self._get_length(self.type_tag(), target_type, True)
        result += length
        return result

    def _get_length(self, tag, target_type, flag):
        result = 0
        if tag.base is not None:
            length, flag = self._get_length(tag.base, target_type, flag)
            result += length
            if not flag:
                return result, flag
        if len(tag.props) == 0:
            return result, flag
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if prop.name.startswith('_'):
                if prop.name == '_Handle':
                    continue
            if self.fingerprint.get(base + index):
                result += Serializer.get_length(prop,
                                                self.values[base + index])
        if (target_type is not None) and (target_type.__name__
                                          == tag.type_name):
            flag = False
        return result, flag

    def type_tag(self):
        return Cell.tag

    def equals(self, other):
        if self is other:
            return True
        if type(self) != type(other):
            return False
        return self._equals(self.type_tag(), other)

    def _equals(self, tag, other):
        if tag.base is not None:
            if not self._equals(tag.base, other):
                return False
        if len(tag.props) == 0:
            return True
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if self.values[base + index] != other.values[base + index]:
                return False
        return True

    def equivalent(self, other):
        if self is other:
            return True
        if not isinstance(self, type(other)):
            return False
        return self._equivalent(self.type_tag(), other)

    def _equivalent(self, tag, other):
        if tag.base is not None:
            if not self._equivalent(tag.base, other):
                return False
        if len(tag.props) == 0:
            return True
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if other.fingerprint.get(base + index):
                if self.values[base + index] != other.values[base + index]:
                    return False
        return True

    def hash_code(self, fingerprint):
        h = Hash()
        self._hash_code(self.type_tag(), h, fingerprint)
        return h.code

    def _hash_code(self, tag, h, fingerprint):
        if tag.base is not None:
            self._hash_code(tag.base, h, fingerprint)
        if len(tag.props) == 0:
            return
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if fingerprint.get(base + index):
                h.update(base + index)  # property index
                h.update(hash(self.values[base + index]))  # property value

    def serialize(self, serializer, target_type=None):
        self.fingerprint.serialize(serializer)
        self._serialize(self.type_tag(), serializer, target_type, True)

    def _serialize(self, tag, serializer, target_type, flag):
        if tag.base is not None:
            flag = self._serialize(tag.base, serializer, target_type, flag)
            if not flag:
                return flag
        if len(tag.props) == 0:
            return flag
        base = tag.offset
        for index, prop in enumerate(tag.props):
            if prop.name.startswith('_'):
                if prop.name == '_Handle':
                    continue
            if self.fingerprint.get(base + index):
                serializer.write(prop, self.values[base + index])
        if (target_type is not None) and (target_type.__name__
                                          == tag.type_name):
            flag = False
        return flag

    def setattrs(self, **kwargs):
        """Sets multiple attributes of this cell object at once."""
        for key, value in kwargs.items():
            setattr(self, key, value)
        return self

    def __eq__(self, other):
        return other.equals(self)

    def __ne__(self, other):
        return not other.equals(self)

    def __hash__(self):
        return self.hash_code(self.fingerprint)

    def __str__(self):
        return self.desc()

    # Property type checkers

    @staticmethod
    def is_bool(value):
        if value == True or value == False:
            return True, value
        else:
            return False, value

    @staticmethod
    def is_byte(value):
        if not isinstance(value, int):
            try:
                value = int(value)
            except:
                return False, value
        if value < 0 or (2**8 - 1) < value:
            return False, value
        return True, value

    @staticmethod
    def is_int8(value):
        if not isinstance(value, int):
            try:
                value = int(value)
            except:
                return False, value
        if value < -(2**7) or (2**7 - 1) < value:
            return False, value
        return True, value

    @staticmethod
    def is_int16(value):
        if not isinstance(value, int):
            try:
                value = int(value)
            except:
                return False, value
        if value < -(2**15) or (2**15 - 1) < value:
            return False, value
        return True, value

    @staticmethod
    def is_int32(value):
        if not isinstance(value, int):
            try:
                value = int(value)
            except:
                return False, value
        if value < -(2**31) or (2**31 - 1) < value:
            return False, value
        return True, value

    @staticmethod
    def is_int64(value):
        if not isinstance(value, int):
            try:
                value = int(value)
            except:
                return False, value
        if value < -(2**63) or (2**63 - 1) < value:
            return False, value
        return True, value

    @staticmethod
    def is_float32(value):
        if not isinstance(value, float):
            try:
                value = float(value)
            except:
                return False, value
        return True, value

    @staticmethod
    def is_float64(value):
        if not isinstance(value, float):
            try:
                value = float(value)
            except:
                return False, value
        return True, value

    @staticmethod
    def is_string(value):
        if value is not None:  # allow None
            if not isinstance(value, str):
                try:
                    value = str(value)
                except:
                    return False, value
        return True, value

    @staticmethod
    def is_datetime(value):
        if not isinstance(value, datetime.datetime):
            try:
                value = datetime.datetime(value)
            except:
                return False, value
        return True, value

    @staticmethod
    def is_bytes(value):
        if value is not None:  # allow None
            if not isinstance(value, bytes):
                try:
                    value = bytes(value)
                except:
                    return False, value
        return True, value

    @staticmethod
    def is_cell(value):
        if value is not None:  # allow None
            if not isinstance(value, Cell):
                return False, value
        return True, value

    @staticmethod
    def is_list(value):
        if value is not None:  # allow None
            if not isinstance(value, list):
                return False, value
        return True, value

    @staticmethod
    def is_map(value):
        if value is not None:  # allow None
            if not isinstance(value, dict):
                return False, value
        return True, value

    @staticmethod
    def is_object(value):
        return True, value

    # Property type checker function table
    checkers = [
        None, is_bool, is_byte, is_int8, is_int16, is_int32, is_int64,
        is_float32, is_float64, is_string, is_datetime, is_bytes, is_cell,
        is_list, is_map, is_object
    ]

    def _set_property(self, index, value, type_index):
        checker = Cell.checkers[type_index]
        valid, value = checker.__func__(value)
        if not valid:
            raise ValueError()
        if value is not None:
            self.fingerprint.touch(index)
        self.values[index] = value