diff --git a/django/contrib/sessions/serializers.py b/django/contrib/sessions/serializers.py index 6ac4aab6a4..5b6c343daa 100644 --- a/django/contrib/sessions/serializers.py +++ b/django/contrib/sessions/serializers.py @@ -1,20 +1,7 @@ -import pickle - +from django.core.serializers.base import ( + PickleSerializer as BasePickleSerializer, +) from django.core.signing import JSONSerializer as BaseJSONSerializer - -class PickleSerializer: - """ - Simple wrapper around pickle to be used in signing.dumps and - signing.loads. - """ - protocol = pickle.HIGHEST_PROTOCOL - - def dumps(self, obj): - return pickle.dumps(obj, self.protocol) - - def loads(self, data): - return pickle.loads(data) - - JSONSerializer = BaseJSONSerializer +PickleSerializer = BasePickleSerializer diff --git a/django/core/serializers/base.py b/django/core/serializers/base.py index 3fee7893df..3bd492ec09 100644 --- a/django/core/serializers/base.py +++ b/django/core/serializers/base.py @@ -1,6 +1,7 @@ """ Module for abstract serializer/unserializer base classes. """ +import pickle from io import StringIO from django.core.exceptions import ObjectDoesNotExist @@ -9,6 +10,21 @@ from django.db import models DEFER_FIELD = object() +class PickleSerializer: + """ + Simple wrapper around pickle to be used in signing.dumps()/loads() and + cache backends. + """ + def __init__(self, protocol=None): + self.protocol = pickle.HIGHEST_PROTOCOL if protocol is None else protocol + + def dumps(self, obj): + return pickle.dumps(obj, self.protocol) + + def loads(self, data): + return pickle.loads(data) + + class SerializerDoesNotExist(KeyError): """The requested serializer was not found.""" pass diff --git a/tests/serializers/tests.py b/tests/serializers/tests.py index 439464980d..4bd6acd982 100644 --- a/tests/serializers/tests.py +++ b/tests/serializers/tests.py @@ -1,3 +1,4 @@ +import pickle from datetime import datetime from functools import partialmethod from io import StringIO @@ -5,7 +6,7 @@ from unittest import mock, skipIf from django.core import serializers from django.core.serializers import SerializerDoesNotExist -from django.core.serializers.base import ProgressBar +from django.core.serializers.base import PickleSerializer, ProgressBar from django.db import connection, transaction from django.http import HttpResponse from django.test import SimpleTestCase, override_settings, skipUnlessDBFeature @@ -418,6 +419,21 @@ class SerializersTransactionTestBase: self.assertEqual(art_obj.author.name, "Agnes") +class PickleSerializerTests(SimpleTestCase): + def test_serializer_protocol(self): + serializer = PickleSerializer(protocol=3) + self.assertEqual(serializer.protocol, 3) + # If protocol is not provided, it defaults to pickle.HIGHEST_PROTOCOL + serializer = PickleSerializer() + self.assertEqual(serializer.protocol, pickle.HIGHEST_PROTOCOL) + + def test_serializer_loads_dumps(self): + serializer = PickleSerializer() + test_data = 'test data' + dump = serializer.dumps(test_data) + self.assertEqual(serializer.loads(dump), test_data) + + def register_tests(test_class, method_name, test_func, exclude=()): """ Dynamically create serializer tests to ensure that all registered