gh-89083: add support for UUID version 8 (RFC 9562) (#123224)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
Bénédikt Tran
2024-11-12 19:08:49 +01:00
committed by GitHub
parent a83472f49b
commit 03924b5dee
5 changed files with 109 additions and 19 deletions

View File

@@ -1,8 +1,8 @@
r"""UUID objects (universally unique identifiers) according to RFC 4122.
r"""UUID objects (universally unique identifiers) according to RFC 4122/9562.
This module provides immutable UUID objects (class UUID) and the functions
uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
UUIDs as specified in RFC 4122.
uuid1(), uuid3(), uuid4(), uuid5(), and uuid8() for generating version 1, 3,
4, 5, and 8 UUIDs as specified in RFC 4122/9562.
If all you want is a unique ID, you should probably call uuid1() or uuid4().
Note that uuid1() may compromise privacy since it creates a UUID containing
@@ -124,12 +124,12 @@ class UUID:
int the UUID as a 128-bit integer
urn the UUID as a URN as specified in RFC 4122
urn the UUID as a URN as specified in RFC 4122/9562
variant the UUID variant (one of the constants RESERVED_NCS,
RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
version the UUID version number (1 through 5, meaningful only
version the UUID version number (1 through 8, meaningful only
when the variant is RFC_4122)
is_safe An enum indicating whether the UUID has been generated in
@@ -214,9 +214,9 @@ class UUID:
if not 0 <= int < 1<<128:
raise ValueError('int is out of range (need a 128-bit value)')
if version is not None:
if not 1 <= version <= 5:
if not 1 <= version <= 8:
raise ValueError('illegal version number')
# Set the variant to RFC 4122.
# Set the variant to RFC 4122/9562.
int &= ~(0xc000 << 48)
int |= 0x8000 << 48
# Set the version number.
@@ -355,7 +355,7 @@ class UUID:
@property
def version(self):
# The version bits are only meaningful for RFC 4122 UUIDs.
# The version bits are only meaningful for RFC 4122/9562 UUIDs.
if self.variant == RFC_4122:
return int((self.int >> 76) & 0xf)
@@ -719,6 +719,28 @@ def uuid5(namespace, name):
hash = sha1(namespace.bytes + name).digest()
return UUID(bytes=hash[:16], version=5)
def uuid8(a=None, b=None, c=None):
"""Generate a UUID from three custom blocks.
* 'a' is the first 48-bit chunk of the UUID (octets 0-5);
* 'b' is the mid 12-bit chunk (octets 6-7);
* 'c' is the last 62-bit chunk (octets 8-15).
When a value is not specified, a pseudo-random value is generated.
"""
if a is None:
import random
a = random.getrandbits(48)
if b is None:
import random
b = random.getrandbits(12)
if c is None:
import random
c = random.getrandbits(62)
int_uuid_8 = (a & 0xffff_ffff_ffff) << 80
int_uuid_8 |= (b & 0xfff) << 64
int_uuid_8 |= c & 0x3fff_ffff_ffff_ffff
return UUID(int=int_uuid_8, version=8)
def main():
"""Run the uuid command line interface."""
@@ -726,7 +748,8 @@ def main():
"uuid1": uuid1,
"uuid3": uuid3,
"uuid4": uuid4,
"uuid5": uuid5
"uuid5": uuid5,
"uuid8": uuid8,
}
uuid_namespace_funcs = ("uuid3", "uuid5")
namespaces = {