From cb3fb34b86b17349ec428e789585d0da9604804a Mon Sep 17 00:00:00 2001 From: Maxime Lorant Date: Sun, 6 Nov 2016 13:53:00 +0100 Subject: [PATCH] Fixed #27378 -- Added support for serialization of uuid.UUID in migrations. Thanks Yuriy Korobko for the initial patch and Tobias McNulty for review. --- django/db/migrations/serializer.py | 8 ++++++++ docs/releases/1.11.txt | 2 +- docs/topics/migrations.txt | 5 +++++ tests/migrations/test_writer.py | 26 ++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py index efda10e9e2f..8f32fb986b4 100644 --- a/django/db/migrations/serializer.py +++ b/django/db/migrations/serializer.py @@ -6,6 +6,7 @@ import decimal import functools import math import types +import uuid from importlib import import_module from django.db import models @@ -320,6 +321,11 @@ class TypeSerializer(BaseSerializer): 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): @@ -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/" diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt index f4781463a89..02d66b66418 100644 --- a/docs/releases/1.11.txt +++ b/docs/releases/1.11.txt @@ -286,7 +286,7 @@ Management Commands Migrations ~~~~~~~~~~ -* ... +* Added support for serialization of ``uuid.UUID`` objects. Models ~~~~~~ diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index b193333d476..d963e39c78e 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -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. @@ -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) diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index e2d85fe21f7..27cb21f4964 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -10,6 +10,7 @@ import re import sys import tokenize import unittest +import uuid import custom_migration_operations.more_operations import custom_migration_operations.operations @@ -321,6 +322,31 @@ class WriterTests(SimpleTestCase): "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)