def test_serialize_multiline_strings(self): self.assertSerializedEqual(b"foo\nbar") string, imports = MigrationWriter.serialize(b"foo\nbar") self.assertEqual(string, "b'foo\\nbar'") self.assertSerializedEqual("föo\nbár") string, imports = MigrationWriter.serialize("foo\nbar") self.assertEqual(string, "'foo\\nbar'")
def test_serialize_enums(self): class TextEnum(enum.Enum): A = 'a-value' B = 'value-b' class BinaryEnum(enum.Enum): A = b'a-value' B = b'value-b' class IntEnum(enum.IntEnum): A = 1 B = 2 self.assertSerializedResultEqual( TextEnum.A, ("migrations.test_writer.TextEnum('a-value')", {'import migrations.test_writer'})) self.assertSerializedResultEqual( BinaryEnum.A, ("migrations.test_writer.BinaryEnum(b'a-value')", {'import migrations.test_writer'})) self.assertSerializedResultEqual(IntEnum.B, ("migrations.test_writer.IntEnum(2)", {'import migrations.test_writer'})) field = models.CharField(default=TextEnum.B, choices=[(m.value, m) for m in TextEnum]) string = MigrationWriter.serialize(field)[0] self.assertEqual( string, "models.CharField(choices=[" "('a-value', migrations.test_writer.TextEnum('a-value')), " "('value-b', migrations.test_writer.TextEnum('value-b'))], " "default=migrations.test_writer.TextEnum('value-b'))") field = models.CharField(default=BinaryEnum.B, choices=[(m.value, m) for m in BinaryEnum]) string = MigrationWriter.serialize(field)[0] self.assertEqual( string, "models.CharField(choices=[" "(b'a-value', migrations.test_writer.BinaryEnum(b'a-value')), " "(b'value-b', migrations.test_writer.BinaryEnum(b'value-b'))], " "default=migrations.test_writer.BinaryEnum(b'value-b'))") field = models.IntegerField(default=IntEnum.A, choices=[(m.value, m) for m in IntEnum]) string = MigrationWriter.serialize(field)[0] self.assertEqual( string, "models.IntegerField(choices=[" "(1, migrations.test_writer.IntEnum(1)), " "(2, migrations.test_writer.IntEnum(2))], " "default=migrations.test_writer.IntEnum(1))")
def test_serialize_functions(self): with self.assertRaisesMessage(ValueError, 'Cannot serialize function: lambda'): self.assertSerializedEqual(lambda x: 42) self.assertSerializedEqual(models.SET_NULL) string, imports = MigrationWriter.serialize(models.SET(42)) self.assertEqual(string, 'models.SET(42)') self.serialize_round_trip(models.SET(42))
def test_deconstruct_class_arguments(self): # Yes, it doesn't make sense to use a class as a default for a # CharField. It does make sense for custom fields though, for example # an enumfield that takes the enum class as an argument. class DeconstructibleInstances: def deconstruct(self): return ('DeconstructibleInstances', [], {}) string = MigrationWriter.serialize( models.CharField(default=DeconstructibleInstances))[0] self.assertEqual( string, "models.CharField(default=migrations.test_writer.DeconstructibleInstances)" )
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_builtins(self): string, imports = MigrationWriter.serialize(range) self.assertEqual(string, 'range') self.assertEqual(imports, set())
def test_serialize_class_based_validators(self): """ Ticket #22943: Test serialization of class-based validators, including compiled regexes. """ validator = RegexValidator(message="hello") string = MigrationWriter.serialize(validator)[0] self.assertEqual( string, "djmodels.core.validators.RegexValidator(message='hello')") self.serialize_round_trip(validator) # Test with a compiled regex. validator = RegexValidator(regex=re.compile(r'^\w+$')) string = MigrationWriter.serialize(validator)[0] self.assertEqual( string, "djmodels.core.validators.RegexValidator(regex=re.compile('^\\\\w+$'))" ) self.serialize_round_trip(validator) # Test a string regex with flag validator = RegexValidator(r'^[0-9]+$', flags=re.S) string = MigrationWriter.serialize(validator)[0] if PY36: self.assertEqual( string, "djmodels.core.validators.RegexValidator('^[0-9]+$', flags=re.RegexFlag(16))" ) else: self.assertEqual( string, "djmodels.core.validators.RegexValidator('^[0-9]+$', flags=16)" ) self.serialize_round_trip(validator) # Test message and code validator = RegexValidator('^[-a-zA-Z0-9_]+$', 'Invalid', 'invalid') string = MigrationWriter.serialize(validator)[0] self.assertEqual( string, "djmodels.core.validators.RegexValidator('^[-a-zA-Z0-9_]+$', 'Invalid', 'invalid')" ) self.serialize_round_trip(validator) # Test with a subclass. validator = EmailValidator(message="hello") string = MigrationWriter.serialize(validator)[0] self.assertEqual( string, "djmodels.core.validators.EmailValidator(message='hello')") self.serialize_round_trip(validator) validator = deconstructible( path="migrations.test_writer.EmailValidator")(EmailValidator)( message="hello") string = MigrationWriter.serialize(validator)[0] self.assertEqual( string, "migrations.test_writer.EmailValidator(message='hello')") validator = deconstructible( path="custom.EmailValidator")(EmailValidator)(message="hello") with self.assertRaisesMessage(ImportError, "No module named 'custom'"): MigrationWriter.serialize(validator) validator = deconstructible( path="djmodels.core.validators.EmailValidator2")(EmailValidator)( message="hello") with self.assertRaisesMessage( ValueError, "Could not find object EmailValidator2 in djmodels.core.validators." ): MigrationWriter.serialize(validator)
def assertSerializedResultEqual(self, value, target): self.assertEqual(MigrationWriter.serialize(value), target)
def serialize_round_trip(self, value): string, imports = MigrationWriter.serialize(value) return self.safe_exec( "%s\ntest_value_result = %s" % ("\n".join(imports), string), value)['test_value_result']