Skip to content

Commit 30fb9d7

Browse files
authored
Fix test_io on windows (RustPython#6387)
* mark skip on test_io * Drop for FileIO * IO Desctructors * Iterator
1 parent 14232ad commit 30fb9d7

File tree

2 files changed

+140
-12
lines changed

2 files changed

+140
-12
lines changed

Lib/test/test_io.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ def test_closefd_attr(self):
780780
file = self.open(f.fileno(), "r", encoding="utf-8", closefd=False)
781781
self.assertEqual(file.buffer.raw.closefd, False)
782782

783+
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
783784
@unittest.expectedFailure # TODO: RUSTPYTHON
784785
def test_garbage_collection(self):
785786
# FileIO objects are collected, and collecting them flushes
@@ -1795,6 +1796,7 @@ def test_misbehaved_io_read(self):
17951796
# checking this is not so easy.
17961797
self.assertRaises(OSError, bufio.read, 10)
17971798

1799+
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
17981800
@unittest.expectedFailure # TODO: RUSTPYTHON
17991801
def test_garbage_collection(self):
18001802
# C BufferedReader objects are collected.
@@ -2166,6 +2168,7 @@ def test_initialization(self):
21662168
self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1)
21672169
self.assertRaises(ValueError, bufio.write, b"def")
21682170

2171+
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
21692172
@unittest.expectedFailure # TODO: RUSTPYTHON
21702173
def test_garbage_collection(self):
21712174
# C BufferedWriter objects are collected, and collecting them flushes
@@ -2677,6 +2680,7 @@ def test_interleaved_readline_write(self):
26772680
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
26782681
tp = io.BufferedRandom
26792682

2683+
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
26802684
@unittest.expectedFailure # TODO: RUSTPYTHON
26812685
def test_garbage_collection(self):
26822686
CBufferedReaderTest.test_garbage_collection(self)
@@ -4122,6 +4126,7 @@ def test_initialization(self):
41224126
t = self.TextIOWrapper.__new__(self.TextIOWrapper)
41234127
self.assertRaises(Exception, repr, t)
41244128

4129+
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; cyclic GC not supported, causes file locking')
41254130
@unittest.expectedFailure # TODO: RUSTPYTHON
41264131
def test_garbage_collection(self):
41274132
# C TextIOWrapper objects are collected, and collecting them flushes
@@ -4271,10 +4276,6 @@ def test_reconfigure_write_through(self):
42714276
def test_repr(self):
42724277
return super().test_repr()
42734278

4274-
@unittest.expectedFailure # TODO: RUSTPYTHON
4275-
def test_telling(self):
4276-
return super().test_telling()
4277-
42784279
@unittest.expectedFailure # TODO: RUSTPYTHON
42794280
def test_uninitialized(self):
42804281
return super().test_uninitialized()

crates/vm/src/stdlib/io.rs

Lines changed: 135 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,11 +1753,23 @@ mod _io {
17531753
}
17541754

17551755
#[pyclass(
1756-
with(Constructor, BufferedMixin, BufferedReadable),
1756+
with(Constructor, BufferedMixin, BufferedReadable, Destructor),
17571757
flags(BASETYPE, HAS_DICT)
17581758
)]
17591759
impl BufferedReader {}
17601760

1761+
impl Destructor for BufferedReader {
1762+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
1763+
let _ = vm.call_method(zelf, "close", ());
1764+
Ok(())
1765+
}
1766+
1767+
#[cold]
1768+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
1769+
unreachable!("slot_del is implemented")
1770+
}
1771+
}
1772+
17611773
impl DefaultConstructor for BufferedReader {}
17621774

17631775
#[pyclass]
@@ -1810,11 +1822,23 @@ mod _io {
18101822
}
18111823

18121824
#[pyclass(
1813-
with(Constructor, BufferedMixin, BufferedWritable),
1825+
with(Constructor, BufferedMixin, BufferedWritable, Destructor),
18141826
flags(BASETYPE, HAS_DICT)
18151827
)]
18161828
impl BufferedWriter {}
18171829

1830+
impl Destructor for BufferedWriter {
1831+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
1832+
let _ = vm.call_method(zelf, "close", ());
1833+
Ok(())
1834+
}
1835+
1836+
#[cold]
1837+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
1838+
unreachable!("slot_del is implemented")
1839+
}
1840+
}
1841+
18181842
impl DefaultConstructor for BufferedWriter {}
18191843

18201844
#[pyattr]
@@ -1852,11 +1876,29 @@ mod _io {
18521876
}
18531877

18541878
#[pyclass(
1855-
with(Constructor, BufferedMixin, BufferedReadable, BufferedWritable),
1879+
with(
1880+
Constructor,
1881+
BufferedMixin,
1882+
BufferedReadable,
1883+
BufferedWritable,
1884+
Destructor
1885+
),
18561886
flags(BASETYPE, HAS_DICT)
18571887
)]
18581888
impl BufferedRandom {}
18591889

1890+
impl Destructor for BufferedRandom {
1891+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
1892+
let _ = vm.call_method(zelf, "close", ());
1893+
Ok(())
1894+
}
1895+
1896+
#[cold]
1897+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
1898+
unreachable!("slot_del is implemented")
1899+
}
1900+
}
1901+
18601902
impl DefaultConstructor for BufferedRandom {}
18611903

