diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 39e82d0e19a9ac..09b4d4ac4ffd56 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -289,6 +289,25 @@ of the :attr:`~UUID.variant` attribute: Reserved for future definition. +The :mod:`uuid` module defines the special Nil and Max UUID values: + + +.. data:: NIL + + A special form of UUID that is specified to have all 128 bits set to zero + according to :rfc:`RFC 9562, §5.9 <9562#section-5.9>`. + + .. versionadded:: next + + +.. data:: MAX + + A special form of UUID that is specified to have all 128 bits set to one + according to :rfc:`RFC 9562, §5.10 <9562#section-5.10>`. + + .. versionadded:: next + + .. seealso:: :rfc:`9562` - A Universally Unique IDentifier (UUID) URN Namespace @@ -380,6 +399,14 @@ Here are some examples of typical usage of the :mod:`uuid` module:: >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') + >>> # get the Nil UUID + >>> uuid.NIL + UUID('00000000-0000-0000-0000-000000000000') + + >>> # get the Max UUID + >>> uuid.MAX + UUID('ffffffff-ffff-ffff-ffff-ffffffffffff') + .. _uuid-cli-example: diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 61f5ffdb6c89d1..e17b686a5c733b 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -665,6 +665,11 @@ uuid in :rfc:`9562`. (Contributed by Bénédikt Tran in :gh:`89083`.) +* :const:`uuid.NIL` and :const:`uuid.MAX` are now available to represent the + Nil and Max UUID formats as defined by :rfc:`9562`. + (Contributed by Nick Pope in :gh:`128427`.) + + zipinfo ------- diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 7bd26a8ca34b62..49fae4e38d1231 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -34,6 +34,47 @@ def get_command_stdout(command, args): class BaseTestUUID: uuid = None + def test_nil_uuid(self): + nil_uuid = self.uuid.NIL + + s = '00000000-0000-0000-0000-000000000000' + i = 0 + self.assertEqual(nil_uuid, self.uuid.UUID(s)) + self.assertEqual(nil_uuid, self.uuid.UUID(int=i)) + self.assertEqual(nil_uuid.int, i) + self.assertEqual(str(nil_uuid), s) + # The Nil UUID falls within the range of the Apollo NCS variant as per + # RFC 9562. + # See https://www.rfc-editor.org/rfc/rfc9562.html#section-5.9-4 + self.assertEqual(nil_uuid.variant, self.uuid.RESERVED_NCS) + # A version field of all zeros is "Unused" in RFC 9562, but the version + # field also only applies to the 10xx variant, i.e. the variant + # specified in RFC 9562. As such, because the Nil UUID falls under a + # different variant, its version is considered undefined. + # See https://www.rfc-editor.org/rfc/rfc9562.html#table2 + self.assertIsNone(nil_uuid.version) + + def test_max_uuid(self): + max_uuid = self.uuid.MAX + + s = 'ffffffff-ffff-ffff-ffff-ffffffffffff' + i = (1 << 128) - 1 + self.assertEqual(max_uuid, self.uuid.UUID(s)) + self.assertEqual(max_uuid, self.uuid.UUID(int=i)) + self.assertEqual(max_uuid.int, i) + self.assertEqual(str(max_uuid), s) + # The Max UUID falls within the range of the "yet-to-be defined" future + # UUID variant as per RFC 9562. + # See https://www.rfc-editor.org/rfc/rfc9562.html#section-5.10-4 + self.assertEqual(max_uuid.variant, self.uuid.RESERVED_FUTURE) + # A version field of all ones is "Reserved for future definition" in + # RFC 9562, but the version field also only applies to the 10xx + # variant, i.e. the variant specified in RFC 9562. As such, because the + # Max UUID falls under a different variant, its version is considered + # undefined. + # See https://www.rfc-editor.org/rfc/rfc9562.html#table2 + self.assertIsNone(max_uuid.version) + def test_safe_uuid_enum(self): class CheckedSafeUUID(enum.Enum): safe = 0 diff --git a/Lib/uuid.py b/Lib/uuid.py index 9c6ad9643cf6d5..aab1a66d49d88c 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -42,6 +42,14 @@ # make a UUID from a 16-byte string >>> uuid.UUID(bytes=x.bytes) UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') + + # get the Nil UUID + >>> uuid.NIL + UUID('00000000-0000-0000-0000-000000000000') + + # get the Max UUID + >>> uuid.MAX + UUID('ffffffff-ffff-ffff-ffff-ffffffffffff') """ import os @@ -799,5 +807,10 @@ def main(): NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') +# RFC 9562 Sections 5.9 and 5.10 define the special Nil and Max UUID formats. + +NIL = UUID('00000000-0000-0000-0000-000000000000') +MAX = UUID('ffffffff-ffff-ffff-ffff-ffffffffffff') + if __name__ == "__main__": main() diff --git a/Misc/ACKS b/Misc/ACKS index c6e53317b37d78..5a59fb74cd8817 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1473,6 +1473,7 @@ Michael Pomraning Martin Pool Iustin Pop Claudiu Popa +Nick Pope John Popplewell Matheus Vieira Portela Davin Potts diff --git a/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst b/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst new file mode 100644 index 00000000000000..54cae43702ded7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst @@ -0,0 +1,2 @@ +:const:`uuid.NIL` and :const:`uuid.MAX` are now available to represent the Nil +and Max UUID formats as defined by :rfc:`9562`.