75d189ff7e348c35dca2214b9697c1dcddb44b21
[clinton/xbmc-groove.git] / resources / lib / uuid / __init__.py
1 r"""UUID objects (universally unique identifiers) according to RFC 4122.
2
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.
6
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.
10
11 Typical usage:
12
13 >>> import uuid
14
15 # make a UUID based on the host ID and current time
16 >>> uuid.uuid1()
17 UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
18
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')
22
23 # make a random UUID
24 >>> uuid.uuid4()
25 UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
26
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')
30
31 # make a UUID from a string of hex digits (braces and hyphens ignored)
32 >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
33
34 # convert a UUID to a string of hex digits in standard form
35 >>> str(x)
36 '00010203-0405-0607-0809-0a0b0c0d0e0f'
37
38 # get the raw 16 bytes of the UUID
39 >>> x.bytes
40 '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
41
42 # make a UUID from a 16-byte string
43 >>> uuid.UUID(bytes=x.bytes)
44 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
45
46 This module works with Python 2.3 or higher."""
47
48 __author__ = 'Ka-Ping Yee <ping@zesty.ca>'
49 __date__ = '$Date: 2006/06/12 23:15:40 $'.split()[1].replace('/', '-')
50 __version__ = '$Revision: 1.30 $'.split()[1]
51
52 RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
53 'reserved for NCS compatibility', 'specified in RFC 4122',
54 'reserved for Microsoft compatibility', 'reserved for future definition']
55
56 class UUID(object):
57 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
58 UUID objects are immutable, hashable, and usable as dictionary keys.
59 Converting a UUID to a string with str() yields something in the form
60 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
61 four possible forms: a similar string of hexadecimal digits, or a
62 string of 16 raw bytes as an argument named 'bytes', or a tuple of
63 six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
64 48-bit values respectively) as an argument named 'fields', or a single
65 128-bit integer as an argument named 'int'.
66
67 UUIDs have these read-only attributes:
68
69 bytes the UUID as a 16-byte string
70
71 fields a tuple of the six integer fields of the UUID,
72 which are also available as six individual attributes
73 and two derived attributes:
74
75 time_low the first 32 bits of the UUID
76 time_mid the next 16 bits of the UUID
77 time_hi_version the next 16 bits of the UUID
78 clock_seq_hi_variant the next 8 bits of the UUID
79 clock_seq_low the next 8 bits of the UUID
80 node the last 48 bits of the UUID
81
82 time the 60-bit timestamp
83 clock_seq the 14-bit sequence number
84
85 hex the UUID as a 32-character hexadecimal string
86
87 int the UUID as a 128-bit integer
88
89 urn the UUID as a URN as specified in RFC 4122
90
91 variant the UUID variant (one of the constants RESERVED_NCS,
92 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
93
94 version the UUID version number (1 through 5, meaningful only
95 when the variant is RFC_4122)
96 """
97
98 def __init__(self, hex=None, bytes=None, fields=None, int=None,
99 version=None):
100 r"""Create a UUID from either a string of 32 hexadecimal digits,
101 a string of 16 bytes as the 'bytes' argument, a tuple of six
102 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
103 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
104 the 'fields' argument, or a single 128-bit integer as the 'int'
105 argument. When a string of hex digits is given, curly braces,
106 hyphens, and a URN prefix are all optional. For example, these
107 expressions all yield the same UUID:
108
109 UUID('{12345678-1234-5678-1234-567812345678}')
110 UUID('12345678123456781234567812345678')
111 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
112 UUID(bytes='\x12\x34\x56\x78'*4)
113 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
114 UUID(int=0x12345678123456781234567812345678)
115
116 Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
117 The 'version' argument is optional; if given, the resulting UUID
118 will have its variant and version number set according to RFC 4122,
119 overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
120 """
121
122 if [hex, bytes, fields, int].count(None) != 3:
123 raise TypeError('need just one of hex, bytes, fields, or int')
124 if hex is not None:
125 hex = hex.replace('urn:', '').replace('uuid:', '')
126 hex = hex.strip('{}').replace('-', '')
127 if len(hex) != 32:
128 raise ValueError('badly formed hexadecimal UUID string')
129 int = long(hex, 16)
130 if bytes is not None:
131 if len(bytes) != 16:
132 raise ValueError('bytes is not a 16-char string')
133 int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
134 if fields is not None:
135 if len(fields) != 6:
136 raise ValueError('fields is not a 6-tuple')
137 (time_low, time_mid, time_hi_version,
138 clock_seq_hi_variant, clock_seq_low, node) = fields
139 if not 0 <= time_low < 1<<32L:
140 raise ValueError('field 1 out of range (need a 32-bit value)')
141 if not 0 <= time_mid < 1<<16L:
142 raise ValueError('field 2 out of range (need a 16-bit value)')
143 if not 0 <= time_hi_version < 1<<16L:
144 raise ValueError('field 3 out of range (need a 16-bit value)')
145 if not 0 <= clock_seq_hi_variant < 1<<8L:
146 raise ValueError('field 4 out of range (need an 8-bit value)')
147 if not 0 <= clock_seq_low < 1<<8L:
148 raise ValueError('field 5 out of range (need an 8-bit value)')
149 if not 0 <= node < 1<<48L:
150 raise ValueError('field 6 out of range (need a 48-bit value)')
151 clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
152 int = ((time_low << 96L) | (time_mid << 80L) |
153 (time_hi_version << 64L) | (clock_seq << 48L) | node)
154 if int is not None:
155 if not 0 <= int < 1<<128L:
156 raise ValueError('int is out of range (need a 128-bit value)')
157 if version is not None:
158 if not 1 <= version <= 5:
159 raise ValueError('illegal version number')
160 # Set the variant to RFC 4122.
161 int &= ~(0xc000 << 48L)
162 int |= 0x8000 << 48L
163 # Set the version number.
164 int &= ~(0xf000 << 64L)
165 int |= version << 76L
166 self.__dict__['int'] = int
167
168 def __cmp__(self, other):
169 if isinstance(other, UUID):
170 return cmp(self.int, other.int)
171 return NotImplemented
172
173 def __hash__(self):
174 return hash(self.int)
175
176 def __int__(self):
177 return self.int
178
179 def __repr__(self):
180 return 'UUID(%r)' % str(self)
181
182 def __setattr__(self, name, value):
183 raise TypeError('UUID objects are immutable')
184
185 def __str__(self):
186 hex = '%032x' % self.int
187 return '%s-%s-%s-%s-%s' % (
188 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
189
190 def get_bytes(self):
191 bytes = ''
192 for shift in range(0, 128, 8):
193 bytes = chr((self.int >> shift) & 0xff) + bytes
194 return bytes
195
196 bytes = property(get_bytes)
197
198 def get_fields(self):
199 return (self.time_low, self.time_mid, self.time_hi_version,
200 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
201
202 fields = property(get_fields)
203
204 def get_time_low(self):
205 return self.int >> 96L
206
207 time_low = property(get_time_low)
208
209 def get_time_mid(self):
210 return (self.int >> 80L) & 0xffff
211
212 time_mid = property(get_time_mid)
213
214 def get_time_hi_version(self):
215 return (self.int >> 64L) & 0xffff
216
217 time_hi_version = property(get_time_hi_version)
218
219 def get_clock_seq_hi_variant(self):
220 return (self.int >> 56L) & 0xff
221
222 clock_seq_hi_variant = property(get_clock_seq_hi_variant)
223
224 def get_clock_seq_low(self):
225 return (self.int >> 48L) & 0xff
226
227 clock_seq_low = property(get_clock_seq_low)
228
229 def get_time(self):
230 return (((self.time_hi_version & 0x0fffL) << 48L) |
231 (self.time_mid << 32L) | self.time_low)
232
233 time = property(get_time)
234
235 def get_clock_seq(self):
236 return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
237 self.clock_seq_low)
238
239 clock_seq = property(get_clock_seq)
240
241 def get_node(self):
242 return self.int & 0xffffffffffff
243
244 node = property(get_node)
245
246 def get_hex(self):
247 return '%032x' % self.int
248
249 hex = property(get_hex)
250
251 def get_urn(self):
252 return 'urn:uuid:' + str(self)
253
254 urn = property(get_urn)
255
256 def get_variant(self):
257 if not self.int & (0x8000 << 48L):
258 return RESERVED_NCS
259 elif not self.int & (0x4000 << 48L):
260 return RFC_4122
261 elif not self.int & (0x2000 << 48L):
262 return RESERVED_MICROSOFT
263 else:
264 return RESERVED_FUTURE
265
266 variant = property(get_variant)
267
268 def get_version(self):
269 # The version bits are only meaningful for RFC 4122 UUIDs.
270 if self.variant == RFC_4122:
271 return int((self.int >> 76L) & 0xf)
272
273 version = property(get_version)
274
275 def _ifconfig_getnode():
276 """Get the hardware address on Unix by running ifconfig."""
277 import os
278 for dir in ['', '/sbin/', '/usr/sbin']:
279 try:
280 pipe = os.popen(os.path.join(dir, 'ifconfig'))
281 except IOError:
282 continue
283 for line in pipe:
284 words = line.lower().split()
285 for i in range(len(words)):
286 if words[i] in ['hwaddr', 'ether']:
287 return int(words[i + 1].replace(':', ''), 16)
288
289 def _ipconfig_getnode():
290 """Get the hardware address on Windows by running ipconfig.exe."""
291 import os, re
292 dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
293 try:
294 import ctypes
295 buffer = ctypes.create_string_buffer(300)
296 ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
297 dirs.insert(0, buffer.value.decode('mbcs'))
298 except:
299 pass
300 for dir in dirs:
301 try:
302 pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all')
303 except IOError:
304 continue
305 for line in pipe:
306 value = line.split(':')[-1].strip().lower()
307 if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
308 return int(value.replace('-', ''), 16)
309
310 def _netbios_getnode():
311 """Get the hardware address on Windows using NetBIOS calls.
312 See http://support.microsoft.com/kb/118623 for details."""
313 import win32wnet, netbios
314 ncb = netbios.NCB()
315 ncb.Command = netbios.NCBENUM
316 ncb.Buffer = adapters = netbios.LANA_ENUM()
317 adapters._pack()
318 if win32wnet.Netbios(ncb) != 0:
319 return
320 adapters._unpack()
321 for i in range(adapters.length):
322 ncb.Reset()
323 ncb.Command = netbios.NCBRESET
324 ncb.Lana_num = ord(adapters.lana[i])
325 if win32wnet.Netbios(ncb) != 0:
326 continue
327 ncb.Reset()
328 ncb.Command = netbios.NCBASTAT
329 ncb.Lana_num = ord(adapters.lana[i])
330 ncb.Callname = '*'.ljust(16)
331 ncb.Buffer = status = netbios.ADAPTER_STATUS()
332 if win32wnet.Netbios(ncb) != 0:
333 continue
334 status._unpack()
335 bytes = map(ord, status.adapter_address)
336 return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
337 (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
338
339 # Thanks to Thomas Heller for ctypes and for his help with its use here.
340
341 # If ctypes is available, use it to find system routines for UUID generation.
342 _uuid_generate_random = _uuid_generate_time = _UuidCreate = None
343 try:
344 import ctypes, ctypes.util
345 _buffer = ctypes.create_string_buffer(16)
346
347 # The uuid_generate_* routines are provided by libuuid on at least
348 # Linux and FreeBSD, and provided by libc on Mac OS X.
349 for libname in ['uuid', 'c']:
350 try:
351 lib = ctypes.CDLL(ctypes.util.find_library(libname))
352 except:
353 continue
354 if hasattr(lib, 'uuid_generate_random'):
355 _uuid_generate_random = lib.uuid_generate_random
356 if hasattr(lib, 'uuid_generate_time'):
357 _uuid_generate_time = lib.uuid_generate_time
358
359 # On Windows prior to 2000, UuidCreate gives a UUID containing the
360 # hardware address. On Windows 2000 and later, UuidCreate makes a
361 # random UUID and UuidCreateSequential gives a UUID containing the
362 # hardware address. These routines are provided by the RPC runtime.
363 try:
364 lib = ctypes.windll.rpcrt4
365 except:
366 lib = None
367 _UuidCreate = getattr(lib, 'UuidCreateSequential',
368 getattr(lib, 'UuidCreate', None))
369 except:
370 pass
371
372 def _unixdll_getnode():
373 """Get the hardware address on Unix using ctypes."""
374 _uuid_generate_time(_buffer)
375 return UUID(bytes=_buffer.raw).node
376
377 def _windll_getnode():
378 """Get the hardware address on Windows using ctypes."""
379 if _UuidCreate(_buffer) == 0:
380 return UUID(bytes=_buffer.raw).node
381
382 def _random_getnode():
383 """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
384 import random
385 return random.randrange(0, 1<<48L) | 0x010000000000L
386
387 _node = None
388
389 def getnode():
390 """Get the hardware address as a 48-bit integer. The first time this
391 runs, it may launch a separate program, which could be quite slow. If
392 all attempts to obtain the hardware address fail, we choose a random
393 48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
394
395 global _node
396 if _node is not None:
397 return _node
398
399 import sys
400 if sys.platform == 'win32':
401 getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
402 else:
403 getters = [_unixdll_getnode, _ifconfig_getnode]
404
405 for getter in getters + [_random_getnode]:
406 try:
407 _node = getter()
408 except:
409 continue
410 if _node is not None:
411 return _node
412
413 def uuid1(node=None, clock_seq=None):
414 """Generate a UUID from a host ID, sequence number, and the current time.
415 If 'node' is not given, getnode() is used to obtain the hardware
416 address. If 'clock_seq' is given, it is used as the sequence number;
417 otherwise a random 14-bit sequence number is chosen."""
418
419 # When the system provides a version-1 UUID generator, use it (but don't
420 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
421 if _uuid_generate_time and node is clock_seq is None:
422 _uuid_generate_time(_buffer)
423 return UUID(bytes=_buffer.raw)
424
425 import time
426 nanoseconds = int(time.time() * 1e9)
427 # 0x01b21dd213814000 is the number of 100-ns intervals between the
428 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
429 timestamp = int(nanoseconds/100) + 0x01b21dd213814000L
430 if clock_seq is None:
431 import random
432 clock_seq = random.randrange(1<<14L) # instead of stable storage
433 time_low = timestamp & 0xffffffffL
434 time_mid = (timestamp >> 32L) & 0xffffL
435 time_hi_version = (timestamp >> 48L) & 0x0fffL
436 clock_seq_low = clock_seq & 0xffL
437 clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
438 if node is None:
439 node = getnode()
440 return UUID(fields=(time_low, time_mid, time_hi_version,
441 clock_seq_hi_variant, clock_seq_low, node), version=1)
442
443 def uuid3(namespace, name):
444 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
445 import md5
446 hash = md5.md5(namespace.bytes + name).digest()
447 return UUID(bytes=hash[:16], version=3)
448
449 def uuid4():
450 """Generate a random UUID."""
451
452 # When the system provides a version-4 UUID generator, use it.
453 if _uuid_generate_random:
454 _uuid_generate_random(_buffer)
455 return UUID(bytes=_buffer.raw)
456
457 # Otherwise, get randomness from urandom or the 'random' module.
458 try:
459 import os
460 return UUID(bytes=os.urandom(16), version=4)
461 except:
462 import random
463 bytes = [chr(random.randrange(256)) for i in range(16)]
464 return UUID(bytes=bytes, version=4)
465
466 def uuid5(namespace, name):
467 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
468 import sha
469 hash = sha.sha(namespace.bytes + name).digest()
470 return UUID(bytes=hash[:16], version=5)
471
472 # The following standard UUIDs are for use with uuid3() or uuid5().
473
474 NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
475 NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
476 NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
477 NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')