From 11029880bf8fd47762e143b9d69337ece242155a Mon Sep 17 00:00:00 2001 From: andreamattei97 Date: Sat, 9 Jul 2022 14:50:05 +0200 Subject: [PATCH 1/7] Add support for name as bytes object in uuid3/uuid5 functions RFC 4122 does not specify that name should be a string, so for completness the functions should also support a name given as a raw byte sequence. --- Lib/uuid.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/uuid.py b/Lib/uuid.py index f179d68e8265ac..9ec7738b05804d 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -704,9 +704,11 @@ def uuid1(node=None, clock_seq=None): def uuid3(namespace, name): """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" + if isinstance(name, str): + name = bytes(name, "utf-8") from hashlib import md5 digest = md5( - namespace.bytes + bytes(name, "utf-8"), + namespace.bytes + name, usedforsecurity=False ).digest() return UUID(bytes=digest[:16], version=3) @@ -717,8 +719,10 @@ def uuid4(): def uuid5(namespace, name): """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" + if isinstance(name, str): + name = bytes(name, "utf-8") from hashlib import sha1 - hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest() + hash = sha1(namespace.bytes + name).digest() return UUID(bytes=hash[:16], version=5) # The following standard UUIDs are for use with uuid3() or uuid5(). From a2e4f2fba3fa948ae36cf0709eb26a6e0dad1d91 Mon Sep 17 00:00:00 2001 From: andreamattei97 Date: Sat, 9 Jul 2022 15:00:37 +0200 Subject: [PATCH 2/7] Update uuid3/uuid5 documentation --- Doc/library/uuid.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index a71fe7abf5b547..a3a14d1408a8e4 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -186,7 +186,7 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid3(namespace, name) Generate a UUID based on the MD5 hash of a namespace identifier (which is a - UUID) and a name (which is a string). + UUID) and a name (which is a byte sequence or a UTF-8-encoded string). .. index:: single: uuid3 @@ -201,7 +201,7 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid5(namespace, name) Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a - UUID) and a name (which is a string). + UUID) and a name (which is a byte sequence or a UTF-8-encoded string). .. index:: single: uuid5 From d8bf7c6c3c44ca06555b3af999272c905124a39a Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 9 Jul 2022 13:07:31 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst diff --git a/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst b/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst new file mode 100644 index 00000000000000..7b2b73682d7e31 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst @@ -0,0 +1 @@ +Now uuid.uuid3 and uuid.uuid5 functions support also the name argument given as a byte sequence (i.e. bytes object) From e044bbefb11a4dbf8c693dd571a04d084a59a6dd Mon Sep 17 00:00:00 2001 From: andreamattei97 Date: Thu, 13 Oct 2022 22:52:45 +0200 Subject: [PATCH 4/7] Improve documentation --- Doc/library/uuid.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index a3a14d1408a8e4..4bb8756438ebc4 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -186,7 +186,7 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid3(namespace, name) Generate a UUID based on the MD5 hash of a namespace identifier (which is a - UUID) and a name (which is a byte sequence or a UTF-8-encoded string). + UUID) and a name (which is a :class:`bytes` object or a UTF-8 string). .. index:: single: uuid3 @@ -201,7 +201,7 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid5(namespace, name) Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a - UUID) and a name (which is a byte sequence or a UTF-8-encoded string). + UUID) and a name (which is a :class:`bytes` object or a UTF-8 string). .. index:: single: uuid5 From b7690832a7614f3c7815efe9b84f1d71f46c006a Mon Sep 17 00:00:00 2001 From: monadchains Date: Thu, 13 Oct 2022 23:50:29 +0200 Subject: [PATCH 5/7] Fix documentation --- Doc/library/uuid.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 4bb8756438ebc4..6012b01acebfe6 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -186,7 +186,8 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid3(namespace, name) Generate a UUID based on the MD5 hash of a namespace identifier (which is a - UUID) and a name (which is a :class:`bytes` object or a UTF-8 string). + UUID) and a name (which is a :class:`bytes` object or a string + that will be encoded using UTF-8). .. index:: single: uuid3 @@ -201,7 +202,8 @@ The :mod:`uuid` module defines the following functions: .. function:: uuid5(namespace, name) Generate a UUID based on the SHA-1 hash of a namespace identifier (which is a - UUID) and a name (which is a :class:`bytes` object or a UTF-8 string). + UUID) and a name (which is a :class:`bytes` object or a string + that will be encoded using UTF-8). .. index:: single: uuid5 From bf65b4c92adfdf6b6eba5957313d1fb74edc782c Mon Sep 17 00:00:00 2001 From: monadchains Date: Fri, 14 Oct 2022 00:01:08 +0200 Subject: [PATCH 6/7] Add test --- Lib/test/test_uuid.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 411eec0f406215..56ff7fcbf534f6 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -600,7 +600,26 @@ def test_uuid1_time(self): def test_uuid3(self): equal = self.assertEqual - # Test some known version-3 UUIDs. + # Test some known version-3 UUIDs with name passed as a byte object + for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, + bytes('python.org', encoding='UTF-8')), + '6fa459ea-ee8a-3ca4-894e-db77e160355e'), + (self.uuid.uuid3(self.uuid.NAMESPACE_URL, + bytes('http://python.org/', encoding='UTF-8')), + '9fe8e8c4-aaa8-32a9-a55c-4535a88b748d'), + (self.uuid.uuid3(self.uuid.NAMESPACE_OID, + bytes('1.3.6.1', encoding='UTF-8')), + 'dd1a1cef-13d5-368a-ad82-eca71acd4cd1'), + (self.uuid.uuid3(self.uuid.NAMESPACE_X500, + bytes('c=ca', encoding='UTF-8')), + '658d3002-db6b-3040-a1d1-8ddd7d189a4d'), + ]: + equal(u.variant, self.uuid.RFC_4122) + equal(u.version, 3) + equal(u, self.uuid.UUID(v)) + equal(str(u), v) + + # Test some known version-3 UUIDs with name passed as a string for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, 'python.org'), '6fa459ea-ee8a-3ca4-894e-db77e160355e'), (self.uuid.uuid3(self.uuid.NAMESPACE_URL, 'http://python.org/'), @@ -632,7 +651,26 @@ def test_uuid4(self): def test_uuid5(self): equal = self.assertEqual - # Test some known version-5 UUIDs. + # Test some known version-5 UUIDs with names given as byte objects + for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, + bytes('python.org', encoding='UTF-8')), + '886313e1-3b8a-5372-9b90-0c9aee199e5d'), + (self.uuid.uuid5(self.uuid.NAMESPACE_URL, + bytes('http://python.org/', encoding='UTF-8')), + '4c565f0d-3f5a-5890-b41b-20cf47701c5e'), + (self.uuid.uuid5(self.uuid.NAMESPACE_OID, + bytes('1.3.6.1', encoding='UTF-8')), + '1447fa61-5277-5fef-a9b3-fbc6e44f4af3'), + (self.uuid.uuid5(self.uuid.NAMESPACE_X500, + bytes('c=ca', encoding='UTF-8')), + 'cc957dd1-a972-5349-98cd-874190002798'), + ]: + equal(u.variant, self.uuid.RFC_4122) + equal(u.version, 5) + equal(u, self.uuid.UUID(v)) + equal(str(u), v) + + # Test some known version-5 UUIDs with names given as strings for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, 'python.org'), '886313e1-3b8a-5372-9b90-0c9aee199e5d'), (self.uuid.uuid5(self.uuid.NAMESPACE_URL, 'http://python.org/'), From 8c880ade7faec96d40a20c687fff20387964cfc1 Mon Sep 17 00:00:00 2001 From: monadchains Date: Fri, 14 Oct 2022 20:01:11 +0200 Subject: [PATCH 7/7] Address feedbacks --- Lib/test/test_uuid.py | 24 +++++++------------ ...2-07-09-13-07-30.gh-issue-94684.nV5yno.rst | 2 +- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 56ff7fcbf534f6..7e381cd9153ccf 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -601,17 +601,13 @@ def test_uuid3(self): equal = self.assertEqual # Test some known version-3 UUIDs with name passed as a byte object - for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, - bytes('python.org', encoding='UTF-8')), + for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, b'python.org'), '6fa459ea-ee8a-3ca4-894e-db77e160355e'), - (self.uuid.uuid3(self.uuid.NAMESPACE_URL, - bytes('http://python.org/', encoding='UTF-8')), + (self.uuid.uuid3(self.uuid.NAMESPACE_URL, b'http://python.org/'), '9fe8e8c4-aaa8-32a9-a55c-4535a88b748d'), - (self.uuid.uuid3(self.uuid.NAMESPACE_OID, - bytes('1.3.6.1', encoding='UTF-8')), + (self.uuid.uuid3(self.uuid.NAMESPACE_OID, b'1.3.6.1'), 'dd1a1cef-13d5-368a-ad82-eca71acd4cd1'), - (self.uuid.uuid3(self.uuid.NAMESPACE_X500, - bytes('c=ca', encoding='UTF-8')), + (self.uuid.uuid3(self.uuid.NAMESPACE_X500, b'c=ca'), '658d3002-db6b-3040-a1d1-8ddd7d189a4d'), ]: equal(u.variant, self.uuid.RFC_4122) @@ -652,17 +648,13 @@ def test_uuid5(self): equal = self.assertEqual # Test some known version-5 UUIDs with names given as byte objects - for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, - bytes('python.org', encoding='UTF-8')), + for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, b'python.org'), '886313e1-3b8a-5372-9b90-0c9aee199e5d'), - (self.uuid.uuid5(self.uuid.NAMESPACE_URL, - bytes('http://python.org/', encoding='UTF-8')), + (self.uuid.uuid5(self.uuid.NAMESPACE_URL, b'http://python.org/'), '4c565f0d-3f5a-5890-b41b-20cf47701c5e'), - (self.uuid.uuid5(self.uuid.NAMESPACE_OID, - bytes('1.3.6.1', encoding='UTF-8')), + (self.uuid.uuid5(self.uuid.NAMESPACE_OID, b'1.3.6.1'), '1447fa61-5277-5fef-a9b3-fbc6e44f4af3'), - (self.uuid.uuid5(self.uuid.NAMESPACE_X500, - bytes('c=ca', encoding='UTF-8')), + (self.uuid.uuid5(self.uuid.NAMESPACE_X500, b'c=ca'), 'cc957dd1-a972-5349-98cd-874190002798'), ]: equal(u.variant, self.uuid.RFC_4122) diff --git a/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst b/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst index 7b2b73682d7e31..1fa38c0044d36f 100644 --- a/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst +++ b/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst @@ -1 +1 @@ -Now uuid.uuid3 and uuid.uuid5 functions support also the name argument given as a byte sequence (i.e. bytes object) +Now :func:`uuid.uuid3` and :func:`uuid.uuid5` functions support :class:`bytes` objects as their *name* argument.