Fixed #18590 - Reverted Python 2.4 workaround for Model pickling

Revert of 08d521efa0. Refs #10547, #12121.
Thanks Michal Petrucha for the report.
This commit is contained in:
Claude Paroz 2012-07-07 18:39:09 +02:00
parent 1aa0d8ac4d
commit 146aff3bac
1 changed files with 11 additions and 29 deletions

View File

@ -16,7 +16,7 @@ from django.db.models.fields.related import (ManyToOneRel,
from django.db import (router, transaction, DatabaseError, from django.db import (router, transaction, DatabaseError,
DEFAULT_DB_ALIAS) DEFAULT_DB_ALIAS)
from django.db.models.query import Q 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.deletion import Collector
from django.db.models.options import Options from django.db.models.options import Options
from django.db.models import signals 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 need to do things manually, as they're dynamically created classes and
only module-level classes can be pickled by the default path. only module-level classes can be pickled by the default path.
""" """
if not self._deferred:
return super(Model, self).__reduce__()
data = self.__dict__ 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 = [] defers = []
if self._deferred:
from django.db.models.query_utils import deferred_class_factory
factory = deferred_class_factory
for field in self._meta.fields: for field in self._meta.fields:
if isinstance(self.__class__.__dict__.get(field.attname), if isinstance(self.__class__.__dict__.get(field.attname),
DeferredAttribute): DeferredAttribute):
defers.append(field.attname) defers.append(field.attname)
model = self._meta.proxy_for_model model = self._meta.proxy_for_model
else: return (model_unpickle, (model, defers), data)
factory = simple_class_factory
return (model_unpickle, (model, defers, factory), data)
def _get_pk_val(self, meta=None): def _get_pk_val(self, meta=None):
if not meta: if not meta:
@ -926,20 +917,11 @@ def get_absolute_url(opts, func, self, *args, **kwargs):
class Empty(object): class Empty(object):
pass pass
def simple_class_factory(model, attrs): def model_unpickle(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):
""" """
Used to unpickle Model subclasses with deferred fields. Used to unpickle Model subclasses with deferred fields.
""" """
cls = factory(model, attrs) cls = deferred_class_factory(model, attrs)
return cls.__new__(cls) return cls.__new__(cls)
model_unpickle.__safe_for_unpickle__ = True model_unpickle.__safe_for_unpickle__ = True