From 183fb7b2b9778f7d7cc91f5a7e5afec61b85179e Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Fri, 1 Dec 2017 19:24:56 +0500 Subject: [PATCH] Fixed #28870 -- Added support for functools.partialmethod serialization in migrations. --- django/db/migrations/serializer.py | 9 ++++++--- docs/releases/2.1.txt | 2 +- docs/topics/migrations.txt | 8 ++++++-- tests/migrations/test_writer.py | 8 ++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py index d49df642cb..8c5f726924 100644 --- a/django/db/migrations/serializer.py +++ b/django/db/migrations/serializer.py @@ -171,8 +171,11 @@ class FunctoolsPartialSerializer(BaseSerializer): imports.update(args_imports) imports.update(keywords_imports) return ( - "functools.partial(%s, *%s, **%s)" % ( - func_string, args_string, keywords_string, + 'functools.%s(%s, *%s, **%s)' % ( + self.value.__class__.__name__, + func_string, + args_string, + keywords_string, ), imports, ) @@ -340,7 +343,7 @@ def serializer_factory(value): return BaseSimpleSerializer(value) if isinstance(value, decimal.Decimal): return DecimalSerializer(value) - if isinstance(value, functools.partial): + if isinstance(value, (functools.partial, functools.partialmethod)): return FunctoolsPartialSerializer(value) if isinstance(value, (types.FunctionType, types.BuiltinFunctionType, types.MethodType)): return FunctionTypeSerializer(value) diff --git a/docs/releases/2.1.txt b/docs/releases/2.1.txt index ed1ee8cb88..1183bd3121 100644 --- a/docs/releases/2.1.txt +++ b/docs/releases/2.1.txt @@ -150,7 +150,7 @@ Management Commands Migrations ~~~~~~~~~~ -* ... +* Added support for serialization of ``functools.partialmethod`` objects. Models ~~~~~~ diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index 227d64d989..a45966ccb0 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -661,8 +661,8 @@ Django can serialize the following: - ``decimal.Decimal`` instances - ``enum.Enum`` instances - ``uuid.UUID`` instances -- ``functools.partial`` instances which have serializable ``func``, ``args``, - and ``keywords`` values. +- :func:`functools.partial` and :class:`functools.partialmethod` instances + which have serializable ``func``, ``args``, and ``keywords`` values. - ``LazyObject`` instances which wrap a serializable value. - Any Django field - Any function or method reference (e.g. ``datetime.datetime.today``) (must be in module's top-level scope) @@ -670,6 +670,10 @@ Django can serialize the following: - Any class reference (must be in module's top-level scope) - Anything with a custom ``deconstruct()`` method (:ref:`see below `) +.. versionchanged:: 2.1 + + Serialization support for :class:`functools.partialmethod` was added. + Django cannot serialize: - Nested classes diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index 5c9aa85c55..f3012181fa 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -520,6 +520,14 @@ class WriterTests(SimpleTestCase): self.assertEqual(result.args, value.args) self.assertEqual(result.keywords, value.keywords) + def test_serialize_functools_partialmethod(self): + value = functools.partialmethod(datetime.timedelta, 1, seconds=2) + result = self.serialize_round_trip(value) + self.assertIsInstance(result, functools.partialmethod) + self.assertEqual(result.func, value.func) + self.assertEqual(result.args, value.args) + self.assertEqual(result.keywords, value.keywords) + def test_simple_migration(self): """ Tests serializing a simple migration.