Optimized Model and QuerySet pickling version comparison.
This commit is contained in:
parent
72a170b4c3
commit
a8b2db1cae
|
@ -4,6 +4,7 @@ import warnings
|
||||||
from functools import partialmethod
|
from functools import partialmethod
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
import django
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import checks
|
from django.core import checks
|
||||||
|
@ -36,7 +37,6 @@ from django.utils.encoding import force_str
|
||||||
from django.utils.hashable import make_hashable
|
from django.utils.hashable import make_hashable
|
||||||
from django.utils.text import capfirst, get_text_list
|
from django.utils.text import capfirst, get_text_list
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.version import get_version
|
|
||||||
|
|
||||||
|
|
||||||
class Deferred:
|
class Deferred:
|
||||||
|
@ -538,7 +538,7 @@ class Model(metaclass=ModelBase):
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
data = self.__getstate__()
|
data = self.__getstate__()
|
||||||
data[DJANGO_VERSION_PICKLE_KEY] = get_version()
|
data[DJANGO_VERSION_PICKLE_KEY] = django.__version__
|
||||||
class_id = self._meta.app_label, self._meta.object_name
|
class_id = self._meta.app_label, self._meta.object_name
|
||||||
return model_unpickle, (class_id,), data
|
return model_unpickle, (class_id,), data
|
||||||
|
|
||||||
|
@ -547,21 +547,22 @@ class Model(metaclass=ModelBase):
|
||||||
return self.__dict__
|
return self.__dict__
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
msg = None
|
|
||||||
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
|
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
|
||||||
if pickled_version:
|
if pickled_version:
|
||||||
current_version = get_version()
|
if pickled_version != django.__version__:
|
||||||
if current_version != pickled_version:
|
warnings.warn(
|
||||||
msg = (
|
"Pickled model instance's Django version %s does not "
|
||||||
"Pickled model instance's Django version %s does not match "
|
"match the current version %s."
|
||||||
"the current version %s." % (pickled_version, current_version)
|
% (pickled_version, django.__version__),
|
||||||
|
RuntimeWarning,
|
||||||
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = "Pickled model instance's Django version is not specified."
|
warnings.warn(
|
||||||
|
"Pickled model instance's Django version is not specified.",
|
||||||
if msg:
|
RuntimeWarning,
|
||||||
warnings.warn(msg, RuntimeWarning, stacklevel=2)
|
stacklevel=2,
|
||||||
|
)
|
||||||
self.__dict__.update(state)
|
self.__dict__.update(state)
|
||||||
|
|
||||||
def _get_pk_val(self, meta=None):
|
def _get_pk_val(self, meta=None):
|
||||||
|
|
|
@ -9,6 +9,7 @@ from collections import namedtuple
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
import django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import exceptions
|
from django.core import exceptions
|
||||||
from django.db import (
|
from django.db import (
|
||||||
|
@ -25,7 +26,6 @@ from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE
|
||||||
from django.db.models.utils import resolve_callables
|
from django.db.models.utils import resolve_callables
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.functional import cached_property, partition
|
from django.utils.functional import cached_property, partition
|
||||||
from django.utils.version import get_version
|
|
||||||
|
|
||||||
# The maximum number of results to fetch in a get() query.
|
# The maximum number of results to fetch in a get() query.
|
||||||
MAX_GET_RESULTS = 21
|
MAX_GET_RESULTS = 21
|
||||||
|
@ -238,24 +238,25 @@ class QuerySet:
|
||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
# Force the cache to be fully populated.
|
# Force the cache to be fully populated.
|
||||||
self._fetch_all()
|
self._fetch_all()
|
||||||
return {**self.__dict__, DJANGO_VERSION_PICKLE_KEY: get_version()}
|
return {**self.__dict__, DJANGO_VERSION_PICKLE_KEY: django.__version__}
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
msg = None
|
|
||||||
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
|
pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY)
|
||||||
if pickled_version:
|
if pickled_version:
|
||||||
current_version = get_version()
|
if pickled_version != django.__version__:
|
||||||
if current_version != pickled_version:
|
warnings.warn(
|
||||||
msg = (
|
|
||||||
"Pickled queryset instance's Django version %s does not "
|
"Pickled queryset instance's Django version %s does not "
|
||||||
"match the current version %s." % (pickled_version, current_version)
|
"match the current version %s."
|
||||||
|
% (pickled_version, django.__version__),
|
||||||
|
RuntimeWarning,
|
||||||
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = "Pickled queryset instance's Django version is not specified."
|
warnings.warn(
|
||||||
|
"Pickled queryset instance's Django version is not specified.",
|
||||||
if msg:
|
RuntimeWarning,
|
||||||
warnings.warn(msg, RuntimeWarning, stacklevel=2)
|
stacklevel=2,
|
||||||
|
)
|
||||||
self.__dict__.update(state)
|
self.__dict__.update(state)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
|
import django
|
||||||
from django.db import DJANGO_VERSION_PICKLE_KEY, models
|
from django.db import DJANGO_VERSION_PICKLE_KEY, models
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
from django.utils.version import get_version
|
|
||||||
|
|
||||||
|
|
||||||
class ModelPickleTests(SimpleTestCase):
|
class ModelPickleTests(SimpleTestCase):
|
||||||
|
@ -40,7 +40,10 @@ class ModelPickleTests(SimpleTestCase):
|
||||||
return reduce_list
|
return reduce_list
|
||||||
|
|
||||||
p = DifferentDjangoVersion(title="FooBar")
|
p = DifferentDjangoVersion(title="FooBar")
|
||||||
msg = "Pickled model instance's Django version 1.0 does not match the current version %s." % get_version()
|
msg = (
|
||||||
|
"Pickled model instance's Django version 1.0 does not match the "
|
||||||
|
"current version %s." % django.__version__
|
||||||
|
)
|
||||||
with self.assertRaisesMessage(RuntimeWarning, msg):
|
with self.assertRaisesMessage(RuntimeWarning, msg):
|
||||||
pickle.loads(pickle.dumps(p))
|
pickle.loads(pickle.dumps(p))
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import datetime
|
import datetime
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
|
import django
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.version import get_version
|
|
||||||
|
|
||||||
from .models import Container, Event, Group, Happening, M2MModel, MyEvent
|
from .models import Container, Event, Group, Happening, M2MModel, MyEvent
|
||||||
|
|
||||||
|
@ -234,7 +234,10 @@ class PickleabilityTestCase(TestCase):
|
||||||
unpickled with a different Django version than the current
|
unpickled with a different Django version than the current
|
||||||
"""
|
"""
|
||||||
qs = Group.previous_django_version_objects.all()
|
qs = Group.previous_django_version_objects.all()
|
||||||
msg = "Pickled queryset instance's Django version 1.0 does not match the current version %s." % get_version()
|
msg = (
|
||||||
|
"Pickled queryset instance's Django version 1.0 does not match "
|
||||||
|
"the current version %s." % django.__version__
|
||||||
|
)
|
||||||
with self.assertRaisesMessage(RuntimeWarning, msg):
|
with self.assertRaisesMessage(RuntimeWarning, msg):
|
||||||
pickle.loads(pickle.dumps(qs))
|
pickle.loads(pickle.dumps(qs))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue