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
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
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):
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):
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