Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/supported-types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ timezone-naive by specifying a ``tz`` constraint (see
--------

`uuid.UUID` values are serialized as RFC4122_ encoded strings in all protocols.
Subclasses of `uuid.UUID` are also supported for encoding only.

When decoding, both hyphenated and unhyphenated forms are supported.

.. code-block:: python
Expand Down
22 changes: 11 additions & 11 deletions msgspec/_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -10660,12 +10660,12 @@ mpack_encode_uncommon(EncoderState *self, PyTypeObject *type, PyObject *obj)
else if (Py_TYPE(type) == self->mod->EnumMetaType) {
return mpack_encode_enum(self, obj);
}
else if (type == (PyTypeObject *)(self->mod->UUIDType)) {
return mpack_encode_uuid(self, obj);
}
else if (type == (PyTypeObject *)(self->mod->DecimalType)) {
return mpack_encode_decimal(self, obj);
}
else if (PyType_IsSubtype(type, (PyTypeObject *)(self->mod->UUIDType))) {
return mpack_encode_uuid(self, obj);
}
else if (PyAnySet_Check(obj)) {
return mpack_encode_set(self, obj);
}
Expand Down Expand Up @@ -11209,9 +11209,6 @@ json_encode_dict_key(EncoderState *self, PyObject *obj) {
else if (Py_TYPE(type) == self->mod->EnumMetaType) {
return json_encode_enum(self, obj, true);
}
else if (type == (PyTypeObject *)(self->mod->UUIDType)) {
return json_encode_uuid(self, obj);
}
else if (type == PyDateTimeAPI->DateTimeType) {
return json_encode_datetime(self, obj);
}
Expand All @@ -11227,6 +11224,9 @@ json_encode_dict_key(EncoderState *self, PyObject *obj) {
else if (type == (PyTypeObject *)(self->mod->DecimalType)) {
return json_encode_decimal(self, obj);
}
else if (PyType_IsSubtype(type, (PyTypeObject *)(self->mod->UUIDType))) {
return json_encode_uuid(self, obj);
}
else {
PyErr_SetString(
PyExc_TypeError,
Expand Down Expand Up @@ -11495,7 +11495,7 @@ json_encode_uncommon(EncoderState *self, PyTypeObject *type, PyObject *obj) {
else if (Py_TYPE(type) == self->mod->EnumMetaType) {
return json_encode_enum(self, obj, false);
}
else if (type == (PyTypeObject *)(self->mod->UUIDType)) {
else if (PyType_IsSubtype(type, (PyTypeObject *)(self->mod->UUIDType))) {
return json_encode_uuid(self, obj);
}
else if (type == (PyTypeObject *)(self->mod->DecimalType)) {
Expand Down Expand Up @@ -17162,10 +17162,6 @@ to_builtins(ToBuiltinsState *self, PyObject *obj, bool is_key) {
if (self->builtin_types & MS_BUILTIN_TIME) goto builtin;
return to_builtins_time(self, obj);
}
else if (type == (PyTypeObject *)(self->mod->UUIDType)) {
if (self->builtin_types & MS_BUILTIN_UUID) goto builtin;
return to_builtins_uuid(self, obj);
}
else if (type == (PyTypeObject *)(self->mod->DecimalType)) {
if (self->builtin_types & MS_BUILTIN_DECIMAL) goto builtin;
return to_builtins_decimal(self, obj);
Expand All @@ -17185,6 +17181,10 @@ to_builtins(ToBuiltinsState *self, PyObject *obj, bool is_key) {
else if (Py_TYPE(type) == self->mod->EnumMetaType) {
return to_builtins_enum(self, obj);
}
else if (PyType_IsSubtype(type, (PyTypeObject *)(self->mod->UUIDType))) {
if (self->builtin_types & MS_BUILTIN_UUID) goto builtin;
return to_builtins_uuid(self, obj);
}
else if (PyAnySet_Check(obj)) {
return to_builtins_set(self, obj, is_key);
}
Expand Down
7 changes: 7 additions & 0 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2951,6 +2951,13 @@ def test_encode_uuid(self, proto):
sol = proto.encode(str(u))
assert res == sol

def test_encode_uuid_subclass(self, proto):
class Ex(uuid.UUID):
pass

s = "4184defa-4d1a-4497-a140-fd1ec0b22383"
assert proto.encode(Ex(s)) == proto.encode(s)

def test_encode_uuid_malformed_internals(self, proto):
"""Ensure that if some other code mutates the uuid object, we error
nicely rather than segfaulting"""
Expand Down
7 changes: 7 additions & 0 deletions tests/test_to_builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ def test_uuid(self):
msg = uuid.uuid4()
assert to_builtins(msg) == str(msg)

def test_uuid_subclass(self):
class Ex(uuid.UUID):
pass

s = "4184defa-4d1a-4497-a140-fd1ec0b22383"
assert to_builtins(Ex(s)) == s

def test_uuid_builtin_types(self):
msg = uuid.uuid4()
res = to_builtins(msg, builtin_types=(uuid.UUID,))
Expand Down