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() # doctest: +SKIP
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() # doctest: +SKIP
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 b'\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
47 import os
48 import sys
49
50 from enum import Enum, _simple_enum
51
52
53 __author__ = 'Ka-Ping Yee <ping@zesty.ca>'
54
55 # The recognized platforms - known behaviors
56 if sys.platform in ('win32', 'darwin'):
57 _AIX = _LINUX = False
58 else:
59 import platform
60 _platform_system = platform.system()
61 _AIX = _platform_system == 'AIX'
62 _LINUX = _platform_system == 'Linux'
63
64 _MAC_DELIM = b':'
65 _MAC_OMITS_LEADING_ZEROES = False
66 if _AIX:
67 _MAC_DELIM = b'.'
68 _MAC_OMITS_LEADING_ZEROES = True
69
70 RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
71 'reserved for NCS compatibility', 'specified in RFC 4122',
72 'reserved for Microsoft compatibility', 'reserved for future definition']
73
74 int_ = int # The built-in int type
75 bytes_ = bytes # The built-in bytes type
76
77
78 @_simple_enum(Enum)
79 class ESC[4;38;5;81mSafeUUID:
80 safe = 0
81 unsafe = -1
82 unknown = None
83
84
85 class ESC[4;38;5;81mUUID:
86 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
87 UUID objects are immutable, hashable, and usable as dictionary keys.
88 Converting a UUID to a string with str() yields something in the form
89 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
90 five possible forms: a similar string of hexadecimal digits, or a tuple
91 of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
92 48-bit values respectively) as an argument named 'fields', or a string
93 of 16 bytes (with all the integer fields in big-endian order) as an
94 argument named 'bytes', or a string of 16 bytes (with the first three
95 fields in little-endian order) as an argument named 'bytes_le', or a
96 single 128-bit integer as an argument named 'int'.
97
98 UUIDs have these read-only attributes:
99
100 bytes the UUID as a 16-byte string (containing the six
101 integer fields in big-endian byte order)
102
103 bytes_le the UUID as a 16-byte string (with time_low, time_mid,
104 and time_hi_version in little-endian byte order)
105
106 fields a tuple of the six integer fields of the UUID,
107 which are also available as six individual attributes
108 and two derived attributes:
109
110 time_low the first 32 bits of the UUID
111 time_mid the next 16 bits of the UUID
112 time_hi_version the next 16 bits of the UUID
113 clock_seq_hi_variant the next 8 bits of the UUID
114 clock_seq_low the next 8 bits of the UUID
115 node the last 48 bits of the UUID
116
117 time the 60-bit timestamp
118 clock_seq the 14-bit sequence number
119
120 hex the UUID as a 32-character hexadecimal string
121
122 int the UUID as a 128-bit integer
123
124 urn the UUID as a URN as specified in RFC 4122
125
126 variant the UUID variant (one of the constants RESERVED_NCS,
127 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
128
129 version the UUID version number (1 through 5, meaningful only
130 when the variant is RFC_4122)
131
132 is_safe An enum indicating whether the UUID has been generated in
133 a way that is safe for multiprocessing applications, via
134 uuid_generate_time_safe(3).
135 """
136
137 __slots__ = ('int', 'is_safe', '__weakref__')
138
139 def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
140 int=None, version=None,
141 *, is_safe=SafeUUID.unknown):
142 r"""Create a UUID from either a string of 32 hexadecimal digits,
143 a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
144 in little-endian order as the 'bytes_le' argument, a tuple of six
145 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
146 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
147 the 'fields' argument, or a single 128-bit integer as the 'int'
148 argument. When a string of hex digits is given, curly braces,
149 hyphens, and a URN prefix are all optional. For example, these
150 expressions all yield the same UUID:
151
152 UUID('{12345678-1234-5678-1234-567812345678}')
153 UUID('12345678123456781234567812345678')
154 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
155 UUID(bytes='\x12\x34\x56\x78'*4)
156 UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
157 '\x12\x34\x56\x78\x12\x34\x56\x78')
158 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
159 UUID(int=0x12345678123456781234567812345678)
160
161 Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
162 be given. The 'version' argument is optional; if given, the resulting
163 UUID will have its variant and version set according to RFC 4122,
164 overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
165
166 is_safe is an enum exposed as an attribute on the instance. It
167 indicates whether the UUID has been generated in a way that is safe
168 for multiprocessing applications, via uuid_generate_time_safe(3).
169 """
170
171 if [hex, bytes, bytes_le, fields, int].count(None) != 4:
172 raise TypeError('one of the hex, bytes, bytes_le, fields, '
173 'or int arguments must be given')
174 if hex is not None:
175 hex = hex.replace('urn:', '').replace('uuid:', '')
176 hex = hex.strip('{}').replace('-', '')
177 if len(hex) != 32:
178 raise ValueError('badly formed hexadecimal UUID string')
179 int = int_(hex, 16)
180 if bytes_le is not None:
181 if len(bytes_le) != 16:
182 raise ValueError('bytes_le is not a 16-char string')
183 bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
184 bytes_le[8-1:6-1:-1] + bytes_le[8:])
185 if bytes is not None:
186 if len(bytes) != 16:
187 raise ValueError('bytes is not a 16-char string')
188 assert isinstance(bytes, bytes_), repr(bytes)
189 int = int_.from_bytes(bytes) # big endian
190 if fields is not None:
191 if len(fields) != 6:
192 raise ValueError('fields is not a 6-tuple')
193 (time_low, time_mid, time_hi_version,
194 clock_seq_hi_variant, clock_seq_low, node) = fields
195 if not 0 <= time_low < 1<<32:
196 raise ValueError('field 1 out of range (need a 32-bit value)')
197 if not 0 <= time_mid < 1<<16:
198 raise ValueError('field 2 out of range (need a 16-bit value)')
199 if not 0 <= time_hi_version < 1<<16:
200 raise ValueError('field 3 out of range (need a 16-bit value)')
201 if not 0 <= clock_seq_hi_variant < 1<<8:
202 raise ValueError('field 4 out of range (need an 8-bit value)')
203 if not 0 <= clock_seq_low < 1<<8:
204 raise ValueError('field 5 out of range (need an 8-bit value)')
205 if not 0 <= node < 1<<48:
206 raise ValueError('field 6 out of range (need a 48-bit value)')
207 clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
208 int = ((time_low << 96) | (time_mid << 80) |
209 (time_hi_version << 64) | (clock_seq << 48) | node)
210 if int is not None:
211 if not 0 <= int < 1<<128:
212 raise ValueError('int is out of range (need a 128-bit value)')
213 if version is not None:
214 if not 1 <= version <= 5:
215 raise ValueError('illegal version number')
216 # Set the variant to RFC 4122.
217 int &= ~(0xc000 << 48)
218 int |= 0x8000 << 48
219 # Set the version number.
220 int &= ~(0xf000 << 64)
221 int |= version << 76
222 object.__setattr__(self, 'int', int)
223 object.__setattr__(self, 'is_safe', is_safe)
224
225 def __getstate__(self):
226 d = {'int': self.int}
227 if self.is_safe != SafeUUID.unknown:
228 # is_safe is a SafeUUID instance. Return just its value, so that
229 # it can be un-pickled in older Python versions without SafeUUID.
230 d['is_safe'] = self.is_safe.value
231 return d
232
233 def __setstate__(self, state):
234 object.__setattr__(self, 'int', state['int'])
235 # is_safe was added in 3.7; it is also omitted when it is "unknown"
236 object.__setattr__(self, 'is_safe',
237 SafeUUID(state['is_safe'])
238 if 'is_safe' in state else SafeUUID.unknown)
239
240 def __eq__(self, other):
241 if isinstance(other, UUID):
242 return self.int == other.int
243 return NotImplemented
244
245 # Q. What's the value of being able to sort UUIDs?
246 # A. Use them as keys in a B-Tree or similar mapping.
247
248 def __lt__(self, other):
249 if isinstance(other, UUID):
250 return self.int < other.int
251 return NotImplemented
252
253 def __gt__(self, other):
254 if isinstance(other, UUID):
255 return self.int > other.int
256 return NotImplemented
257
258 def __le__(self, other):
259 if isinstance(other, UUID):
260 return self.int <= other.int
261 return NotImplemented
262
263 def __ge__(self, other):
264 if isinstance(other, UUID):
265 return self.int >= other.int
266 return NotImplemented
267
268 def __hash__(self):
269 return hash(self.int)
270
271 def __int__(self):
272 return self.int
273
274 def __repr__(self):
275 return '%s(%r)' % (self.__class__.__name__, str(self))
276
277 def __setattr__(self, name, value):
278 raise TypeError('UUID objects are immutable')
279
280 def __str__(self):
281 hex = '%032x' % self.int
282 return '%s-%s-%s-%s-%s' % (
283 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
284
285 @property
286 def bytes(self):
287 return self.int.to_bytes(16) # big endian
288
289 @property
290 def bytes_le(self):
291 bytes = self.bytes
292 return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] +
293 bytes[8:])
294
295 @property
296 def fields(self):
297 return (self.time_low, self.time_mid, self.time_hi_version,
298 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
299
300 @property
301 def time_low(self):
302 return self.int >> 96
303
304 @property
305 def time_mid(self):
306 return (self.int >> 80) & 0xffff
307
308 @property
309 def time_hi_version(self):
310 return (self.int >> 64) & 0xffff
311
312 @property
313 def clock_seq_hi_variant(self):
314 return (self.int >> 56) & 0xff
315
316 @property
317 def clock_seq_low(self):
318 return (self.int >> 48) & 0xff
319
320 @property
321 def time(self):
322 return (((self.time_hi_version & 0x0fff) << 48) |
323 (self.time_mid << 32) | self.time_low)
324
325 @property
326 def clock_seq(self):
327 return (((self.clock_seq_hi_variant & 0x3f) << 8) |
328 self.clock_seq_low)
329
330 @property
331 def node(self):
332 return self.int & 0xffffffffffff
333
334 @property
335 def hex(self):
336 return '%032x' % self.int
337
338 @property
339 def urn(self):
340 return 'urn:uuid:' + str(self)
341
342 @property
343 def variant(self):
344 if not self.int & (0x8000 << 48):
345 return RESERVED_NCS
346 elif not self.int & (0x4000 << 48):
347 return RFC_4122
348 elif not self.int & (0x2000 << 48):
349 return RESERVED_MICROSOFT
350 else:
351 return RESERVED_FUTURE
352
353 @property
354 def version(self):
355 # The version bits are only meaningful for RFC 4122 UUIDs.
356 if self.variant == RFC_4122:
357 return int((self.int >> 76) & 0xf)
358
359
360 def _get_command_stdout(command, *args):
361 import io, os, shutil, subprocess
362
363 try:
364 path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep)
365 path_dirs.extend(['/sbin', '/usr/sbin'])
366 executable = shutil.which(command, path=os.pathsep.join(path_dirs))
367 if executable is None:
368 return None
369 # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
370 # on stderr (Note: we don't have an example where the words we search
371 # for are actually localized, but in theory some system could do so.)
372 env = dict(os.environ)
373 env['LC_ALL'] = 'C'
374 # Empty strings will be quoted by popen so we should just ommit it
375 if args != ('',):
376 command = (executable, *args)
377 else:
378 command = (executable,)
379 proc = subprocess.Popen(command,
380 stdout=subprocess.PIPE,
381 stderr=subprocess.DEVNULL,
382 env=env)
383 if not proc:
384 return None
385 stdout, stderr = proc.communicate()
386 return io.BytesIO(stdout)
387 except (OSError, subprocess.SubprocessError):
388 return None
389
390
391 # For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
392 # bit of the first octet signifies whether the MAC address is universally (0)
393 # or locally (1) administered. Network cards from hardware manufacturers will
394 # always be universally administered to guarantee global uniqueness of the MAC
395 # address, but any particular machine may have other interfaces which are
396 # locally administered. An example of the latter is the bridge interface to
397 # the Touch Bar on MacBook Pros.
398 #
399 # This bit works out to be the 42nd bit counting from 1 being the least
400 # significant, or 1<<41. We'll prefer universally administered MAC addresses
401 # over locally administered ones since the former are globally unique, but
402 # we'll return the first of the latter found if that's all the machine has.
403 #
404 # See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
405
406 def _is_universal(mac):
407 return not (mac & (1 << 41))
408
409
410 def _find_mac_near_keyword(command, args, keywords, get_word_index):
411 """Searches a command's output for a MAC address near a keyword.
412
413 Each line of words in the output is case-insensitively searched for
414 any of the given keywords. Upon a match, get_word_index is invoked
415 to pick a word from the line, given the index of the match. For
416 example, lambda i: 0 would get the first word on the line, while
417 lambda i: i - 1 would get the word preceding the keyword.
418 """
419 stdout = _get_command_stdout(command, args)
420 if stdout is None:
421 return None
422
423 first_local_mac = None
424 for line in stdout:
425 words = line.lower().rstrip().split()
426 for i in range(len(words)):
427 if words[i] in keywords:
428 try:
429 word = words[get_word_index(i)]
430 mac = int(word.replace(_MAC_DELIM, b''), 16)
431 except (ValueError, IndexError):
432 # Virtual interfaces, such as those provided by
433 # VPNs, do not have a colon-delimited MAC address
434 # as expected, but a 16-byte HWAddr separated by
435 # dashes. These should be ignored in favor of a
436 # real MAC address
437 pass
438 else:
439 if _is_universal(mac):
440 return mac
441 first_local_mac = first_local_mac or mac
442 return first_local_mac or None
443
444
445 def _parse_mac(word):
446 # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
447 # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8').
448 #
449 # Virtual interfaces, such as those provided by VPNs, do not have a
450 # colon-delimited MAC address as expected, but a 16-byte HWAddr separated
451 # by dashes. These should be ignored in favor of a real MAC address
452 parts = word.split(_MAC_DELIM)
453 if len(parts) != 6:
454 return
455 if _MAC_OMITS_LEADING_ZEROES:
456 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
457 # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
458 # not
459 # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
460 if not all(1 <= len(part) <= 2 for part in parts):
461 return
462 hexstr = b''.join(part.rjust(2, b'0') for part in parts)
463 else:
464 if not all(len(part) == 2 for part in parts):
465 return
466 hexstr = b''.join(parts)
467 try:
468 return int(hexstr, 16)
469 except ValueError:
470 return
471
472
473 def _find_mac_under_heading(command, args, heading):
474 """Looks for a MAC address under a heading in a command's output.
475
476 The first line of words in the output is searched for the given
477 heading. Words at the same word index as the heading in subsequent
478 lines are then examined to see if they look like MAC addresses.
479 """
480 stdout = _get_command_stdout(command, args)
481 if stdout is None:
482 return None
483
484 keywords = stdout.readline().rstrip().split()
485 try:
486 column_index = keywords.index(heading)
487 except ValueError:
488 return None
489
490 first_local_mac = None
491 for line in stdout:
492 words = line.rstrip().split()
493 try:
494 word = words[column_index]
495 except IndexError:
496 continue
497
498 mac = _parse_mac(word)
499 if mac is None:
500 continue
501 if _is_universal(mac):
502 return mac
503 if first_local_mac is None:
504 first_local_mac = mac
505
506 return first_local_mac
507
508
509 # The following functions call external programs to 'get' a macaddr value to
510 # be used as basis for an uuid
511 def _ifconfig_getnode():
512 """Get the hardware address on Unix by running ifconfig."""
513 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
514 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
515 for args in ('', '-a', '-av'):
516 mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1)
517 if mac:
518 return mac
519 return None
520
521 def _ip_getnode():
522 """Get the hardware address on Unix by running ip."""
523 # This works on Linux with iproute2.
524 mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1)
525 if mac:
526 return mac
527 return None
528
529 def _arp_getnode():
530 """Get the hardware address on Unix by running arp."""
531 import os, socket
532 if not hasattr(socket, "gethostbyname"):
533 return None
534 try:
535 ip_addr = socket.gethostbyname(socket.gethostname())
536 except OSError:
537 return None
538
539 # Try getting the MAC addr from arp based on our IP address (Solaris).
540 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
541 if mac:
542 return mac
543
544 # This works on OpenBSD
545 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
546 if mac:
547 return mac
548
549 # This works on Linux, FreeBSD and NetBSD
550 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
551 lambda i: i+2)
552 # Return None instead of 0.
553 if mac:
554 return mac
555 return None
556
557 def _lanscan_getnode():
558 """Get the hardware address on Unix by running lanscan."""
559 # This might work on HP-UX.
560 return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0)
561
562 def _netstat_getnode():
563 """Get the hardware address on Unix by running netstat."""
564 # This works on AIX and might work on Tru64 UNIX.
565 return _find_mac_under_heading('netstat', '-ian', b'Address')
566
567 def _ipconfig_getnode():
568 """[DEPRECATED] Get the hardware address on Windows."""
569 # bpo-40501: UuidCreateSequential() is now the only supported approach
570 return _windll_getnode()
571
572 def _netbios_getnode():
573 """[DEPRECATED] Get the hardware address on Windows."""
574 # bpo-40501: UuidCreateSequential() is now the only supported approach
575 return _windll_getnode()
576
577
578 # Import optional C extension at toplevel, to help disabling it when testing
579 try:
580 import _uuid
581 _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
582 _UuidCreate = getattr(_uuid, "UuidCreate", None)
583 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
584 except ImportError:
585 _uuid = None
586 _generate_time_safe = None
587 _UuidCreate = None
588 _has_uuid_generate_time_safe = None
589
590
591 def _load_system_functions():
592 """[DEPRECATED] Platform-specific functions loaded at import time"""
593
594
595 def _unix_getnode():
596 """Get the hardware address on Unix using the _uuid extension module."""
597 if _generate_time_safe:
598 uuid_time, _ = _generate_time_safe()
599 return UUID(bytes=uuid_time).node
600
601 def _windll_getnode():
602 """Get the hardware address on Windows using the _uuid extension module."""
603 if _UuidCreate:
604 uuid_bytes = _UuidCreate()
605 return UUID(bytes_le=uuid_bytes).node
606
607 def _random_getnode():
608 """Get a random node ID."""
609 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
610 # pseudo-randomly generated value may be used; see Section 4.5. The
611 # multicast bit must be set in such addresses, in order that they will
612 # never conflict with addresses obtained from network cards."
613 #
614 # The "multicast bit" of a MAC address is defined to be "the least
615 # significant bit of the first octet". This works out to be the 41st bit
616 # counting from 1 being the least significant bit, or 1<<40.
617 #
618 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
619 import random
620 return random.getrandbits(48) | (1 << 40)
621
622
623 # _OS_GETTERS, when known, are targeted for a specific OS or platform.
624 # The order is by 'common practice' on the specified platform.
625 # Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
626 # which, when successful, means none of these "external" methods are called.
627 # _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
628 # @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
629 if _LINUX:
630 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
631 elif sys.platform == 'darwin':
632 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
633 elif sys.platform == 'win32':
634 # bpo-40201: _windll_getnode will always succeed, so these are not needed
635 _OS_GETTERS = []
636 elif _AIX:
637 _OS_GETTERS = [_netstat_getnode]
638 else:
639 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
640 _netstat_getnode, _lanscan_getnode]
641 if os.name == 'posix':
642 _GETTERS = [_unix_getnode] + _OS_GETTERS
643 elif os.name == 'nt':
644 _GETTERS = [_windll_getnode] + _OS_GETTERS
645 else:
646 _GETTERS = _OS_GETTERS
647
648 _node = None
649
650 def getnode():
651 """Get the hardware address as a 48-bit positive integer.
652
653 The first time this runs, it may launch a separate program, which could
654 be quite slow. If all attempts to obtain the hardware address fail, we
655 choose a random 48-bit number with its eighth bit set to 1 as recommended
656 in RFC 4122.
657 """
658 global _node
659 if _node is not None:
660 return _node
661
662 for getter in _GETTERS + [_random_getnode]:
663 try:
664 _node = getter()
665 except:
666 continue
667 if (_node is not None) and (0 <= _node < (1 << 48)):
668 return _node
669 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
670
671
672 _last_timestamp = None
673
674 def uuid1(node=None, clock_seq=None):
675 """Generate a UUID from a host ID, sequence number, and the current time.
676 If 'node' is not given, getnode() is used to obtain the hardware
677 address. If 'clock_seq' is given, it is used as the sequence number;
678 otherwise a random 14-bit sequence number is chosen."""
679
680 # When the system provides a version-1 UUID generator, use it (but don't
681 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
682 if _generate_time_safe is not None and node is clock_seq is None:
683 uuid_time, safely_generated = _generate_time_safe()
684 try:
685 is_safe = SafeUUID(safely_generated)
686 except ValueError:
687 is_safe = SafeUUID.unknown
688 return UUID(bytes=uuid_time, is_safe=is_safe)
689
690 global _last_timestamp
691 import time
692 nanoseconds = time.time_ns()
693 # 0x01b21dd213814000 is the number of 100-ns intervals between the
694 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
695 timestamp = nanoseconds // 100 + 0x01b21dd213814000
696 if _last_timestamp is not None and timestamp <= _last_timestamp:
697 timestamp = _last_timestamp + 1
698 _last_timestamp = timestamp
699 if clock_seq is None:
700 import random
701 clock_seq = random.getrandbits(14) # instead of stable storage
702 time_low = timestamp & 0xffffffff
703 time_mid = (timestamp >> 32) & 0xffff
704 time_hi_version = (timestamp >> 48) & 0x0fff
705 clock_seq_low = clock_seq & 0xff
706 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
707 if node is None:
708 node = getnode()
709 return UUID(fields=(time_low, time_mid, time_hi_version,
710 clock_seq_hi_variant, clock_seq_low, node), version=1)
711
712 def uuid3(namespace, name):
713 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
714 from hashlib import md5
715 digest = md5(
716 namespace.bytes + bytes(name, "utf-8"),
717 usedforsecurity=False
718 ).digest()
719 return UUID(bytes=digest[:16], version=3)
720
721 def uuid4():
722 """Generate a random UUID."""
723 return UUID(bytes=os.urandom(16), version=4)
724
725 def uuid5(namespace, name):
726 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
727 from hashlib import sha1
728 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
729 return UUID(bytes=hash[:16], version=5)
730
731 # The following standard UUIDs are for use with uuid3() or uuid5().
732
733 NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
734 NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
735 NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
736 NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')