1
0
mirror of https://github.com/django/django.git synced 2024-11-18 07:26:04 +00:00
django/tests/model_regress/test_pickle.py
David D. Riddle 31e6c9c8e3 Fixed #24717 -- Fixed model_regress test failure on RHEL6 SCL
The test failed on RHEL6 systems running python 2.7 from a RedHat
Software Collection (SCL) because this test runs an external python
script with a stripped system environment. RedHat SCLs work by setting
a number of system environment variables when these are stripped out by
this test the python 2.7 interpreter is no longer able to function
properly because it can not find the system libraries needed.

Now we use use mock to modify the system environment directly.
2015-04-29 12:28:24 -04:00

101 lines
3.7 KiB
Python

import datetime
import os
import pickle
import subprocess
import sys
import warnings
from django.core.files.temp import NamedTemporaryFile
from django.db import DJANGO_VERSION_PICKLE_KEY, models
from django.test import TestCase, mock
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.version import get_version
from .models import Article
class ModelPickleTestCase(TestCase):
def test_missing_django_version_unpickling(self):
"""
#21430 -- Verifies a warning is raised for models that are
unpickled without a Django version
"""
class MissingDjangoVersion(models.Model):
title = models.CharField(max_length=10)
def __reduce__(self):
reduce_list = super(MissingDjangoVersion, self).__reduce__()
data = reduce_list[-1]
del data[DJANGO_VERSION_PICKLE_KEY]
return reduce_list
p = MissingDjangoVersion(title="FooBar")
with warnings.catch_warnings(record=True) as recorded:
pickle.loads(pickle.dumps(p))
msg = force_text(recorded.pop().message)
self.assertEqual(msg,
"Pickled model instance's Django version is not specified.")
def test_unsupported_unpickle(self):
"""
#21430 -- Verifies a warning is raised for models that are
unpickled with a different Django version than the current
"""
class DifferentDjangoVersion(models.Model):
title = models.CharField(max_length=10)
def __reduce__(self):
reduce_list = super(DifferentDjangoVersion, self).__reduce__()
data = reduce_list[-1]
data[DJANGO_VERSION_PICKLE_KEY] = '1.0'
return reduce_list
p = DifferentDjangoVersion(title="FooBar")
with warnings.catch_warnings(record=True) as recorded:
pickle.loads(pickle.dumps(p))
msg = force_text(recorded.pop().message)
self.assertEqual(
msg,
"Pickled model instance's Django version 1.0 does not "
"match the current version %s." % get_version()
)
def test_unpickling_when_appregistrynotready(self):
"""
#24007 -- Verifies that a pickled model can be unpickled without having
to manually setup the apps registry beforehand.
"""
script_template = """#!/usr/bin/env python
import pickle
from django.conf import settings
data = %r
settings.configure(DEBUG=False, INSTALLED_APPS=['model_regress'], SECRET_KEY = "blah")
article = pickle.loads(data)
print(article.headline)"""
a = Article.objects.create(
headline="Some object",
pub_date=datetime.datetime.now(),
article_text="This is an article",
)
with NamedTemporaryFile(mode='w+', suffix=".py") as script:
script.write(script_template % pickle.dumps(a))
script.flush()
# A path to model_regress must be set in PYTHONPATH
model_regress_dir = os.path.dirname(upath(__file__))
model_regress_path = os.path.abspath(model_regress_dir)
tests_path = os.path.split(model_regress_path)[0]
pythonpath = os.environ.get('PYTHONPATH', '')
pythonpath = os.pathsep.join([tests_path, pythonpath])
with mock.patch.dict('os.environ', {'PYTHONPATH': pythonpath}):
try:
result = subprocess.check_output([sys.executable, script.name])
except subprocess.CalledProcessError:
self.fail("Unable to reload model pickled data")
self.assertEqual(result.strip().decode(), "Some object")