Update code and tests to support the 'bytes_le' attribute (for

little-endian byte order on Windows), and to work around clocks
with low resolution yielding duplicate UUIDs.

Anthony Baxter has approved this change.
This commit is contained in:
Ka-Ping Yee 2006-08-16 07:02:50 +00:00
parent d112bc7958
commit b1cb56ad17
2 changed files with 103 additions and 52 deletions

View file

@ -16,12 +16,13 @@ class TestUUID(TestCase):
def test_UUID(self): def test_UUID(self):
equal = self.assertEqual equal = self.assertEqual
ascending = [] ascending = []
for (string, curly, hex, bytes, fields, integer, urn, for (string, curly, hex, bytes, bytes_le, fields, integer, urn,
time, clock_seq, variant, version) in [ time, clock_seq, variant, version) in [
('00000000-0000-0000-0000-000000000000', ('00000000-0000-0000-0000-000000000000',
'{00000000-0000-0000-0000-000000000000}', '{00000000-0000-0000-0000-000000000000}',
'00000000000000000000000000000000', '00000000000000000000000000000000',
'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
(0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0),
0, 0,
'urn:uuid:00000000-0000-0000-0000-000000000000', 'urn:uuid:00000000-0000-0000-0000-000000000000',
@ -30,6 +31,7 @@ class TestUUID(TestCase):
'{00010203-0405-0607-0809-0a0b0c0d0e0f}', '{00010203-0405-0607-0809-0a0b0c0d0e0f}',
'000102030405060708090a0b0c0d0e0f', '000102030405060708090a0b0c0d0e0f',
'\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\x0d\x0e\x0f', '\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\x0d\x0e\x0f',
'\x03\x02\x01\0\x05\x04\x07\x06\x08\t\n\x0b\x0c\x0d\x0e\x0f',
(0x00010203L, 0x0405, 0x0607, 8, 9, 0x0a0b0c0d0e0fL), (0x00010203L, 0x0405, 0x0607, 8, 9, 0x0a0b0c0d0e0fL),
0x000102030405060708090a0b0c0d0e0fL, 0x000102030405060708090a0b0c0d0e0fL,
'urn:uuid:00010203-0405-0607-0809-0a0b0c0d0e0f', 'urn:uuid:00010203-0405-0607-0809-0a0b0c0d0e0f',
@ -38,6 +40,7 @@ class TestUUID(TestCase):
'{02d9e6d5-9467-382e-8f9b-9300a64ac3cd}', '{02d9e6d5-9467-382e-8f9b-9300a64ac3cd}',
'02d9e6d59467382e8f9b9300a64ac3cd', '02d9e6d59467382e8f9b9300a64ac3cd',
'\x02\xd9\xe6\xd5\x94\x67\x38\x2e\x8f\x9b\x93\x00\xa6\x4a\xc3\xcd', '\x02\xd9\xe6\xd5\x94\x67\x38\x2e\x8f\x9b\x93\x00\xa6\x4a\xc3\xcd',
'\xd5\xe6\xd9\x02\x67\x94\x2e\x38\x8f\x9b\x93\x00\xa6\x4a\xc3\xcd',
(0x02d9e6d5L, 0x9467, 0x382e, 0x8f, 0x9b, 0x9300a64ac3cdL), (0x02d9e6d5L, 0x9467, 0x382e, 0x8f, 0x9b, 0x9300a64ac3cdL),
0x02d9e6d59467382e8f9b9300a64ac3cdL, 0x02d9e6d59467382e8f9b9300a64ac3cdL,
'urn:uuid:02d9e6d5-9467-382e-8f9b-9300a64ac3cd', 'urn:uuid:02d9e6d5-9467-382e-8f9b-9300a64ac3cd',
@ -46,6 +49,7 @@ class TestUUID(TestCase):
'{12345678-1234-5678-1234-567812345678}', '{12345678-1234-5678-1234-567812345678}',
'12345678123456781234567812345678', '12345678123456781234567812345678',
'\x12\x34\x56\x78'*4, '\x12\x34\x56\x78'*4,
'\x78\x56\x34\x12\x34\x12\x78\x56\x12\x34\x56\x78\x12\x34\x56\x78',
(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678), (0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678),
0x12345678123456781234567812345678, 0x12345678123456781234567812345678,
'urn:uuid:12345678-1234-5678-1234-567812345678', 'urn:uuid:12345678-1234-5678-1234-567812345678',
@ -54,6 +58,7 @@ class TestUUID(TestCase):
'{6ba7b810-9dad-11d1-80b4-00c04fd430c8}', '{6ba7b810-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8109dad11d180b400c04fd430c8', '6ba7b8109dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8', '\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
'\x10\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b810L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L), (0x6ba7b810L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8109dad11d180b400c04fd430c8L, 0x6ba7b8109dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8', 'urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8',
@ -62,6 +67,7 @@ class TestUUID(TestCase):
'{6ba7b811-9dad-11d1-80b4-00c04fd430c8}', '{6ba7b811-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8119dad11d180b400c04fd430c8', '6ba7b8119dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x11\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8', '\x6b\xa7\xb8\x11\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
'\x11\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b811L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L), (0x6ba7b811L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8119dad11d180b400c04fd430c8L, 0x6ba7b8119dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b811-9dad-11d1-80b4-00c04fd430c8', 'urn:uuid:6ba7b811-9dad-11d1-80b4-00c04fd430c8',
@ -70,6 +76,7 @@ class TestUUID(TestCase):
'{6ba7b812-9dad-11d1-80b4-00c04fd430c8}', '{6ba7b812-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8129dad11d180b400c04fd430c8', '6ba7b8129dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x12\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8', '\x6b\xa7\xb8\x12\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
'\x12\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b812L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L), (0x6ba7b812L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8129dad11d180b400c04fd430c8L, 0x6ba7b8129dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b812-9dad-11d1-80b4-00c04fd430c8', 'urn:uuid:6ba7b812-9dad-11d1-80b4-00c04fd430c8',
@ -78,6 +85,7 @@ class TestUUID(TestCase):
'{6ba7b814-9dad-11d1-80b4-00c04fd430c8}', '{6ba7b814-9dad-11d1-80b4-00c04fd430c8}',
'6ba7b8149dad11d180b400c04fd430c8', '6ba7b8149dad11d180b400c04fd430c8',
'\x6b\xa7\xb8\x14\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8', '\x6b\xa7\xb8\x14\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
'\x14\xb8\xa7\x6b\xad\x9d\xd1\x11\x80\xb4\x00\xc0\x4f\xd4\x30\xc8',
(0x6ba7b814L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L), (0x6ba7b814L, 0x9dad, 0x11d1, 0x80, 0xb4, 0x00c04fd430c8L),
0x6ba7b8149dad11d180b400c04fd430c8L, 0x6ba7b8149dad11d180b400c04fd430c8L,
'urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8', 'urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8',
@ -86,6 +94,7 @@ class TestUUID(TestCase):
'{7d444840-9dc0-11d1-b245-5ffdce74fad2}', '{7d444840-9dc0-11d1-b245-5ffdce74fad2}',
'7d4448409dc011d1b2455ffdce74fad2', '7d4448409dc011d1b2455ffdce74fad2',
'\x7d\x44\x48\x40\x9d\xc0\x11\xd1\xb2\x45\x5f\xfd\xce\x74\xfa\xd2', '\x7d\x44\x48\x40\x9d\xc0\x11\xd1\xb2\x45\x5f\xfd\xce\x74\xfa\xd2',
'\x40\x48\x44\x7d\xc0\x9d\xd1\x11\xb2\x45\x5f\xfd\xce\x74\xfa\xd2',
(0x7d444840L, 0x9dc0, 0x11d1, 0xb2, 0x45, 0x5ffdce74fad2L), (0x7d444840L, 0x9dc0, 0x11d1, 0xb2, 0x45, 0x5ffdce74fad2L),
0x7d4448409dc011d1b2455ffdce74fad2L, 0x7d4448409dc011d1b2455ffdce74fad2L,
'urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2', 'urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2',
@ -94,6 +103,7 @@ class TestUUID(TestCase):
'{e902893a-9d22-3c7e-a7b8-d6e313b71d9f}', '{e902893a-9d22-3c7e-a7b8-d6e313b71d9f}',
'e902893a9d223c7ea7b8d6e313b71d9f', 'e902893a9d223c7ea7b8d6e313b71d9f',
'\xe9\x02\x89\x3a\x9d\x22\x3c\x7e\xa7\xb8\xd6\xe3\x13\xb7\x1d\x9f', '\xe9\x02\x89\x3a\x9d\x22\x3c\x7e\xa7\xb8\xd6\xe3\x13\xb7\x1d\x9f',
'\x3a\x89\x02\xe9\x22\x9d\x7e\x3c\xa7\xb8\xd6\xe3\x13\xb7\x1d\x9f',
(0xe902893aL, 0x9d22, 0x3c7e, 0xa7, 0xb8, 0xd6e313b71d9fL), (0xe902893aL, 0x9d22, 0x3c7e, 0xa7, 0xb8, 0xd6e313b71d9fL),
0xe902893a9d223c7ea7b8d6e313b71d9fL, 0xe902893a9d223c7ea7b8d6e313b71d9fL,
'urn:uuid:e902893a-9d22-3c7e-a7b8-d6e313b71d9f', 'urn:uuid:e902893a-9d22-3c7e-a7b8-d6e313b71d9f',
@ -102,6 +112,7 @@ class TestUUID(TestCase):
'{eb424026-6f54-4ef8-a4d0-bb658a1fc6cf}', '{eb424026-6f54-4ef8-a4d0-bb658a1fc6cf}',
'eb4240266f544ef8a4d0bb658a1fc6cf', 'eb4240266f544ef8a4d0bb658a1fc6cf',
'\xeb\x42\x40\x26\x6f\x54\x4e\xf8\xa4\xd0\xbb\x65\x8a\x1f\xc6\xcf', '\xeb\x42\x40\x26\x6f\x54\x4e\xf8\xa4\xd0\xbb\x65\x8a\x1f\xc6\xcf',
'\x26\x40\x42\xeb\x54\x6f\xf8\x4e\xa4\xd0\xbb\x65\x8a\x1f\xc6\xcf',
(0xeb424026L, 0x6f54, 0x4ef8, 0xa4, 0xd0, 0xbb658a1fc6cfL), (0xeb424026L, 0x6f54, 0x4ef8, 0xa4, 0xd0, 0xbb658a1fc6cfL),
0xeb4240266f544ef8a4d0bb658a1fc6cfL, 0xeb4240266f544ef8a4d0bb658a1fc6cfL,
'urn:uuid:eb424026-6f54-4ef8-a4d0-bb658a1fc6cf', 'urn:uuid:eb424026-6f54-4ef8-a4d0-bb658a1fc6cf',
@ -110,6 +121,7 @@ class TestUUID(TestCase):
'{f81d4fae-7dec-11d0-a765-00a0c91e6bf6}', '{f81d4fae-7dec-11d0-a765-00a0c91e6bf6}',
'f81d4fae7dec11d0a76500a0c91e6bf6', 'f81d4fae7dec11d0a76500a0c91e6bf6',
'\xf8\x1d\x4f\xae\x7d\xec\x11\xd0\xa7\x65\x00\xa0\xc9\x1e\x6b\xf6', '\xf8\x1d\x4f\xae\x7d\xec\x11\xd0\xa7\x65\x00\xa0\xc9\x1e\x6b\xf6',
'\xae\x4f\x1d\xf8\xec\x7d\xd0\x11\xa7\x65\x00\xa0\xc9\x1e\x6b\xf6',
(0xf81d4faeL, 0x7dec, 0x11d0, 0xa7, 0x65, 0x00a0c91e6bf6L), (0xf81d4faeL, 0x7dec, 0x11d0, 0xa7, 0x65, 0x00a0c91e6bf6L),
0xf81d4fae7dec11d0a76500a0c91e6bf6L, 0xf81d4fae7dec11d0a76500a0c91e6bf6L,
'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6', 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
@ -118,6 +130,7 @@ class TestUUID(TestCase):
'{fffefdfc-fffe-fffe-fffe-fffefdfcfbfa}', '{fffefdfc-fffe-fffe-fffe-fffefdfcfbfa}',
'fffefdfcfffefffefffefffefdfcfbfa', 'fffefdfcfffefffefffefffefdfcfbfa',
'\xff\xfe\xfd\xfc\xff\xfe\xff\xfe\xff\xfe\xff\xfe\xfd\xfc\xfb\xfa', '\xff\xfe\xfd\xfc\xff\xfe\xff\xfe\xff\xfe\xff\xfe\xfd\xfc\xfb\xfa',
'\xfc\xfd\xfe\xff\xfe\xff\xfe\xff\xff\xfe\xff\xfe\xfd\xfc\xfb\xfa',
(0xfffefdfcL, 0xfffe, 0xfffe, 0xff, 0xfe, 0xfffefdfcfbfaL), (0xfffefdfcL, 0xfffe, 0xfffe, 0xff, 0xfe, 0xfffefdfcfbfaL),
0xfffefdfcfffefffefffefffefdfcfbfaL, 0xfffefdfcfffefffefffefffefdfcfbfaL,
'urn:uuid:fffefdfc-fffe-fffe-fffe-fffefdfcfbfa', 'urn:uuid:fffefdfc-fffe-fffe-fffe-fffefdfcfbfa',
@ -126,6 +139,7 @@ class TestUUID(TestCase):
'{ffffffff-ffff-ffff-ffff-ffffffffffff}', '{ffffffff-ffff-ffff-ffff-ffffffffffff}',
'ffffffffffffffffffffffffffffffff', 'ffffffffffffffffffffffffffffffff',
'\xff'*16, '\xff'*16,
'\xff'*16,
(0xffffffffL, 0xffffL, 0xffffL, 0xff, 0xff, 0xffffffffffffL), (0xffffffffL, 0xffffL, 0xffffL, 0xff, 0xff, 0xffffffffffffL),
0xffffffffffffffffffffffffffffffffL, 0xffffffffffffffffffffffffffffffffL,
'urn:uuid:ffffffff-ffff-ffff-ffff-ffffffffffff', 'urn:uuid:ffffffff-ffff-ffff-ffff-ffffffffffff',
@ -134,12 +148,14 @@ class TestUUID(TestCase):
equivalents = [] equivalents = []
# Construct each UUID in several different ways. # Construct each UUID in several different ways.
for u in [uuid.UUID(string), uuid.UUID(curly), uuid.UUID(hex), for u in [uuid.UUID(string), uuid.UUID(curly), uuid.UUID(hex),
uuid.UUID(bytes=bytes), uuid.UUID(fields=fields), uuid.UUID(bytes=bytes), uuid.UUID(bytes_le=bytes_le),
uuid.UUID(int=integer), uuid.UUID(urn)]: uuid.UUID(fields=fields), uuid.UUID(int=integer),
uuid.UUID(urn)]:
# Test all conversions and properties of the UUID object. # Test all conversions and properties of the UUID object.
equal(str(u), string) equal(str(u), string)
equal(int(u), integer) equal(int(u), integer)
equal(u.bytes, bytes) equal(u.bytes, bytes)
equal(u.bytes_le, bytes_le)
equal(u.fields, fields) equal(u.fields, fields)
equal(u.time_low, fields[0]) equal(u.time_low, fields[0])
equal(u.time_mid, fields[1]) equal(u.time_mid, fields[1])
@ -189,6 +205,11 @@ class TestUUID(TestCase):
badvalue(lambda: uuid.UUID(bytes='\0'*15)) badvalue(lambda: uuid.UUID(bytes='\0'*15))
badvalue(lambda: uuid.UUID(bytes='\0'*17)) badvalue(lambda: uuid.UUID(bytes='\0'*17))
# Badly formed bytes_le.
badvalue(lambda: uuid.UUID(bytes_le='abc'))
badvalue(lambda: uuid.UUID(bytes_le='\0'*15))
badvalue(lambda: uuid.UUID(bytes_le='\0'*17))
# Badly formed fields. # Badly formed fields.
badvalue(lambda: uuid.UUID(fields=(1,))) badvalue(lambda: uuid.UUID(fields=(1,)))
badvalue(lambda: uuid.UUID(fields=(1, 2, 3, 4, 5))) badvalue(lambda: uuid.UUID(fields=(1, 2, 3, 4, 5)))
@ -221,51 +242,43 @@ class TestUUID(TestCase):
uuid.UUID(h) uuid.UUID(h)
uuid.UUID(hex=h) uuid.UUID(hex=h)
uuid.UUID(bytes=b) uuid.UUID(bytes=b)
uuid.UUID(bytes_le=b)
uuid.UUID(fields=f) uuid.UUID(fields=f)
uuid.UUID(int=i) uuid.UUID(int=i)
# Wrong number of arguments (positional). # Wrong number of arguments (positional).
badtype(lambda: uuid.UUID()) badtype(lambda: uuid.UUID())
badtype(lambda: uuid.UUID(h, b)) badtype(lambda: uuid.UUID(h, b))
badtype(lambda: uuid.UUID(h, b, f)) badtype(lambda: uuid.UUID(h, b, b))
badtype(lambda: uuid.UUID(h, b, f, i)) badtype(lambda: uuid.UUID(h, b, b, f))
badtype(lambda: uuid.UUID(h, b, b, f, i))
# Duplicate arguments (named). # Duplicate arguments.
badtype(lambda: uuid.UUID(hex=h, bytes=b)) for hh in [[], [('hex', h)]]:
badtype(lambda: uuid.UUID(hex=h, fields=f)) for bb in [[], [('bytes', b)]]:
badtype(lambda: uuid.UUID(hex=h, int=i)) for bble in [[], [('bytes_le', b)]]:
badtype(lambda: uuid.UUID(bytes=b, fields=f)) for ii in [[], [('int', i)]]:
badtype(lambda: uuid.UUID(bytes=b, int=i)) for ff in [[], [('fields', f)]]:
badtype(lambda: uuid.UUID(fields=f, int=i)) args = dict(hh + bb + bble + ii + ff)
badtype(lambda: uuid.UUID(hex=h, bytes=b, fields=f)) if len(args) != 0:
badtype(lambda: uuid.UUID(hex=h, bytes=b, int=i)) badtype(lambda: uuid.UUID(h, **args))
badtype(lambda: uuid.UUID(hex=h, fields=f, int=i)) if len(args) != 1:
badtype(lambda: uuid.UUID(bytes=b, int=i, fields=f)) badtype(lambda: uuid.UUID(**args))
badtype(lambda: uuid.UUID(hex=h, bytes=b, int=i, fields=f))
# Duplicate arguments (positional and named).
badtype(lambda: uuid.UUID(h, hex=h))
badtype(lambda: uuid.UUID(h, bytes=b))
badtype(lambda: uuid.UUID(h, fields=f))
badtype(lambda: uuid.UUID(h, int=i))
badtype(lambda: uuid.UUID(h, hex=h, bytes=b))
badtype(lambda: uuid.UUID(h, hex=h, fields=f))
badtype(lambda: uuid.UUID(h, hex=h, int=i))
badtype(lambda: uuid.UUID(h, bytes=b, fields=f))
badtype(lambda: uuid.UUID(h, bytes=b, int=i))
badtype(lambda: uuid.UUID(h, fields=f, int=i))
badtype(lambda: uuid.UUID(h, hex=h, bytes=b, fields=f))
badtype(lambda: uuid.UUID(h, hex=h, bytes=b, int=i))
badtype(lambda: uuid.UUID(h, hex=h, fields=f, int=i))
badtype(lambda: uuid.UUID(h, bytes=b, int=i, fields=f))
badtype(lambda: uuid.UUID(h, hex=h, bytes=b, int=i, fields=f))
# Immutability. # Immutability.
u = uuid.UUID(h) u = uuid.UUID(h)
badtype(lambda: setattr(u, 'hex', h)) badtype(lambda: setattr(u, 'hex', h))
badtype(lambda: setattr(u, 'bytes', b)) badtype(lambda: setattr(u, 'bytes', b))
badtype(lambda: setattr(u, 'bytes_le', b))
badtype(lambda: setattr(u, 'fields', f)) badtype(lambda: setattr(u, 'fields', f))
badtype(lambda: setattr(u, 'int', i)) badtype(lambda: setattr(u, 'int', i))
badtype(lambda: setattr(u, 'time_low', 0))
badtype(lambda: setattr(u, 'time_mid', 0))
badtype(lambda: setattr(u, 'time_hi_version', 0))
badtype(lambda: setattr(u, 'time_hi_version', 0))
badtype(lambda: setattr(u, 'clock_seq_hi_variant', 0))
badtype(lambda: setattr(u, 'clock_seq_low', 0))
badtype(lambda: setattr(u, 'node', 0))
def check_node(self, node, source): def check_node(self, node, source):
individual_group_bit = (node >> 40L) & 1 individual_group_bit = (node >> 40L) & 1
@ -356,11 +369,17 @@ class TestUUID(TestCase):
def test_uuid1(self): def test_uuid1(self):
equal = self.assertEqual equal = self.assertEqual
# Make sure uuid4() generates UUIDs that are actually version 1. # Make sure uuid1() generates UUIDs that are actually version 1.
for u in [uuid.uuid1() for i in range(10)]: for u in [uuid.uuid1() for i in range(10)]:
equal(u.variant, uuid.RFC_4122) equal(u.variant, uuid.RFC_4122)
equal(u.version, 1) equal(u.version, 1)
# Make sure the generated UUIDs are actually unique.
uuids = {}
for u in [uuid.uuid1() for i in range(1000)]:
uuids[u] = 1
equal(len(uuids.keys()), 1000)
# Make sure the supplied node ID appears in the UUID. # Make sure the supplied node ID appears in the UUID.
u = uuid.uuid1(0) u = uuid.uuid1(0)
equal(u.node, 0) equal(u.node, 0)
@ -408,6 +427,12 @@ class TestUUID(TestCase):
equal(u.variant, uuid.RFC_4122) equal(u.variant, uuid.RFC_4122)
equal(u.version, 4) equal(u.version, 4)
# Make sure the generated UUIDs are actually unique.
uuids = {}
for u in [uuid.uuid1() for i in range(1000)]:
uuids[u] = 1
equal(len(uuids.keys()), 1000)
def test_uuid5(self): def test_uuid5(self):
equal = self.assertEqual equal = self.assertEqual

View file

@ -45,8 +45,6 @@ Typical usage:
""" """
__author__ = 'Ka-Ping Yee <ping@zesty.ca>' __author__ = 'Ka-Ping Yee <ping@zesty.ca>'
__date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
__version__ = '$Revision: 1.30 $'.split()[1]
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
'reserved for NCS compatibility', 'specified in RFC 4122', 'reserved for NCS compatibility', 'specified in RFC 4122',
@ -57,15 +55,21 @@ class UUID(object):
UUID objects are immutable, hashable, and usable as dictionary keys. UUID objects are immutable, hashable, and usable as dictionary keys.
Converting a UUID to a string with str() yields something in the form Converting a UUID to a string with str() yields something in the form
'12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
four possible forms: a similar string of hexadecimal digits, or a five possible forms: a similar string of hexadecimal digits, or a tuple
string of 16 raw bytes as an argument named 'bytes', or a tuple of of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values respectively) as an argument named 'fields', or a string
48-bit values respectively) as an argument named 'fields', or a single of 16 bytes (with all the integer fields in big-endian order) as an
128-bit integer as an argument named 'int'. argument named 'bytes', or a string of 16 bytes (with the first three
fields in little-endian order) as an argument named 'bytes_le', or a
single 128-bit integer as an argument named 'int'.
UUIDs have these read-only attributes: UUIDs have these read-only attributes:
bytes the UUID as a 16-byte string bytes the UUID as a 16-byte string (containing the six
integer fields in big-endian byte order)
bytes_le the UUID as a 16-byte string (with time_low, time_mid,
and time_hi_version in little-endian byte order)
fields a tuple of the six integer fields of the UUID, fields a tuple of the six integer fields of the UUID,
which are also available as six individual attributes which are also available as six individual attributes
@ -94,10 +98,11 @@ class UUID(object):
when the variant is RFC_4122) when the variant is RFC_4122)
""" """
def __init__(self, hex=None, bytes=None, fields=None, int=None, def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
version=None): int=None, version=None):
r"""Create a UUID from either a string of 32 hexadecimal digits, r"""Create a UUID from either a string of 32 hexadecimal digits,
a string of 16 bytes as the 'bytes' argument, a tuple of six a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
in little-endian order as the 'bytes_le' argument, a tuple of six
integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
the 'fields' argument, or a single 128-bit integer as the 'int' the 'fields' argument, or a single 128-bit integer as the 'int'
@ -109,23 +114,31 @@ class UUID(object):
UUID('12345678123456781234567812345678') UUID('12345678123456781234567812345678')
UUID('urn:uuid:12345678-1234-5678-1234-567812345678') UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
UUID(bytes='\x12\x34\x56\x78'*4) UUID(bytes='\x12\x34\x56\x78'*4)
UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
'\x12\x34\x56\x78\x12\x34\x56\x78')
UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
UUID(int=0x12345678123456781234567812345678) UUID(int=0x12345678123456781234567812345678)
Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given. Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
The 'version' argument is optional; if given, the resulting UUID be given. The 'version' argument is optional; if given, the resulting
will have its variant and version number set according to RFC 4122, UUID will have its variant and version set according to RFC 4122,
overriding bits in the given 'hex', 'bytes', 'fields', or 'int'. overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
""" """
if [hex, bytes, fields, int].count(None) != 3: if [hex, bytes, bytes_le, fields, int].count(None) != 4:
raise TypeError('need just one of hex, bytes, fields, or int') raise TypeError('need one of hex, bytes, bytes_le, fields, or int')
if hex is not None: if hex is not None:
hex = hex.replace('urn:', '').replace('uuid:', '') hex = hex.replace('urn:', '').replace('uuid:', '')
hex = hex.strip('{}').replace('-', '') hex = hex.strip('{}').replace('-', '')
if len(hex) != 32: if len(hex) != 32:
raise ValueError('badly formed hexadecimal UUID string') raise ValueError('badly formed hexadecimal UUID string')
int = long(hex, 16) int = long(hex, 16)
if bytes_le is not None:
if len(bytes_le) != 16:
raise ValueError('bytes_le is not a 16-char string')
bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] +
bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] +
bytes_le[8:])
if bytes is not None: if bytes is not None:
if len(bytes) != 16: if len(bytes) != 16:
raise ValueError('bytes is not a 16-char string') raise ValueError('bytes is not a 16-char string')
@ -194,6 +207,13 @@ class UUID(object):
bytes = property(get_bytes) bytes = property(get_bytes)
def get_bytes_le(self):
bytes = self.bytes
return (bytes[3] + bytes[2] + bytes[1] + bytes[0] +
bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:])
bytes_le = property(get_bytes_le)
def get_fields(self): def get_fields(self):
return (self.time_low, self.time_mid, self.time_hi_version, return (self.time_low, self.time_mid, self.time_hi_version,
self.clock_seq_hi_variant, self.clock_seq_low, self.node) self.clock_seq_hi_variant, self.clock_seq_low, self.node)
@ -448,6 +468,8 @@ def getnode():
if _node is not None: if _node is not None:
return _node return _node
_last_timestamp = None
def uuid1(node=None, clock_seq=None): def uuid1(node=None, clock_seq=None):
"""Generate a UUID from a host ID, sequence number, and the current time. """Generate a UUID from a host ID, sequence number, and the current time.
If 'node' is not given, getnode() is used to obtain the hardware If 'node' is not given, getnode() is used to obtain the hardware
@ -460,11 +482,15 @@ def uuid1(node=None, clock_seq=None):
_uuid_generate_time(_buffer) _uuid_generate_time(_buffer)
return UUID(bytes=_buffer.raw) return UUID(bytes=_buffer.raw)
global _last_timestamp
import time import time
nanoseconds = int(time.time() * 1e9) nanoseconds = int(time.time() * 1e9)
# 0x01b21dd213814000 is the number of 100-ns intervals between the # 0x01b21dd213814000 is the number of 100-ns intervals between the
# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
timestamp = int(nanoseconds/100) + 0x01b21dd213814000L timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
if timestamp == _last_timestamp:
timestamp += 1
_last_timestamp = timestamp
if clock_seq is None: if clock_seq is None:
import random import random
clock_seq = random.randrange(1<<14L) # instead of stable storage clock_seq = random.randrange(1<<14L) # instead of stable storage