示例#1
0
def test_sequence_type():
    """ Test sequence type. """

    # With default sequence builder.
    checker = parsing.SequenceType(int)
    checker.validate((1, 2, 3))
    checker.validate([1, 2, 3])
    checker.validate({1, 2, 3})
    checker.validate(SortedSet(int))
    checker.validate(SortedSet(int, (1, 2, 3)))
    assert_raises(lambda: checker.validate((1, 2, 3.0)),
                  exceptions.TypeException)
    assert_raises(lambda: checker.validate((1.0, 2.0, 3.0)),
                  exceptions.TypeException)
    assert isinstance(checker.to_type((1, 2, 3)), list)
    # With SortedSet as sequence builder.
    checker = parsing.SequenceType(float)
    checker.validate((1.0, 2.0, 3.0))
    checker.validate([1.0, 2.0, 3.0])
    checker.validate({1.0, 2.0, 3.0})
    assert_raises(lambda: checker.validate((1, 2, 3.0)),
                  exceptions.TypeException)
    assert_raises(lambda: checker.validate((1.0, 2.0, 3)),
                  exceptions.TypeException)
    checker = parsing.SequenceType(int,
                                   sequence_builder=SortedSet.builder(int))
    initial_list = (1, 2, 7, 7, 1)
    checker.validate(initial_list)
    updated_list = checker.update(initial_list)
    assert isinstance(updated_list,
                      SortedSet) and updated_list.element_type is int
    assert updated_list == SortedSet(int, (1, 2, 7))
    assert checker.to_json(updated_list) == [1, 2, 7]
    assert checker.to_type([7, 2, 1, 1, 7, 1, 7]) == updated_list
示例#2
0
def test_init_bool_and_len():
    """ Test SortedSet initialization, length and conversion to boolean. """

    sorted_set = SortedSet(int)
    assert not sorted_set
    sorted_set = SortedSet(int, (2, 4, 99))
    assert sorted_set
    assert len(sorted_set) == 3
示例#3
0
 def __init__(self, key_type, val_type, kwargs=None):
     """ Initialize a typed SortedDict.
         :param key_type: expected type for keys.
         :param val_type: expected type for values.
         :param kwargs: (optional) dictionary-like object: initial values for sorted dict.
     """
     self.__val_type = val_type
     self.__keys = SortedSet(key_type)
     self.__couples = {}
     if kwargs is not None:
         assert is_dictionary(kwargs)
         for key, value in kwargs.items():
             self.put(key, value)
示例#4
0
class MyJsonable(Jsonable):
    """ Example of class derived from Jsonable. """
    __slots__ = ('field_a', 'field_b', 'field_c', 'field_d', 'field_e',
                 'field_f', 'field_g')

    model = {
        'field_a':
        bool,
        'field_b':
        str,
        'field_c':
        parsing.OptionalValueType(float),
        'field_d':
        parsing.DefaultValueType(str, 'super'),
        'field_e':
        parsing.SequenceType(int),
        'field_f':
        parsing.SequenceType(float, sequence_builder=SortedSet.builder(float)),
        'field_g':
        parsing.DefaultValueType(
            parsing.DictType(str, int, SortedDict.builder(str, int)),
            {'x': -1})
    }

    def __init__(self, **kwargs):
        """ Constructor """
        self.field_a = None
        self.field_b = None
        self.field_c = None
        self.field_d = None
        self.field_e = None
        self.field_f = None
        self.field_g = {}
        super(MyJsonable, self).__init__(**kwargs)
示例#5
0
def test_iteration():
    """ Test SortedSet iteration. """

    expected_sorted_values = ['cat', 'lion', 'panthera', 'serval', 'tiger']
    sorted_set = SortedSet(str, ('lion', 'tiger', 'panthera', 'cat', 'serval'))
    computed_sorted_values = [key for key in sorted_set]
    assert_equals(expected_sorted_values, computed_sorted_values)
