@@ -963,6 +963,7 @@ pub(super) mod types {
963963 use crate :: {
964964 builtins:: { traceback:: PyTracebackRef , PyInt , PyTupleRef , PyTypeRef } ,
965965 function:: { FuncArgs , IntoPyResult } ,
966+ pyobject:: { PyValue , TypeProtocol } ,
966967 PyObjectRef , PyRef , PyResult , VirtualMachine ,
967968 } ;
968969 use crossbeam_utils:: atomic:: AtomicCell ;
@@ -1160,8 +1161,9 @@ pub(super) mod types {
11601161 os_error,
11611162 "Base class for I/O related errors." ,
11621163 os_error_new,
1163- base_exception_init ,
1164+ os_error_init ,
11641165 }
1166+
11651167 #[ cfg( not( target_arch = "wasm32" ) ) ]
11661168 fn os_error_optional_new (
11671169 args : Vec < PyObjectRef > ,
@@ -1217,29 +1219,80 @@ pub(super) mod types {
12171219 }
12181220 #[ cfg( not( target_arch = "wasm32" ) ) ]
12191221 fn os_error_new ( cls : PyTypeRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
1220- // We need this method, because of how `CPython` copies `init`
1221- // from `BaseException` in `SimpleExtendsException` macro.
1222- // See: `BaseException_new`
1223- if cls. name ( ) . deref ( ) == vm. ctx . exceptions . os_error . name ( ) . deref ( ) {
1224- match os_error_optional_new ( args. args . to_vec ( ) , vm) {
1225- Some ( error) => error. unwrap ( ) . into_pyresult ( vm) ,
1226- None => PyBaseException :: slot_new ( cls, args, vm) ,
1227- }
1228- } else {
1229- PyBaseException :: slot_new ( cls, args, vm)
1230- }
1222+ let exc_self: PyBaseExceptionRef =
1223+ if cls. name ( ) . deref ( ) == vm. ctx . exceptions . os_error . name ( ) . deref ( ) {
1224+ match os_error_optional_new ( args. args . to_vec ( ) , vm) {
1225+ Some ( error) => error. unwrap ( ) ,
1226+ None => PyBaseException :: new ( args. args . to_vec ( ) , vm)
1227+ . into_ref_with_type ( vm, cls)
1228+ . unwrap ( ) ,
1229+ }
1230+ } else {
1231+ PyBaseException :: new ( args. args . to_vec ( ) , vm)
1232+ . into_ref_with_type ( vm, cls)
1233+ . unwrap ( )
1234+ } ;
1235+
1236+ os_error_parse_args ( exc_self. clone ( ) , & args, vm) ?;
1237+ exc_self. into_pyresult ( vm)
12311238 }
12321239 #[ cfg( target_arch = "wasm32" ) ]
12331240 fn os_error_new ( cls : PyTypeRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult {
1234- PyBaseException :: slot_new ( cls, args, vm)
1241+ let exc_self = PyBaseException :: new ( args. args . to_vec ( ) , vm)
1242+ . into_ref_with_type ( vm, cls)
1243+ . unwrap ( ) ;
1244+ os_error_parse_args ( exc_self. clone ( ) , & args, vm) ?;
1245+ exc_self. into_pyresult ( vm)
1246+ }
1247+
1248+ fn os_error_parse_args (
1249+ exc_self : PyBaseExceptionRef ,
1250+ args : & FuncArgs ,
1251+ vm : & VirtualMachine ,
1252+ ) -> PyResult < ( ) > {
1253+ os_error_set_attr ( & exc_self, args, vm, "filename" , 2 ) ?;
1254+ #[ cfg( windows) ]
1255+ os_error_set_attr ( & exc_self, args, vm, "winerror" , 3 ) ?;
1256+ os_error_set_attr ( & exc_self, args, vm, "filename2" , 4 ) ?;
1257+ Ok ( ( ) )
12351258 }
12361259
1237- fn base_exception_init (
1260+ fn os_error_set_attr (
1261+ exc_self : & PyBaseExceptionRef ,
1262+ args : & FuncArgs ,
1263+ vm : & VirtualMachine ,
1264+ attr_name : & str ,
1265+ arg_idx : usize ,
1266+ ) -> PyResult < ( ) > {
1267+ let exc_self = exc_self. as_ref ( ) ;
1268+
1269+ if let Some ( arg) = args. args . as_slice ( ) . get ( arg_idx) . cloned ( ) {
1270+ exc_self. set_attr ( attr_name, arg, vm) ?;
1271+ }
1272+
1273+ Ok ( ( ) )
1274+ }
1275+
1276+ fn os_error_init (
12381277 zelf : PyRef < PyBaseException > ,
12391278 args : FuncArgs ,
12401279 vm : & VirtualMachine ,
12411280 ) -> PyResult < ( ) > {
1242- PyBaseException :: init ( zelf, args, vm)
1281+ PyBaseException :: init ( zelf. clone ( ) , args. clone ( ) , vm) ?;
1282+
1283+ let exc_self = zelf. as_object ( ) ;
1284+
1285+ if exc_self. class ( ) . name ( ) . deref ( ) == "BlockingIOError" {
1286+ exc_self. set_attr (
1287+ "characters_written" ,
1288+ vm. unwrap_or_none ( args. args . as_slice ( ) . get ( 2 ) . cloned ( ) ) ,
1289+ vm,
1290+ ) ?;
1291+ } else {
1292+ os_error_parse_args ( zelf, & args, vm) ?;
1293+ }
1294+
1295+ Ok ( ( ) )
12431296 }
12441297
12451298 define_exception ! {
@@ -1248,6 +1301,7 @@ pub(super) mod types {
12481301 blocking_io_error,
12491302 "I/O operation would block."
12501303 }
1304+
12511305 define_exception ! {
12521306 PyChildProcessError ,
12531307 PyOSError ,
0 commit comments