From 0b138f147e4050829e08b8b4abe417cfda086149 Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Wed, 27 Apr 2022 18:06:17 -0700 Subject: [PATCH 1/3] Just modify the Django UUIDField for our 32 digit hex representation. --- morango/models/fields/uuids.py | 47 +++++----------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/morango/models/fields/uuids.py b/morango/models/fields/uuids.py index 4a4f5e40..7396568c 100644 --- a/morango/models/fields/uuids.py +++ b/morango/models/fields/uuids.py @@ -10,60 +10,27 @@ def sha2_uuid(*args): return hashlib.sha256("::".join(args).encode("utf-8")).hexdigest()[:32] -class UUIDField(models.CharField): +class UUIDField(models.UUIDField): """ Adaptation of Django's UUIDField, but with 32-char hex representation as Python representation rather than a UUID instance. """ - def __init__(self, *args, **kwargs): - kwargs["max_length"] = 32 - super(UUIDField, self).__init__(*args, **kwargs) - - def prepare_value(self, value): - if isinstance(value, uuid.UUID): - return value.hex - return value - - def deconstruct(self): - name, path, args, kwargs = super(UUIDField, self).deconstruct() - del kwargs["max_length"] - return name, path, args, kwargs - - def get_internal_type(self): - return "UUIDField" - def get_db_prep_value(self, value, connection, prepared=False): if value is None: return None if not isinstance(value, uuid.UUID): - try: - value = uuid.UUID(value) - except AttributeError: - raise TypeError(self.error_messages["invalid"] % {"value": value}) + value = super(UUIDField, self).to_python(value) + + if connection.features.has_native_uuid_field: + return value return value.hex def from_db_value(self, value, expression, connection): return self.to_python(value) def to_python(self, value): - if isinstance(value, uuid.UUID): - return value.hex - return value - - def get_default(self): - """ - Returns the default value for this field. - """ - if self.has_default(): - if callable(self.default): - default = self.default() - if isinstance(default, uuid.UUID): - return default.hex - return default - if isinstance(self.default, uuid.UUID): - return self.default.hex - return self.default - return None + value = super(UUIDField, self).to_python(value) + return value.hex if isinstance(value, uuid.UUID) else value class UUIDModelMixin(models.Model): From f94706f0479ddedc0c68083f039b5ddc15fefd7c Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Thu, 28 Apr 2022 07:20:21 -0700 Subject: [PATCH 2/3] Override value_from_object method to ensure its value is properly coerced. --- morango/models/fields/uuids.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/morango/models/fields/uuids.py b/morango/models/fields/uuids.py index 7396568c..0f1f23ee 100644 --- a/morango/models/fields/uuids.py +++ b/morango/models/fields/uuids.py @@ -32,6 +32,15 @@ def to_python(self, value): value = super(UUIDField, self).to_python(value) return value.hex if isinstance(value, uuid.UUID) else value + def get_default(self): + default = super(UUIDField, self).get_default() + if isinstance(default, uuid.UUID): + return default.hex + return default + + def value_from_object(self, obj): + return self.to_python(super(UUIDField, self).value_from_object(obj)) + class UUIDModelMixin(models.Model): """ From 791ca152dfd1f7aad1e9ec38186704feeca08bbc Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Thu, 28 Apr 2022 14:13:19 -0700 Subject: [PATCH 3/3] Set invalid uuid after serialization to test deserialization from store. --- tests/testapp/tests/sync/test_operations.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/testapp/tests/sync/test_operations.py b/tests/testapp/tests/sync/test_operations.py index 650b1e1f..2a41bed6 100644 --- a/tests/testapp/tests/sync/test_operations.py +++ b/tests/testapp/tests/sync/test_operations.py @@ -1064,10 +1064,12 @@ def setUp(self): "content_id": uuid.uuid4().hex, } - def serialize_to_store(self, Model, data): + def serialize_to_store(self, Model, data, post_serialization=None): instance = Model(**data) instance.calculate_uuid() serialized = instance.serialize() + if post_serialization: + serialized.update(post_serialization) Store.objects.create( id=serialized["id"], serialized=json.dumps(serialized), @@ -1080,11 +1082,12 @@ def serialize_to_store(self, Model, data): model_name=instance.morango_model_name, ) - def serialize_all_to_store(self): + def serialize_all_to_store(self, post_serialization=None): + post_serialization = post_serialization or {} self.serialize_to_store(Facility, self.serialized_facility) - self.serialize_to_store(MyUser, self.serialized_user) - self.serialize_to_store(SummaryLog, self.serialized_log1) - self.serialize_to_store(SummaryLog, self.serialized_log2) + self.serialize_to_store(MyUser, self.serialized_user, post_serialization=post_serialization.get("user", {})) + self.serialize_to_store(SummaryLog, self.serialized_log1, post_serialization=post_serialization.get("log1", {})) + self.serialize_to_store(SummaryLog, self.serialized_log2, post_serialization=post_serialization.get("log2", {})) self.serialize_to_store(ConditionalLog, self.serialized_conditional) def assert_deserialization( @@ -1186,15 +1189,13 @@ def test_deserialization_with_excessively_long_username(self): def test_deserialization_with_invalid_content_id(self): - self.serialized_log1["content_id"] = "invalid" - - self.serialize_all_to_store() + self.serialize_all_to_store({"log1": {"content_id": "invalid"}}) _deserialize_from_store(self.profile) self.assert_deserialization(log1_deserialized=False) - def test_deserialization_with_invalid_log_user_id(self): + def test_deserialization_with_log_non_existent_user_id(self): self.serialized_log1["user_id"] = uuid.uuid4().hex