1 r
"""UUID objects (universally unique identifiers) according to RFC 4122.
3 This module provides immutable UUID objects (class UUID) and the functions
4 uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
5 UUIDs as specified in RFC 4122.
7 If all you want is a unique ID, you should probably call uuid1() or uuid4().
8 Note that uuid1() may compromise privacy since it creates a UUID containing
9 the computer's network address. uuid4() creates a random UUID.
15 # make a UUID based on the host ID and current time
17 UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
19 # make a UUID using an MD5 hash of a namespace UUID and a name
20 >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
21 UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
25 UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
27 # make a UUID using a SHA-1 hash of a namespace UUID and a name
28 >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
29 UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
31 # make a UUID from a string of hex digits (braces and hyphens ignored)
32 >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
34 # convert a UUID to a string of hex digits in standard form
36 '00010203-0405-0607-0809-0a0b0c0d0e0f'
38 # get the raw 16 bytes of the UUID
40 '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
42 # make a UUID from a 16-byte string
43 >>> uuid.UUID(bytes=x.bytes)
44 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
47 __author__
= 'Ka-Ping Yee <ping@zesty.ca>'
48 __date__
= '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
49 __version__
= '$Revision: 1.30 $'.split()[1]
51 RESERVED_NCS
, RFC_4122
, RESERVED_MICROSOFT
, RESERVED_FUTURE
= [
52 'reserved for NCS compatibility', 'specified in RFC 4122',
53 'reserved for Microsoft compatibility', 'reserved for future definition']
56 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
57 UUID objects are immutable, hashable, and usable as dictionary keys.
58 Converting a UUID to a string with str() yields something in the form
59 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
60 four possible forms: a similar string of hexadecimal digits, or a
61 string of 16 raw bytes as an argument named 'bytes', or a tuple of
62 six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
63 48-bit values respectively) as an argument named 'fields', or a single
64 128-bit integer as an argument named 'int'.
66 UUIDs have these read-only attributes:
68 bytes the UUID as a 16-byte string
70 fields a tuple of the six integer fields of the UUID,
71 which are also available as six individual attributes
72 and two derived attributes:
74 time_low the first 32 bits of the UUID
75 time_mid the next 16 bits of the UUID
76 time_hi_version the next 16 bits of the UUID
77 clock_seq_hi_variant the next 8 bits of the UUID
78 clock_seq_low the next 8 bits of the UUID
79 node the last 48 bits of the UUID
81 time the 60-bit timestamp
82 clock_seq the 14-bit sequence number
84 hex the UUID as a 32-character hexadecimal string
86 int the UUID as a 128-bit integer
88 urn the UUID as a URN as specified in RFC 4122
90 variant the UUID variant (one of the constants RESERVED_NCS,
91 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
93 version the UUID version number (1 through 5, meaningful only
94 when the variant is RFC_4122)
97 def __init__(self
, hex=None, bytes
=None, fields
=None, int=None,
99 r
"""Create a UUID from either a string of 32 hexadecimal digits,
100 a string of 16 bytes as the 'bytes' argument, a tuple of six
101 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
102 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
103 the 'fields' argument, or a single 128-bit integer as the 'int'
104 argument. When a string of hex digits is given, curly braces,
105 hyphens, and a URN prefix are all optional. For example, these
106 expressions all yield the same UUID:
108 UUID('{12345678-1234-5678-1234-567812345678}')
109 UUID('12345678123456781234567812345678')
110 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
111 UUID(bytes='\x12\x34\x56\x78'*4)
112 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
113 UUID(int=0x12345678123456781234567812345678)
115 Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
116 The 'version' argument is optional; if given, the resulting UUID
117 will have its variant and version number set according to RFC 4122,
118 overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
121 if [hex, bytes
, fields
, int].count(None) != 3:
122 raise TypeError('need just one of hex, bytes, fields, or int')
124 hex = hex.replace('urn:', '').replace('uuid:', '')
125 hex = hex.strip('{}').replace('-', '')
127 raise ValueError('badly formed hexadecimal UUID string')
129 if bytes
is not None:
131 raise ValueError('bytes is not a 16-char string')
132 int = long(('%02x'*16) % tuple(map(ord, bytes
)), 16)
133 if fields
is not None:
135 raise ValueError('fields is not a 6-tuple')
136 (time_low
, time_mid
, time_hi_version
,
137 clock_seq_hi_variant
, clock_seq_low
, node
) = fields
138 if not 0 <= time_low
< 1<<32L:
139 raise ValueError('field 1 out of range (need a 32-bit value)')
140 if not 0 <= time_mid
< 1<<16L:
141 raise ValueError('field 2 out of range (need a 16-bit value)')
142 if not 0 <= time_hi_version
< 1<<16L:
143 raise ValueError('field 3 out of range (need a 16-bit value)')
144 if not 0 <= clock_seq_hi_variant
< 1<<8L:
145 raise ValueError('field 4 out of range (need an 8-bit value)')
146 if not 0 <= clock_seq_low
< 1<<8L:
147 raise ValueError('field 5 out of range (need an 8-bit value)')
148 if not 0 <= node
< 1<<48L:
149 raise ValueError('field 6 out of range (need a 48-bit value)')
150 clock_seq
= (clock_seq_hi_variant
<< 8L) | clock_seq_low
151 int = ((time_low
<< 96L) |
(time_mid
<< 80L) |
152 (time_hi_version
<< 64L) |
(clock_seq
<< 48L) | node
)
154 if not 0 <= int < 1<<128L:
155 raise ValueError('int is out of range (need a 128-bit value)')
156 if version
is not None:
157 if not 1 <= version
<= 5:
158 raise ValueError('illegal version number')
159 # Set the variant to RFC 4122.
160 int &= ~
(0xc000 << 48L)
162 # Set the version number.
163 int &= ~
(0xf000 << 64L)
164 int |
= version
<< 76L
165 self
.__dict
__['int'] = int
167 def __cmp__(self
, other
):
168 if isinstance(other
, UUID
):
169 return cmp(self
.int, other
.int)
170 return NotImplemented
173 return hash(self
.int)
179 return 'UUID(%r)' % str(self
)
181 def __setattr__(self
, name
, value
):
182 raise TypeError('UUID objects are immutable')
185 hex = '%032x' % self
.int
186 return '%s-%s-%s-%s-%s' % (
187 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
191 for shift
in range(0, 128, 8):
192 bytes
= chr((self
.int >> shift
) & 0xff) + bytes
195 bytes
= property(get_bytes
)
197 def get_fields(self
):
198 return (self
.time_low
, self
.time_mid
, self
.time_hi_version
,
199 self
.clock_seq_hi_variant
, self
.clock_seq_low
, self
.node
)
201 fields
= property(get_fields
)
203 def get_time_low(self
):
204 return self
.int >> 96L
206 time_low
= property(get_time_low
)
208 def get_time_mid(self
):
209 return (self
.int >> 80L) & 0xffff
211 time_mid
= property(get_time_mid
)
213 def get_time_hi_version(self
):
214 return (self
.int >> 64L) & 0xffff
216 time_hi_version
= property(get_time_hi_version
)
218 def get_clock_seq_hi_variant(self
):
219 return (self
.int >> 56L) & 0xff
221 clock_seq_hi_variant
= property(get_clock_seq_hi_variant
)
223 def get_clock_seq_low(self
):
224 return (self
.int >> 48L) & 0xff
226 clock_seq_low
= property(get_clock_seq_low
)
229 return (((self
.time_hi_version
& 0x0fffL
) << 48L) |
230 (self
.time_mid
<< 32L) | self
.time_low
)
232 time
= property(get_time
)
234 def get_clock_seq(self
):
235 return (((self
.clock_seq_hi_variant
& 0x3fL
) << 8L) |
238 clock_seq
= property(get_clock_seq
)
241 return self
.int & 0xffffffffffff
243 node
= property(get_node
)
246 return '%032x' % self
.int
248 hex = property(get_hex
)
251 return 'urn:uuid:' + str(self
)
253 urn
= property(get_urn
)
255 def get_variant(self
):
256 if not self
.int & (0x8000 << 48L):
258 elif not self
.int & (0x4000 << 48L):
260 elif not self
.int & (0x2000 << 48L):
261 return RESERVED_MICROSOFT
263 return RESERVED_FUTURE
265 variant
= property(get_variant
)
267 def get_version(self
):
268 # The version bits are only meaningful for RFC 4122 UUIDs.
269 if self
.variant
== RFC_4122
:
270 return int((self
.int >> 76L) & 0xf)
272 version
= property(get_version
)
274 def _find_mac(command
, args
, hw_identifiers
, get_index
):
276 for dir in ['', '/sbin/', '/usr/sbin']:
277 executable
= os
.path
.join(dir, command
)
278 if not os
.path
.exists(executable
):
282 # LC_ALL to get English output, 2>/dev/null to
283 # prevent output on stderr
284 cmd
= 'LC_ALL=C %s %s 2>/dev/null' % (executable
, args
)
290 words
= line
.lower().split()
291 for i
in range(len(words
)):
292 if words
[i
] in hw_identifiers
:
293 return int(words
[get_index(i
)].replace(':', ''), 16)
296 def _ifconfig_getnode():
297 """Get the hardware address on Unix by running ifconfig."""
299 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
300 for args
in ('', '-a', '-av'):
301 mac
= _find_mac('ifconfig', args
, ['hwaddr', 'ether'], lambda i
: i
+1)
306 ip_addr
= socket
.gethostbyname(socket
.gethostname())
308 # Try getting the MAC addr from arp based on our IP address (Solaris).
309 mac
= _find_mac('arp', '-an', [ip_addr
], lambda i
: -1)
313 # This might work on HP-UX.
314 mac
= _find_mac('lanscan', '-ai', ['lan0'], lambda i
: 0)
320 def _ipconfig_getnode():
321 """Get the hardware address on Windows by running ipconfig.exe."""
323 dirs
= ['', r
'c:\windows\system32', r
'c:\winnt\system32']
326 buffer = ctypes
.create_string_buffer(300)
327 ctypes
.windll
.kernel32
.GetSystemDirectoryA(buffer, 300)
328 dirs
.insert(0, buffer.value
.decode('mbcs'))
333 pipe
= os
.popen(os
.path
.join(dir, 'ipconfig') + ' /all')
337 value
= line
.split(':')[-1].strip().lower()
338 if re
.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value
):
339 return int(value
.replace('-', ''), 16)
341 def _netbios_getnode():
342 """Get the hardware address on Windows using NetBIOS calls.
343 See http://support.microsoft.com/kb/118623 for details."""
344 import win32wnet
, netbios
346 ncb
.Command
= netbios
.NCBENUM
347 ncb
.Buffer
= adapters
= netbios
.LANA_ENUM()
349 if win32wnet
.Netbios(ncb
) != 0:
352 for i
in range(adapters
.length
):
354 ncb
.Command
= netbios
.NCBRESET
355 ncb
.Lana_num
= ord(adapters
.lana
[i
])
356 if win32wnet
.Netbios(ncb
) != 0:
359 ncb
.Command
= netbios
.NCBASTAT
360 ncb
.Lana_num
= ord(adapters
.lana
[i
])
361 ncb
.Callname
= '*'.ljust(16)
362 ncb
.Buffer
= status
= netbios
.ADAPTER_STATUS()
363 if win32wnet
.Netbios(ncb
) != 0:
366 bytes
= map(ord, status
.adapter_address
)
367 return ((bytes
[0]<<40L) + (bytes
[1]<<32L) + (bytes
[2]<<24L) +
368 (bytes
[3]<<16L) + (bytes
[4]<<8L) + bytes
[5])
370 # Thanks to Thomas Heller for ctypes and for his help with its use here.
372 # If ctypes is available, use it to find system routines for UUID generation.
373 _uuid_generate_random
= _uuid_generate_time
= _UuidCreate
= None
375 import ctypes
, ctypes
.util
376 _buffer
= ctypes
.create_string_buffer(16)
378 # The uuid_generate_* routines are provided by libuuid on at least
379 # Linux and FreeBSD, and provided by libc on Mac OS X.
380 for libname
in ['uuid', 'c']:
382 lib
= ctypes
.CDLL(ctypes
.util
.find_library(libname
))
385 if hasattr(lib
, 'uuid_generate_random'):
386 _uuid_generate_random
= lib
.uuid_generate_random
387 if hasattr(lib
, 'uuid_generate_time'):
388 _uuid_generate_time
= lib
.uuid_generate_time
390 # On Windows prior to 2000, UuidCreate gives a UUID containing the
391 # hardware address. On Windows 2000 and later, UuidCreate makes a
392 # random UUID and UuidCreateSequential gives a UUID containing the
393 # hardware address. These routines are provided by the RPC runtime.
394 # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
395 # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
396 # to bear any relationship to the MAC address of any network device
399 lib
= ctypes
.windll
.rpcrt4
402 _UuidCreate
= getattr(lib
, 'UuidCreateSequential',
403 getattr(lib
, 'UuidCreate', None))
407 def _unixdll_getnode():
408 """Get the hardware address on Unix using ctypes."""
409 _uuid_generate_time(_buffer
)
410 return UUID(bytes
=_buffer
.raw
).node
412 def _windll_getnode():
413 """Get the hardware address on Windows using ctypes."""
414 if _UuidCreate(_buffer
) == 0:
415 return UUID(bytes
=_buffer
.raw
).node
417 def _random_getnode():
418 """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
420 return random
.randrange(0, 1<<48L) |
0x010000000000L
425 """Get the hardware address as a 48-bit positive integer.
427 The first time this runs, it may launch a separate program, which could
428 be quite slow. If all attempts to obtain the hardware address fail, we
429 choose a random 48-bit number with its eighth bit set to 1 as recommended
434 if _node
is not None:
438 if sys
.platform
== 'win32':
439 getters
= [_windll_getnode
, _netbios_getnode
, _ipconfig_getnode
]
441 getters
= [_unixdll_getnode
, _ifconfig_getnode
]
443 for getter
in getters
+ [_random_getnode
]:
448 if _node
is not None:
451 def uuid1(node
=None, clock_seq
=None):
452 """Generate a UUID from a host ID, sequence number, and the current time.
453 If 'node' is not given, getnode() is used to obtain the hardware
454 address. If 'clock_seq' is given, it is used as the sequence number;
455 otherwise a random 14-bit sequence number is chosen."""
457 # When the system provides a version-1 UUID generator, use it (but don't
458 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
459 if _uuid_generate_time
and node
is clock_seq
is None:
460 _uuid_generate_time(_buffer
)
461 return UUID(bytes
=_buffer
.raw
)
464 nanoseconds
= int(time
.time() * 1e9
)
465 # 0x01b21dd213814000 is the number of 100-ns intervals between the
466 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
467 timestamp
= int(nanoseconds
/100) + 0x01b21dd213814000L
468 if clock_seq
is None:
470 clock_seq
= random
.randrange(1<<14L) # instead of stable storage
471 time_low
= timestamp
& 0xffffffffL
472 time_mid
= (timestamp
>> 32L) & 0xffffL
473 time_hi_version
= (timestamp
>> 48L) & 0x0fffL
474 clock_seq_low
= clock_seq
& 0xffL
475 clock_seq_hi_variant
= (clock_seq
>> 8L) & 0x3fL
478 return UUID(fields
=(time_low
, time_mid
, time_hi_version
,
479 clock_seq_hi_variant
, clock_seq_low
, node
), version
=1)
481 def uuid3(namespace
, name
):
482 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
484 hash = md5
.md5(namespace
.bytes
+ name
).digest()
485 return UUID(bytes
=hash[:16], version
=3)
488 """Generate a random UUID."""
490 # When the system provides a version-4 UUID generator, use it.
491 if _uuid_generate_random
:
492 _uuid_generate_random(_buffer
)
493 return UUID(bytes
=_buffer
.raw
)
495 # Otherwise, get randomness from urandom or the 'random' module.
498 return UUID(bytes
=os
.urandom(16), version
=4)
501 bytes
= [chr(random
.randrange(256)) for i
in range(16)]
502 return UUID(bytes
=bytes
, version
=4)
504 def uuid5(namespace
, name
):
505 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
507 hash = sha
.sha(namespace
.bytes
+ name
).digest()
508 return UUID(bytes
=hash[:16], version
=5)
510 # The following standard UUIDs are for use with uuid3() or uuid5().
512 NAMESPACE_DNS
= UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
513 NAMESPACE_URL
= UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
514 NAMESPACE_OID
= UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
515 NAMESPACE_X500
= UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')