Fix test_io on windows (#6387)

* mark skip on test_io

* Drop for FileIO

* IO Desctructors

* Iterator
This commit is contained in:
Jeong, YunWon
2025-12-10 09:21:32 +09:00
committed by GitHub
parent 14232ad0d2
commit 30fb9d73cc
2 changed files with 140 additions and 12 deletions

9
Lib/test/test_io.py vendored
View File

@@ -780,6 +780,7 @@ class IOTest(unittest.TestCase):
file = self.open(f.fileno(), "r", encoding="utf-8", closefd=False)
self.assertEqual(file.buffer.raw.closefd, False)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_garbage_collection(self):
# FileIO objects are collected, and collecting them flushes
@@ -1795,6 +1796,7 @@ class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
# checking this is not so easy.
self.assertRaises(OSError, bufio.read, 10)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_garbage_collection(self):
# C BufferedReader objects are collected.
@@ -2166,6 +2168,7 @@ class CBufferedWriterTest(BufferedWriterTest, SizeofTest):
self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
self.assertRaises(ValueError, bufio.write, b"def")
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_garbage_collection(self):
# C BufferedWriter objects are collected, and collecting them flushes
@@ -2677,6 +2680,7 @@ class BufferedRandomTest(BufferedReaderTest, BufferedWriterTest):
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
tp = io.BufferedRandom
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_garbage_collection(self):
CBufferedReaderTest.test_garbage_collection(self)
@@ -4122,6 +4126,7 @@ class CTextIOWrapperTest(TextIOWrapperTest):
t = self.TextIOWrapper.__new__(self.TextIOWrapper)
self.assertRaises(Exception, repr, t)
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_garbage_collection(self):
# C TextIOWrapper objects are collected, and collecting them flushes
@@ -4271,10 +4276,6 @@ class CTextIOWrapperTest(TextIOWrapperTest):
def test_repr(self):
return super().test_repr()
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_telling(self):
return super().test_telling()
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_uninitialized(self):
return super().test_uninitialized()

View File

@@ -1753,11 +1753,23 @@ mod _io {
}
#[pyclass(
with(Constructor, BufferedMixin, BufferedReadable),
with(Constructor, BufferedMixin, BufferedReadable, Destructor),
flags(BASETYPE, HAS_DICT)
)]
impl BufferedReader {}
impl Destructor for BufferedReader {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
impl DefaultConstructor for BufferedReader {}
#[pyclass]
@@ -1810,11 +1822,23 @@ mod _io {
}
#[pyclass(
with(Constructor, BufferedMixin, BufferedWritable),
with(Constructor, BufferedMixin, BufferedWritable, Destructor),
flags(BASETYPE, HAS_DICT)
)]
impl BufferedWriter {}
impl Destructor for BufferedWriter {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
impl DefaultConstructor for BufferedWriter {}
#[pyattr]
@@ -1852,11 +1876,29 @@ mod _io {
}
#[pyclass(
with(Constructor, BufferedMixin, BufferedReadable, BufferedWritable),
with(
Constructor,
BufferedMixin,
BufferedReadable,
BufferedWritable,
Destructor
),
flags(BASETYPE, HAS_DICT)
)]
impl BufferedRandom {}
impl Destructor for BufferedRandom {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
impl DefaultConstructor for BufferedRandom {}
#[pyattr]
@@ -1900,7 +1942,13 @@ mod _io {
}
#[pyclass(
with(Constructor, Initializer, BufferedReadable, BufferedWritable),
with(
Constructor,
Initializer,
BufferedReadable,
BufferedWritable,
Destructor
),
flags(BASETYPE, HAS_DICT)
)]
impl BufferedRWPair {
@@ -1942,6 +1990,18 @@ mod _io {
}
}
impl Destructor for BufferedRWPair {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
#[derive(FromArgs)]
struct TextIOWrapperArgs {
#[pyarg(any, default)]
@@ -2413,7 +2473,10 @@ mod _io {
vm.call_method(&textio.buffer, "flush", ())
}
#[pyclass(with(Constructor, Initializer), flags(BASETYPE))]
#[pyclass(
with(Constructor, Initializer, Destructor, Iterable, IterNext),
flags(BASETYPE)
)]
impl TextIOWrapper {
#[pymethod]
fn reconfigure(&self, args: TextIOWrapperArgs, vm: &VirtualMachine) -> PyResult<()> {
@@ -3276,6 +3339,57 @@ mod _io {
}
}
impl Destructor for TextIOWrapper {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
impl Iterable for TextIOWrapper {
fn slot_iter(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult {
check_closed(&zelf, vm)?;
Ok(zelf)
}
fn iter(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult {
unreachable!("slot_iter is implemented")
}
}
impl IterNext for TextIOWrapper {
fn slot_iternext(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
// Set telling = false during iteration (matches CPython behavior)
let textio_ref: PyRef<TextIOWrapper> =
zelf.downcast_ref::<TextIOWrapper>().unwrap().to_owned();
{
let mut textio = textio_ref.lock(vm)?;
textio.telling = false;
}
let line = vm.call_method(zelf, "readline", ())?;
if !line.clone().try_to_bool(vm)? {
// Restore telling on StopIteration
let mut textio = textio_ref.lock(vm)?;
textio.snapshot = None;
textio.telling = textio.seekable;
Ok(PyIterReturn::StopIteration(None))
} else {
Ok(PyIterReturn::Return(line))
}
}
fn next(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<PyIterReturn> {
unreachable!("slot_iternext is implemented")
}
}
#[pyattr]
#[pyclass(name)]
#[derive(Debug, PyPayload, Default)]
@@ -4166,14 +4280,15 @@ mod _io {
mod fileio {
use super::{_io::*, Offset};
use crate::{
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
builtins::{PyBaseExceptionRef, PyUtf8Str, PyUtf8StrRef},
common::crt_fd,
convert::{IntoPyException, ToPyException},
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
ospath::{IOErrorBuilder, OsPath, OsPathOrFd},
stdlib::os,
types::{Constructor, DefaultConstructor, Initializer, Representable},
types::{Constructor, DefaultConstructor, Destructor, Initializer, Representable},
};
use crossbeam_utils::atomic::AtomicCell;
use std::io::{Read, Write};
@@ -4433,7 +4548,7 @@ mod fileio {
}
#[pyclass(
with(Constructor, Initializer, Representable),
with(Constructor, Initializer, Representable, Destructor),
flags(BASETYPE, HAS_DICT)
)]
impl FileIO {
@@ -4649,4 +4764,16 @@ mod fileio {
Err(vm.new_type_error(format!("cannot pickle '{}' object", zelf.class().name())))
}
}
impl Destructor for FileIO {
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
let _ = vm.call_method(zelf, "close", ());
Ok(())
}
#[cold]
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_del is implemented")
}
}
}