@@ -408,15 +408,18 @@ def save_dynamic_class(self, obj):
408408 from global modules.
409409 """
410410 clsdict = dict (obj .__dict__ ) # copy dict proxy to a dict
411- if not isinstance (clsdict .get ('__dict__' , None ), property ):
412- # don't extract dict that are properties
413- clsdict .pop ('__dict__' , None )
414- clsdict .pop ('__weakref__' , None )
411+ clsdict .pop ('__weakref__' , None )
415412
416- # hack as __new__ is stored differently in the __dict__
417- new_override = clsdict .get ('__new__' , None )
418- if new_override :
419- clsdict ['__new__' ] = obj .__new__
413+ # On PyPy, __doc__ is a readonly attribute, so we need to include it in
414+ # the initial skeleton class. This is safe because we know that the
415+ # doc can't participate in a cycle with the original class.
416+ type_kwargs = {'__doc__' : clsdict .pop ('__doc__' , None )}
417+
418+ # If type overrides __dict__ as a property, include it in the type kwargs.
419+ # In Python 2, we can't set this attribute after construction.
420+ __dict__ = clsdict .pop ('__dict__' , None )
421+ if isinstance (__dict__ , property ):
422+ type_kwargs ['__dict__' ] = __dict__
420423
421424 save = self .save
422425 write = self .write
@@ -439,17 +442,12 @@ def save_dynamic_class(self, obj):
439442 # Mark the start of the args for the rehydration function.
440443 write (pickle .MARK )
441444
442- # On PyPy, __doc__ is a readonly attribute, so we need to include it in
443- # the initial skeleton class. This is safe because we know that the
444- # doc can't participate in a cycle with the original class.
445- doc_dict = {'__doc__' : clsdict .pop ('__doc__' , None )}
446-
447445 # Create and memoize an empty class with obj's name and bases.
448446 save (type (obj ))
449447 save ((
450448 obj .__name__ ,
451449 obj .__bases__ ,
452- doc_dict ,
450+ type_kwargs ,
453451 ))
454452 write (pickle .REDUCE )
455453 self .memoize (obj )
0 commit comments