18621904
#[pyattr]
@@ -1900,7 +1942,13 @@ mod _io {
19001942
}
19011943

19021944
#[pyclass(
1903-
with(Constructor, Initializer, BufferedReadable, BufferedWritable),
1945+
with(
1946+
Constructor,
1947+
Initializer,
1948+
BufferedReadable,
1949+
BufferedWritable,
1950+
Destructor
1951+
),
19041952
flags(BASETYPE, HAS_DICT)
19051953
)]
19061954
impl BufferedRWPair {
@@ -1942,6 +1990,18 @@ mod _io {
19421990
}
19431991
}
19441992

1993+
impl Destructor for BufferedRWPair {
1994+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
1995+
let _ = vm.call_method(zelf, "close", ());
1996+
Ok(())
1997+
}
1998+
1999+
#[cold]
2000+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
2001+
unreachable!("slot_del is implemented")
2002+
}
2003+
}
2004+
19452005
#[derive(FromArgs)]
19462006
struct TextIOWrapperArgs {
19472007
#[pyarg(any, default)]
@@ -2413,7 +2473,10 @@ mod _io {
24132473
vm.call_method(&textio.buffer, "flush", ())
24142474
}
24152475

2416-
#[pyclass(with(Constructor, Initializer), flags(BASETYPE))]
2476+
#[pyclass(
2477+
with(Constructor, Initializer, Destructor, Iterable, IterNext),
2478+
flags(BASETYPE)
2479+
)]
24172480
impl TextIOWrapper {
24182481
#[pymethod]
24192482
fn reconfigure(&self, args: TextIOWrapperArgs, vm: &VirtualMachine) -> PyResult<()> {
@@ -3276,6 +3339,57 @@ mod _io {
32763339
}
32773340
}
32783341

3342+
impl Destructor for TextIOWrapper {
3343+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
3344+
let _ = vm.call_method(zelf, "close", ());
3345+
Ok(())
3346+
}
3347+
3348+
#[cold]
3349+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
3350+
unreachable!("slot_del is implemented")
3351+
}
3352+
}
3353+
3354+
impl Iterable for TextIOWrapper {
3355+
fn slot_iter(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult {
3356+
check_closed(&zelf, vm)?;
3357+
Ok(zelf)
3358+
}
3359+
3360+
fn iter(_zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyResult {
3361+
unreachable!("slot_iter is implemented")
3362+
}
3363+
}
3364+
3365+
impl IterNext for TextIOWrapper {
3366+
fn slot_iternext(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
3367+
// Set telling = false during iteration (matches CPython behavior)
3368+
let textio_ref: PyRef<TextIOWrapper> =
3369+
zelf.downcast_ref::<TextIOWrapper>().unwrap().to_owned();
3370+
{
3371+
let mut textio = textio_ref.lock(vm)?;
3372+
textio.telling = false;
3373+
}
3374+
3375+
let line = vm.call_method(zelf, "readline", ())?;
3376+
3377+
if !line.clone().try_to_bool(vm)? {
3378+
// Restore telling on StopIteration
3379+
let mut textio = textio_ref.lock(vm)?;
3380+
textio.snapshot = None;
3381+
textio.telling = textio.seekable;
3382+
Ok(PyIterReturn::StopIteration(None))
3383+
} else {
3384+
Ok(PyIterReturn::Return(line))
3385+
}
3386+
}
3387+
3388+
fn next(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<PyIterReturn> {
3389+
unreachable!("slot_iternext is implemented")
3390+
}
3391+
}
3392+
32793393
#[pyattr]
32803394
#[pyclass(name)]
32813395
#[derive(Debug, PyPayload, Default)]
@@ -4166,14 +4280,15 @@ mod _io {
41664280
mod fileio {
41674281
use super::{_io::*, Offset};
41684282
use crate::{
4169-
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
4283+
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
4284+
VirtualMachine,
41704285
builtins::{PyBaseExceptionRef, PyUtf8Str, PyUtf8StrRef},
41714286
common::crt_fd,
41724287
convert::{IntoPyException, ToPyException},
41734288
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
41744289
ospath::{IOErrorBuilder, OsPath, OsPathOrFd},
41754290
stdlib::os,
4176-
types::{Constructor, DefaultConstructor, Initializer, Representable},
4291+
types::{Constructor, DefaultConstructor, Destructor, Initializer, Representable},
41774292
};
41784293
use crossbeam_utils::atomic::AtomicCell;
41794294
use std::io::{Read, Write};
@@ -4433,7 +4548,7 @@ mod fileio {
44334548
}
44344549

44354550
#[pyclass(
4436-
with(Constructor, Initializer, Representable),
4551+
with(Constructor, Initializer, Representable, Destructor),
44374552
flags(BASETYPE, HAS_DICT)
44384553
)]
44394554
impl FileIO {
@@ -4649,4 +4764,16 @@ mod fileio {
46494764
Err(vm.new_type_error(format!("cannot pickle '{}' object", zelf.class().name())))
46504765
}
46514766
}
4767+
4768+
impl Destructor for FileIO {
4769+
fn slot_del(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
4770+
let _ = vm.call_method(zelf, "close", ());
4771+
Ok(())
4772+
}
4773+
4774+
#[cold]
4775+
fn del(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
4776+
unreachable!("slot_del is implemented")
4777+
}
4778+
}
46524779
}

0 commit comments

Comments
 (0)