示例#6
0
def test_builder_and_property():
    """ Test SortedSet builder and property element_type. """

    builder_float = SortedSet.builder(float)
    sorted_set = builder_float((2.5, 2.7, 2.9))
    assert isinstance(sorted_set,
                      SortedSet) and sorted_set.element_type is float
示例#7
0
def test_index():
    """ Test SortedSet method index(). """

    sorted_set = SortedSet(int,
                           (2, 5, 1, 9, 4, 5, 20, 0, 6, 17, 8, 3, 7, 0, 4))
    sorted_set.remove(8)
    sorted_set.remove(4)
    index_of_2 = sorted_set.index(2)
    index_of_17 = sorted_set.index(17)
    assert index_of_2 == 2
    assert sorted_set.index(4) is None
    assert sorted_set.index(8) is None
    assert index_of_17 == len(sorted_set) - 2
    assert sorted_set.pop(index_of_2) == 2
示例#8
0
def test_item_add_get_and_contains():
    """ Test SortedSet methods add(), __getitem__(), and __contains__(). """

    expected_values = ['cat', 'lion', 'panthera', 'serval', 'tiger']
    sorted_set = SortedSet(str, ('lion', 'tiger'))
    # Test setter.
    sorted_set.add('panthera')
    sorted_set.add('cat')
    sorted_set.add('serval')
    # Test __contains__.
    assert 'lions' not in sorted_set
    assert all(key in sorted_set for key in expected_values)
    # Test getter.
    assert sorted_set[0] == 'cat'
    assert sorted_set[1] == 'lion'
    assert sorted_set[2] == 'panthera'
    assert sorted_set[3] == 'serval'
    assert sorted_set[4] == 'tiger'
    # Test add then getter.
    sorted_set.add('onca')
    assert sorted_set[1] == 'lion'
    assert sorted_set[2] == 'onca'
    assert sorted_set[3] == 'panthera'
示例#9
0
def test_pop_and_remove():
    """ Test SortedSet methods remove() and pop(). """

    sorted_set = SortedSet(str, ('lion', 'tiger', 'panthera', 'cat', 'serval'))
    assert len(sorted_set) == 5
    assert 'serval' in sorted_set
    sorted_set.remove('serval')
    assert len(sorted_set) == 4
    assert 'serval' not in sorted_set
    assert sorted_set.remove('tiger') == 'tiger'
    assert len(sorted_set) == 3
    assert 'tiger' not in sorted_set
    assert sorted_set.remove('tiger') is None
    assert sorted_set.remove('key not in set') is None
    index_of_panthera = sorted_set.index('panthera')
    assert index_of_panthera == 2
    assert sorted_set.pop(index_of_panthera) == 'panthera'
    assert len(sorted_set) == 2
    assert 'panthera' not in sorted_set
    assert 'cat' in sorted_set
    assert 'lion' in sorted_set
示例#10
0
def test_equality():
    """ Test SortedSet equality. """

    empty_sorted_set_float = SortedSet(float)
    empty_sorted_set_int = SortedSet(int)
    another_empty_sorted_set_int = SortedSet(int)
    sorted_set_float_1 = SortedSet(float, (2.5, 3.3, -5.7))
    sorted_set_float_2 = SortedSet(float, (2.5, 3.3, -5.7))
    sorted_set_float_3 = SortedSet(float, (2.5, 3.3, 5.7))
    assert empty_sorted_set_float != empty_sorted_set_int
    assert empty_sorted_set_int == another_empty_sorted_set_int
    assert sorted_set_float_1 == sorted_set_float_2
    assert sorted_set_float_1 != sorted_set_float_3
