Package elisa :: Package extern :: Package coherence :: Package uuid :: Module uuid
[hide private]
[frames] | no frames]

Source Code for Module elisa.extern.coherence.uuid.uuid

  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 """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') 478