@@ -1193,6 +1193,8 @@ pub(crate) fn errno_to_exc_type(_errno: i32, _vm: &VirtualMachine) -> Option<&'s
11931193 None
11941194}
11951195
1196+ pub ( crate ) use types:: { OSErrorBuilder , ToOSErrorBuilder } ;
1197+
11961198pub ( super ) mod types {
11971199 use crate :: common:: lock:: PyRwLock ;
11981200 use crate :: object:: { MaybeTraverse , Traverse , TraverseFn } ;
@@ -1204,6 +1206,7 @@ pub(super) mod types {
12041206 PyInt , PyStrRef , PyTupleRef , PyType , PyTypeRef , traceback:: PyTracebackRef ,
12051207 tuple:: IntoPyTuple ,
12061208 } ,
1209+ convert:: ToPyObject ,
12071210 convert:: ToPyResult ,
12081211 function:: { ArgBytesLike , FuncArgs } ,
12091212 types:: { Constructor , Initializer } ,
@@ -1212,6 +1215,113 @@ pub(super) mod types {
12121215 use itertools:: Itertools ;
12131216 use rustpython_common:: str:: UnicodeEscapeCodepoint ;
12141217
1218+ pub ( crate ) trait ToOSErrorBuilder {
1219+ fn to_os_error_builder ( & self , vm : & VirtualMachine ) -> OSErrorBuilder ;
1220+ }
1221+
1222+ pub struct OSErrorBuilder {
1223+ exc_type : PyTypeRef ,
1224+ errno : Option < i32 > ,
1225+ strerror : Option < PyObjectRef > ,
1226+ filename : Option < PyObjectRef > ,
1227+ #[ cfg( windows) ]
1228+ winerror : Option < PyObjectRef > ,
1229+ filename2 : Option < PyObjectRef > ,
1230+ }
1231+
1232+ impl OSErrorBuilder {
1233+ #[ must_use]
1234+ pub fn with_subtype (
1235+ exc_type : PyTypeRef ,
1236+ errno : Option < i32 > ,
1237+ strerror : impl ToPyObject ,
1238+ vm : & VirtualMachine ,
1239+ ) -> Self {
1240+ let strerror = strerror. to_pyobject ( vm) ;
1241+ Self {
1242+ exc_type,
1243+ errno,
1244+ strerror : Some ( strerror. to_pyobject ( vm) ) ,
1245+ filename : None ,
1246+ #[ cfg( windows) ]
1247+ winerror : None ,
1248+ filename2 : None ,
1249+ }
1250+ }
1251+ #[ must_use]
1252+ pub fn with_errno ( errno : i32 , strerror : impl ToPyObject , vm : & VirtualMachine ) -> Self {
1253+ let exc_type = crate :: exceptions:: errno_to_exc_type ( errno, vm)
1254+ . unwrap_or ( vm. ctx . exceptions . os_error )
1255+ . to_owned ( ) ;
1256+ Self :: with_subtype ( exc_type, Some ( errno) , strerror, vm)
1257+ }
1258+
1259+ // #[must_use]
1260+ // pub(crate) fn errno(mut self, errno: i32) -> Self {
1261+ // self.errno.replace(errno);
1262+ // self
1263+ // }
1264+
1265+ #[ must_use]
1266+ pub ( crate ) fn filename ( mut self , filename : PyObjectRef ) -> Self {
1267+ self . filename . replace ( filename) ;
1268+ self
1269+ }
1270+
1271+ #[ must_use]
1272+ pub ( crate ) fn filename2 ( mut self , filename : PyObjectRef ) -> Self {
1273+ self . filename2 . replace ( filename) ;
1274+ self
1275+ }
1276+
1277+ #[ must_use]
1278+ #[ cfg( windows) ]
1279+ pub ( crate ) fn winerror ( mut self , winerror : PyObjectRef ) -> Self {
1280+ self . winerror . replace ( winerror) ;
1281+ self
1282+ }
1283+
1284+ pub fn build ( self , vm : & VirtualMachine ) -> PyRef < PyOSError > {
1285+ let OSErrorBuilder {
1286+ exc_type,
1287+ errno,
1288+ strerror,
1289+ filename,
1290+ #[ cfg( windows) ]
1291+ winerror,
1292+ filename2,
1293+ } = self ;
1294+
1295+ #[ cfg( windows) ]
1296+ let winerror = winerror. to_pyobject ( vm) ;
1297+ #[ cfg( not( windows) ) ]
1298+ let winerror = vm. ctx . none ( ) ;
1299+
1300+ let args = vec ! [
1301+ errno. to_pyobject( vm) ,
1302+ strerror. to_pyobject( vm) ,
1303+ filename. to_pyobject( vm) ,
1304+ winerror,
1305+ filename2. to_pyobject( vm) ,
1306+ ] ;
1307+
1308+ let payload = PyOSError :: py_new ( & exc_type, args. clone ( ) . into ( ) , vm)
1309+ . expect ( "new_os_error usage error" ) ;
1310+ let os_error = payload
1311+ . into_ref_with_type ( vm, exc_type)
1312+ . expect ( "new_os_error usage error" ) ;
1313+ PyOSError :: slot_init ( os_error. as_object ( ) . to_owned ( ) , args. into ( ) , vm)
1314+ . expect ( "new_os_error usage error" ) ;
1315+ os_error
1316+ }
1317+ }
1318+
1319+ impl crate :: convert:: IntoPyException for OSErrorBuilder {
1320+ fn into_pyexception ( self , vm : & VirtualMachine ) -> PyBaseExceptionRef {
1321+ self . build ( vm) . upcast ( )
1322+ }
1323+ }
1324+
12151325 // Re-export exception group types from dedicated module
12161326 pub use crate :: exception_group:: types:: PyBaseExceptionGroup ;
12171327
0 commit comments