示例#11
0
def test_jsonable_parsing():
    """ Test parsing for Jsonable. """

    attributes = ('field_a', 'field_b', 'field_c', 'field_d', 'field_e',
                  'field_f', 'field_g')

    # Building and validating
    my_jsonable = MyJsonable(field_a=False,
                             field_b='test',
                             field_e={1},
                             field_f=[6.5])
    for attribute_name in attributes:
        assert hasattr(my_jsonable, attribute_name)
    assert isinstance(my_jsonable.field_a, bool)
    assert isinstance(my_jsonable.field_b, str)
    assert my_jsonable.field_c is None
    assert isinstance(my_jsonable.field_d, str), my_jsonable.field_d
    assert isinstance(my_jsonable.field_e, list)
    assert isinstance(my_jsonable.field_f, SortedSet)
    assert isinstance(my_jsonable.field_g, SortedDict)
    assert my_jsonable.field_d == 'super'
    assert my_jsonable.field_e == [1]
    assert my_jsonable.field_f == SortedSet(float, (6.5, ))
    assert len(my_jsonable.field_g) == 1 and my_jsonable.field_g['x'] == -1

    # Building from its json representation and validating
    from_json = MyJsonable.from_dict(
        json.loads(json.dumps(my_jsonable.to_dict())))
    for attribute_name in attributes:
        assert hasattr(from_json, attribute_name), attribute_name
    assert from_json.field_a == my_jsonable.field_a
    assert from_json.field_b == my_jsonable.field_b
    assert from_json.field_c == my_jsonable.field_c
    assert from_json.field_d == my_jsonable.field_d
    assert from_json.field_e == my_jsonable.field_e
    assert from_json.field_f == my_jsonable.field_f
    assert from_json.field_g == my_jsonable.field_g
