Pickle warning for itertools (#6129)

This commit is contained in:
Shahar Naveh
2025-09-07 10:10:22 +03:00
committed by GitHub
parent b640ef1241
commit da71b92dd3
3 changed files with 51 additions and 24 deletions

View File

@@ -23,6 +23,7 @@ freevars
fromlist
heaptype
HIGHRES
Itertool
IMMUTABLETYPE
kwonlyarg
kwonlyargs
@@ -58,4 +59,4 @@ weakreflist
withitem
withs
xstat
XXPRIME
XXPRIME

View File

@@ -30,10 +30,11 @@ def pickle_deprecated(testfunc):
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
testfunc(self)
with warnings.catch_warnings():
warnings.simplefilter("error", category=DeprecationWarning)
with self.assertRaises((DeprecationWarning, AssertionError, SystemError)):
testfunc(self)
# XXX: RUSTPYTHON; Patch to make tests pass. It will be removed once 3.14 is released anyway.
# with warnings.catch_warnings():
# warnings.simplefilter("error", category=DeprecationWarning)
# with self.assertRaises((DeprecationWarning, AssertionError, SystemError)):
# testfunc(self)
return inner
@@ -145,7 +146,7 @@ class TestBasicOps(unittest.TestCase):
c = expand(compare[took:])
self.assertEqual(a, c);
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; [7, 7, 8, 10] != <itertools.accumulate object at 0xb4000073f32b4480>
@pickle_deprecated
def test_accumulate(self):
self.assertEqual(list(accumulate(range(10))), # one positional arg
@@ -247,7 +248,6 @@ class TestBasicOps(unittest.TestCase):
self.assertRaises(TypeError, list, chain.from_iterable([2, 3]))
self.assertEqual(list(islice(chain.from_iterable(repeat(range(5))), 2)), [0, 1])
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_chain_reducible(self):
for oper in [copy.deepcopy] + picklecopiers:
@@ -567,7 +567,6 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(comb, list(filter(set(perm).__contains__, cwr))) # comb: cwr that is a perm
self.assertEqual(comb, sorted(set(cwr) & set(perm))) # comb: both a cwr and a perm
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_compress(self):
self.assertEqual(list(compress(data='ABCDEF', selectors=[1,0,1,0,1,1])), list('ACEF'))
@@ -602,7 +601,6 @@ class TestBasicOps(unittest.TestCase):
next(testIntermediate)
self.assertEqual(list(op(testIntermediate)), list(result2))
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: DeprecationWarning not triggered
@pickle_deprecated
def test_count(self):
self.assertEqual(lzip('abc',count()), [('a', 0), ('b', 1), ('c', 2)])
@@ -663,7 +661,7 @@ class TestBasicOps(unittest.TestCase):
#check proper internal error handling for large "step' sizes
count(1, maxsize+5); sys.exc_info()
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; 'count(10.5)' != 'count(10.5, 1.0)'
@pickle_deprecated
def test_count_with_step(self):
self.assertEqual(lzip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)])
@@ -1037,7 +1035,6 @@ class TestBasicOps(unittest.TestCase):
c = filter(isEven, range(6))
self.pickletest(proto, c)
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_filterfalse(self):
self.assertEqual(list(filterfalse(isEven, range(6))), [1,3,5])
@@ -1145,7 +1142,6 @@ class TestBasicOps(unittest.TestCase):
ids = list(map(id, list(zip_longest('abc', 'def'))))
self.assertEqual(len(dict.fromkeys(ids)), len(ids))
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_zip_longest_pickling(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
@@ -1369,7 +1365,6 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(len(set(map(id, product('abc', 'def')))), 1)
self.assertNotEqual(len(set(map(id, list(product('abc', 'def'))))), 1)
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_product_pickling(self):
# check copy, deepcopy, pickle
@@ -1398,7 +1393,6 @@ class TestBasicOps(unittest.TestCase):
p.__setstate__((0, 0, 0x1000)) # will access tuple element 1 if not clamped
self.assertRaises(StopIteration, next, p)
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_repeat(self):
self.assertEqual(list(repeat(object='a', times=3)), ['a', 'a', 'a'])
@@ -1464,7 +1458,6 @@ class TestBasicOps(unittest.TestCase):
c = map(tupleize, 'abc', count())
self.pickletest(proto, c)
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_starmap(self):
self.assertEqual(list(starmap(operator.pow, zip(range(3), range(1,7)))),
@@ -1589,7 +1582,6 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(list(islice(range(100), IntLike(10), IntLike(50), IntLike(5))),
list(range(10,50,5)))
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_takewhile(self):
data = [1, 3, 5, 20, 2, 4, 6, 8]
@@ -1950,7 +1942,6 @@ class TestExamples(unittest.TestCase):
def test_accumulate(self):
self.assertEqual(list(accumulate([1,2,3,4,5])), [1, 3, 6, 10, 15])
@unittest.expectedFailure # TODO: RUSTPYTHON
@pickle_deprecated
def test_accumulate_reducible(self):
# check copy, deepcopy, pickle

View File

@@ -19,7 +19,7 @@ mod decl {
identifier,
protocol::{PyIter, PyIterReturn, PyNumber},
raise_if_stop,
stdlib::sys,
stdlib::{sys, warnings},
types::{Constructor, IterNext, Iterable, Representable, SelfIter},
};
use crossbeam_utils::atomic::AtomicCell;
@@ -29,6 +29,15 @@ mod decl {
use num_traits::{Signed, ToPrimitive};
use std::fmt;
fn pickle_deprecation(vm: &VirtualMachine) -> PyResult<()> {
warnings::warn(
vm.ctx.exceptions.deprecation_warning,
"Itertool pickle/copy/deepcopy support will be removed in a Python 3.14.".to_owned(),
1,
vm,
)
}
#[pyattr]
#[pyclass(name = "chain")]
#[derive(Debug, PyPayload)]
@@ -74,6 +83,7 @@ mod decl {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
pickle_deprecation(vm)?;
let source = zelf.source.read().clone();
let active = zelf.active.read().clone();
let cls = zelf.class().to_owned();
@@ -204,7 +214,8 @@ mod decl {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyItertoolsCompress {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyIter, PyIter)) {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, (PyIter, PyIter)) {
let _ = pickle_deprecation(vm);
(
zelf.class().to_owned(),
(zelf.data.clone(), zelf.selectors.clone()),
@@ -274,7 +285,8 @@ mod decl {
// if (lz->cnt == PY_SSIZE_T_MAX)
// return Py_BuildValue("0(00)", Py_TYPE(lz), lz->long_cnt, lz->long_step);
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef,)) {
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, (PyObjectRef,)) {
let _ = pickle_deprecation(vm);
(zelf.class().to_owned(), (zelf.cur.read().clone(),))
}
}
@@ -406,6 +418,7 @@ mod decl {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
pickle_deprecation(vm)?;
let cls = zelf.class().to_owned();
Ok(match zelf.times {
Some(ref times) => vm.new_tuple((cls, (zelf.object.clone(), *times.read()))),
@@ -474,7 +487,11 @@ mod decl {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyItertoolsStarmap {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef, PyIter)) {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> (PyTypeRef, (PyObjectRef, PyIter)) {
let _ = pickle_deprecation(vm);
(
zelf.class().to_owned(),
(zelf.function.clone(), zelf.iterable.clone()),
@@ -539,7 +556,11 @@ mod decl {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyItertoolsTakewhile {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef, PyIter), u32) {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> (PyTypeRef, (PyObjectRef, PyIter), u32) {
let _ = pickle_deprecation(vm);
(
zelf.class().to_owned(),
(zelf.predicate.clone(), zelf.iterable.clone()),
@@ -623,7 +644,11 @@ mod decl {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyItertoolsDropwhile {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef, PyIter), u32) {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> (PyTypeRef, (PyObjectRef, PyIter), u32) {
let _ = pickle_deprecation(vm);
(
zelf.class().to_owned(),
(zelf.predicate.clone().into(), zelf.iterable.clone()),
@@ -937,6 +962,7 @@ mod decl {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
pickle_deprecation(vm)?;
let cls = zelf.class().to_owned();
let itr = zelf.iterable.clone();
let cur = zelf.cur.take();
@@ -1032,7 +1058,11 @@ mod decl {
#[pyclass(with(IterNext, Iterable, Constructor), flags(BASETYPE))]
impl PyItertoolsFilterFalse {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>) -> (PyTypeRef, (PyObjectRef, PyIter)) {
fn __reduce__(
zelf: PyRef<Self>,
vm: &VirtualMachine,
) -> (PyTypeRef, (PyObjectRef, PyIter)) {
let _ = pickle_deprecation(vm);
(
zelf.class().to_owned(),
(zelf.predicate.clone(), zelf.iterable.clone()),
@@ -1110,6 +1140,7 @@ mod decl {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
let _ = pickle_deprecation(vm);
let class = zelf.class().to_owned();
let bin_op = zelf.bin_op.clone();
let it = zelf.iterable.clone();
@@ -1374,6 +1405,7 @@ mod decl {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
let _ = pickle_deprecation(vm);
let class = zelf.class().to_owned();
if zelf.stop.load() {
@@ -1483,6 +1515,7 @@ mod decl {
impl PyItertoolsCombinations {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
let _ = pickle_deprecation(vm);
let r = zelf.r.load();
let class = zelf.class().to_owned();
@@ -1724,6 +1757,7 @@ mod decl {
impl PyItertoolsPermutations {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyRef<PyTuple> {
let _ = pickle_deprecation(vm);
vm.new_tuple((
zelf.class().to_owned(),
vm.new_tuple((zelf.pool.clone(), vm.ctx.new_int(zelf.r.load()))),
@@ -1837,6 +1871,7 @@ mod decl {
impl PyItertoolsZipLongest {
#[pymethod]
fn __reduce__(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
pickle_deprecation(vm)?;
let args: Vec<PyObjectRef> = zelf
.iterators
.iter()