Update test_enumerate.py from 3.13.5 (#6032)

This commit is contained in:
Shahar Naveh authored and GitHub committed 2025-07-25 10:43:16 +09:00
1 parent 96f47a415e
commit b7336366cb
2 files changed
+36 -8

No files matched your search

+29 -2
View File
@@ -2,6 +2,7 @@ import unittest
import operator
import sys
import pickle
import gc
from test import support
@@ -127,6 +128,18 @@ class EnumerateTestCase(unittest.TestCase, PickleTest):
self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type
self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments
def test_kwargs(self):
self.assertEqual(list(self.enum(iterable=Ig(self.seq))), self.res)
expected = list(self.enum(Ig(self.seq), 0))
self.assertEqual(list(self.enum(iterable=Ig(self.seq), start=0)),
expected)
self.assertEqual(list(self.enum(start=0, iterable=Ig(self.seq))),
expected)
self.assertRaises(TypeError, self.enum, iterable=[], x=3)
self.assertRaises(TypeError, self.enum, start=0, x=3)
self.assertRaises(TypeError, self.enum, x=0, y=3)
self.assertRaises(TypeError, self.enum, x=0)
@support.cpython_only
def test_tuple_reuse(self):
# Tests an implementation detail where tuple is reused
@@ -134,6 +147,18 @@ class EnumerateTestCase(unittest.TestCase, PickleTest):
self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
@support.cpython_only
def test_enumerate_result_gc(self):
# bpo-42536: enumerate's tuple-reuse speed trick breaks the GC's
# assumptions about what can be untracked. Make sure we re-track result
# tuples whenever we reuse them.
it = self.enum([[]])
gc.collect()
# That GC collection probably untracked the recycled internal result
# tuple, which is initialized to (None, None). Make sure it's re-tracked
# when it's mutated and returned from __next__:
self.assertTrue(gc.is_tracked(next(it)))
class MyEnum(enumerate):
pass
@@ -253,14 +278,16 @@ class EnumerateStartTestCase(EnumerateTestCase):
class TestStart(EnumerateStartTestCase):
def enum(self, iterable, start=11):
return enumerate(iterable, start=start)
enum = lambda self, i: enumerate(i, start=11)
seq, res = 'abc', [(11, 'a'), (12, 'b'), (13, 'c')]
class TestLongStart(EnumerateStartTestCase):
def enum(self, iterable, start=sys.maxsize + 1):
return enumerate(iterable, start=start)
enum = lambda self, i: enumerate(i, start=sys.maxsize+1)
seq, res = 'abc', [(sys.maxsize+1,'a'), (sys.maxsize+2,'b'),
(sys.maxsize+3,'c')]
+7 -6
View File
@@ -19,7 +19,7 @@ use num_traits::Zero;
pub struct PyEnumerate {
#[pytraverse(skip)]
counter: PyRwLock<BigInt>,
iterator: PyIter,
iterable: PyIter,
}
impl PyPayload for PyEnumerate {
@@ -31,7 +31,8 @@ impl PyPayload for PyEnumerate {
#[derive(FromArgs)]
pub struct EnumerateArgs {
iterator: PyIter,
#[pyarg(any)]
iterable: PyIter,
#[pyarg(any, optional)]
start: OptionalArg<PyIntRef>,
}
@@ -41,13 +42,13 @@ impl Constructor for PyEnumerate {
fn py_new(
cls: PyTypeRef,
Self::Args { iterator, start }: Self::Args,
Self::Args { iterable, start }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
let counter = start.map_or_else(BigInt::zero, |start| start.as_bigint().clone());
Self {
counter: PyRwLock::new(counter),
iterator,
iterable,
}
.into_ref_with_type(vm, cls)
.map(Into::into)
@@ -68,7 +69,7 @@ impl Py<PyEnumerate> {
fn __reduce__(&self) -> (PyTypeRef, (PyIter, BigInt)) {
(
self.class().to_owned(),
(self.iterator.clone(), self.counter.read().clone()),
(self.iterable.clone(), self.counter.read().clone()),
)
}
}
@@ -77,7 +78,7 @@ impl SelfIter for PyEnumerate {}
impl IterNext for PyEnumerate {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
let next_obj = raise_if_stop!(zelf.iterator.next(vm)?);
let next_obj = raise_if_stop!(zelf.iterable.next(vm)?);
let mut counter = zelf.counter.write();
let position = counter.clone();
*counter += 1;