示例#12
0
class SortedDict():
    """ Dict with sorted keys. """
    __slots__ = ['__val_type', '__keys', '__couples']

    def __init__(self, key_type, val_type, kwargs=None):
        """ Initialize a typed SortedDict.
            :param key_type: expected type for keys.
            :param val_type: expected type for values.
            :param kwargs: (optional) dictionary-like object: initial values for sorted dict.
        """
        self.__val_type = val_type
        self.__keys = SortedSet(key_type)
        self.__couples = {}
        if kwargs is not None:
            assert is_dictionary(kwargs)
            for key, value in kwargs.items():
                self.put(key, value)

    @staticmethod
    def builder(key_type, val_type):
        """ Return a function to build sorted dicts from a dictionary-like object.
            Returned function expects a dictionary parameter (an object with method items()).
                builder_fn = SortedDict.builder(str, int)
                my_sorted_dict = builder_fn({'a': 1, 'b': 2})

            :param key_type: expected type for keys.
            :param val_type: expected type for values.
            :return: callable
        """
        return lambda dictionary: SortedDict(key_type, val_type, dictionary)

    @property
    def key_type(self):
        """ Get key type. """
        return self.__keys.element_type

    @property
    def val_type(self):
        """ Get value type. """
        return self.__val_type

    def __str__(self):
        return 'SortedDict{%s}' % ', '.join('%s:%s' % (k, self.__couples[k])
                                            for k in self.__keys)

    def __bool__(self):
        return bool(self.__keys)

    def __len__(self):
        return len(self.__keys)

    def __eq__(self, other):
        """ Return True if self and other are equal.
            Note that self and other must also have same key and value types.
        """
        assert isinstance(other, SortedDict)
        return (self.key_type is other.key_type
                and self.val_type is other.val_type and len(self) == len(other)
                and all(key in other and self[key] == other[key]
                        for key in self.__keys))

    def __getitem__(self, key):
        return self.__couples[key]

    def __setitem__(self, key, value):
        self.put(key, value)

    def __delitem__(self, key):
        self.remove(key)

    def __iter__(self):
        return self.__keys.__iter__()

    def __contains__(self, key):
        return key in self.__couples

    def get(self, key, default=None):
        """ Return value associated with key, or default value if key not found. """
        return self.__couples.get(key, default)

    def put(self, key, value):
        """ Add a key with a value to the dict. """
        if not isinstance(value, self.__val_type):
            raise TypeError('Expected value type %s, got %s' %
                            (self.__val_type, type(value)))
        if key not in self.__keys:
            self.__keys.add(key)
        self.__couples[key] = value

    def remove(self, key):
        """ Pop (remove and return) value associated with given key, or None if key not found. """
        if key in self.__couples:
            self.__keys.remove(key)
        return self.__couples.pop(key, None)

    def first_key(self):
        """ Get the lowest key from the dict. """
        return self.__keys[0]

    def first_value(self):
        """ Get the value associated to lowest key in the dict. """
        return self.__couples[self.__keys[0]]

    def last_key(self):
        """ Get the highest key from the dict. """
        return self.__keys[-1]

    def last_value(self):
        """ Get the value associated to highest key in the dict. """
        return self.__couples[self.__keys[-1]]

    def last_item(self):
        """ Get the item (key-value pair) for the highest key in the dict. """
        return self.__keys[-1], self.__couples[self.__keys[-1]]

    def keys(self):
        """ Get an iterator to the keys in the dict. """
        return iter(self.__keys)

    def values(self):
        """ Get an iterator to the values in the dict. """
        return (self.__couples[k] for k in self.__keys)

    def reversed_values(self):
        """ Get an iterator to the values in the dict in reversed order or keys. """
        return (self.__couples[k] for k in reversed(self.__keys))

    def items(self):
        """ Get an iterator to the items in the dict. """
        return ((k, self.__couples[k]) for k in self.__keys)

    def reversed_items(self):
        """ Get an iterator to the items in the dict in reversed order of keys. """
        return ((k, self.__couples[k]) for k in reversed(self.__keys))

    def sub_keys(self, key_from=None, key_to=None):
        """ Return list of keys between key_from and key_to (both bounds included). """
        position_from, position_to = self._get_keys_interval(key_from, key_to)
        return self.__keys[position_from:(position_to + 1)]

    def sub(self, key_from=None, key_to=None):
        """ Return a list of values associated to keys between key_from and key_to (both bounds included).

            If key_from is None, lowest key in dict is used.
            If key_to is None, greatest key in dict is used.
            If key_from is not in dict, lowest key in dict greater than key_from is used.
            If key_to is not in dict, greatest key in dict less than key_to is used.

            If dict is empty, return empty list.
            With keys (None, None) return a copy of all values.
            With keys (None, key_to), return values from first to the one associated to key_to.
            With keys (key_from, None), return values from the one associated to key_from to the last value.

            :param key_from: start key
            :param key_to: end key
            :return: list: values in closed keys interval [key_from; key_to]
        """
        position_from, position_to = self._get_keys_interval(key_from, key_to)
        return [
            self.__couples[k]
            for k in self.__keys[position_from:(position_to + 1)]
        ]

    def remove_sub(self, key_from=None, key_to=None):
        """ Remove values associated to keys between key_from and key_to (both bounds included).

            See sub() doc about key_from and key_to.

            :param key_from: start key
            :param key_to: end key
            :return: nothing
            """
        position_from, position_to = self._get_keys_interval(key_from, key_to)
        keys_to_remove = self.__keys[position_from:(position_to + 1)]
        for key in keys_to_remove:
            self.remove(key)

    def key_from_index(self, index):
        """ Return key matching given position in sorted dict, or None for invalid position. """
        return self.__keys[index] if -len(self.__keys) <= index < len(
            self.__keys) else None

    def get_previous_key(self, key):
        """ Return greatest key lower than given key, or None if not exists. """
        return self.__keys.get_previous_value(key)

    def get_next_key(self, key):
        """ Return smallest key greater then given key, or None if not exists. """
        return self.__keys.get_next_value(key)

    def _get_keys_interval(self, key_from, key_to):
        """ Get a couple of internal key positions (index of key_from, index of key_to) allowing
            to easily retrieve values in closed interval [index of key_from; index of key_to]
            corresponding to Python slice [index of key_from : (index of key_to + 1)]

            If dict is empty, return (0, -1), so that python slice [0 : -1 + 1] corresponds to empty interval.
            If key_from is None, lowest key in dict is used.
            If key_to is None, greatest key in dict is used.
            If key_from is not in dict, lowest key in dict greater than key_from is used.
            If key_to is not in dict, greatest key in dict less than key_to is used.

            Thus:
            - With keys (None, None), we get interval of all values.
            - With keys (key_from, None), we get interval for values from key_from to the last key.
            - With keys (None, key_to), we get interval for values from the first key to key_to.

            :param key_from: start key
            :param key_to: end key
            :return: (int, int): couple of integers: (index of key_from, index of key_to).
        """
        if not self:
            return 0, -1
        if key_from is not None and key_from not in self.__couples:
            key_from = self.__keys.get_next_value(key_from)
            if key_from is None:
                return 0, -1
        if key_to is not None and key_to not in self.__couples:
            key_to = self.__keys.get_previous_value(key_to)
            if key_to is None:
                return 0, -1
        if key_from is None and key_to is None:
            key_from = self.first_key()
            key_to = self.last_key()
        elif key_from is not None and key_to is None:
            key_to = self.last_key()
        elif key_from is None and key_to is not None:
            key_from = self.first_key()
        if key_from > key_to:
            raise IndexError('expected key_from <= key_to (%s vs %s)' %
                             (key_from, key_to))
        position_from = self.__keys.index(key_from)
        position_to = self.__keys.index(key_to)
        assert position_from is not None and position_to is not None
        return position_from, position_to

    def clear(self):
        """ Remove all items from dict. """
        self.__couples.clear()
        self.__keys.clear()

    def fill(self, dct):
        """ Add given dict to this sorted dict. """
        if dct:
            assert is_dictionary(dct)
            for key, value in dct.items():
                self.put(key, value)

    def copy(self):
        """ Return a copy of this sorted dict. """
        return SortedDict(self.__keys.element_type, self.__val_type,
                          self.__couples)
