Save a class that can't be stored as module global.

        This method is used to serialize classes that are defined inside
        functions, or that otherwise can't be serialized as attribute lookups
        from global modules.

def save_dynamic_class(self, obj):
        """
        Save a class that can't be stored as module global.

        This method is used to serialize classes that are defined inside
        functions, or that otherwise can't be serialized as attribute lookups
        from global modules.
        """
        clsdict = dict(obj.__dict__)  # copy dict proxy to a dict
        if not isinstance(clsdict.get('__dict__', None), property):
            # don't extract dict that are properties
            clsdict.pop('__dict__', None)
            clsdict.pop('__weakref__', None)

        # hack as __new__ is stored differently in the __dict__
        new_override = clsdict.get('__new__', None)
        if new_override:
            clsdict['__new__'] = obj.__new__

        # namedtuple is a special case for Spark where we use the _load_namedtuple function
        if getattr(obj, '_is_namedtuple_', False):
            self.save_reduce(_load_namedtuple, (obj.__name__, obj._fields))
            return

        save = self.save
        write = self.write

        # We write pickle instructions explicitly here to handle the
        # possibility that the type object participates in a cycle with its own
        # __dict__. We first write an empty "skeleton" version of the class and
        # memoize it before writing the class' __dict__ itself. We then write
        # instructions to "rehydrate" the skeleton class by restoring the
        # attributes from the __dict__.
        #
        # A type can appear in a cycle with its __dict__ if an instance of the
        # type appears in the type's __dict__ (which happens for the stdlib
        # Enum class), or if the type defines methods that close over the name
        # of the type, (which is common for Python 2-style super() calls).

        # Push the rehydration function.
        save(_rehydrate_skeleton_class)

        # Mark the start of the args for the rehydration function.
        write(pickle.MARK)

        # On PyPy, __doc__ is a readonly attribute, so we need to include it in
        # the initial skeleton class.  This is safe because we know that the
        # doc can't participate in a cycle with the original class.
        doc_dict = {'__doc__': clsdict.pop('__doc__', None)}

        # Create and memoize an empty class with obj's name and bases.
        save(type(obj))
        save((
            obj.__name__,
            obj.__bases__,
            doc_dict,
        ))
        write(pickle.REDUCE)
        self.memoize(obj)

        # Now save the rest of obj's __dict__. Any references to obj
        # encountered while saving will point to the skeleton class.
        save(clsdict)

        # Write a tuple of (skeleton_class, clsdict).
        write(pickle.TUPLE)

        # Call _rehydrate_skeleton_class(skeleton_class, clsdict)
        write(pickle.REDUCE)