xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/uuid.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1r"""UUID objects (universally unique identifiers) according to RFC 4122.
2
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.
6
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.
10
11Typical 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
47import os
48import sys
49
50from enum import Enum, _simple_enum
51
52
53__author__ = 'Ka-Ping Yee <[email protected]>'
54
55# The recognized platforms - known behaviors
56if sys.platform in ('win32', 'darwin'):
57    _AIX = _LINUX = False
58else:
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
66if _AIX:
67    _MAC_DELIM = b'.'
68    _MAC_OMITS_LEADING_ZEROES = True
69
70RESERVED_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
74int_ = int      # The built-in int type
75bytes_ = bytes  # The built-in bytes type
76
77
78@_simple_enum(Enum)
79class SafeUUID:
80    safe = 0
81    unsafe = -1
82    unknown = None
83
84
85class UUID:
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
360def _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
406def _is_universal(mac):
407    return not (mac & (1 << 41))
408
409
410def _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
445def _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
473def _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
511def _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
521def _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
529def _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
557def _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
562def _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
567def _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
572def _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
579try:
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
584except ImportError:
585    _uuid = None
586    _generate_time_safe = None
587    _UuidCreate = None
588    _has_uuid_generate_time_safe = None
589
590
591def _load_system_functions():
592    """[DEPRECATED] Platform-specific functions loaded at import time"""
593
594
595def _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
601def _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
607def _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, ...)
629if _LINUX:
630    _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
631elif sys.platform == 'darwin':
632    _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
633elif sys.platform == 'win32':
634    # bpo-40201: _windll_getnode will always succeed, so these are not needed
635    _OS_GETTERS = []
636elif _AIX:
637    _OS_GETTERS = [_netstat_getnode]
638else:
639    _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
640                   _netstat_getnode, _lanscan_getnode]
641if os.name == 'posix':
642    _GETTERS = [_unix_getnode] + _OS_GETTERS
643elif os.name == 'nt':
644    _GETTERS = [_windll_getnode] + _OS_GETTERS
645else:
646    _GETTERS = _OS_GETTERS
647
648_node = None
649
650def 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
674def 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
712def 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
721def uuid4():
722    """Generate a random UUID."""
723    return UUID(bytes=os.urandom(16), version=4)
724
725def 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
733NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
734NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
735NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
736NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')
737