@@ -959,9 +959,7 @@ impl ExceptionZoo {
959959 "exceptions" => ctx. new_readonly_getset( "exceptions" , excs. base_exception_group, make_arg_getter( 1 ) ) ,
960960 } ) ;
961961
962- extend_exception ! ( PySystemExit , ctx, excs. system_exit, {
963- "code" => ctx. none( ) ,
964- } ) ;
962+ extend_exception ! ( PySystemExit , ctx, excs. system_exit) ;
965963 extend_exception ! ( PyKeyboardInterrupt , ctx, excs. keyboard_interrupt) ;
966964 extend_exception ! ( PyGeneratorExit , ctx, excs. generator_exit) ;
967965
@@ -1580,7 +1578,7 @@ pub(super) mod types {
15801578 tuple:: IntoPyTuple ,
15811579 } ,
15821580 convert:: ToPyResult ,
1583- function:: { ArgBytesLike , FuncArgs , KwArgs } ,
1581+ function:: { ArgBytesLike , FuncArgs , KwArgs , PySetterValue } ,
15841582 set_attrs,
15851583 types:: { Constructor , Initializer } ,
15861584 } ;
@@ -1611,14 +1609,51 @@ pub(super) mod types {
16111609 pub ( super ) args : PyRwLock < PyTupleRef > ,
16121610 }
16131611
1614- #[ pyexception( name, base = PyBaseException , ctx = "system_exit" ) ]
1615- #[ derive( Debug ) ]
1616- #[ repr( transparent) ]
1617- pub struct PySystemExit ( PyBaseException ) ;
1612+ #[ pyexception( name, base = PyBaseException , ctx = "system_exit" , traverse = "manual" ) ]
1613+ #[ repr( C ) ]
1614+ pub struct PySystemExit {
1615+ base : PyBaseException ,
1616+ code : PyAtomicRef < Option < PyObject > > ,
1617+ }
16181618
1619- // SystemExit_init: has its own __init__ that sets the code attribute
1620- #[ pyexception( with( Initializer ) ) ]
1621- impl PySystemExit { }
1619+ impl crate :: class:: PySubclass for PySystemExit {
1620+ type Base = PyBaseException ;
1621+ fn as_base ( & self ) -> & Self :: Base {
1622+ & self . base
1623+ }
1624+ }
1625+
1626+ unsafe impl Traverse for PySystemExit {
1627+ fn traverse ( & self , tracer_fn : & mut TraverseFn < ' _ > ) {
1628+ self . base . traverse ( tracer_fn) ;
1629+ if let Some ( obj) = self . code . deref ( ) {
1630+ tracer_fn ( obj) ;
1631+ }
1632+ }
1633+ }
1634+
1635+ impl core:: fmt:: Debug for PySystemExit {
1636+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
1637+ f. debug_struct ( "PySystemExit" ) . finish_non_exhaustive ( )
1638+ }
1639+ }
1640+
1641+ #[ pyexception( with( Constructor , Initializer ) ) ]
1642+ impl PySystemExit {
1643+ #[ pygetset]
1644+ fn code ( & self ) -> Option < PyObjectRef > {
1645+ self . code . to_owned ( )
1646+ }
1647+
1648+ #[ pygetset( setter) ]
1649+ fn set_code ( & self , value : PySetterValue , vm : & VirtualMachine ) {
1650+ let code = match value {
1651+ PySetterValue :: Assign ( v) => Some ( v) ,
1652+ PySetterValue :: Delete => None ,
1653+ } ;
1654+ self . code . swap_to_temporary_refs ( code, vm) ;
1655+ }
1656+ }
16221657
16231658 impl Initializer for PySystemExit {
16241659 type Args = FuncArgs ;
@@ -1630,7 +1665,8 @@ pub(super) mod types {
16301665 _ => vm. ctx . new_tuple ( args. args . clone ( ) ) . into ( ) ,
16311666 } ;
16321667 PyBaseException :: slot_init ( zelf. clone ( ) , args, vm) ?;
1633- zelf. set_attr ( "code" , code, vm) ?;
1668+ let exc: & Py < Self > = zelf. downcast_ref :: < Self > ( ) . unwrap ( ) ;
1669+ exc. code . swap_to_temporary_refs ( Some ( code) , vm) ;
16341670 Ok ( ( ) )
16351671 }
16361672
@@ -1639,6 +1675,18 @@ pub(super) mod types {
16391675 }
16401676 }
16411677
1678+ impl Constructor for PySystemExit {
1679+ type Args = FuncArgs ;
1680+
1681+ fn py_new ( _cls : & Py < PyType > , args : FuncArgs , vm : & VirtualMachine ) -> PyResult < Self > {
1682+ let base_exception = PyBaseException :: new ( args. args , vm) ;
1683+ Ok ( Self {
1684+ base : base_exception,
1685+ code : None . into ( ) ,
1686+ } )
1687+ }
1688+ }
1689+
16421690 #[ pyexception( name, base = PyBaseException , ctx = "generator_exit" , impl ) ]
16431691 #[ derive( Debug ) ]
16441692 #[ repr( transparent) ]
0 commit comments