From a8b2db1cae581d083db999ffeb8244864e6be125 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Fri, 3 Apr 2020 21:13:02 +0100 Subject: [PATCH] Optimized Model and QuerySet pickling version comparison. --- django/db/models/base.py | 27 ++++++++++++++------------- django/db/models/query.py | 25 +++++++++++++------------ tests/model_regress/test_pickle.py | 7 +++++-- tests/queryset_pickle/tests.py | 7 +++++-- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index bc6f7d283e2..7bb3fa4706f 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -4,6 +4,7 @@ import warnings from functools import partialmethod from itertools import chain +import django from django.apps import apps from django.conf import settings 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.text import capfirst, get_text_list from django.utils.translation import gettext_lazy as _ -from django.utils.version import get_version class Deferred: @@ -538,7 +538,7 @@ class Model(metaclass=ModelBase): def __reduce__(self): 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 return model_unpickle, (class_id,), data @@ -547,21 +547,22 @@ class Model(metaclass=ModelBase): return self.__dict__ def __setstate__(self, state): - msg = None pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY) if pickled_version: - current_version = get_version() - if current_version != pickled_version: - msg = ( - "Pickled model instance's Django version %s does not match " - "the current version %s." % (pickled_version, current_version) + if pickled_version != django.__version__: + warnings.warn( + "Pickled model instance's Django version %s does not " + "match the current version %s." + % (pickled_version, django.__version__), + RuntimeWarning, + stacklevel=2, ) else: - msg = "Pickled model instance's Django version is not specified." - - if msg: - warnings.warn(msg, RuntimeWarning, stacklevel=2) - + warnings.warn( + "Pickled model instance's Django version is not specified.", + RuntimeWarning, + stacklevel=2, + ) self.__dict__.update(state) def _get_pk_val(self, meta=None): diff --git a/django/db/models/query.py b/django/db/models/query.py index c1aa3527012..e0eeccefa68 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -9,6 +9,7 @@ from collections import namedtuple from functools import lru_cache from itertools import chain +import django from django.conf import settings from django.core import exceptions 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.utils import timezone 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. MAX_GET_RESULTS = 21 @@ -238,24 +238,25 @@ class QuerySet: def __getstate__(self): # Force the cache to be fully populated. 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): - msg = None pickled_version = state.get(DJANGO_VERSION_PICKLE_KEY) if pickled_version: - current_version = get_version() - if current_version != pickled_version: - msg = ( + if pickled_version != django.__version__: + warnings.warn( "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: - msg = "Pickled queryset instance's Django version is not specified." - - if msg: - warnings.warn(msg, RuntimeWarning, stacklevel=2) - + warnings.warn( + "Pickled queryset instance's Django version is not specified.", + RuntimeWarning, + stacklevel=2, + ) self.__dict__.update(state) def __repr__(self): diff --git a/tests/model_regress/test_pickle.py b/tests/model_regress/test_pickle.py index f8676404c05..6a09c3734fd 100644 --- a/tests/model_regress/test_pickle.py +++ b/tests/model_regress/test_pickle.py @@ -1,8 +1,8 @@ import pickle +import django from django.db import DJANGO_VERSION_PICKLE_KEY, models from django.test import SimpleTestCase -from django.utils.version import get_version class ModelPickleTests(SimpleTestCase): @@ -40,7 +40,10 @@ class ModelPickleTests(SimpleTestCase): return reduce_list 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): pickle.loads(pickle.dumps(p)) diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py index 793141cfdde..baf2e96aafb 100644 --- a/tests/queryset_pickle/tests.py +++ b/tests/queryset_pickle/tests.py @@ -1,9 +1,9 @@ import datetime import pickle +import django from django.db import models from django.test import TestCase -from django.utils.version import get_version 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 """ 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): pickle.loads(pickle.dumps(qs))