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