Skip to content

Commit

Permalink
Fixed #27378 -- Added support for serialization of uuid.UUID in migra…
Browse files Browse the repository at this point in the history
…tions.

Thanks Yuriy Korobko for the initial patch and Tobias McNulty for review.
  • Loading branch information
mlorant authored and timgraham committed Nov 6, 2016
1 parent 7301770 commit cb3fb34
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 1 deletion.
8 changes: 8 additions & 0 deletions django/db/migrations/serializer.py
Expand Up @@ -6,6 +6,7 @@
import functools
import math
import types
import uuid
from importlib import import_module

from django.db import models
Expand Down Expand Up @@ -320,6 +321,11 @@ def serialize(self):
return "%s.%s" % (module, self.value.__name__), {"import %s" % module}


class UUIDSerializer(BaseSerializer):
def serialize(self):
return "uuid.%s" % repr(self.value), {"import uuid"}


def serializer_factory(value):
from django.db.migrations.writer import SettingsReference
if isinstance(value, Promise):
Expand Down Expand Up @@ -382,6 +388,8 @@ def serializer_factory(value):
return IterableSerializer(value)
if isinstance(value, (COMPILED_REGEX_TYPE, RegexObject)):
return RegexSerializer(value)
if isinstance(value, uuid.UUID):
return UUIDSerializer(value)
raise ValueError(
"Cannot serialize: %r\nThere are some values Django cannot serialize into "
"migration files.\nFor more, see https://docs.djangoproject.com/en/%s/"
Expand Down
2 changes: 1 addition & 1 deletion docs/releases/1.11.txt
Expand Up @@ -286,7 +286,7 @@ Management Commands
Migrations
~~~~~~~~~~

* ...
* Added support for serialization of ``uuid.UUID`` objects.

Models
~~~~~~
Expand Down
5 changes: 5 additions & 0 deletions docs/topics/migrations.txt
Expand Up @@ -670,6 +670,7 @@ Django can serialize the following:
(include those that are timezone-aware)
- ``decimal.Decimal`` instances
- ``enum.Enum`` instances
- ``uuid.UUID`` instances
- ``functools.partial`` instances which have serializable ``func``, ``args``,
and ``keywords`` values.
- ``LazyObject`` instances which wrap a serializable value.
Expand All @@ -682,6 +683,10 @@ Django can serialize the following:

Serialization support for ``enum.Enum`` was added.

.. versionchanged:: 1.11

Serialization support for ``uuid.UUID`` was added.

Django can serialize the following on Python 3 only:

- Unbound methods used from within the class body (see below)
Expand Down
26 changes: 26 additions & 0 deletions tests/migrations/test_writer.py
Expand Up @@ -10,6 +10,7 @@
import sys
import tokenize
import unittest
import uuid

import custom_migration_operations.more_operations
import custom_migration_operations.operations
Expand Down Expand Up @@ -321,6 +322,31 @@ class IntEnum(enum.IntEnum):
"default=migrations.test_writer.IntEnum(1))"
)

def test_serialize_uuid(self):
self.assertSerializedEqual(uuid.uuid1())
self.assertSerializedEqual(uuid.uuid4())

uuid_a = uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')
uuid_b = uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')
self.assertSerializedResultEqual(
uuid_a,
("uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')", {'import uuid'})
)
self.assertSerializedResultEqual(
uuid_b,
("uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')", {'import uuid'})
)

field = models.UUIDField(choices=((uuid_a, 'UUID A'), (uuid_b, 'UUID B')), default=uuid_a)
string = MigrationWriter.serialize(field)[0]
self.assertEqual(
string,
"models.UUIDField(choices=["
"(uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'), 'UUID A'), "
"(uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2'), 'UUID B')], "
"default=uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'))"
)

def test_serialize_functions(self):
with self.assertRaisesMessage(ValueError, 'Cannot serialize function: lambda'):
self.assertSerializedEqual(lambda x: 42)
Expand Down

0 comments on commit cb3fb34

Please sign in to comment.