示例#13
0
def test_common_utils_with_sorted_set():
    """Check sorted set with is_sequence() and is_dictionary()."""
    assert common.is_sequence(SortedSet(int, (1, 2, 3)))
    assert common.is_sequence(SortedSet(int))
    assert not common.is_dictionary(SortedSet(int, (1, 2, 3)))
    assert not common.is_dictionary(SortedSet(int))
示例#14
0
def test_getters_around_values():
    """Test SortedSet methods get_next_value() and get_previous_value()."""

    sorted_set = SortedSet(int,
                           (2, 5, 1, 9, 4, 5, 20, 0, 6, 17, 8, 3, 7, 0, 4))
    expected = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 20)
    assert sorted_set
    assert len(sorted_set) == len(expected)
    assert all(expected[i] == sorted_set[i] for i in range(len(expected)))
    assert all(e in sorted_set for e in expected)
    assert sorted_set.get_next_value(0) == 1
    assert sorted_set.get_next_value(5) == 6
    assert sorted_set.get_next_value(9) == 17
    assert sorted_set.get_next_value(-1) == 0
    assert sorted_set.get_next_value(20) is None
    assert sorted_set.get_previous_value(0) is None
    assert sorted_set.get_previous_value(17) == 9
    assert sorted_set.get_previous_value(20) == 17
    assert sorted_set.get_previous_value(1) == 0
    assert sorted_set.get_previous_value(6) == 5

    assert sorted_set.get_next_value(3) == 4
    assert sorted_set.get_next_value(4) == 5
    assert sorted_set.get_next_value(7) == 8
    assert sorted_set.get_next_value(8) == 9
    assert sorted_set.get_previous_value(5) == 4
    assert sorted_set.get_previous_value(4) == 3
    assert sorted_set.get_previous_value(9) == 8
    assert sorted_set.get_previous_value(8) == 7
    sorted_set.remove(8)
    assert len(sorted_set) == len(expected) - 1
    assert 8 not in sorted_set
    sorted_set.remove(4)
    assert len(sorted_set) == len(expected) - 2
    assert 4 not in sorted_set
    assert sorted_set.get_next_value(3) == 5
    assert sorted_set.get_next_value(4) == 5
    assert sorted_set.get_next_value(7) == 9
    assert sorted_set.get_next_value(8) == 9
    assert sorted_set.get_previous_value(5) == 3
    assert sorted_set.get_previous_value(4) == 3
    assert sorted_set.get_previous_value(9) == 7
    assert sorted_set.get_previous_value(8) == 7