8000 gh-89083: support UUID version 7 (monotonous version) (RFC 9562) [abandoned proposal] by picnixz · Pull Request #120830 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-89083: support UUID version 7 (monotonous version) (RFC 9562) [abandoned proposal] #120830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Prev Previous commit
Next Next commit
fix random bytes generation
  • Loading branch information
picnixz committed Jun 17, 2024
commit 8344e64309ce633e42059cae3207864f387c4554
33 changes: 17 additions & 16 deletions Lib/test/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,22 +721,23 @@ def test_uuid7(self):
fake_nanoseconds = 1545052026752910643
# some fake 74 = 12 + 62 random bits speared over 76 bits
# are generated by generating a random 76-bit number, and
# split into chunks of 62 (hi) and 12 (lo) bits. It is a
rand_a = random.getrandbits(12)
rand_b = random.getrandbits(62)
fake_bytes = (rand_b << 12) | rand_a
fake_bytes = fake_bytes.to_bytes(19, byteorder='big')

with mock.patch.object(self.uuid, '_last_timestamp_v7', None), \
mock.patch('time.time_ns', return_value=fake_nanoseconds), \
mock.patch('os.urandom', return_value=fake_bytes):
u = self.uuid.uuid7()
equal(u.variant, self.uuid.RFC_4122)
equal(u.version, 7)
fake_milliseconds = (fake_nanoseconds // 1_000_000) & 0xffffffffffff
equal((u.int >> 80) & 0xffffffffffff, fake_milliseconds)
equal((u.int >> 64) & 0x0fff, rand_a)
equal(u.int & 0x3fffffffffffffff, rand_b)
# split into chunks of 62 (hi) and 12 (lo) bits.
for _ in range(100):
rand_a = random.getrandbits(12)
rand_b = random.getrandbits(62)
fake_bytes = (rand_b << 12) | rand_a
fake_bytes = fake_bytes.to_bytes(10, byteorder='big')

with mock.patch.object(self.uuid, '_last_timestamp_v7', None), \
mock.patch('time.time_ns', return_value=fake_nanoseconds), \
mock.patch('os.urandom', return_value=fake_bytes):
u = self.uuid.uuid7()
equal(u.variant, self.uuid.RFC_4122)
equal(u.version, 7)
fake_milliseconds = (fake_nanoseconds // 1_000_000) & 0xffffffffffff
equal((u.int >> 80) & 0xffffffffffff, fake_milliseconds)
equal((u.int >> 64) & 0x0fff, rand_a)
equal(u.int & 0x3fffffffffffffff, rand_b)

def test_uuid8(self):
equal = self.assertEqual
Expand Down
4 changes: 2 additions & 2 deletions Lib/uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,9 +782,9 @@ def uuid7():
# Ideally, we would have 'rand_a' = first 12 bits of 'rand'
# and 'rand_b' = lowest 62 bits, but it is easier to test
# when we pick 'rand_a' from the lowest bits of 'rand' and
# 'rand_b' from the next 62 bits, ignoring the first bits
# 'rand_b' from the next 62 bits, ignoring the 6 first bits
# of 'rand'.
rand = int.from_bytes(os.urandom(19)) # 76 random bits (ignore 2 first)
rand = int.from_bytes(os.urandom(10)) # 80 random bits (ignore 6 first)
int_uuid_7 |= (rand & 0x0fff) << 64 # rand_a
int_uuid_7 |= (rand >> 12) & 0x3fffffffffffffff # rand_b
return UUID(int=int_uuid_7, version=7)
Expand Down
Loading
0