File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -70,6 +70,12 @@ pub trait CodeObject: Copy {
7070 fn varnames ( & self ) -> * mut Self :: TupleObject ;
7171
7272 fn get_line_number ( & self , lasti : i32 , table : & [ u8 ] ) -> i32 ;
73+
74+ /// Returns the qualified name (co_qualname) if available (Python 3.11+).
75+ /// For older Python versions, returns None.
76+ fn qualname ( & self ) -> Option < * mut Self :: StringObject > {
77+ None
78+ }
7379}
7480
7581pub trait BytesObject : Copy {
@@ -354,6 +360,10 @@ macro_rules! CompactCodeObjectImpl {
354360 }
355361 line_number
356362 }
363+
364+ fn qualname( & self ) -> Option <* mut Self :: StringObject > {
365+ Some ( self . co_qualname as * mut Self :: StringObject )
366+ }
357367 }
358368 } ;
359369}
@@ -921,4 +931,24 @@ mod tests {
921931 ] ;
922932 assert_eq ! ( code. get_line_number( 214 , & table) , 5 ) ;
923933 }
934+
935+ #[ test]
936+ fn test_py3_11_qualname ( ) {
937+ use crate :: python_bindings:: v3_11_0:: PyCodeObject ;
938+ let code = PyCodeObject {
939+ co_firstlineno : 1 ,
940+ ..Default :: default ( )
941+ } ;
942+ assert ! ( code. qualname( ) . is_some( ) ) ;
943+ }
944+
945+ #[ test]
946+ fn test_py3_10_qualname_not_available ( ) {
947+ use crate :: python_bindings:: v3_10_0:: PyCodeObject ;
948+ let code = PyCodeObject {
949+ co_firstlineno : 1 ,
950+ ..Default :: default ( )
951+ } ;
952+ assert ! ( code. qualname( ) . is_none( ) ) ;
953+ }
924954}
Original file line number Diff line number Diff line change @@ -150,7 +150,15 @@ where
150150 . context ( "Failed to copy PyCodeObject" ) ?;
151151
152152 let filename = copy_string ( code. filename ( ) , process) . context ( "Failed to copy filename" ) ;
153- let name = copy_string ( code. name ( ) , process) . context ( "Failed to copy function name" ) ;
153+
154+ // Try to get qualname first (available in Python 3.11+), fall back to name
155+ let name = match code. qualname ( ) {
156+ Some ( qualname_ptr) => {
157+ copy_string ( qualname_ptr, process) . or_else ( |_| copy_string ( code. name ( ) , process) )
158+ }
159+ None => copy_string ( code. name ( ) , process) ,
160+ }
161+ . context ( "Failed to copy function name" ) ;
154162
155163 // just skip processing the current frame if we can't load the filename or function name.
156164 // this can happen in python 3.13+ since the f_executable isn't guaranteed to be
You can’t perform that action at this time.
0 commit comments