From 6c92f711eaf382113e811e43900f4fabd0f95c26 Mon Sep 17 00:00:00 2001 From: Rachel Tobin Date: Fri, 13 Oct 2017 06:16:09 -0700 Subject: [PATCH] Refs #28575 -- Allowed pickling Model.DoesNotExist and MultipleObjectsReturned classes. --- django/db/models/base.py | 2 ++ django/test/runner.py | 2 +- tests/queryset_pickle/tests.py | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index 87bd8c09bf..1349b1d417 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -64,6 +64,8 @@ def subclass_exception(name, parents, module, attached_to=None): class_dict['__reduce__'] = __reduce__ class_dict['__setstate__'] = __setstate__ + if attached_to: + class_dict['__qualname__'] = '%s.%s' % (attached_to.__qualname__, name) return type(name, parents, class_dict) diff --git a/django/test/runner.py b/django/test/runner.py index 0975a8c8c0..49c106049f 100644 --- a/django/test/runner.py +++ b/django/test/runner.py @@ -350,7 +350,7 @@ class ParallelTestSuite(unittest.TestSuite): - make tracebacks picklable with tblib, if available Even with tblib, errors may still occur for dynamically created - exception classes such Model.DoesNotExist which cannot be unpickled. + exception classes which cannot be unpickled. """ counter = multiprocessing.Value(ctypes.c_int, 0) pool = multiprocessing.Pool( diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py index 61ffba6c0b..ebefb690df 100644 --- a/tests/queryset_pickle/tests.py +++ b/tests/queryset_pickle/tests.py @@ -47,6 +47,14 @@ class PickleabilityTestCase(TestCase): self.assertEqual(original.__class__, unpickled.__class__) self.assertEqual(original.args, unpickled.args) + def test_doesnotexist_class(self): + klass = Event.DoesNotExist + self.assertIs(pickle.loads(pickle.dumps(klass)), klass) + + def test_multipleobjectsreturned_class(self): + klass = Event.MultipleObjectsReturned + self.assertIs(pickle.loads(pickle.dumps(klass)), klass) + def test_manager_pickle(self): pickle.loads(pickle.dumps(Happening.objects))