def test_list_constructor(): regular_list = ['a', 'b'] ll = sanest.list(regular_list) assert len(ll) == 2 with pytest.raises(TypeError) as excinfo: sanest.list([1, 2, 3], [4, 5], [6, 7]) assert str(excinfo.value) == "expected at most 1 argument, got 3"
def test_list_comparison_ordering(): l1 = sanest.list([1, 2]) l2 = sanest.list([2, 3, 4]) normal_list = [1, 2] assert l1 < l2 assert l1 <= l2 assert l2 > l1 assert l2 >= l1 assert not l1 < normal_list assert not l1 > normal_list assert l1 <= normal_list assert l1 >= normal_list assert l2 > normal_list assert normal_list < l2 if sys.version_info >= (3, 6): pattern = r" not supported between instances " else: pattern = r"^unorderable types: " with pytest.raises(TypeError) as excinfo: l1 < object() assert excinfo.match(pattern) with pytest.raises(TypeError) as excinfo: l1 <= object() assert excinfo.match(pattern) with pytest.raises(TypeError) as excinfo: l1 > object() assert excinfo.match(pattern) with pytest.raises(TypeError) as excinfo: l1 >= object() assert excinfo.match(pattern)
def test_list_validate(): ll = sanest.list([1, 2, 3]) ll.check_types(type=int) ll = sanest.list([{'a': 1}, {'a': 2}, {'a': 3}]) ll.check_types(type={str: int}) with pytest.raises(sanest.InvalidValueError) as excinfo: ll.check_types(type=str) assert str(excinfo.value) == "expected str, got dict at path [0]: {'a': 1}"
def test_list_setitem(): ll = sanest.list(['a', 'b']) ll[0] = 'b' ll[1] = sanest.list() assert ll == ['b', []] with pytest.raises(IndexError) as excinfo: ll[5] = 'a' assert str(excinfo.value) == "[5]" assert ll == ['b', []]
def test_list_iteration_with_type(): ll = sanest.list(['a', 'a']) assert list(ll.iter()) == ['a', 'a'] assert list(ll.iter(type=str)) == ['a', 'a'] ll = sanest.list([1, 2, 'oops']) with pytest.raises(sanest.InvalidValueError) as excinfo: ll.iter(type=int) # eager validation, not during yielding assert str(excinfo.value) == "expected int, got str at path [2]: 'oops'" ll = sanest.list([{}]) assert isinstance(next(ll.iter(type=dict)), sanest.dict)
def test_list_comparison_equality(): l1 = sanest.list([1, 2]) l2 = sanest.list([1, 2]) normal_list = [1, 2] assert l1 == normal_list assert l1 == l1 assert l1 == l2 assert l1 != [2, 1] assert l1 != [3] assert l1 != object()
def test_list_append(): ll = sanest.list() ll.append(1) with pytest.raises(sanest.InvalidValueError) as excinfo: ll.append('a', type=int) assert str(excinfo.value) == "expected int, got str: 'a'" assert ll == [1] ll.append(2) ll.append([3, 4]) ll.append(sanest.list([5, 6])) assert len(ll) == 4 assert ll == [1, 2, [3, 4], [5, 6]]
def test_list_extend_nested_unwrapping(): ll = sanest.list([ [[1, 2], [3, 4]], sanest.list([ sanest.list([5, 6]), sanest.list([7, 8]), ]), ]) assert ll == [ [[1, 2], [3, 4]], [[5, 6], [7, 8]], ]
def test_list_extend(): ll = sanest.list([1, 2]) ll.extend(sanest.list([3, 4])) ll.extend([5, 6], type=int) assert ll == [1, 2, 3, 4, 5, 6] with pytest.raises(sanest.InvalidValueError) as excinfo: ll.extend(['a', 'b'], type=int) assert str(excinfo.value) == "expected int, got str: 'a'" assert ll == [1, 2, 3, 4, 5, 6] with pytest.raises(sanest.InvalidValueError) as excinfo: ll.extend([MyClass()]) assert str(excinfo.value) == "invalid value of type MyClass: <MyClass>" ll.extend(n for n in [7, 8]) assert ll == [1, 2, 3, 4, 5, 6, 7, 8]
def test_list_delitem_with_path(): ll = sanest.list([['a', 'aa'], ['b', 'bb']]) del ll[0, 1] assert ll == [['a'], ['b', 'bb']] path = [1, 0] del ll[path] assert ll == [['a'], ['bb']]
def test_list_index(): ll = sanest.list([ 'a', # 0 { 'b': 'c' }, # 1 None, # 2 None, # 3 'a', # 4 None, # 5 None, # 6 ]) assert ll.index('a') == 0 assert ll.index('a', type=str) == 0 assert ll.index('a', 2) == 4 assert ll.index('a', 2, type=str) == 4 assert ll.index('a', 2, 6) == 4 assert ll.index(None, 2) == 2 assert ll.index(None, 4) == 5 assert ll.index({'b': 'c'}) == 1 assert ll.index(sanest.dict({'b': 'c'})) == 1 with pytest.raises(ValueError) as excinfo: ll.index('a', 5) assert str(excinfo.value) == "'a' is not in list" with pytest.raises(ValueError) as excinfo: ll.index('a', 2, 3) assert str(excinfo.value) == "'a' is not in list" with pytest.raises(sanest.InvalidValueError) as excinfo: ll.index(2, type=str) assert str(excinfo.value) == "expected str, got int: 2"
def test_list_set_slice(): ll = sanest.list(['a', 'b', 'c', 'd', 'e']) ll[::2] = ['x', 'y', 'z'] assert ll == ['x', 'b', 'y', 'd', 'z'] ll[:] = ['p', 'q', 'r'] assert ll == ['p', 'q', 'r'] with pytest.raises(sanest.InvalidValueError) as excinfo: ll[:3] = [MyClass()] assert str(excinfo.value) == "invalid value of type MyClass: <MyClass>" assert ll == ['p', 'q', 'r'] ll[:2] = sanest.list([{}, []]) assert ll == [{}, [], 'r'] with pytest.raises(ValueError) as excinfo: ll[0::2] = ['this', 'one', 'is', 'too', 'long'] assert str(excinfo.value) == ( "attempt to assign sequence of size 5 to extended slice of size 2")
def test_slots(): d = sanest.dict() with pytest.raises(AttributeError): d.foo = 123 ll = sanest.list() with pytest.raises(AttributeError): ll.foo = 123
def test_list_getitem_with_type(): ll = sanest.list(['a', {}]) assert ll[0:str] == 'a' with pytest.raises(sanest.InvalidValueError) as excinfo: assert ll[0:bool] == 'a' assert str(excinfo.value) == "expected bool, got str at path [0]: 'a'" assert isinstance(ll[1], sanest.dict)
def test_list_getitem(): ll = sanest.list(['a', 'b']) assert ll[0] == 'a' assert ll[1] == 'b' with pytest.raises(IndexError) as excinfo: ll[2] assert str(excinfo.value) == "[2]"
def test_list_getitem_with_path_and_type(): ll = sanest.list(['a', ['b1', 'b2']]) assert ll[1, 0:str] == "b1" path = [1, 0] assert ll[path:str] == "b1" with pytest.raises(sanest.InvalidValueError) as excinfo: ll[1, 1:bool] assert str(excinfo.value) == "expected bool, got str at path [1, 1]: 'b2'"
def test_list_basics(): d = sanest.list() d.append('a') assert d[0] == 'a' d.append('b') d.append('c') assert d[1] == 'b' assert d[2] == 'c'
def test_list_del_slice(): ll = sanest.list(['a', 'b', 'c', 'd', 'e']) del ll[:2] assert ll == ['c', 'd', 'e'] del ll[-1:] assert ll == ['c', 'd'] del ll[:] assert ll == []
def test_list_delitem_with_type(): ll = sanest.list(['a', 'b', 'c']) del ll[0:str] assert ll == ['b', 'c'] with pytest.raises(sanest.InvalidValueError) as excinfo: del ll[-1:int] assert str(excinfo.value) == "expected int, got str at path [-1]: 'c'" assert ll == ['b', 'c']
def test_list_delitem(): ll = sanest.list(['a', 'b', 'c']) del ll[1] assert ll == ['a', 'c'] del ll[-1] assert ll == ['a'] del ll[0] assert ll == []
def test_wrong_path_for_container_type(): d = sanest.dict() ll = sanest.list() with pytest.raises(sanest.InvalidPathError) as excinfo: d[2, 'a'] assert str(excinfo.value) == "dict path must start with str: [2, 'a']" with pytest.raises(sanest.InvalidPathError) as excinfo: ll['a', 2] assert str(excinfo.value) == "list path must start with int: ['a', 2]"
def test_list_contains_with_type(): ll = sanest.list([1, 'a', {'c': 'd'}]) assert ll.contains(1, type=int) assert ll.contains('a', type=str) assert ll.contains({'c': 'd'}, type=dict) assert not ll.contains(1, type=str) assert not ll.contains(2, type=str) assert not ll.contains({'x': 'y'}, type=dict) assert not ll.contains({'x': 'y'}, type=int)
def test_list_count(): ll = sanest.list([1, 2, 3, 1, 1, 2, 3, {'a': 'b'}]) assert ll.count(1) == 3 assert ll.count(1, type=int) == 3 with pytest.raises(sanest.InvalidValueError) as excinfo: ll.count(1, type=str) assert str(excinfo.value) == "expected str, got int: 1" assert ll.count({'a': 'b'}) == 1 assert ll.count(sanest.dict({'a': 'b'})) == 1
def test_list_repeat(): ll = sanest.list([1, 2]) assert ll * 2 == [1, 2, 1, 2] assert 2 * ll == [1, 2, 1, 2] assert ll == [1, 2] assert isinstance(ll, sanest.list) ll *= 2 assert ll == [1, 2, 1, 2] assert isinstance(ll, sanest.list)
def test_dict_values_view_contains(): d = sanest.dict({'a': 1, 'b': 2, 'c': [3, 4, 5]}) values_view = d.values() assert len(values_view) == len(d) == 3 assert 1 in values_view assert [3, 4, 5] in values_view assert sanest.list([3, 4, 5]) in values_view with pytest.raises(sanest.InvalidValueError) as excinfo: MyClass() in values_view assert str(excinfo.value) == "invalid value of type MyClass: <MyClass>"
def test_list_setitem_with_path_and_type(): ll = sanest.list(['a', ['b', 'c']]) ll[1, 0:str] = "d" path = [1, 1] ll[path:str] = "e" assert ll == ['a', ['d', 'e']] with pytest.raises(sanest.InvalidValueError) as excinfo: ll[1, 1:bool] = 'x' assert str(excinfo.value) == "expected bool, got str: 'x'" assert ll == ['a', ['d', 'e']]
def test_list_get_slice(): ll = sanest.list(['a', 'b', 'c']) assert ll[0:] == ['a', 'b', 'c'] assert ll[2:] == ['c'] assert ll[:0] == [] assert ll[:-2] == ['a'] assert ll[0:20] == ['a', 'b', 'c'] assert ll[:] == ['a', 'b', 'c'] assert ll[::2] == ['a', 'c'] assert isinstance(ll[1:2], sanest.list)
def test_list_delitem_with_path_and_type(): ll = sanest.list([['a', 'aa'], ['b', 'bb']]) del ll[0, 0:str] with pytest.raises(sanest.InvalidValueError) as excinfo: del ll[0, 0:int] assert str(excinfo.value) == "expected int, got str at path [0, 0]: 'aa'" assert ll == [['aa'], ['b', 'bb']] path = [1, 1] del ll[path:str] assert ll == [['aa'], ['b']]
def test_list_reversing(): ll = sanest.list(['a', {}]) rev = reversed(ll) first, second = rev assert first == {} assert isinstance(first, sanest.dict) assert second == 'a' assert ll == ['a', {}] ll.reverse() assert ll == [{}, 'a']
def test_list_concat(): x = sanest.list(['a', 'b']) y = sanest.list(['c']) z = ['d'] xy = x + y assert xy == ['a', 'b', 'c'] assert isinstance(xy, sanest.list) xz = x + z assert xz == ['a', 'b', 'd'] assert isinstance(xz, sanest.list) assert x == ['a', 'b'] zx = z + x assert zx == ['d', 'a', 'b'] assert isinstance(zx, builtins.list) x += z assert isinstance(x, sanest.list) assert x == xz xy += z assert isinstance(xy, sanest.list) assert xy == ['a', 'b', 'c', 'd']