Commit 146aff3b authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #18590 - Reverted Python 2.4 workaround for Model pickling

Revert of 08d521ef. Refs #10547, #12121.
Thanks Michal Petrucha for the report.
parent 1aa0d8ac
Loading
Loading
Loading
Loading
+11 −29
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ from django.db.models.fields.related import (ManyToOneRel,
from django.db import (router, transaction, DatabaseError,
    DEFAULT_DB_ALIAS)
from django.db.models.query import Q
from django.db.models.query_utils import DeferredAttribute
from django.db.models.query_utils import DeferredAttribute, deferred_class_factory
from django.db.models.deletion import Collector
from django.db.models.options import Options
from django.db.models import signals
@@ -400,25 +400,16 @@ class Model(object):
        need to do things manually, as they're dynamically created classes and
        only module-level classes can be pickled by the default path.
        """
        if not self._deferred:
            return super(Model, self).__reduce__()
        data = self.__dict__
        model = self.__class__
        # The obvious thing to do here is to invoke super().__reduce__()
        # for the non-deferred case. Don't do that.
        # On Python 2.4, there is something weird with __reduce__,
        # and as a result, the super call will cause an infinite recursion.
        # See #10547 and #12121.
        defers = []
        if self._deferred:
            from django.db.models.query_utils import deferred_class_factory
            factory = deferred_class_factory
        for field in self._meta.fields:
            if isinstance(self.__class__.__dict__.get(field.attname),
                    DeferredAttribute):
                defers.append(field.attname)
        model = self._meta.proxy_for_model
        else:
            factory = simple_class_factory
        return (model_unpickle, (model, defers, factory), data)
        return (model_unpickle, (model, defers), data)

    def _get_pk_val(self, meta=None):
        if not meta:
@@ -926,20 +917,11 @@ def get_absolute_url(opts, func, self, *args, **kwargs):
class Empty(object):
    pass

def simple_class_factory(model, attrs):
    """Used to unpickle Models without deferred fields.

    We need to do this the hard way, rather than just using
    the default __reduce__ implementation, because of a
    __deepcopy__ problem in Python 2.4
    """
    return model

def model_unpickle(model, attrs, factory):
def model_unpickle(model, attrs):
    """
    Used to unpickle Model subclasses with deferred fields.
    """
    cls = factory(model, attrs)
    cls = deferred_class_factory(model, attrs)
    return cls.__new__(cls)
model_unpickle.__safe_for_unpickle__ = True