Skip to content
Closed
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
4 changes: 4 additions & 0 deletions Lib/test/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ def test_UUID(self):
self.uuid.UUID(urn)]:
# Test all conversions and properties of the UUID object.
equal(str(u), string)
if hasattr(self.uuid, "_c_uuid_str_method"):
# If we have the C accelerator, test both implementations.
equal(self.uuid._py_uuid_str_method(u), string)
equal(self.uuid._c_uuid_str_method(u), string)
equal(int(u), integer)
equal(u.bytes, bytes)
equal(u.bytes_le, bytes_le)
Expand Down
6 changes: 6 additions & 0 deletions Lib/uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,12 @@ def _netstat_getnode():
_generate_time_safe = getattr(_uuid, "generate_time_safe", None)
_has_stable_extractable_node = _uuid.has_stable_extractable_node
_UuidCreate = getattr(_uuid, "UuidCreate", None)
_uuid_int_to_str = getattr(_uuid, "uuid_int_to_str", None)
_py_uuid_str_method = UUID.__str__
if _uuid_int_to_str is not None:
def _c_uuid_str_method(self):
return _uuid_int_to_str(self.int)
UUID.__str__ = _c_uuid_str_method
except ImportError:
_uuid = None
_generate_time_safe = None
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Improve performance of :meth:`uuid.UUID.__str__ <object.__str__>` by adding
a C implementation in _uuidmodule.
45 changes: 39 additions & 6 deletions Modules/_uuidmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
* DCE compatible Universally Unique Identifier library.
*/

// Need limited C API version 3.13 for Py_mod_gil
#include "pyconfig.h" // Py_GIL_DISABLED
#ifndef Py_GIL_DISABLED
# define Py_LIMITED_API 0x030d0000
#endif

#define Py_BUILD_CORE_MODULE
#include "Python.h"
#include "pycore_long.h" // _PyLong_AsByteArray
#if defined(HAVE_UUID_H)
// AIX, FreeBSD, libuuid with pkgconf
#include <uuid.h>
Expand Down Expand Up @@ -90,6 +86,42 @@
}
#endif /* MS_WINDOWS */

static PyObject *
py_uuid_int_to_str(PyObject *Py_UNUSED(context), PyObject *uuid_int)
{
if (!PyLong_Check(uuid_int)) {
PyErr_SetString(PyExc_TypeError, "uuid_int must be an integer");
return NULL;
}

unsigned char bytes[16];
if (_PyLong_AsByteArray((PyLongObject *)uuid_int, bytes, 16, 0, 0, 1) < 0) {
return NULL;
}

PyObject *result = PyUnicode_New(36, 127);
if (result == NULL) {
return NULL;
}
assert(PyUnicode_KIND(result) == PyUnicode_1BYTE_KIND);
Py_UCS1 *str = PyUnicode_1BYTE_DATA(result);
static const Py_UCS1 hex_digits[] = "0123456789abcdef";

int pos = 0;
for (int i = 0; i < 16; i++) {
if (i == 4 || i == 6 || i == 8 || i == 10) {
str[pos++] = '-';
}
unsigned char byte = bytes[i];
str[pos++] = hex_digits[byte >> 4];
str[pos++] = hex_digits[byte & 0x0f];
}
#ifdef Py_DEBUG
assert(pos == 36);
assert(_PyUnicode_CheckConsistency(result, 1));

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu / build and test (ubuntu-24.04-arm)

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (bolt) / build and test (ubuntu-24.04)

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04)

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu / build and test (ubuntu-24.04)

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Hypothesis tests on Ubuntu

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check failure on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Ubuntu (free-threading) / build and test (ubuntu-24.04-arm)

implicit declaration of function ‘_PyUnicode_CheckConsistency’ [-Werror=implicit-function-declaration]

Check warning on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Windows / Build and test (arm64)

'_PyUnicode_CheckConsistency' undefined; assuming extern returning int [C:\a\cpython\cpython\PCbuild\_uuid.vcxproj]

Check warning on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Windows / Build and test (x64)

'_PyUnicode_CheckConsistency' undefined; assuming extern returning int [D:\a\cpython\cpython\PCbuild\_uuid.vcxproj]

Check warning on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / Build and test (arm64)

'_PyUnicode_CheckConsistency' undefined; assuming extern returning int [C:\a\cpython\cpython\PCbuild\_uuid.vcxproj]

Check warning on line 121 in Modules/_uuidmodule.c

View workflow job for this annotation

GitHub Actions / Windows (free-threading) / Build and test (x64)

'_PyUnicode_CheckConsistency' undefined; assuming extern returning int [D:\a\cpython\cpython\PCbuild\_uuid.vcxproj]
#endif
return result;
}

static int
uuid_exec(PyObject *module)
Expand Down Expand Up @@ -129,6 +161,7 @@
#if defined(MS_WINDOWS)
{"UuidCreate", py_UuidCreate, METH_NOARGS, NULL},
#endif
{"uuid_int_to_str", py_uuid_int_to_str, METH_O, NULL},
{NULL, NULL, 0, NULL} /* sentinel */
};

Expand Down
Loading