@@ -749,6 +749,73 @@ def _function_getstate(func):
749749 return state , slotstate
750750
751751
752+ def _is_copied_annotation_function (obj ):
753+ """Detect __annotate__ copied by functools.update_wrapper on Python 3.14+."""
754+ if sys .version_info < (3 , 14 ):
755+ return False
756+
757+ try :
758+ obj_dict = obj .__dict__
759+ except Exception :
760+ return False
761+ if not isinstance (obj_dict , dict ):
762+ return False
763+
764+ annotate = obj_dict .get ("__annotate__" )
765+ if not isinstance (annotate , types .FunctionType ):
766+ return False
767+
768+ wrapped = obj_dict .get ("__wrapped__" )
769+ if wrapped is None :
770+ return False
771+
772+ if annotate .__name__ != "__annotate__" :
773+ return False
774+
775+ annotate_module = getattr (annotate , "__module__" , None )
776+ wrapped_module = getattr (wrapped , "__module__" , None )
777+ if (
778+ annotate_module is not None
779+ and wrapped_module is not None
780+ and annotate_module != wrapped_module
781+ ):
782+ return False
783+
784+ return True
785+
786+
787+ def _remove_key_from_state (state , key ):
788+ if isinstance (state , dict ):
789+ if key not in state :
790+ return state
791+ state = state .copy ()
792+ state .pop (key , None )
793+ return state
794+
795+ if (
796+ isinstance (state , tuple )
797+ and len (state ) == 2
798+ and isinstance (state [0 ], dict )
799+ and key in state [0 ]
800+ ):
801+ state_dict = state [0 ].copy ()
802+ state_dict .pop (key , None )
803+ return state_dict , state [1 ]
804+
805+ return state
806+
807+
808+ def _reduced_without_copied_annotation_function (obj , proto ):
809+ """Remove redundant __annotate__ copied from a wrapped callable."""
810+ rv = obj .__reduce_ex__ (proto )
811+ if not isinstance (rv , tuple ) or len (rv ) < 3 :
812+ return rv
813+
814+ state = rv [2 ]
815+ state = _remove_key_from_state (state , "__annotate__" )
816+ return rv [:2 ] + (state ,) + rv [3 :]
817+
818+
752819def _class_getstate (obj ):
753820 clsdict = _extract_class_dict (obj )
754821 clsdict .pop ("__weakref__" , None )
@@ -1402,6 +1469,8 @@ def reducer_override(self, obj):
14021469 return _class_reduce (obj )
14031470 elif isinstance (obj , types .FunctionType ):
14041471 return self ._function_reduce (obj )
1472+ elif _is_copied_annotation_function (obj ):
1473+ return _reduced_without_copied_annotation_function (obj , self .proto )
14051474 else :
14061475 # fallback to save_global, including the Pickler's
14071476 # dispatch_table
0 commit comments