From 8da2f643c69ae6c0e160ab2d0df11ddc9ef8b314 Mon Sep 17 00:00:00 2001 From: Vasyl Dizhak Date: Sun, 10 Oct 2021 21:49:32 +0200 Subject: [PATCH] Change pickle default version to Python default instead of Highest version --- README.rst | 6 +++--- django_redis/serializers/pickle.py | 7 ++++++- tests/test_serializers.py | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/test_serializers.py diff --git a/README.rst b/README.rst index c26e3f2f..07c7c620 100644 --- a/README.rst +++ b/README.rst @@ -193,8 +193,8 @@ Pickle version For almost all values, django-redis uses pickle to serialize objects. -The latest available version of pickle is used by default. If you want set a -concrete version, you can do it, using ``PICKLE_VERSION`` option: +The ``pickle.DEFAULT_PROTOCOL`` version of pickle is used by default to ensure safe upgrades and compatibility across Python versions. +If you want set a concrete version, you can do it, using ``PICKLE_VERSION`` option: .. code-block:: python @@ -202,7 +202,7 @@ concrete version, you can do it, using ``PICKLE_VERSION`` option: "default": { # ... "OPTIONS": { - "PICKLE_VERSION": -1 # Use the latest protocol version + "PICKLE_VERSION": -1 # Will use highest protocol version available } } } diff --git a/django_redis/serializers/pickle.py b/django_redis/serializers/pickle.py index 2f47a491..c304360d 100644 --- a/django_redis/serializers/pickle.py +++ b/django_redis/serializers/pickle.py @@ -8,7 +8,7 @@ class PickleSerializer(BaseSerializer): def __init__(self, options) -> None: - self._pickle_version = -1 + self._pickle_version = pickle.DEFAULT_PROTOCOL self.setup_pickle_version(options) super().__init__(options=options) @@ -17,6 +17,11 @@ def setup_pickle_version(self, options) -> None: if "PICKLE_VERSION" in options: try: self._pickle_version = int(options["PICKLE_VERSION"]) + if self._pickle_version > pickle.HIGHEST_PROTOCOL: + raise ImproperlyConfigured( + f"PICKLE_VERSION can't be higher than pickle.HIGHEST_PROTOCOL:" + f" {pickle.HIGHEST_PROTOCOL}" + ) except (ValueError, TypeError): raise ImproperlyConfigured("PICKLE_VERSION value must be an integer") diff --git a/tests/test_serializers.py b/tests/test_serializers.py new file mode 100644 index 00000000..b3c77ec0 --- /dev/null +++ b/tests/test_serializers.py @@ -0,0 +1,26 @@ +import pickle + +import pytest +from django.core.exceptions import ImproperlyConfigured + +from django_redis.serializers.pickle import PickleSerializer + + +class TestPickleSerializer: + def test_invalid_pickle_version_provided(self): + with pytest.raises( + ImproperlyConfigured, match="PICKLE_VERSION value must be an integer" + ): + PickleSerializer({"PICKLE_VERSION": "not-an-integer"}) + + def test_setup_pickle_version_not_explicitly_specified(self): + serializer = PickleSerializer({}) + assert serializer._pickle_version == pickle.DEFAULT_PROTOCOL + + def test_setup_pickle_version_too_high(self): + with pytest.raises( + ImproperlyConfigured, + match=f"PICKLE_VERSION can't be higher than pickle.HIGHEST_PROTOCOL:" + f" {pickle.HIGHEST_PROTOCOL}", + ): + PickleSerializer({"PICKLE_VERSION": pickle.HIGHEST_PROTOCOL + 1})