diff options
author | MonadChains <monadchains@gmail.com> | 2023-03-23 23:42:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-23 23:42:43 (GMT) |
commit | 413b7db8a480ea6e0d3e8c9729502282ca748a84 (patch) | |
tree | 605e3b2e78cddf41558d7e0b0f010496f33cceee | |
parent | f1e3eeebc01941f9c25bca4d2fa6313cf5041cc4 (diff) | |
download | cpython-413b7db8a480ea6e0d3e8c9729502282ca748a84.zip cpython-413b7db8a480ea6e0d3e8c9729502282ca748a84.tar.gz cpython-413b7db8a480ea6e0d3e8c9729502282ca748a84.tar.bz2 |
gh-94684: uuid: support bytes in the name argument to uuid3/5 (#94709)
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.
-rw-r--r-- | Doc/library/uuid.rst | 6 | ||||
-rwxr-xr-x | Lib/test/test_uuid.py | 34 | ||||
-rw-r--r-- | Lib/uuid.py | 8 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst | 1 |
4 files changed, 43 insertions, 6 deletions
diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 38b6434..94b9a43 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 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 string). + UUID) and a name (which is a :class:`bytes` object or a string + that will be encoded using UTF-8). .. index:: single: uuid5 diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index b2c229c..a178e94 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -600,7 +600,22 @@ class BaseTestUUID: 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, b'python.org'), + '6fa459ea-ee8a-3ca4-894e-db77e160355e'), + (self.uuid.uuid3(self.uuid.NAMESPACE_URL, b'http://python.org/'), + '9fe8e8c4-aaa8-32a9-a55c-4535a88b748d'), + (self.uuid.uuid3(self.uuid.NAMESPACE_OID, b'1.3.6.1'), + 'dd1a1cef-13d5-368a-ad82-eca71acd4cd1'), + (self.uuid.uuid3(self.uuid.NAMESPACE_X500, b'c=ca'), + '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 +647,22 @@ class BaseTestUUID: 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, b'python.org'), + '886313e1-3b8a-5372-9b90-0c9aee199e5d'), + (self.uuid.uuid5(self.uuid.NAMESPACE_URL, b'http://python.org/'), + '4c565f0d-3f5a-5890-b41b-20cf47701c5e'), + (self.uuid.uuid5(self.uuid.NAMESPACE_OID, b'1.3.6.1'), + '1447fa61-5277-5fef-a9b3-fbc6e44f4af3'), + (self.uuid.uuid5(self.uuid.NAMESPACE_X500, b'c=ca'), + '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/'), diff --git a/Lib/uuid.py b/Lib/uuid.py index 1c5578b..698be34 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -711,9 +711,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) @@ -724,8 +726,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) 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 0000000..1fa38c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-07-09-13-07-30.gh-issue-94684.nV5yno.rst @@ -0,0 +1 @@ +Now :func:`uuid.uuid3` and :func:`uuid.uuid5` functions support :class:`bytes` objects as their *name* argument. |