18 RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
19 'reserved for NCS compatibility',
'specified in RFC 4122',
20 'reserved for Microsoft compatibility',
'reserved for future definition']
36 def __init__(self, hex=None, bytes=None, fields=None, int_value=None,
38 r"""Create a UUID from either a string of 32 hexadecimal digits,
39 a string of 16 bytes as the 'bytes' argument, a tuple of six
40 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
41 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
42 the 'fields' argument, or a single 128-bit integer as the 'int'
43 argument. When a string of hex digits is given, curly braces,
44 hyphens, and a URN prefix are all optional. For example, these
45 expressions all yield the same UUID:
47 UUID('{12345678-1234-5678-1234-567812345678}')
48 UUID('12345678123456781234567812345678')
49 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
50 UUID(bytes='\x12\x34\x56\x78'*4)
51 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
52 UUID(int=0x12345678123456781234567812345678)
54 Exactly one of 'hex', 'bytes', 'fields', or 'int' must be given.
55 The 'version' argument is optional; if given, the resulting UUID
56 will have its variant and version number set according to RFC 4122,
57 overriding bits in the given 'hex', 'bytes', 'fields', or 'int'.
60 if [hex, bytes, fields, int_value].count(
None) != 3:
61 raise TypeError(
'need just one of hex, bytes, fields, or int')
63 hex = hex.replace(
'urn:',
'').replace(
'uuid:',
'')
64 hex = hex.strip(
'{}').replace(
'-',
'')
66 raise ValueError(
'badly formed hexadecimal UUID string')
67 int_value = int(hex, 16)
70 raise ValueError(
'bytes is not a 16-char string')
71 int_value = int((
'%02x'*16) % tuple(bytes), 16)
74 raise ValueError(
'fields is not a 6-tuple')
75 (time_low, time_mid, time_hi_version,
76 clock_seq_hi_variant, clock_seq_low, node) = fields
77 if not 0 <= time_low < 1<<32:
78 raise ValueError(
'field 1 out of range (need a 32-bit value)')
79 if not 0 <= time_mid < 1<<16:
80 raise ValueError(
'field 2 out of range (need a 16-bit value)')
81 if not 0 <= time_hi_version < 1<<16:
82 raise ValueError(
'field 3 out of range (need a 16-bit value)')
83 if not 0 <= clock_seq_hi_variant < 1<<8:
84 raise ValueError(
'field 4 out of range (need an 8-bit value)')
85 if not 0 <= clock_seq_low < 1<<8:
86 raise ValueError(
'field 5 out of range (need an 8-bit value)')
87 if not 0 <= node < 1<<48:
88 raise ValueError(
'field 6 out of range (need a 48-bit value)')
89 clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
90 int_value = ((time_low << 96) | (time_mid << 80) |
91 (time_hi_version << 64) | (clock_seq << 48) | node)
93 if not 0 <= int_value < 1<<128:
94 raise ValueError(
'int is out of range (need a 128-bit value)')
96 if not 1 <= version <= 5:
97 raise ValueError(
'illegal version number')
99 int_value &= ~(0xc000 << 48)
100 int_value |= 0x8000 << 48
102 int_value &= ~(0xf000 << 64)
103 int_value |= version << 76
104 self.__dict__[
'int_value'] = int_value
107 if isinstance(other, UUID):
108 return cmp(self.int_value, other.int_value)
109 return NotImplemented
112 return hash(self.int_value)
115 return self.int_value
118 return 'UUID(%r)' % str(self)
121 raise TypeError(
'UUID objects are immutable')
124 hex =
'%032x' % self.int_value
125 return '%s-%s-%s-%s-%s' % (
126 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
130 for shift
in range(0, 128, 8):
131 bytes = chr((self.int_value >> shift) & 0xff) + bytes
134 bytes = property(get_bytes)
140 fields = property(get_fields)
143 return self.int_value >> 96
145 time_low = property(get_time_low)
148 return (self.int_value >> 80) & 0xffff
150 time_mid = property(get_time_mid)
153 return (self.int_value >> 64) & 0xffff
155 time_hi_version = property(get_time_hi_version)
158 return (self.int_value >> 56) & 0xff
160 clock_seq_hi_variant = property(get_clock_seq_hi_variant)
163 return (self.int_value >> 48) & 0xff
165 clock_seq_low = property(get_clock_seq_low)
171 time = property(get_time)
177 clock_seq = property(get_clock_seq)
180 return self.int_value & 0xffffffffffff
182 node = property(get_node)
185 return '%032x' % self.int_value
187 hex = property(get_hex)
190 return 'urn:uuid:' + str(self)
192 urn = property(get_urn)
195 if not self.int_value & (0x8000 << 48):
197 elif not self.int_value & (0x4000 << 48):
199 elif not self.int_value & (0x2000 << 48):
200 return RESERVED_MICROSOFT
202 return RESERVED_FUTURE
204 variant = property(get_variant)
209 return int((self.int_value >> 76) & 0xf)
211 version = property(get_version)
214 """Get the hardware address on Unix by running ifconfig."""
217 pipe = os.popen(os.path.join(dir,
'ifconfig'))
220 words = line.lower().
split()
221 for i
in range(len(words)):
222 if words[i]
in [
'hwaddr',
'ether']:
223 return int(words[i + 1].replace(
':',
''), 16)
226 """Get the hardware address on Windows by running ipconfig.exe."""
228 dirs = [
'',
r'c:\windows\system32',
r'c:\winnt\system32']
231 buffer = ctypes.create_string_buffer(300)
232 ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
233 dirs.insert(0, buffer.value.decode(
'mbcs'))
238 pipe = os.popen(os.path.join(dir,
'ipconfig') +
' /all')
242 value = line.split(
':')[-1].strip().lower()
243 if re.match(
'([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
244 return int(value.replace(
'-',
''), 16)
247 """Get the hardware address on Windows using NetBIOS calls.
248 See http://support.microsoft.com/kb/118623 for details."""
249 import win32wnet, netbios
251 ncb.Command = netbios.NCBENUM
252 ncb.Buffer = adapters = netbios.LANA_ENUM()
254 if win32wnet.Netbios(ncb) != 0:
257 for i
in range(adapters.length):
259 ncb.Command = netbios.NCBRESET
260 ncb.Lana_num = ord(adapters.lana[i])
261 if win32wnet.Netbios(ncb) != 0:
264 ncb.Command = netbios.NCBASTAT
265 ncb.Lana_num = ord(adapters.lana[i])
266 ncb.Callname =
'*'.ljust(16)
267 ncb.Buffer = status = netbios.ADAPTER_STATUS()
268 if win32wnet.Netbios(ncb) != 0:
271 bytes = list(map(ord, status.adapter_address))
272 return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) +
273 (bytes[3]<<16) + (bytes[4]<<8) + bytes[5])
278 _uuid_generate_random = _uuid_generate_time = _UuidCreate =
None
280 import ctypes, ctypes.util
281 _buffer = ctypes.create_string_buffer(16)
285 for libname
in [
'uuid',
'c']:
287 lib = ctypes.CDLL(ctypes.util.find_library(libname))
290 if hasattr(lib,
'uuid_generate_random'):
291 _uuid_generate_random = lib.uuid_generate_random
292 if hasattr(lib,
'uuid_generate_time'):
293 _uuid_generate_time = lib.uuid_generate_time
300 lib = ctypes.windll.rpcrt4
303 _UuidCreate = getattr(lib,
'UuidCreateSequential',
304 getattr(lib,
'UuidCreate',
None))
309 """Get the hardware address on Unix using ctypes."""
311 return UUID(bytes=_buffer.raw).node
314 """Get the hardware address on Windows using ctypes."""
316 return UUID(bytes=_buffer.raw).node
319 """Get a random node ID, with eighth bit set as suggested by RFC 4122."""
321 return random.randrange(0, 1<<48) | 0x010000000000
326 """Get the hardware address as a 48-bit integer. The first time this
327 runs, it may launch a separate program, which could be quite slow. If
328 all attempts to obtain the hardware address fail, we choose a random
329 48-bit number with its eighth bit set to 1 as recommended in RFC 4122."""
336 if sys.platform ==
'win32':
337 getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
339 getters = [_unixdll_getnode, _ifconfig_getnode]
341 for getter
in getters + [_random_getnode]:
349 def uuid1(node=None, clock_seq=None):
350 """Generate a UUID from a host ID, sequence number, and the current time.
351 If 'node' is not given, getnode() is used to obtain the hardware
352 address. If 'clock_seq' is given, it is used as the sequence number;
353 otherwise a random 14-bit sequence number is chosen."""
357 if _uuid_generate_time
and node
is clock_seq
is None:
359 return UUID(bytes=_buffer.raw)
362 nanoseconds = int(time.time() * 1e9)
365 timestamp = int(nanoseconds/100) + 0x01b21dd213814000
366 if clock_seq
is None:
368 clock_seq = random.randrange(1<<14)
369 time_low = timestamp & 0xffffffff
370 time_mid = (timestamp >> 32) & 0xffff
371 time_hi_version = (timestamp >> 48) & 0x0fff
372 clock_seq_low = clock_seq & 0xff
373 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
376 return UUID(fields=(time_low, time_mid, time_hi_version,
377 clock_seq_hi_variant, clock_seq_low, node), version=1)
380 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
382 hash = md5.md5(namespace.bytes + name).digest()
383 return UUID(bytes=hash[:16], version=3)
386 """Generate a random UUID."""
389 if _uuid_generate_random:
391 return UUID(bytes=_buffer.raw)
396 return UUID(bytes=os.urandom(16), version=4)
399 bytes = [chr(random.randrange(256))
for i
in range(16)]
400 return UUID(bytes=bytes, version=4)
403 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
405 hash = sha.sha(namespace.bytes + name).digest()
406 return UUID(bytes=hash[:16], version=5)
410 NAMESPACE_DNS =
UUID(
'6ba7b810-9dad-11d1-80b4-00c04fd430c8')
411 NAMESPACE_URL =
UUID(
'6ba7b811-9dad-11d1-80b4-00c04fd430c8')
412 NAMESPACE_OID =
UUID(
'6ba7b812-9dad-11d1-80b4-00c04fd430c8')
413 NAMESPACE_X500 =
UUID(
'6ba7b814-9dad-11d1-80b4-00c04fd430c8')