Commit b4a1d545 authored by Simon Charette's avatar Simon Charette
Browse files

[1.9.x] Fixed #25807 -- Instructed the migration writer about lazy objects.

Thanks to Trac alias mrgaolei for the report, Baptiste for the confirmation
and Tim for the review.

Backport of cc2ca9c5 from master
parent f7e599ad
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject
from django.utils import datetime_safe, six
from django.utils._os import upath
from django.utils.encoding import force_text
from django.utils.functional import Promise
from django.utils.functional import LazyObject, Promise
from django.utils.inspect import get_func_args
from django.utils.module_loading import module_dir
from django.utils.timezone import now, utc
@@ -344,6 +344,10 @@ class MigrationWriter(object):
        # process.
        if isinstance(value, Promise):
            value = force_text(value)
        elif isinstance(value, LazyObject):
            # The unwrapped value is returned as the first item of the
            # arguments tuple.
            value = value.__reduce__()[1][0]

        # Sequences
        if isinstance(value, (frozenset, list, set, tuple)):
+2 −1
Original line number Diff line number Diff line
@@ -448,7 +448,8 @@ Migrations
  :djadminopt:`migrate --fake-initial <--fake-initial>` to more easily detect
  initial migrations.

* Added support for serialization of ``functools.partial`` objects.
* Added support for serialization of ``functools.partial`` and ``LazyObject``
  instances.

* When supplying ``None`` as a value in :setting:`MIGRATION_MODULES`, Django
  will consider the app an app without migrations.
+3 −1
Original line number Diff line number Diff line
@@ -659,6 +659,7 @@ Django can serialize the following:
- ``decimal.Decimal`` instances
- ``functools.partial`` 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)
- Any class reference (must be in module's top-level scope)
@@ -666,7 +667,8 @@ Django can serialize the following:

.. versionchanged:: 1.9

    Serialization support for `functools.partial` was added.
    Serialization support for ``functools.partial`` and ``LazyObject``
    instances was added.

Django can serialize the following on Python 3 only:

+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ from django.test import SimpleTestCase, ignore_warnings, mock
from django.utils import datetime_safe, six
from django.utils._os import upath
from django.utils.deconstruct import deconstructible
from django.utils.functional import SimpleLazyObject
from django.utils.timezone import FixedOffset, get_default_timezone, utc
from django.utils.translation import ugettext_lazy as _

@@ -229,6 +230,11 @@ class WriterTests(SimpleTestCase):
            ("[list, tuple, dict, set, frozenset]", set())
        )

    def test_serialize_lazy_objects(self):
        pattern = re.compile(r'^foo$', re.UNICODE)
        lazy_pattern = SimpleLazyObject(lambda: pattern)
        self.assertEqual(self.serialize_round_trip(lazy_pattern), pattern)

    def test_serialize_functions(self):
        with six.assertRaisesRegex(self, ValueError, 'Cannot serialize function: lambda'):
            self.assertSerializedEqual(lambda x: 42)