Commit 537818af authored by Piper Merriam's avatar Piper Merriam Committed by Tim Graham
Browse files

Fixed #25185 -- Added support for functools.partial serialization in migrations

parent b1e552de
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
import collections
import datetime
import decimal
import functools
import math
import os
import re
@@ -439,6 +440,22 @@ class MigrationWriter(object):
            string, imports = OperationWriter(value, indentation=0).serialize()
            # Nested operation, trailing comma is handled in upper OperationWriter._write()
            return string.rstrip(','), imports
        elif isinstance(value, functools.partial):
            imports = {'import functools'}
            # Serialize functools.partial() arguments
            func_string, func_imports = cls.serialize(value.func)
            args_string, args_imports = cls.serialize(value.args)
            keywords_string, keywords_imports = cls.serialize(value.keywords)
            # Add any imports needed by arguments
            imports.update(func_imports)
            imports.update(args_imports)
            imports.update(keywords_imports)
            return (
                "functools.partial(%s, *%s, **%s)" % (
                    func_string, args_string, keywords_string,
                ),
                imports,
            )
        # Anything that knows how to deconstruct itself.
        elif hasattr(value, 'deconstruct'):
            return cls.serialize_deconstructed(*value.deconstruct())
+2 −0
Original line number Diff line number Diff line
@@ -385,6 +385,8 @@ Migrations
  :djadminopt:`migrate --fake-initial <--fake-initial>` to more easily detect
  initial migrations.

* Added support for serialization of ``functools.partial`` objects.

Models
^^^^^^

+6 −0
Original line number Diff line number Diff line
@@ -652,11 +652,17 @@ Django can serialize the following:
- ``datetime.date``, ``datetime.time``, and ``datetime.datetime`` instances
  (include those that are timezone-aware)
- ``decimal.Decimal`` instances
- ``functools.partial`` instances which have serializable ``func``, ``args``,
  and ``keywords`` values.
- Any Django field
- Any function or method reference (e.g. ``datetime.datetime.today``) (must be in module's top-level scope)
- Any class reference (must be in module's top-level scope)
- Anything with a custom ``deconstruct()`` method (:ref:`see below <custom-deconstruct-method>`)

.. versionchanged:: 1.9

    Serialization support for `functools.partial` was added.

Django can serialize the following on Python 3 only:

- Unbound methods used from within the class body (see below)
+8 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
from __future__ import unicode_literals

import datetime
import functools
import math
import os
import re
@@ -414,6 +415,13 @@ class WriterTests(SimpleTestCase):
        self.assertSerializedEqual(datetime.timedelta())
        self.assertSerializedEqual(datetime.timedelta(minutes=42))

    def test_serialize_functools_partial(self):
        value = functools.partial(datetime.timedelta, 1, seconds=2)
        result = self.serialize_round_trip(value)
        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.