Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:57

0001 import pytest
0002 from pytest import approx
0003 
0004 from pybind11_tests import ConstructorStats
0005 from pybind11_tests import sequences_and_iterators as m
0006 
0007 
0008 def test_slice_constructors():
0009     assert m.make_forward_slice_size_t() == slice(0, -1, 1)
0010     assert m.make_reversed_slice_object() == slice(None, None, -1)
0011 
0012 
0013 @pytest.mark.skipif(not m.has_optional, reason="no <optional>")
0014 def test_slice_constructors_explicit_optional():
0015     assert m.make_reversed_slice_size_t_optional() == slice(None, None, -1)
0016     assert m.make_reversed_slice_size_t_optional_verbose() == slice(None, None, -1)
0017 
0018 
0019 def test_generalized_iterators():
0020     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).nonzero()) == [(1, 2), (3, 4)]
0021     assert list(m.IntPairs([(1, 2), (2, 0), (0, 3), (4, 5)]).nonzero()) == [(1, 2)]
0022     assert list(m.IntPairs([(0, 3), (1, 2), (3, 4)]).nonzero()) == []
0023 
0024     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).nonzero_keys()) == [1, 3]
0025     assert list(m.IntPairs([(1, 2), (2, 0), (0, 3), (4, 5)]).nonzero_keys()) == [1]
0026     assert list(m.IntPairs([(0, 3), (1, 2), (3, 4)]).nonzero_keys()) == []
0027 
0028     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).nonzero_values()) == [2, 4]
0029     assert list(m.IntPairs([(1, 2), (2, 0), (0, 3), (4, 5)]).nonzero_values()) == [2]
0030     assert list(m.IntPairs([(0, 3), (1, 2), (3, 4)]).nonzero_values()) == []
0031 
0032     # __next__ must continue to raise StopIteration
0033     it = m.IntPairs([(0, 0)]).nonzero()
0034     for _ in range(3):
0035         with pytest.raises(StopIteration):
0036             next(it)
0037 
0038     it = m.IntPairs([(0, 0)]).nonzero_keys()
0039     for _ in range(3):
0040         with pytest.raises(StopIteration):
0041             next(it)
0042 
0043 
0044 def test_nonref_iterators():
0045     pairs = m.IntPairs([(1, 2), (3, 4), (0, 5)])
0046     assert list(pairs.nonref()) == [(1, 2), (3, 4), (0, 5)]
0047     assert list(pairs.nonref_keys()) == [1, 3, 0]
0048     assert list(pairs.nonref_values()) == [2, 4, 5]
0049 
0050 
0051 def test_generalized_iterators_simple():
0052     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).simple_iterator()) == [
0053         (1, 2),
0054         (3, 4),
0055         (0, 5),
0056     ]
0057     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).simple_keys()) == [1, 3, 0]
0058     assert list(m.IntPairs([(1, 2), (3, 4), (0, 5)]).simple_values()) == [2, 4, 5]
0059 
0060 
0061 def test_iterator_referencing():
0062     """Test that iterators reference rather than copy their referents."""
0063     vec = m.VectorNonCopyableInt()
0064     vec.append(3)
0065     vec.append(5)
0066     assert [int(x) for x in vec] == [3, 5]
0067     # Increment everything to make sure the referents can be mutated
0068     for x in vec:
0069         x.set(int(x) + 1)
0070     assert [int(x) for x in vec] == [4, 6]
0071 
0072     vec = m.VectorNonCopyableIntPair()
0073     vec.append([3, 4])
0074     vec.append([5, 7])
0075     assert [int(x) for x in vec.keys()] == [3, 5]
0076     assert [int(x) for x in vec.values()] == [4, 7]
0077     for x in vec.keys():
0078         x.set(int(x) + 1)
0079     for x in vec.values():
0080         x.set(int(x) + 10)
0081     assert [int(x) for x in vec.keys()] == [4, 6]
0082     assert [int(x) for x in vec.values()] == [14, 17]
0083 
0084 
0085 def test_sliceable():
0086     sliceable = m.Sliceable(100)
0087     assert sliceable[::] == (0, 100, 1)
0088     assert sliceable[10::] == (10, 100, 1)
0089     assert sliceable[:10:] == (0, 10, 1)
0090     assert sliceable[::10] == (0, 100, 10)
0091     assert sliceable[-10::] == (90, 100, 1)
0092     assert sliceable[:-10:] == (0, 90, 1)
0093     assert sliceable[::-10] == (99, -1, -10)
0094     assert sliceable[50:60:1] == (50, 60, 1)
0095     assert sliceable[50:60:-1] == (50, 60, -1)
0096 
0097 
0098 def test_sequence():
0099     cstats = ConstructorStats.get(m.Sequence)
0100 
0101     s = m.Sequence(5)
0102     assert cstats.values() == ["of size", "5"]
0103 
0104     assert "Sequence" in repr(s)
0105     assert len(s) == 5
0106     assert s[0] == 0 and s[3] == 0
0107     assert 12.34 not in s
0108     s[0], s[3] = 12.34, 56.78
0109     assert 12.34 in s
0110     assert s[0] == approx(12.34, rel=1e-05)
0111     assert s[3] == approx(56.78, rel=1e-05)
0112 
0113     rev = reversed(s)
0114     assert cstats.values() == ["of size", "5"]
0115 
0116     rev2 = s[::-1]
0117     assert cstats.values() == ["of size", "5"]
0118 
0119     it = iter(m.Sequence(0))
0120     for _ in range(3):  # __next__ must continue to raise StopIteration
0121         with pytest.raises(StopIteration):
0122             next(it)
0123     assert cstats.values() == ["of size", "0"]
0124 
0125     expected = [0, 56.78, 0, 0, 12.34]
0126     assert rev == approx(expected, rel=1e-05)
0127     assert rev2 == approx(expected, rel=1e-05)
0128     assert rev == rev2
0129 
0130     rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
0131     assert cstats.values() == ["of size", "3", "from std::vector"]
0132 
0133     assert rev == approx([2, 56.78, 2, 0, 2], rel=1e-05)
0134 
0135     assert cstats.alive() == 4
0136     del it
0137     assert cstats.alive() == 3
0138     del s
0139     assert cstats.alive() == 2
0140     del rev
0141     assert cstats.alive() == 1
0142     del rev2
0143     assert cstats.alive() == 0
0144 
0145     assert cstats.values() == []
0146     assert cstats.default_constructions == 0
0147     assert cstats.copy_constructions == 0
0148     assert cstats.move_constructions >= 1
0149     assert cstats.copy_assignments == 0
0150     assert cstats.move_assignments == 0
0151 
0152 
0153 def test_sequence_length():
0154     """#2076: Exception raised by len(arg) should be propagated"""
0155 
0156     class BadLen(RuntimeError):
0157         pass
0158 
0159     class SequenceLike:
0160         def __getitem__(self, i):
0161             return None
0162 
0163         def __len__(self):
0164             raise BadLen()
0165 
0166     with pytest.raises(BadLen):
0167         m.sequence_length(SequenceLike())
0168 
0169     assert m.sequence_length([1, 2, 3]) == 3
0170     assert m.sequence_length("hello") == 5
0171 
0172 
0173 def test_map_iterator():
0174     sm = m.StringMap({"hi": "bye", "black": "white"})
0175     assert sm["hi"] == "bye"
0176     assert len(sm) == 2
0177     assert sm["black"] == "white"
0178 
0179     with pytest.raises(KeyError):
0180         assert sm["orange"]
0181     sm["orange"] = "banana"
0182     assert sm["orange"] == "banana"
0183 
0184     expected = {"hi": "bye", "black": "white", "orange": "banana"}
0185     for k in sm:
0186         assert sm[k] == expected[k]
0187     for k, v in sm.items():
0188         assert v == expected[k]
0189     assert list(sm.values()) == [expected[k] for k in sm]
0190 
0191     it = iter(m.StringMap({}))
0192     for _ in range(3):  # __next__ must continue to raise StopIteration
0193         with pytest.raises(StopIteration):
0194             next(it)
0195 
0196 
0197 def test_python_iterator_in_cpp():
0198     t = (1, 2, 3)
0199     assert m.object_to_list(t) == [1, 2, 3]
0200     assert m.object_to_list(iter(t)) == [1, 2, 3]
0201     assert m.iterator_to_list(iter(t)) == [1, 2, 3]
0202 
0203     with pytest.raises(TypeError) as excinfo:
0204         m.object_to_list(1)
0205     assert "object is not iterable" in str(excinfo.value)
0206 
0207     with pytest.raises(TypeError) as excinfo:
0208         m.iterator_to_list(1)
0209     assert "incompatible function arguments" in str(excinfo.value)
0210 
0211     def bad_next_call():
0212         raise RuntimeError("py::iterator::advance() should propagate errors")
0213 
0214     with pytest.raises(RuntimeError) as excinfo:
0215         m.iterator_to_list(iter(bad_next_call, None))
0216     assert str(excinfo.value) == "py::iterator::advance() should propagate errors"
0217 
0218     lst = [1, None, 0, None]
0219     assert m.count_none(lst) == 2
0220     assert m.find_none(lst) is True
0221     assert m.count_nonzeros({"a": 0, "b": 1, "c": 2}) == 2
0222 
0223     r = range(5)
0224     assert all(m.tuple_iterator(tuple(r)))
0225     assert all(m.list_iterator(list(r)))
0226     assert all(m.sequence_iterator(r))
0227 
0228 
0229 def test_iterator_passthrough():
0230     """#181: iterator passthrough did not compile"""
0231     from pybind11_tests.sequences_and_iterators import iterator_passthrough
0232 
0233     values = [3, 5, 7, 9, 11, 13, 15]
0234     assert list(iterator_passthrough(iter(values))) == values
0235 
0236 
0237 def test_iterator_rvp():
0238     """#388: Can't make iterators via make_iterator() with different r/v policies"""
0239     import pybind11_tests.sequences_and_iterators as m
0240 
0241     assert list(m.make_iterator_1()) == [1, 2, 3]
0242     assert list(m.make_iterator_2()) == [1, 2, 3]
0243     assert not isinstance(m.make_iterator_1(), type(m.make_iterator_2()))
0244 
0245 
0246 def test_carray_iterator():
0247     """#4100: Check for proper iterator overload with C-Arrays"""
0248     args_gt = list(float(i) for i in range(3))
0249     arr_h = m.CArrayHolder(*args_gt)
0250     args = list(arr_h)
0251     assert args_gt == args