@@ -1086,15 +1086,16 @@ fn syntax_error_set_msg(
10861086}
10871087
10881088fn system_exit_code ( exc : PyBaseExceptionRef ) -> Option < PyObjectRef > {
1089- exc. args . read ( ) . first ( ) . map ( |code| {
1090- match_class ! ( match code {
1091- ref tup @ PyTuple => match tup. as_slice( ) {
1092- [ x] => x. clone( ) ,
1093- _ => code. clone( ) ,
1094- } ,
1095- other => other. clone( ) ,
1096- } )
1097- } )
1089+ // SystemExit.code based on args length:
1090+ // - size == 0: code is None
1091+ // - size == 1: code is args[0]
1092+ // - size > 1: code is args (the whole tuple)
1093+ let args = exc. args . read ( ) ;
1094+ match args. len ( ) {
1095+ 0 => None ,
1096+ 1 => Some ( args. first ( ) . unwrap ( ) . clone ( ) ) ,
1097+ _ => Some ( args. as_object ( ) . to_owned ( ) ) ,
1098+ }
10981099}
10991100
11001101#[ cfg( feature = "serde" ) ]
@@ -1255,7 +1256,7 @@ pub(super) mod types {
12551256 } ,
12561257 convert:: ToPyObject ,
12571258 convert:: ToPyResult ,
1258- function:: { ArgBytesLike , FuncArgs } ,
1259+ function:: { ArgBytesLike , FuncArgs , KwArgs } ,
12591260 types:: { Constructor , Initializer } ,
12601261 } ;
12611262 use crossbeam_utils:: atomic:: AtomicCell ;
@@ -1393,11 +1394,29 @@ pub(super) mod types {
13931394 pub ( super ) args : PyRwLock < PyTupleRef > ,
13941395 }
13951396
1396- #[ pyexception( name, base = PyBaseException , ctx = "system_exit" , impl ) ]
1397+ #[ pyexception( name, base = PyBaseException , ctx = "system_exit" ) ]
13971398 #[ derive( Debug ) ]
13981399 #[ repr( transparent) ]
13991400 pub struct PySystemExit ( PyBaseException ) ;
14001401
1402+ // SystemExit_init: has its own __init__ that sets the code attribute
1403+ #[ pyexception( with( Initializer ) ) ]
1404+ impl PySystemExit { }
1405+
1406+ impl Initializer for PySystemExit {
1407+ type Args = FuncArgs ;
1408+ fn slot_init ( zelf : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
1409+ // Call BaseException_init first (handles args)
1410+ PyBaseException :: slot_init ( zelf, args, vm)
1411+ // Note: code is computed dynamically via system_exit_code getter
1412+ // so we don't need to set it here explicitly
1413+ }
1414+
1415+ fn init ( _zelf : PyRef < Self > , _args : Self :: Args , _vm : & VirtualMachine ) -> PyResult < ( ) > {
1416+ unreachable ! ( "slot_init is defined" )
1417+ }
1418+ }
1419+
14011420 #[ pyexception( name, base = PyBaseException , ctx = "generator_exit" , impl ) ]
14021421 #[ derive( Debug ) ]
14031422 #[ repr( transparent) ]
@@ -1474,16 +1493,25 @@ pub(super) mod types {
14741493 type Args = FuncArgs ;
14751494
14761495 fn slot_init ( zelf : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
1477- zelf. set_attr (
1478- "name" ,
1479- vm. unwrap_or_none ( args. kwargs . get ( "name" ) . cloned ( ) ) ,
1480- vm,
1481- ) ?;
1482- zelf. set_attr (
1483- "obj" ,
1484- vm. unwrap_or_none ( args. kwargs . get ( "obj" ) . cloned ( ) ) ,
1485- vm,
1486- ) ?;
1496+ // Only 'name' and 'obj' kwargs are allowed
1497+ let mut kwargs = args. kwargs . clone ( ) ;
1498+ let name = kwargs. swap_remove ( "name" ) ;
1499+ let obj = kwargs. swap_remove ( "obj" ) ;
1500+
1501+ // Reject unknown kwargs
1502+ if let Some ( invalid_key) = kwargs. keys ( ) . next ( ) {
1503+ return Err ( vm. new_type_error ( format ! (
1504+ "AttributeError() got an unexpected keyword argument '{invalid_key}'"
1505+ ) ) ) ;
1506+ }
1507+
1508+ // Pass args without kwargs to BaseException_init
1509+ let base_args = FuncArgs :: new ( args. args . clone ( ) , KwArgs :: default ( ) ) ;
1510+ PyBaseException :: slot_init ( zelf. clone ( ) , base_args, vm) ?;
1511+
1512+ // Set attributes
1513+ zelf. set_attr ( "name" , vm. unwrap_or_none ( name) , vm) ?;
1514+ zelf. set_attr ( "obj" , vm. unwrap_or_none ( obj) , vm) ?;
14871515 Ok ( ( ) )
14881516 }
14891517
@@ -1529,9 +1557,11 @@ pub(super) mod types {
15291557 type Args = FuncArgs ;
15301558
15311559 fn slot_init ( zelf : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
1560+ // Only 'name', 'path', 'name_from' kwargs are allowed
15321561 let mut kwargs = args. kwargs . clone ( ) ;
15331562 let name = kwargs. swap_remove ( "name" ) ;
15341563 let path = kwargs. swap_remove ( "path" ) ;
1564+ let name_from = kwargs. swap_remove ( "name_from" ) ;
15351565
15361566 // Check for any remaining invalid keyword arguments
15371567 if let Some ( invalid_key) = kwargs. keys ( ) . next ( ) {
@@ -1543,6 +1573,7 @@ pub(super) mod types {
15431573 let dict = zelf. dict ( ) . unwrap ( ) ;
15441574 dict. set_item ( "name" , vm. unwrap_or_none ( name) , vm) ?;
15451575 dict. set_item ( "path" , vm. unwrap_or_none ( path) , vm) ?;
1576+ dict. set_item ( "name_from" , vm. unwrap_or_none ( name_from) , vm) ?;
15461577 PyBaseException :: slot_init ( zelf, args, vm)
15471578 }
15481579
@@ -1592,11 +1623,45 @@ pub(super) mod types {
15921623 #[ repr( transparent) ]
15931624 pub struct PyMemoryError ( PyException ) ;
15941625
1595- #[ pyexception( name, base = PyException , ctx = "name_error" , impl ) ]
1626+ #[ pyexception( name, base = PyException , ctx = "name_error" ) ]
15961627 #[ derive( Debug ) ]
15971628 #[ repr( transparent) ]
15981629 pub struct PyNameError ( PyException ) ;
15991630
1631+ // NameError_init: handles the .name. kwarg
1632+ #[ pyexception( with( Initializer ) ) ]
1633+ impl PyNameError { }
1634+
1635+ impl Initializer for PyNameError {
1636+ type Args = FuncArgs ;
1637+ fn slot_init ( zelf : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
1638+ // Only 'name' kwarg is allowed
1639+ let mut kwargs = args. kwargs . clone ( ) ;
1640+ let name = kwargs. swap_remove ( "name" ) ;
1641+
1642+ // Reject unknown kwargs
1643+ if let Some ( invalid_key) = kwargs. keys ( ) . next ( ) {
1644+ return Err ( vm. new_type_error ( format ! (
1645+ "NameError() got an unexpected keyword argument '{invalid_key}'"
1646+ ) ) ) ;
1647+ }
1648+
1649+ // Pass args without kwargs to BaseException_init
1650+ let base_args = FuncArgs :: new ( args. args . clone ( ) , KwArgs :: default ( ) ) ;
1651+ PyBaseException :: slot_init ( zelf. clone ( ) , base_args, vm) ?;
1652+
1653+ // Set name attribute if provided
1654+ if let Some ( name) = name {
1655+ zelf. set_attr ( "name" , name, vm) ?;
1656+ }
1657+ Ok ( ( ) )
1658+ }
1659+
1660+ fn init ( _zelf : PyRef < Self > , _args : Self :: Args , _vm : & VirtualMachine ) -> PyResult < ( ) > {
1661+ unreachable ! ( "slot_init is defined" )
1662+ }
1663+ }
1664+
16001665 #[ pyexception( name, base = PyNameError , ctx = "unbound_local_error" , impl ) ]
16011666 #[ derive( Debug ) ]
16021667 #[ repr( transparent) ]
@@ -2232,31 +2297,17 @@ pub(super) mod types {
22322297 }
22332298 }
22342299
2300+ // MiddlingExtendsException: inherits __init__ from SyntaxError via MRO
22352301 #[ pyexception(
22362302 name = "_IncompleteInputError" ,
22372303 base = PySyntaxError ,
2238- ctx = "incomplete_input_error"
2304+ ctx = "incomplete_input_error" ,
2305+ impl
22392306 ) ]
22402307 #[ derive( Debug ) ]
22412308 #[ repr( transparent) ]
22422309 pub struct PyIncompleteInputError ( PySyntaxError ) ;
22432310
2244- #[ pyexception( with( Initializer ) ) ]
2245- impl PyIncompleteInputError { }
2246-
2247- impl Initializer for PyIncompleteInputError {
2248- type Args = FuncArgs ;
2249-
2250- fn slot_init ( zelf : PyObjectRef , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
2251- zelf. set_attr ( "name" , vm. ctx . new_str ( "SyntaxError" ) , vm) ?;
2252- PySyntaxError :: slot_init ( zelf, args, vm)
2253- }
2254-
2255- fn init ( _zelf : PyRef < Self > , _args : Self :: Args , _vm : & VirtualMachine ) -> PyResult < ( ) > {
2256- unreachable ! ( "slot_init is defined" )
2257- }
2258- }
2259-
22602311 #[ pyexception( name, base = PySyntaxError , ctx = "indentation_error" , impl ) ]
22612312 #[ derive( Debug ) ]
22622313 #[ repr( transparent) ]
0 commit comments