From edc8b7cf7e2c88051f4b4ba0133f19e2d6857133 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 15 Oct 2018 16:41:53 +1100 Subject: [PATCH 1/3] uuid: Provide UUID class and uuid4() implementation using os.urandom(). Includes unit test. Signed-off-by: Damien George --- python-stdlib/uuid/manifest.py | 3 +++ python-stdlib/uuid/test_uuid.py | 15 +++++++++++++++ python-stdlib/uuid/uuid.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 python-stdlib/uuid/manifest.py create mode 100644 python-stdlib/uuid/test_uuid.py create mode 100644 python-stdlib/uuid/uuid.py diff --git a/python-stdlib/uuid/manifest.py b/python-stdlib/uuid/manifest.py new file mode 100644 index 000000000..e59bdf2c0 --- /dev/null +++ b/python-stdlib/uuid/manifest.py @@ -0,0 +1,3 @@ +metadata(version="0.1.0") + +module("uuid.py") diff --git a/python-stdlib/uuid/test_uuid.py b/python-stdlib/uuid/test_uuid.py new file mode 100644 index 000000000..5e9c81483 --- /dev/null +++ b/python-stdlib/uuid/test_uuid.py @@ -0,0 +1,15 @@ +import uuid + +u1 = uuid.uuid4() +u2 = uuid.uuid4() + +assert str(u1) != str(u2), "Two uuid4 should not match" + +assert len(str(u1)) == len(str(u1)) == 36 + +assert str(repr(u1)).startswith("") + +assert len(u1.hex) == 32 + +print("OK") diff --git a/python-stdlib/uuid/uuid.py b/python-stdlib/uuid/uuid.py new file mode 100644 index 000000000..db16473db --- /dev/null +++ b/python-stdlib/uuid/uuid.py @@ -0,0 +1,28 @@ +import os +import ubinascii + + +class UUID: + def __init__(self, bytes): + if len(bytes) != 16: + raise ValueError('bytes arg must be 16 bytes long') + self._bytes = bytes + + @property + def hex(self): + return ubinascii.hexlify(self._bytes).decode() + + def __str__(self): + h = self.hex + return '-'.join((h[0:8], h[8:12], h[12:16], h[16:20], h[20:32])) + + def __repr__(self): + return "" % str(self) + + +def uuid4(): + """Generates a random UUID compliant to RFC 4122 pg.14""" + random = bytearray(os.urandom(16)) + random[6] = (random[6] & 0x0F) | 0x40 + random[8] = (random[8] & 0x3F) | 0x80 + return UUID(bytes=random) From 91b10e6f3ba49dc4ad3f84d3fd9d97cdc4de2716 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 11 Jul 2026 15:02:12 +1000 Subject: [PATCH 2/3] uuid: Convert test to use unittest. And run it as part of CI. Signed-off-by: Damien George --- python-stdlib/uuid/test_uuid.py | 30 ++++++++++++++++++++++-------- tools/ci.sh | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/python-stdlib/uuid/test_uuid.py b/python-stdlib/uuid/test_uuid.py index 5e9c81483..138dd3360 100644 --- a/python-stdlib/uuid/test_uuid.py +++ b/python-stdlib/uuid/test_uuid.py @@ -1,15 +1,29 @@ +import unittest import uuid -u1 = uuid.uuid4() -u2 = uuid.uuid4() -assert str(u1) != str(u2), "Two uuid4 should not match" +class TestUUID(unittest.TestCase): + def test_unique(self): + u1 = uuid.uuid4() + u2 = uuid.uuid4() + self.assertNotEqual(u1.hex, u2.hex) + self.assertNotEqual(str(u1), str(u2)) -assert len(str(u1)) == len(str(u1)) == 36 + def test_len(self): + u = uuid.uuid4() + self.assertEqual(len(str(u)), 36) + self.assertEqual(len(u.hex), 32) -assert str(repr(u1)).startswith("") + def test_repr(self): + u = str(repr(uuid.uuid4())) + self.assertTrue(u.startswith("")) -assert len(u1.hex) == 32 + def test_constructor(self): + u1 = uuid.uuid4() + u2 = uuid.UUID(bytes.fromhex(u1.hex)) + self.assertEqual(u1.hex, u2.hex) -print("OK") + +if __name__ == "__main__": + unittest.main() diff --git a/tools/ci.sh b/tools/ci.sh index e2b6919be..1cb813432 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -104,6 +104,7 @@ function ci_package_tests_run { python-stdlib/time \ python-stdlib/unittest/tests \ python-stdlib/unittest-discover/tests \ + python-stdlib/uuid \ ; do (cd $path && "${MICROPYTHON}" -m unittest) if [ $? -ne 0 ]; then false; return; fi From 06519512710c14cf20d1a445fe5e3aa30313e665 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 11 Jul 2026 15:02:38 +1000 Subject: [PATCH 3/3] uuid: Use bytes.hex instead of binascii.hexlify. Using `bytes.hex()` eliminates an import, and eliminates the call to `.decode()` to convert it to a str. Also run ruff format. Signed-off-by: Damien George --- python-stdlib/uuid/uuid.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/python-stdlib/uuid/uuid.py b/python-stdlib/uuid/uuid.py index db16473db..9790923c3 100644 --- a/python-stdlib/uuid/uuid.py +++ b/python-stdlib/uuid/uuid.py @@ -1,20 +1,19 @@ import os -import ubinascii class UUID: def __init__(self, bytes): if len(bytes) != 16: - raise ValueError('bytes arg must be 16 bytes long') + raise ValueError("bytes arg must be 16 bytes long") self._bytes = bytes @property def hex(self): - return ubinascii.hexlify(self._bytes).decode() + return self._bytes.hex() def __str__(self): h = self.hex - return '-'.join((h[0:8], h[8:12], h[12:16], h[16:20], h[20:32])) + return "-".join((h[0:8], h[8:12], h[12:16], h[16:20], h[20:32])) def __repr__(self): return "" % str(self)