summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-09-04 11:46:35 (GMT)
committerGitHub <noreply@github.com>2023-09-04 11:46:35 (GMT)
commit183bb673a8ce65d6bef6c8da44f34ba70f25340b (patch)
tree68bdf12c794b2bad9b2d08ff4af7c2c4e1b579cd
parentc8cf6be213826c8d0e3e2acbcf31b8c1069df3ed (diff)
downloadcpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.zip
cpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.tar.gz
cpython-183bb673a8ce65d6bef6c8da44f34ba70f25340b.tar.bz2
[3.12] gh-107208: Fix iter_index() recipe to not swallow exceptions (gh-108835) (#108837)
gh-107208: Fix iter_index() recipe to not swallow exceptions (gh-108835) (cherry picked from commit f373c6b9483e12d7f6e03a631601149ed60ab883) gh-107208: iter_index now supports "stop" and no longer swallows ValueError Co-authored-by: Raymond Hettinger <rhettinger@users.noreply.github.com>
-rw-r--r--Doc/library/itertools.rst35
1 files changed, 23 insertions, 12 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 730736b..72c6851 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -865,26 +865,22 @@ which incur interpreter overhead.
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
return next(filter(pred, iterable), default)
- def iter_index(iterable, value, start=0):
+ def iter_index(iterable, value, start=0, stop=None):
"Return indices where a value occurs in a sequence or iterable."
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
- try:
- seq_index = iterable.index
- except AttributeError:
+ seq_index = getattr(iterable, 'index', None)
+ if seq_index is None:
# Slow path for general iterables
- it = islice(iterable, start, None)
- i = start - 1
- try:
- while True:
- yield (i := i + operator.indexOf(it, value) + 1)
- except ValueError:
- pass
+ it = islice(iterable, start, stop)
+ for i, element in enumerate(it, start):
+ if element is value or element == value:
+ yield i
else:
# Fast path for sequences
i = start - 1
try:
while True:
- yield (i := seq_index(value, i+1))
+ yield (i := seq_index(value, i+1, stop))
except ValueError:
pass
@@ -1333,6 +1329,21 @@ The following recipes have a more mathematical flavor:
[]
>>> list(iter_index(iter('AABCADEAF'), 'A', 10))
[]
+ >>> list(iter_index('AABCADEAF', 'A', 1, 7))
+ [1, 4]
+ >>> list(iter_index(iter('AABCADEAF'), 'A', 1, 7))
+ [1, 4]
+ >>> # Verify that ValueErrors not swallowed (gh-107208)
+ >>> def assert_no_value(iterable, forbidden_value):
+ ... for item in iterable:
+ ... if item == forbidden_value:
+ ... raise ValueError
+ ... yield item
+ ...
+ >>> list(iter_index(assert_no_value('AABCADEAF', 'B'), 'A'))
+ Traceback (most recent call last):
+ ...
+ ValueError
>>> list(sieve(30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]