test_sequences_and_iterators.py revision 14299
111986Sandreas.sandberg@arm.comimport pytest 212391Sjason@lowepower.comfrom pybind11_tests import sequences_and_iterators as m 312391Sjason@lowepower.comfrom pybind11_tests import ConstructorStats 411986Sandreas.sandberg@arm.com 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.comdef isclose(a, b, rel_tol=1e-05, abs_tol=0.0): 711986Sandreas.sandberg@arm.com """Like math.isclose() from Python 3.5""" 811986Sandreas.sandberg@arm.com return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com 1111986Sandreas.sandberg@arm.comdef allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0): 1211986Sandreas.sandberg@arm.com return all(isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list)) 1311986Sandreas.sandberg@arm.com 1411986Sandreas.sandberg@arm.com 1511986Sandreas.sandberg@arm.comdef test_generalized_iterators(): 1612391Sjason@lowepower.com assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).nonzero()) == [(1, 2), (3, 4)] 1712391Sjason@lowepower.com assert list(m.IntPairs([(1, 2), (2, 0), (0, 3), (4, 5)]).nonzero()) == [(1, 2)] 1812391Sjason@lowepower.com assert list(m.IntPairs([(0, 3), (1, 2), (3, 4)]).nonzero()) == [] 1911986Sandreas.sandberg@arm.com 2012391Sjason@lowepower.com assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).nonzero_keys()) == [1, 3] 2112391Sjason@lowepower.com assert list(m.IntPairs([(1, 2), (2, 0), (0, 3), (4, 5)]).nonzero_keys()) == [1] 2212391Sjason@lowepower.com assert list(m.IntPairs([(0, 3), (1, 2), (3, 4)]).nonzero_keys()) == [] 2311986Sandreas.sandberg@arm.com 2412391Sjason@lowepower.com # __next__ must continue to raise StopIteration 2512391Sjason@lowepower.com it = m.IntPairs([(0, 0)]).nonzero() 2612391Sjason@lowepower.com for _ in range(3): 2712391Sjason@lowepower.com with pytest.raises(StopIteration): 2812391Sjason@lowepower.com next(it) 2912391Sjason@lowepower.com 3012391Sjason@lowepower.com it = m.IntPairs([(0, 0)]).nonzero_keys() 3112391Sjason@lowepower.com for _ in range(3): 3212391Sjason@lowepower.com with pytest.raises(StopIteration): 3312391Sjason@lowepower.com next(it) 3411986Sandreas.sandberg@arm.com 3511986Sandreas.sandberg@arm.com 3614299Sbbruce@ucdavis.edudef test_sliceable(): 3714299Sbbruce@ucdavis.edu sliceable = m.Sliceable(100) 3814299Sbbruce@ucdavis.edu assert sliceable[::] == (0, 100, 1) 3914299Sbbruce@ucdavis.edu assert sliceable[10::] == (10, 100, 1) 4014299Sbbruce@ucdavis.edu assert sliceable[:10:] == (0, 10, 1) 4114299Sbbruce@ucdavis.edu assert sliceable[::10] == (0, 100, 10) 4214299Sbbruce@ucdavis.edu assert sliceable[-10::] == (90, 100, 1) 4314299Sbbruce@ucdavis.edu assert sliceable[:-10:] == (0, 90, 1) 4414299Sbbruce@ucdavis.edu assert sliceable[::-10] == (99, -1, -10) 4514299Sbbruce@ucdavis.edu assert sliceable[50:60:1] == (50, 60, 1) 4614299Sbbruce@ucdavis.edu assert sliceable[50:60:-1] == (50, 60, -1) 4714299Sbbruce@ucdavis.edu 4814299Sbbruce@ucdavis.edu 4911986Sandreas.sandberg@arm.comdef test_sequence(): 5012391Sjason@lowepower.com cstats = ConstructorStats.get(m.Sequence) 5111986Sandreas.sandberg@arm.com 5212391Sjason@lowepower.com s = m.Sequence(5) 5311986Sandreas.sandberg@arm.com assert cstats.values() == ['of size', '5'] 5411986Sandreas.sandberg@arm.com 5511986Sandreas.sandberg@arm.com assert "Sequence" in repr(s) 5611986Sandreas.sandberg@arm.com assert len(s) == 5 5711986Sandreas.sandberg@arm.com assert s[0] == 0 and s[3] == 0 5811986Sandreas.sandberg@arm.com assert 12.34 not in s 5911986Sandreas.sandberg@arm.com s[0], s[3] = 12.34, 56.78 6011986Sandreas.sandberg@arm.com assert 12.34 in s 6111986Sandreas.sandberg@arm.com assert isclose(s[0], 12.34) and isclose(s[3], 56.78) 6211986Sandreas.sandberg@arm.com 6311986Sandreas.sandberg@arm.com rev = reversed(s) 6411986Sandreas.sandberg@arm.com assert cstats.values() == ['of size', '5'] 6511986Sandreas.sandberg@arm.com 6611986Sandreas.sandberg@arm.com rev2 = s[::-1] 6711986Sandreas.sandberg@arm.com assert cstats.values() == ['of size', '5'] 6811986Sandreas.sandberg@arm.com 6912391Sjason@lowepower.com it = iter(m.Sequence(0)) 7012391Sjason@lowepower.com for _ in range(3): # __next__ must continue to raise StopIteration 7112391Sjason@lowepower.com with pytest.raises(StopIteration): 7212391Sjason@lowepower.com next(it) 7312391Sjason@lowepower.com assert cstats.values() == ['of size', '0'] 7412391Sjason@lowepower.com 7511986Sandreas.sandberg@arm.com expected = [0, 56.78, 0, 0, 12.34] 7611986Sandreas.sandberg@arm.com assert allclose(rev, expected) 7711986Sandreas.sandberg@arm.com assert allclose(rev2, expected) 7811986Sandreas.sandberg@arm.com assert rev == rev2 7911986Sandreas.sandberg@arm.com 8012391Sjason@lowepower.com rev[0::2] = m.Sequence([2.0, 2.0, 2.0]) 8111986Sandreas.sandberg@arm.com assert cstats.values() == ['of size', '3', 'from std::vector'] 8211986Sandreas.sandberg@arm.com 8311986Sandreas.sandberg@arm.com assert allclose(rev, [2, 56.78, 2, 0, 2]) 8411986Sandreas.sandberg@arm.com 8512391Sjason@lowepower.com assert cstats.alive() == 4 8612391Sjason@lowepower.com del it 8711986Sandreas.sandberg@arm.com assert cstats.alive() == 3 8811986Sandreas.sandberg@arm.com del s 8911986Sandreas.sandberg@arm.com assert cstats.alive() == 2 9011986Sandreas.sandberg@arm.com del rev 9111986Sandreas.sandberg@arm.com assert cstats.alive() == 1 9211986Sandreas.sandberg@arm.com del rev2 9311986Sandreas.sandberg@arm.com assert cstats.alive() == 0 9411986Sandreas.sandberg@arm.com 9511986Sandreas.sandberg@arm.com assert cstats.values() == [] 9611986Sandreas.sandberg@arm.com assert cstats.default_constructions == 0 9711986Sandreas.sandberg@arm.com assert cstats.copy_constructions == 0 9811986Sandreas.sandberg@arm.com assert cstats.move_constructions >= 1 9911986Sandreas.sandberg@arm.com assert cstats.copy_assignments == 0 10011986Sandreas.sandberg@arm.com assert cstats.move_assignments == 0 10111986Sandreas.sandberg@arm.com 10211986Sandreas.sandberg@arm.com 10311986Sandreas.sandberg@arm.comdef test_map_iterator(): 10412391Sjason@lowepower.com sm = m.StringMap({'hi': 'bye', 'black': 'white'}) 10512391Sjason@lowepower.com assert sm['hi'] == 'bye' 10612391Sjason@lowepower.com assert len(sm) == 2 10712391Sjason@lowepower.com assert sm['black'] == 'white' 10811986Sandreas.sandberg@arm.com 10911986Sandreas.sandberg@arm.com with pytest.raises(KeyError): 11012391Sjason@lowepower.com assert sm['orange'] 11112391Sjason@lowepower.com sm['orange'] = 'banana' 11212391Sjason@lowepower.com assert sm['orange'] == 'banana' 11311986Sandreas.sandberg@arm.com 11411986Sandreas.sandberg@arm.com expected = {'hi': 'bye', 'black': 'white', 'orange': 'banana'} 11512391Sjason@lowepower.com for k in sm: 11612391Sjason@lowepower.com assert sm[k] == expected[k] 11712391Sjason@lowepower.com for k, v in sm.items(): 11811986Sandreas.sandberg@arm.com assert v == expected[k] 11912037Sandreas.sandberg@arm.com 12012391Sjason@lowepower.com it = iter(m.StringMap({})) 12112391Sjason@lowepower.com for _ in range(3): # __next__ must continue to raise StopIteration 12212391Sjason@lowepower.com with pytest.raises(StopIteration): 12312391Sjason@lowepower.com next(it) 12412391Sjason@lowepower.com 12512037Sandreas.sandberg@arm.com 12612037Sandreas.sandberg@arm.comdef test_python_iterator_in_cpp(): 12712037Sandreas.sandberg@arm.com t = (1, 2, 3) 12812037Sandreas.sandberg@arm.com assert m.object_to_list(t) == [1, 2, 3] 12912037Sandreas.sandberg@arm.com assert m.object_to_list(iter(t)) == [1, 2, 3] 13012037Sandreas.sandberg@arm.com assert m.iterator_to_list(iter(t)) == [1, 2, 3] 13112037Sandreas.sandberg@arm.com 13212037Sandreas.sandberg@arm.com with pytest.raises(TypeError) as excinfo: 13312037Sandreas.sandberg@arm.com m.object_to_list(1) 13412037Sandreas.sandberg@arm.com assert "object is not iterable" in str(excinfo.value) 13512037Sandreas.sandberg@arm.com 13612037Sandreas.sandberg@arm.com with pytest.raises(TypeError) as excinfo: 13712037Sandreas.sandberg@arm.com m.iterator_to_list(1) 13812037Sandreas.sandberg@arm.com assert "incompatible function arguments" in str(excinfo.value) 13912037Sandreas.sandberg@arm.com 14012037Sandreas.sandberg@arm.com def bad_next_call(): 14112037Sandreas.sandberg@arm.com raise RuntimeError("py::iterator::advance() should propagate errors") 14212037Sandreas.sandberg@arm.com 14312037Sandreas.sandberg@arm.com with pytest.raises(RuntimeError) as excinfo: 14412037Sandreas.sandberg@arm.com m.iterator_to_list(iter(bad_next_call, None)) 14512037Sandreas.sandberg@arm.com assert str(excinfo.value) == "py::iterator::advance() should propagate errors" 14612037Sandreas.sandberg@arm.com 14714299Sbbruce@ucdavis.edu lst = [1, None, 0, None] 14814299Sbbruce@ucdavis.edu assert m.count_none(lst) == 2 14914299Sbbruce@ucdavis.edu assert m.find_none(lst) is True 15012037Sandreas.sandberg@arm.com assert m.count_nonzeros({"a": 0, "b": 1, "c": 2}) == 2 15112037Sandreas.sandberg@arm.com 15212037Sandreas.sandberg@arm.com r = range(5) 15312037Sandreas.sandberg@arm.com assert all(m.tuple_iterator(tuple(r))) 15412037Sandreas.sandberg@arm.com assert all(m.list_iterator(list(r))) 15512037Sandreas.sandberg@arm.com assert all(m.sequence_iterator(r)) 15612391Sjason@lowepower.com 15712391Sjason@lowepower.com 15812391Sjason@lowepower.comdef test_iterator_passthrough(): 15912391Sjason@lowepower.com """#181: iterator passthrough did not compile""" 16012391Sjason@lowepower.com from pybind11_tests.sequences_and_iterators import iterator_passthrough 16112391Sjason@lowepower.com 16212391Sjason@lowepower.com assert list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))) == [3, 5, 7, 9, 11, 13, 15] 16312391Sjason@lowepower.com 16412391Sjason@lowepower.com 16512391Sjason@lowepower.comdef test_iterator_rvp(): 16612391Sjason@lowepower.com """#388: Can't make iterators via make_iterator() with different r/v policies """ 16712391Sjason@lowepower.com import pybind11_tests.sequences_and_iterators as m 16812391Sjason@lowepower.com 16912391Sjason@lowepower.com assert list(m.make_iterator_1()) == [1, 2, 3] 17012391Sjason@lowepower.com assert list(m.make_iterator_2()) == [1, 2, 3] 17112391Sjason@lowepower.com assert not isinstance(m.make_iterator_1(), type(m.make_iterator_2())) 172