Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/uuid.py: 26%
428 statements
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
« prev ^ index » next coverage.py v7.0.1, created at 2022-12-25 06:11 +0000
1r"""UUID objects (universally unique identifiers) according to RFC 4122.
3This module provides immutable UUID objects (class UUID) and the functions
4uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
5UUIDs as specified in RFC 4122.
7If all you want is a unique ID, you should probably call uuid1() or uuid4().
8Note that uuid1() may compromise privacy since it creates a UUID containing
9the computer's network address. uuid4() creates a random UUID.
11Typical usage:
13 >>> import uuid
15 # make a UUID based on the host ID and current time
16 >>> uuid.uuid1() # doctest: +SKIP
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')
23 # make a random UUID
24 >>> uuid.uuid4() # doctest: +SKIP
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
35 >>> str(x)
36 '00010203-0405-0607-0809-0a0b0c0d0e0f'
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'
42 # make a UUID from a 16-byte string
43 >>> uuid.UUID(bytes=x.bytes)
44 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
45"""
47import os
48import platform
49import sys
51from enum import Enum
54__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
56# The recognized platforms - known behaviors
57_AIX = platform.system() == 'AIX'
58_DARWIN = platform.system() == 'Darwin'
59_LINUX = platform.system() == 'Linux'
60_WINDOWS = platform.system() == 'Windows'
62RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
63 'reserved for NCS compatibility', 'specified in RFC 4122',
64 'reserved for Microsoft compatibility', 'reserved for future definition']
66int_ = int # The built-in int type
67bytes_ = bytes # The built-in bytes type
70class SafeUUID(Enum):
71 safe = 0
72 unsafe = -1
73 unknown = None
76class UUID:
77 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
78 UUID objects are immutable, hashable, and usable as dictionary keys.
79 Converting a UUID to a string with str() yields something in the form
80 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
81 five possible forms: a similar string of hexadecimal digits, or a tuple
82 of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
83 48-bit values respectively) as an argument named 'fields', or a string
84 of 16 bytes (with all the integer fields in big-endian order) as an
85 argument named 'bytes', or a string of 16 bytes (with the first three
86 fields in little-endian order) as an argument named 'bytes_le', or a
87 single 128-bit integer as an argument named 'int'.
89 UUIDs have these read-only attributes:
91 bytes the UUID as a 16-byte string (containing the six
92 integer fields in big-endian byte order)
94 bytes_le the UUID as a 16-byte string (with time_low, time_mid,
95 and time_hi_version in little-endian byte order)
97 fields a tuple of the six integer fields of the UUID,
98 which are also available as six individual attributes
99 and two derived attributes:
101 time_low the first 32 bits of the UUID
102 time_mid the next 16 bits of the UUID
103 time_hi_version the next 16 bits of the UUID
104 clock_seq_hi_variant the next 8 bits of the UUID
105 clock_seq_low the next 8 bits of the UUID
106 node the last 48 bits of the UUID
108 time the 60-bit timestamp
109 clock_seq the 14-bit sequence number
111 hex the UUID as a 32-character hexadecimal string
113 int the UUID as a 128-bit integer
115 urn the UUID as a URN as specified in RFC 4122
117 variant the UUID variant (one of the constants RESERVED_NCS,
118 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
120 version the UUID version number (1 through 5, meaningful only
121 when the variant is RFC_4122)
123 is_safe An enum indicating whether the UUID has been generated in
124 a way that is safe for multiprocessing applications, via
125 uuid_generate_time_safe(3).
126 """
128 __slots__ = ('int', 'is_safe', '__weakref__')
130 def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
131 int=None, version=None,
132 *, is_safe=SafeUUID.unknown):
133 r"""Create a UUID from either a string of 32 hexadecimal digits,
134 a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
135 in little-endian order as the 'bytes_le' argument, a tuple of six
136 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
137 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
138 the 'fields' argument, or a single 128-bit integer as the 'int'
139 argument. When a string of hex digits is given, curly braces,
140 hyphens, and a URN prefix are all optional. For example, these
141 expressions all yield the same UUID:
143 UUID('{12345678-1234-5678-1234-567812345678}')
144 UUID('12345678123456781234567812345678')
145 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
146 UUID(bytes='\x12\x34\x56\x78'*4)
147 UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
148 '\x12\x34\x56\x78\x12\x34\x56\x78')
149 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
150 UUID(int=0x12345678123456781234567812345678)
152 Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
153 be given. The 'version' argument is optional; if given, the resulting
154 UUID will have its variant and version set according to RFC 4122,
155 overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
157 is_safe is an enum exposed as an attribute on the instance. It
158 indicates whether the UUID has been generated in a way that is safe
159 for multiprocessing applications, via uuid_generate_time_safe(3).
160 """
162 if [hex, bytes, bytes_le, fields, int].count(None) != 4:
163 raise TypeError('one of the hex, bytes, bytes_le, fields, '
164 'or int arguments must be given')
165 if hex is not None:
166 hex = hex.replace('urn:', '').replace('uuid:', '')
167 hex = hex.strip('{}').replace('-', '')
168 if len(hex) != 32:
169 raise ValueError('badly formed hexadecimal UUID string')
170 int = int_(hex, 16)
171 if bytes_le is not None:
172 if len(bytes_le) != 16:
173 raise ValueError('bytes_le is not a 16-char string')
174 bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
175 bytes_le[8-1:6-1:-1] + bytes_le[8:])
176 if bytes is not None:
177 if len(bytes) != 16:
178 raise ValueError('bytes is not a 16-char string')
179 assert isinstance(bytes, bytes_), repr(bytes)
180 int = int_.from_bytes(bytes, byteorder='big')
181 if fields is not None:
182 if len(fields) != 6:
183 raise ValueError('fields is not a 6-tuple')
184 (time_low, time_mid, time_hi_version,
185 clock_seq_hi_variant, clock_seq_low, node) = fields
186 if not 0 <= time_low < 1<<32:
187 raise ValueError('field 1 out of range (need a 32-bit value)')
188 if not 0 <= time_mid < 1<<16:
189 raise ValueError('field 2 out of range (need a 16-bit value)')
190 if not 0 <= time_hi_version < 1<<16:
191 raise ValueError('field 3 out of range (need a 16-bit value)')
192 if not 0 <= clock_seq_hi_variant < 1<<8:
193 raise ValueError('field 4 out of range (need an 8-bit value)')
194 if not 0 <= clock_seq_low < 1<<8:
195 raise ValueError('field 5 out of range (need an 8-bit value)')
196 if not 0 <= node < 1<<48:
197 raise ValueError('field 6 out of range (need a 48-bit value)')
198 clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
199 int = ((time_low << 96) | (time_mid << 80) |
200 (time_hi_version << 64) | (clock_seq << 48) | node)
201 if int is not None:
202 if not 0 <= int < 1<<128:
203 raise ValueError('int is out of range (need a 128-bit value)')
204 if version is not None:
205 if not 1 <= version <= 5:
206 raise ValueError('illegal version number')
207 # Set the variant to RFC 4122.
208 int &= ~(0xc000 << 48)
209 int |= 0x8000 << 48
210 # Set the version number.
211 int &= ~(0xf000 << 64)
212 int |= version << 76
213 object.__setattr__(self, 'int', int)
214 object.__setattr__(self, 'is_safe', is_safe)
216 def __getstate__(self):
217 d = {'int': self.int}
218 if self.is_safe != SafeUUID.unknown:
219 # is_safe is a SafeUUID instance. Return just its value, so that
220 # it can be un-pickled in older Python versions without SafeUUID.
221 d['is_safe'] = self.is_safe.value
222 return d
224 def __setstate__(self, state):
225 object.__setattr__(self, 'int', state['int'])
226 # is_safe was added in 3.7; it is also omitted when it is "unknown"
227 object.__setattr__(self, 'is_safe',
228 SafeUUID(state['is_safe'])
229 if 'is_safe' in state else SafeUUID.unknown)
231 def __eq__(self, other):
232 if isinstance(other, UUID):
233 return self.int == other.int
234 return NotImplemented
236 # Q. What's the value of being able to sort UUIDs?
237 # A. Use them as keys in a B-Tree or similar mapping.
239 def __lt__(self, other):
240 if isinstance(other, UUID):
241 return self.int < other.int
242 return NotImplemented
244 def __gt__(self, other):
245 if isinstance(other, UUID):
246 return self.int > other.int
247 return NotImplemented
249 def __le__(self, other):
250 if isinstance(other, UUID):
251 return self.int <= other.int
252 return NotImplemented
254 def __ge__(self, other):
255 if isinstance(other, UUID):
256 return self.int >= other.int
257 return NotImplemented
259 def __hash__(self):
260 return hash(self.int)
262 def __int__(self):
263 return self.int
265 def __repr__(self):
266 return '%s(%r)' % (self.__class__.__name__, str(self))
268 def __setattr__(self, name, value):
269 raise TypeError('UUID objects are immutable')
271 def __str__(self):
272 hex = '%032x' % self.int
273 return '%s-%s-%s-%s-%s' % (
274 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
276 @property
277 def bytes(self):
278 return self.int.to_bytes(16, 'big')
280 @property
281 def bytes_le(self):
282 bytes = self.bytes
283 return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] +
284 bytes[8:])
286 @property
287 def fields(self):
288 return (self.time_low, self.time_mid, self.time_hi_version,
289 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
291 @property
292 def time_low(self):
293 return self.int >> 96
295 @property
296 def time_mid(self):
297 return (self.int >> 80) & 0xffff
299 @property
300 def time_hi_version(self):
301 return (self.int >> 64) & 0xffff
303 @property
304 def clock_seq_hi_variant(self):
305 return (self.int >> 56) & 0xff
307 @property
308 def clock_seq_low(self):
309 return (self.int >> 48) & 0xff
311 @property
312 def time(self):
313 return (((self.time_hi_version & 0x0fff) << 48) |
314 (self.time_mid << 32) | self.time_low)
316 @property
317 def clock_seq(self):
318 return (((self.clock_seq_hi_variant & 0x3f) << 8) |
319 self.clock_seq_low)
321 @property
322 def node(self):
323 return self.int & 0xffffffffffff
325 @property
326 def hex(self):
327 return '%032x' % self.int
329 @property
330 def urn(self):
331 return 'urn:uuid:' + str(self)
333 @property
334 def variant(self):
335 if not self.int & (0x8000 << 48):
336 return RESERVED_NCS
337 elif not self.int & (0x4000 << 48):
338 return RFC_4122
339 elif not self.int & (0x2000 << 48):
340 return RESERVED_MICROSOFT
341 else:
342 return RESERVED_FUTURE
344 @property
345 def version(self):
346 # The version bits are only meaningful for RFC 4122 UUIDs.
347 if self.variant == RFC_4122:
348 return int((self.int >> 76) & 0xf)
350def _popen(command, *args):
351 import os, shutil, subprocess
352 executable = shutil.which(command)
353 if executable is None:
354 path = os.pathsep.join(('/sbin', '/usr/sbin'))
355 executable = shutil.which(command, path=path)
356 if executable is None:
357 return None
358 # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
359 # on stderr (Note: we don't have an example where the words we search
360 # for are actually localized, but in theory some system could do so.)
361 env = dict(os.environ)
362 env['LC_ALL'] = 'C'
363 proc = subprocess.Popen((executable,) + args,
364 stdout=subprocess.PIPE,
365 stderr=subprocess.DEVNULL,
366 env=env)
367 return proc
369# For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
370# bit of the first octet signifies whether the MAC address is universally (0)
371# or locally (1) administered. Network cards from hardware manufacturers will
372# always be universally administered to guarantee global uniqueness of the MAC
373# address, but any particular machine may have other interfaces which are
374# locally administered. An example of the latter is the bridge interface to
375# the Touch Bar on MacBook Pros.
376#
377# This bit works out to be the 42nd bit counting from 1 being the least
378# significant, or 1<<41. We'll prefer universally administered MAC addresses
379# over locally administered ones since the former are globally unique, but
380# we'll return the first of the latter found if that's all the machine has.
381#
382# See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
384def _is_universal(mac):
385 return not (mac & (1 << 41))
387def _find_mac(command, args, hw_identifiers, get_index):
388 first_local_mac = None
389 try:
390 proc = _popen(command, *args.split())
391 if not proc:
392 return None
393 with proc:
394 for line in proc.stdout:
395 words = line.lower().rstrip().split()
396 for i in range(len(words)):
397 if words[i] in hw_identifiers:
398 try:
399 word = words[get_index(i)]
400 mac = int(word.replace(b':', b''), 16)
401 if _is_universal(mac):
402 return mac
403 first_local_mac = first_local_mac or mac
404 except (ValueError, IndexError):
405 # Virtual interfaces, such as those provided by
406 # VPNs, do not have a colon-delimited MAC address
407 # as expected, but a 16-byte HWAddr separated by
408 # dashes. These should be ignored in favor of a
409 # real MAC address
410 pass
411 except OSError:
412 pass
413 return first_local_mac or None
415def _ifconfig_getnode():
416 """Get the hardware address on Unix by running ifconfig."""
417 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
418 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
419 for args in ('', '-a', '-av'):
420 mac = _find_mac('ifconfig', args, keywords, lambda i: i+1)
421 if mac:
422 return mac
423 return None
425def _ip_getnode():
426 """Get the hardware address on Unix by running ip."""
427 # This works on Linux with iproute2.
428 mac = _find_mac('ip', 'link', [b'link/ether'], lambda i: i+1)
429 if mac:
430 return mac
431 return None
433def _arp_getnode():
434 """Get the hardware address on Unix by running arp."""
435 import os, socket
436 try:
437 ip_addr = socket.gethostbyname(socket.gethostname())
438 except OSError:
439 return None
441 # Try getting the MAC addr from arp based on our IP address (Solaris).
442 mac = _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
443 if mac:
444 return mac
446 # This works on OpenBSD
447 mac = _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
448 if mac:
449 return mac
451 # This works on Linux, FreeBSD and NetBSD
452 mac = _find_mac('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
453 lambda i: i+2)
454 # Return None instead of 0.
455 if mac:
456 return mac
457 return None
459def _lanscan_getnode():
460 """Get the hardware address on Unix by running lanscan."""
461 # This might work on HP-UX.
462 return _find_mac('lanscan', '-ai', [b'lan0'], lambda i: 0)
464def _netstat_getnode():
465 """Get the hardware address on Unix by running netstat."""
466 # This might work on AIX, Tru64 UNIX.
467 first_local_mac = None
468 try:
469 proc = _popen('netstat', '-ia')
470 if not proc:
471 return None
472 with proc:
473 words = proc.stdout.readline().rstrip().split()
474 try:
475 i = words.index(b'Address')
476 except ValueError:
477 return None
478 for line in proc.stdout:
479 try:
480 words = line.rstrip().split()
481 word = words[i]
482 if len(word) == 17 and word.count(b':') == 5:
483 mac = int(word.replace(b':', b''), 16)
484 if _is_universal(mac):
485 return mac
486 first_local_mac = first_local_mac or mac
487 except (ValueError, IndexError):
488 pass
489 except OSError:
490 pass
491 return first_local_mac or None
493def _ipconfig_getnode():
494 """Get the hardware address on Windows by running ipconfig.exe."""
495 import os, re, subprocess
496 first_local_mac = None
497 dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
498 try:
499 import ctypes
500 buffer = ctypes.create_string_buffer(300)
501 ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
502 dirs.insert(0, buffer.value.decode('mbcs'))
503 except:
504 pass
505 for dir in dirs:
506 try:
507 proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'],
508 stdout=subprocess.PIPE,
509 encoding="oem")
510 except OSError:
511 continue
512 with proc:
513 for line in proc.stdout:
514 value = line.split(':')[-1].strip().lower()
515 if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
516 mac = int(value.replace('-', ''), 16)
517 if _is_universal(mac):
518 return mac
519 first_local_mac = first_local_mac or mac
520 return first_local_mac or None
522def _netbios_getnode():
523 """Get the hardware address on Windows using NetBIOS calls.
524 See http://support.microsoft.com/kb/118623 for details."""
525 import win32wnet, netbios
526 first_local_mac = None
527 ncb = netbios.NCB()
528 ncb.Command = netbios.NCBENUM
529 ncb.Buffer = adapters = netbios.LANA_ENUM()
530 adapters._pack()
531 if win32wnet.Netbios(ncb) != 0:
532 return None
533 adapters._unpack()
534 for i in range(adapters.length):
535 ncb.Reset()
536 ncb.Command = netbios.NCBRESET
537 ncb.Lana_num = ord(adapters.lana[i])
538 if win32wnet.Netbios(ncb) != 0:
539 continue
540 ncb.Reset()
541 ncb.Command = netbios.NCBASTAT
542 ncb.Lana_num = ord(adapters.lana[i])
543 ncb.Callname = '*'.ljust(16)
544 ncb.Buffer = status = netbios.ADAPTER_STATUS()
545 if win32wnet.Netbios(ncb) != 0:
546 continue
547 status._unpack()
548 bytes = status.adapter_address[:6]
549 if len(bytes) != 6:
550 continue
551 mac = int.from_bytes(bytes, 'big')
552 if _is_universal(mac):
553 return mac
554 first_local_mac = first_local_mac or mac
555 return first_local_mac or None
558_generate_time_safe = _UuidCreate = None
559_has_uuid_generate_time_safe = None
561# Import optional C extension at toplevel, to help disabling it when testing
562try:
563 import _uuid
564except ImportError:
565 _uuid = None
568def _load_system_functions():
569 """
570 Try to load platform-specific functions for generating uuids.
571 """
572 global _generate_time_safe, _UuidCreate, _has_uuid_generate_time_safe
574 if _has_uuid_generate_time_safe is not None:
575 return
577 _has_uuid_generate_time_safe = False
579 if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
580 # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
581 # in issue #8621 the function generates the same sequence of values
582 # in the parent process and all children created using fork (unless
583 # those children use exec as well).
584 #
585 # Assume that the uuid_generate functions are broken from 10.5 onward,
586 # the test can be adjusted when a later version is fixed.
587 pass
588 elif _uuid is not None:
589 _generate_time_safe = _uuid.generate_time_safe
590 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
591 return
593 try:
594 # If we couldn't find an extension module, try ctypes to find
595 # system routines for UUID generation.
596 # Thanks to Thomas Heller for ctypes and for his help with its use here.
597 import ctypes
598 import ctypes.util
600 # The uuid_generate_* routines are provided by libuuid on at least
601 # Linux and FreeBSD, and provided by libc on Mac OS X.
602 _libnames = ['uuid']
603 if not sys.platform.startswith('win'):
604 _libnames.append('c')
605 for libname in _libnames:
606 try:
607 lib = ctypes.CDLL(ctypes.util.find_library(libname))
608 except Exception: # pragma: nocover
609 continue
610 # Try to find the safe variety first.
611 if hasattr(lib, 'uuid_generate_time_safe'):
612 _uuid_generate_time_safe = lib.uuid_generate_time_safe
613 # int uuid_generate_time_safe(uuid_t out);
614 def _generate_time_safe():
615 _buffer = ctypes.create_string_buffer(16)
616 res = _uuid_generate_time_safe(_buffer)
617 return bytes(_buffer.raw), res
618 _has_uuid_generate_time_safe = True
619 break
621 elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
622 _uuid_generate_time = lib.uuid_generate_time
623 # void uuid_generate_time(uuid_t out);
624 _uuid_generate_time.restype = None
625 def _generate_time_safe():
626 _buffer = ctypes.create_string_buffer(16)
627 _uuid_generate_time(_buffer)
628 return bytes(_buffer.raw), None
629 break
631 # On Windows prior to 2000, UuidCreate gives a UUID containing the
632 # hardware address. On Windows 2000 and later, UuidCreate makes a
633 # random UUID and UuidCreateSequential gives a UUID containing the
634 # hardware address. These routines are provided by the RPC runtime.
635 # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
636 # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
637 # to bear any relationship to the MAC address of any network device
638 # on the box.
639 try:
640 lib = ctypes.windll.rpcrt4
641 except:
642 lib = None
643 _UuidCreate = getattr(lib, 'UuidCreateSequential',
644 getattr(lib, 'UuidCreate', None))
646 except Exception as exc:
647 import warnings
648 warnings.warn(f"Could not find fallback ctypes uuid functions: {exc}",
649 ImportWarning)
652def _unix_getnode():
653 """Get the hardware address on Unix using the _uuid extension module
654 or ctypes."""
655 _load_system_functions()
656 uuid_time, _ = _generate_time_safe()
657 return UUID(bytes=uuid_time).node
659def _windll_getnode():
660 """Get the hardware address on Windows using ctypes."""
661 import ctypes
662 _load_system_functions()
663 _buffer = ctypes.create_string_buffer(16)
664 if _UuidCreate(_buffer) == 0:
665 return UUID(bytes=bytes_(_buffer.raw)).node
667def _random_getnode():
668 """Get a random node ID."""
669 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
670 # pseudo-randomly generated value may be used; see Section 4.5. The
671 # multicast bit must be set in such addresses, in order that they will
672 # never conflict with addresses obtained from network cards."
673 #
674 # The "multicast bit" of a MAC address is defined to be "the least
675 # significant bit of the first octet". This works out to be the 41st bit
676 # counting from 1 being the least significant bit, or 1<<40.
677 #
678 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
679 import random
680 return random.getrandbits(48) | (1 << 40)
683# _OS_GETTERS, when known, are targeted for a specific OS or platform.
684# The order is by 'common practice' on the specified platform.
685# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
686# which, when successful, means none of these "external" methods are called.
687# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
688# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
689if _LINUX:
690 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
691elif _DARWIN:
692 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
693elif _WINDOWS:
694 _OS_GETTERS = [_netbios_getnode, _ipconfig_getnode]
695elif _AIX:
696 _OS_GETTERS = [_netstat_getnode]
697else:
698 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
699 _netstat_getnode, _lanscan_getnode]
700if os.name == 'posix':
701 _GETTERS = [_unix_getnode] + _OS_GETTERS
702elif os.name == 'nt':
703 _GETTERS = [_windll_getnode] + _OS_GETTERS
704else:
705 _GETTERS = _OS_GETTERS
707_node = None
709def getnode(*, getters=None):
710 """Get the hardware address as a 48-bit positive integer.
712 The first time this runs, it may launch a separate program, which could
713 be quite slow. If all attempts to obtain the hardware address fail, we
714 choose a random 48-bit number with its eighth bit set to 1 as recommended
715 in RFC 4122.
716 """
717 global _node
718 if _node is not None:
719 return _node
721 for getter in _GETTERS + [_random_getnode]:
722 try:
723 _node = getter()
724 except:
725 continue
726 if (_node is not None) and (0 <= _node < (1 << 48)):
727 return _node
728 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
731_last_timestamp = None
733def uuid1(node=None, clock_seq=None):
734 """Generate a UUID from a host ID, sequence number, and the current time.
735 If 'node' is not given, getnode() is used to obtain the hardware
736 address. If 'clock_seq' is given, it is used as the sequence number;
737 otherwise a random 14-bit sequence number is chosen."""
739 # When the system provides a version-1 UUID generator, use it (but don't
740 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
741 _load_system_functions()
742 if _generate_time_safe is not None and node is clock_seq is None:
743 uuid_time, safely_generated = _generate_time_safe()
744 try:
745 is_safe = SafeUUID(safely_generated)
746 except ValueError:
747 is_safe = SafeUUID.unknown
748 return UUID(bytes=uuid_time, is_safe=is_safe)
750 global _last_timestamp
751 import time
752 nanoseconds = time.time_ns()
753 # 0x01b21dd213814000 is the number of 100-ns intervals between the
754 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
755 timestamp = nanoseconds // 100 + 0x01b21dd213814000
756 if _last_timestamp is not None and timestamp <= _last_timestamp:
757 timestamp = _last_timestamp + 1
758 _last_timestamp = timestamp
759 if clock_seq is None:
760 import random
761 clock_seq = random.getrandbits(14) # instead of stable storage
762 time_low = timestamp & 0xffffffff
763 time_mid = (timestamp >> 32) & 0xffff
764 time_hi_version = (timestamp >> 48) & 0x0fff
765 clock_seq_low = clock_seq & 0xff
766 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
767 if node is None:
768 node = getnode()
769 return UUID(fields=(time_low, time_mid, time_hi_version,
770 clock_seq_hi_variant, clock_seq_low, node), version=1)
772def uuid3(namespace, name):
773 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
774 from hashlib import md5
775 hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()
776 return UUID(bytes=hash[:16], version=3)
778def uuid4():
779 """Generate a random UUID."""
780 return UUID(bytes=os.urandom(16), version=4)
782def uuid5(namespace, name):
783 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
784 from hashlib import sha1
785 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
786 return UUID(bytes=hash[:16], version=5)
788# The following standard UUIDs are for use with uuid3() or uuid5().
790NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
791NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
792NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
793NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')