@@ -67,19 +67,34 @@ impl Constructor for PyClassMethod {
6767 type Args = PyObjectRef ;
6868
6969 fn py_new ( cls : PyTypeRef , callable : Self :: Args , vm : & VirtualMachine ) -> PyResult {
70- let doc = callable. get_attr ( "__doc__" , vm) ;
70+ // Create a dictionary to hold copied attributes
71+ let dict = vm. ctx . new_dict ( ) ;
7172
72- let result = PyClassMethod {
73- callable : PyMutex :: new ( callable) ,
73+ // Copy attributes from the callable to the dict
74+ // This is similar to functools.wraps in CPython
75+ if let Ok ( doc) = callable. get_attr ( "__doc__" , vm) {
76+ dict. set_item ( identifier ! ( vm. ctx, __doc__) , doc, vm) ?;
7477 }
75- . into_ref_with_type ( vm, cls) ?;
76- let obj = PyObjectRef :: from ( result) ;
77-
78- if let Ok ( doc) = doc {
79- obj. set_attr ( "__doc__" , doc, vm) ?;
78+ if let Ok ( name) = callable. get_attr ( "__name__" , vm) {
79+ dict. set_item ( identifier ! ( vm. ctx, __name__) , name, vm) ?;
80+ }
81+ if let Ok ( qualname) = callable. get_attr ( "__qualname__" , vm) {
82+ dict. set_item ( identifier ! ( vm. ctx, __qualname__) , qualname, vm) ?;
83+ }
84+ if let Ok ( module) = callable. get_attr ( "__module__" , vm) {
85+ dict. set_item ( identifier ! ( vm. ctx, __module__) , module, vm) ?;
8086 }
87+ if let Ok ( annotations) = callable. get_attr ( "__annotations__" , vm) {
88+ dict. set_item ( identifier ! ( vm. ctx, __annotations__) , annotations, vm) ?;
89+ }
90+
91+ // Create PyClassMethod instance with the pre-populated dict
92+ let classmethod = PyClassMethod {
93+ callable : PyMutex :: new ( callable) ,
94+ } ;
8195
82- Ok ( obj)
96+ let result = PyRef :: new_ref ( classmethod, cls, Some ( dict) ) ;
97+ Ok ( PyObjectRef :: from ( result) )
8398 }
8499}
85100
0 commit comments