[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 cc2ca9c550
from master
This commit is contained in:
parent
f7e599ad25
commit
b4a1d545db
|
@ -19,7 +19,7 @@ from django.db.migrations.utils import COMPILED_REGEX_TYPE, RegexObject
|
||||||
from django.utils import datetime_safe, six
|
from django.utils import datetime_safe, six
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.encoding import force_text
|
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.inspect import get_func_args
|
||||||
from django.utils.module_loading import module_dir
|
from django.utils.module_loading import module_dir
|
||||||
from django.utils.timezone import now, utc
|
from django.utils.timezone import now, utc
|
||||||
|
@ -344,6 +344,10 @@ class MigrationWriter(object):
|
||||||
# process.
|
# process.
|
||||||
if isinstance(value, Promise):
|
if isinstance(value, Promise):
|
||||||
value = force_text(value)
|
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
|
# Sequences
|
||||||
if isinstance(value, (frozenset, list, set, tuple)):
|
if isinstance(value, (frozenset, list, set, tuple)):
|
||||||
|
|
|
@ -448,7 +448,8 @@ Migrations
|
||||||
:djadminopt:`migrate --fake-initial <--fake-initial>` to more easily detect
|
:djadminopt:`migrate --fake-initial <--fake-initial>` to more easily detect
|
||||||
initial migrations.
|
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
|
* When supplying ``None`` as a value in :setting:`MIGRATION_MODULES`, Django
|
||||||
will consider the app an app without migrations.
|
will consider the app an app without migrations.
|
||||||
|
|
|
@ -659,6 +659,7 @@ Django can serialize the following:
|
||||||
- ``decimal.Decimal`` instances
|
- ``decimal.Decimal`` instances
|
||||||
- ``functools.partial`` instances which have serializable ``func``, ``args``,
|
- ``functools.partial`` instances which have serializable ``func``, ``args``,
|
||||||
and ``keywords`` values.
|
and ``keywords`` values.
|
||||||
|
- ``LazyObject`` instances which wrap a serializable value.
|
||||||
- Any Django field
|
- Any Django field
|
||||||
- Any function or method reference (e.g. ``datetime.datetime.today``) (must be in module's top-level scope)
|
- 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)
|
- Any class reference (must be in module's top-level scope)
|
||||||
|
@ -666,7 +667,8 @@ Django can serialize the following:
|
||||||
|
|
||||||
.. versionchanged:: 1.9
|
.. 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:
|
Django can serialize the following on Python 3 only:
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ from django.test import SimpleTestCase, ignore_warnings, mock
|
||||||
from django.utils import datetime_safe, six
|
from django.utils import datetime_safe, six
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.deconstruct import deconstructible
|
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.timezone import FixedOffset, get_default_timezone, utc
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -229,6 +230,11 @@ class WriterTests(SimpleTestCase):
|
||||||
("[list, tuple, dict, set, frozenset]", set())
|
("[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):
|
def test_serialize_functions(self):
|
||||||
with six.assertRaisesRegex(self, ValueError, 'Cannot serialize function: lambda'):
|
with six.assertRaisesRegex(self, ValueError, 'Cannot serialize function: lambda'):
|
||||||
self.assertSerializedEqual(lambda x: 42)
|
self.assertSerializedEqual(lambda x: 42)
|
||||||
|
|
Loading…
Reference in New Issue