Skip to content

Commit a18bad2

Browse files
committed
Fill OSError attributes
1 parent 3301220 commit a18bad2

File tree

5 files changed

+61
-12
lines changed

5 files changed

+61
-12
lines changed

Lib/test/test_exception_hierarchy.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import unittest
66
import errno
77
from errno import EEXIST
8+
import sys
89

910

1011
class SubOSError(OSError):
@@ -130,8 +131,8 @@ def test_windows_error(self):
130131
else:
131132
self.assertNotIn('winerror', dir(OSError))
132133

133-
# TODO: RUSTPYTHON
134-
@unittest.expectedFailure
134+
@unittest.skip("TODO: RUSTPYTHON")
135+
@unittest.skipIf(sys.platform == 'win32', 'winerror not filled yet')
135136
def test_posix_error(self):
136137
e = OSError(EEXIST, "File already exists", "foo.txt")
137138
self.assertEqual(e.errno, EEXIST)

Lib/test/test_fileio.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,6 @@ class PyAutoFileTests(AutoFileTests, unittest.TestCase):
391391
FileIO = _pyio.FileIO
392392
modulename = '_pyio'
393393

394-
# TODO: RUSTPYTHON
395-
@unittest.expectedFailure
396394
def testOpendir(self):
397395
super().testOpendir()
398396

Lib/test/test_subprocess.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,8 +1547,6 @@ def test_failed_child_execute_fd_leak(self):
15471547
fds_after_exception = os.listdir(fd_directory)
15481548
self.assertEqual(fds_before_popen, fds_after_exception)
15491549

1550-
# TODO: RUSTPYTHON
1551-
@unittest.expectedFailure
15521550
@unittest.skipIf(mswindows, "behavior currently not supported on Windows")
15531551
def test_file_not_found_includes_filename(self):
15541552
with self.assertRaises(FileNotFoundError) as c:

extra_tests/snippets/builtin_exceptions.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,40 @@ class SubError(MyError):
264264
assert OSError(1, 2).errno
265265
assert OSError(1, 2).strerror
266266

267+
268+
# OSError Unexpected number of arguments
269+
w = OSError()
270+
assert w.errno == None
271+
assert not sys.platform.startswith("win") or w.winerror == None
272+
assert w.strerror == None
273+
assert w.filename == None
274+
assert w.filename2 == None
275+
assert str(w) == ""
276+
277+
w = OSError(0)
278+
assert w.errno == None
279+
assert not sys.platform.startswith("win") or w.winerror == None
280+
assert w.strerror == None
281+
assert w.filename == None
282+
assert w.filename2 == None
283+
assert str(w) == "0"
284+
285+
w = OSError('foo')
286+
assert w.errno == None
287+
assert not sys.platform.startswith("win") or w.winerror == None
288+
assert w.strerror == None
289+
assert w.filename == None
290+
assert w.filename2 == None
291+
assert str(w) == "foo"
292+
293+
w = OSError('a', 'b', 'c', 'd', 'e', 'f')
294+
assert w.errno == None
295+
assert not sys.platform.startswith("win") or w.winerror == None
296+
assert w.strerror == None
297+
assert w.filename == None
298+
assert w.filename2 == None
299+
assert str(w) == "('a', 'b', 'c', 'd', 'e', 'f')"
300+
267301
# Custom `__new__` and `__init__`:
268302
assert ImportError.__init__.__qualname__ == 'ImportError.__init__'
269303
assert ImportError(name='a').name == 'a'

vm/src/exceptions.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -752,13 +752,22 @@ impl ExceptionZoo {
752752
let errno_getter =
753753
ctx.new_readonly_getset("errno", excs.os_error, |exc: PyBaseExceptionRef| {
754754
let args = exc.args();
755-
args.get(0).filter(|_| args.len() > 1).cloned()
755+
args.get(0)
756+
.filter(|_| args.len() > 1 && args.len() <= 5)
757+
.cloned()
758+
});
759+
let strerror_getter =
760+
ctx.new_readonly_getset("strerror", excs.os_error, |exc: PyBaseExceptionRef| {
761+
let args = exc.args();
762+
args.get(1)
763+
.filter(|_| args.len() >= 2 && args.len() <= 5)
764+
.cloned()
756765
});
757766
extend_exception!(PyOSError, ctx, excs.os_error, {
758767
// POSIX exception code
759768
"errno" => errno_getter.clone(),
760769
// exception strerror
761-
"strerror" => ctx.new_readonly_getset("strerror", excs.os_error, make_arg_getter(1)),
770+
"strerror" => strerror_getter.clone(),
762771
// exception filename
763772
"filename" => ctx.none(),
764773
// second exception filename
@@ -1260,15 +1269,15 @@ pub(super) mod types {
12601269
os_error,
12611270
"Base class for I/O related errors.",
12621271
os_error_new,
1263-
base_exception_init,
1272+
os_error_init,
12641273
}
12651274
#[cfg(not(target_arch = "wasm32"))]
12661275
fn os_error_optional_new(
12671276
args: Vec<PyObjectRef>,
12681277
vm: &VirtualMachine,
12691278
) -> Option<PyBaseExceptionRef> {
12701279
let len = args.len();
1271-
if len >= 2 {
1280+
if (2..=5).contains(&len) {
12721281
let errno = &args[0];
12731282
errno
12741283
.payload_if_subclass::<PyInt>(vm)
@@ -1297,9 +1306,18 @@ pub(super) mod types {
12971306
fn os_error_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
12981307
PyBaseException::slot_new(cls, args, vm)
12991308
}
1309+
fn os_error_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
1310+
let len = args.args.len();
1311+
let mut new_args = args;
1312+
if (3..=5).contains(&len) {
1313+
zelf.set_attr("filename", new_args.args[2].clone(), vm)?;
1314+
if len == 5 {
1315+
zelf.set_attr("filename2", new_args.args[4].clone(), vm)?;
1316+
}
13001317

1301-
fn base_exception_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
1302-
PyBaseException::init(zelf, args, vm)
1318+
new_args.args.truncate(2);
1319+
}
1320+
PyBaseException::init(zelf, new_args, vm)
13031321
}
13041322

13051323
define_exception! {

0 commit comments

Comments
 (0)