@@ -302,17 +302,7 @@ pub(crate) mod _typing {
302302
303303 let obj = typevar. into_ref_with_type ( vm, cls) ?;
304304 let obj_ref: PyObjectRef = obj. into ( ) ;
305-
306- // Set __module__ from the current frame
307- if let Some ( frame) = vm. current_frame ( ) {
308- if let Ok ( module_name) = frame. globals . get_item ( "__name__" , vm) {
309- // Don't set __module__ if it's None
310- if !vm. is_none ( & module_name) {
311- obj_ref. set_attr ( "__module__" , module_name, vm) ?;
312- }
313- }
314- }
315-
305+ set_module_from_caller ( & obj_ref, vm) ?;
316306 Ok ( obj_ref)
317307 }
318308 }
@@ -559,23 +549,7 @@ pub(crate) mod _typing {
559549
560550 let obj = paramspec. into_ref_with_type ( vm, cls) ?;
561551 let obj_ref: PyObjectRef = obj. into ( ) ;
562-
563- // Set __module__ from the current frame
564- if let Some ( frame) = vm. current_frame ( ) {
565- if let Ok ( module_name) = frame. globals . get_item ( "__name__" , vm) {
566- // Set __module__ to None for modules that start with "<"
567- if let Ok ( name_str) = module_name. str ( vm) {
568- if name_str. as_str ( ) . starts_with ( '<' ) {
569- obj_ref. set_attr ( "__module__" , vm. ctx . none ( ) , vm) ?;
570- } else {
571- obj_ref. set_attr ( "__module__" , module_name, vm) ?;
572- }
573- } else {
574- obj_ref. set_attr ( "__module__" , module_name, vm) ?;
575- }
576- }
577- }
578-
552+ set_module_from_caller ( & obj_ref, vm) ?;
579553 Ok ( obj_ref)
580554 }
581555 }
@@ -722,23 +696,7 @@ pub(crate) mod _typing {
722696
723697 let obj = typevartuple. into_ref_with_type ( vm, cls) ?;
724698 let obj_ref: PyObjectRef = obj. into ( ) ;
725-
726- // Set __module__ from the current frame
727- if let Some ( frame) = vm. current_frame ( ) {
728- if let Ok ( module_name) = frame. globals . get_item ( "__name__" , vm) {
729- // Set __module__ to None for modules that start with "<"
730- if let Ok ( name_str) = module_name. str ( vm) {
731- if name_str. as_str ( ) . starts_with ( '<' ) {
732- obj_ref. set_attr ( "__module__" , vm. ctx . none ( ) , vm) ?;
733- } else {
734- obj_ref. set_attr ( "__module__" , module_name, vm) ?;
735- }
736- } else {
737- obj_ref. set_attr ( "__module__" , module_name, vm) ?;
738- }
739- }
740- }
741-
699+ set_module_from_caller ( & obj_ref, vm) ?;
742700 Ok ( obj_ref)
743701 }
744702 }
@@ -893,4 +851,40 @@ pub(crate) mod _typing {
893851 // &AS_MAPPING
894852 // }
895853 // }
854+
855+ /// Get the module of the caller frame, similar to CPython's caller() function.
856+ /// Returns the module name or None if not found.
857+ ///
858+ /// Note: CPython's implementation (in typevarobject.c) gets the module from the
859+ /// frame's function object using PyFunction_GetModule(f->f_funcobj). However,
860+ /// RustPython's Frame doesn't store a reference to the function object, so we
861+ /// get the module name from the frame's globals dictionary instead.
862+ fn caller ( vm : & VirtualMachine ) -> Option < PyObjectRef > {
863+ let frame = vm. current_frame ( ) ?;
864+
865+ // In RustPython, we get the module name from frame's globals
866+ // This is similar to CPython's sys._getframe().f_globals.get('__name__')
867+ frame. globals . get_item ( "__name__" , vm) . ok ( )
868+ }
869+
870+ /// Set __module__ attribute for an object based on the caller's module.
871+ /// This follows CPython's behavior for TypeVar and similar objects.
872+ fn set_module_from_caller ( obj : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
873+ // Note: CPython gets module from frame->f_funcobj, but RustPython's Frame
874+ // architecture is different - we use globals['__name__'] instead
875+ if let Some ( module_name) = caller ( vm) {
876+ // Special handling for certain module names
877+ if let Ok ( name_str) = module_name. str ( vm) {
878+ let name = name_str. as_str ( ) ;
879+ // CPython sets __module__ to None for builtins and <...> modules
880+ if name == "builtins" || name. starts_with ( '<' ) {
881+ // Don't set __module__ attribute at all (CPython behavior)
882+ // This allows the typing module to handle it
883+ return Ok ( ( ) ) ;
884+ }
885+ }
886+ obj. set_attr ( "__module__" , module_name, vm) ?;
887+ }
888+ Ok ( ( ) )
889+ }
896890}
0 commit comments