diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py index 9d9e4a1e658..9004af4998e 100644 --- a/django/utils/translation/__init__.py +++ b/django/utils/translation/__init__.py @@ -106,6 +106,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 __bool__(self): return bool(kwargs['singular']) @@ -134,9 +136,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 1ceada6f541..4eea5a3b7b8 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/docs/releases/1.9.3.txt b/docs/releases/1.9.3.txt index e6f200c864c..05c65423291 100644 --- a/docs/releases/1.9.3.txt +++ b/docs/releases/1.9.3.txt @@ -24,3 +24,6 @@ Bugfixes * Fixed regression with an ``__in=qs`` lookup for a ``ForeignKey`` with ``to_field`` set (:ticket:`26196`). + +* 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 c4798076d36..bd33cff4fd7 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -949,6 +949,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 1e07378ec26..05c78284307 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -243,6 +243,14 @@ class TranslationTests(SimpleTestCase): self.assertTrue(ungettext_lazy('%d good result', '%d good results')) self.assertFalse(ungettext_lazy('', '')) + 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()