From 180d4cbfe64f261ecb96bc15047c95c3b008fe4b Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Mon, 15 Feb 2016 11:46:12 -0500 Subject: [PATCH] [1.8.x] Fixed #26212 -- Made forms.FileField and translation.lazy_number() picklable. Backport of b59f963ad2a49322725b20fac71661bd49643443 from master --- django/utils/translation/__init__.py | 7 +++++++ docs/releases/1.8.10.txt | 3 +++ tests/forms_tests/tests/test_fields.py | 3 +++ tests/i18n/tests.py | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index a4c6963f0c..ed452501f7 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -105,6 +105,8 @@ def lazy_number(func, resultclass, number=None, **kwargs): kwargs['number'] = number proxy = lazy(func, resultclass)(**kwargs) else: + original_kwargs = kwargs.copy() + class NumberAwareString(resultclass): def __mod__(self, rhs): if isinstance(rhs, dict) and number: @@ -127,9 +129,14 @@ def lazy_number(func, resultclass, number=None, **kwargs): return translated proxy = lazy(lambda **kwargs: NumberAwareString(), NumberAwareString)(**kwargs) + proxy.__reduce__ = lambda: (_lazy_number_unpickle, (func, resultclass, number, original_kwargs)) return proxy +def _lazy_number_unpickle(func, resultclass, number, kwargs): + return lazy_number(func, resultclass, number=number, **kwargs) + + def ngettext_lazy(singular, plural, number=None): return lazy_number(ngettext, str, singular=singular, plural=plural, number=number) diff --git a/docs/releases/1.8.10.txt b/docs/releases/1.8.10.txt index 1ceada6f54..4eea5a3b7b 100644 --- a/docs/releases/1.8.10.txt +++ b/docs/releases/1.8.10.txt @@ -14,3 +14,6 @@ Bugfixes * Added system checks for query name clashes of hidden relationships (:ticket:`26162`). + +* Made ``forms.FileField`` and ``utils.translation.lazy_number()`` picklable + (:ticket:`26212`). diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index e9c426acd6..145f6a985e 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -788,6 +788,9 @@ class FieldsTests(SimpleTestCase): # with here) self.assertTrue(f.has_changed('resume.txt', {'filename': 'resume.txt', 'content': 'My resume'})) + def test_file_picklable(self): + self.assertIsInstance(pickle.loads(pickle.dumps(FileField())), FileField) + # ImageField ################################################################## @skipIf(Image is None, "Pillow is required to test ImageField") diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 715057844f..ce4f7c18d6 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -229,6 +229,14 @@ class TranslationTests(TestCase): ) self.assertEqual(result % {'name': 'Joe', 'num': 4}, "Joe has 4 good results") + def test_ungettext_lazy_pickle(self): + s1 = ungettext_lazy('%d good result', '%d good results') + self.assertEqual(s1 % 1, '1 good result') + self.assertEqual(s1 % 8, '8 good results') + s2 = pickle.loads(pickle.dumps(s1)) + self.assertEqual(s2 % 1, '1 good result') + self.assertEqual(s2 % 8, '8 good results') + @override_settings(LOCALE_PATHS=extended_locale_paths) def test_pgettext(self): trans_real._active = local()