blob: 67da88560cfb1235a720011e35f033c402799617 [file] [log] [blame]
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001r"""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
Georg Brandl1d523e12009-12-19 18:23:28 +000016 >>> uuid.uuid1() # doctest: +SKIP
Thomas Wouters0e3f5912006-08-11 14:57:12 +000017 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
Georg Brandl1d523e12009-12-19 18:23:28 +000024 >>> uuid.uuid4() # doctest: +SKIP
Thomas Wouters0e3f5912006-08-11 14:57:12 +000025 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
Guido van Rossum65b6a802007-07-09 14:03:08 +000040 b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041
42 # make a UUID from a 16-byte string
43 >>> uuid.UUID(bytes=x.bytes)
44 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
45"""
46
Benjamin Peterson788cb522015-10-29 20:38:04 -070047import os
Antoine Pitroua106aec2017-09-28 23:03:06 +020048import sys
Benjamin Peterson788cb522015-10-29 20:38:04 -070049
Ethan Furmana02cb472021-04-21 10:20:44 -070050from enum import Enum, _simple_enum
Barry Warsaw8c130d72017-02-18 15:45:49 -050051
52
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
Thomas Wouters0e3f5912006-08-11 14:57:12 +000054
Michael Felt3a1d50e2019-06-15 17:52:29 +020055# The recognized platforms - known behaviors
Steve Dowerbf2f76e2020-07-22 00:15:47 +010056if 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'
Michael Felt3a1d50e2019-06-15 17:52:29 +020063
Michael Felt0bcbfa42019-09-26 20:43:15 +010064_MAC_DELIM = b':'
65_MAC_OMITS_LEADING_ZEROES = False
66if _AIX:
67 _MAC_DELIM = b'.'
68 _MAC_OMITS_LEADING_ZEROES = True
69
Thomas Wouters0e3f5912006-08-11 14:57:12 +000070RESERVED_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
Guido van Rossum65b6a802007-07-09 14:03:08 +000074int_ = int # The built-in int type
75bytes_ = bytes # The built-in bytes type
Guido van Rossume2a383d2007-01-15 16:59:06 +000076
Barry Warsaw8c130d72017-02-18 15:45:49 -050077
Ethan Furmana02cb472021-04-21 10:20:44 -070078@_simple_enum(Enum)
79class SafeUUID:
Barry Warsaw8c130d72017-02-18 15:45:49 -050080 safe = 0
81 unsafe = -1
82 unknown = None
83
84
85class UUID:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000086 """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
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000090 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'.
Thomas Wouters0e3f5912006-08-11 14:57:12 +000097
98 UUIDs have these read-only attributes:
99
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000100 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)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000105
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)
Barry Warsaw8c130d72017-02-18 15:45:49 -0500131
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).
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000135 """
136
David Hf1d8e7c2019-01-17 13:16:51 +0100137 __slots__ = ('int', 'is_safe', '__weakref__')
Tal Einat3e2b29d2018-09-06 14:34:25 +0300138
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000139 def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
Barry Warsaw8c130d72017-02-18 15:45:49 -0500140 int=None, version=None,
141 *, is_safe=SafeUUID.unknown):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000142 r"""Create a UUID from either a string of 32 hexadecimal digits,
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000143 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
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000145 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)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000156 UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
157 '\x12\x34\x56\x78\x12\x34\x56\x78')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000158 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
159 UUID(int=0x12345678123456781234567812345678)
160
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000161 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'.
Barry Warsaw8c130d72017-02-18 15:45:49 -0500165
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).
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000169 """
170
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000171 if [hex, bytes, bytes_le, fields, int].count(None) != 4:
Berker Peksagd02eb8a2016-03-20 16:49:10 +0200172 raise TypeError('one of the hex, bytes, bytes_le, fields, '
173 'or int arguments must be given')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000174 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')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000179 int = int_(hex, 16)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000180 if bytes_le is not None:
181 if len(bytes_le) != 16:
182 raise ValueError('bytes_le is not a 16-char string')
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300183 bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
184 bytes_le[8-1:6-1:-1] + bytes_le[8:])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000185 if bytes is not None:
186 if len(bytes) != 16:
187 raise ValueError('bytes is not a 16-char string')
Guido van Rossum65b6a802007-07-09 14:03:08 +0000188 assert isinstance(bytes, bytes_), repr(bytes)
Philip Jenvey1221f6b2013-08-29 18:33:50 -0700189 int = int_.from_bytes(bytes, byteorder='big')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000190 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
Guido van Rossume2a383d2007-01-15 16:59:06 +0000195 if not 0 <= time_low < 1<<32:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000196 raise ValueError('field 1 out of range (need a 32-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000197 if not 0 <= time_mid < 1<<16:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000198 raise ValueError('field 2 out of range (need a 16-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000199 if not 0 <= time_hi_version < 1<<16:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000200 raise ValueError('field 3 out of range (need a 16-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000201 if not 0 <= clock_seq_hi_variant < 1<<8:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000202 raise ValueError('field 4 out of range (need an 8-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000203 if not 0 <= clock_seq_low < 1<<8:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000204 raise ValueError('field 5 out of range (need an 8-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000205 if not 0 <= node < 1<<48:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000206 raise ValueError('field 6 out of range (need a 48-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000207 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)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000210 if int is not None:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000211 if not 0 <= int < 1<<128:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000212 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.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000217 int &= ~(0xc000 << 48)
218 int |= 0x8000 << 48
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000219 # Set the version number.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000220 int &= ~(0xf000 << 64)
221 int |= version << 76
Tal Einat3e2b29d2018-09-06 14:34:25 +0300222 object.__setattr__(self, 'int', int)
223 object.__setattr__(self, 'is_safe', is_safe)
224
225 def __getstate__(self):
Tal Einat54752532018-09-10 16:11:04 +0300226 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
Tal Einat3e2b29d2018-09-06 14:34:25 +0300231 return d
232
233 def __setstate__(self, state):
Tal Einat54752532018-09-10 16:11:04 +0300234 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)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000239
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000240 def __eq__(self, other):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000241 if isinstance(other, UUID):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000242 return self.int == other.int
243 return NotImplemented
244
Guido van Rossum65b6a802007-07-09 14:03:08 +0000245 # Q. What's the value of being able to sort UUIDs?
246 # A. Use them as keys in a B-Tree or similar mapping.
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000247
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
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000266 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):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300275 return '%s(%r)' % (self.__class__.__name__, str(self))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000276
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
Guido van Rossum65b6a802007-07-09 14:03:08 +0000285 @property
286 def bytes(self):
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300287 return self.int.to_bytes(16, 'big')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000288
Guido van Rossum65b6a802007-07-09 14:03:08 +0000289 @property
290 def bytes_le(self):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000291 bytes = self.bytes
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300292 return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] +
Guido van Rossum65b6a802007-07-09 14:03:08 +0000293 bytes[8:])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000294
Guido van Rossum65b6a802007-07-09 14:03:08 +0000295 @property
296 def fields(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000297 return (self.time_low, self.time_mid, self.time_hi_version,
298 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
299
Guido van Rossum65b6a802007-07-09 14:03:08 +0000300 @property
301 def time_low(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000302 return self.int >> 96
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000303
Guido van Rossum65b6a802007-07-09 14:03:08 +0000304 @property
305 def time_mid(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000306 return (self.int >> 80) & 0xffff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000307
Guido van Rossum65b6a802007-07-09 14:03:08 +0000308 @property
309 def time_hi_version(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000310 return (self.int >> 64) & 0xffff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000311
Guido van Rossum65b6a802007-07-09 14:03:08 +0000312 @property
313 def clock_seq_hi_variant(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000314 return (self.int >> 56) & 0xff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000315
Guido van Rossum65b6a802007-07-09 14:03:08 +0000316 @property
317 def clock_seq_low(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000318 return (self.int >> 48) & 0xff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000319
Guido van Rossum65b6a802007-07-09 14:03:08 +0000320 @property
321 def time(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000322 return (((self.time_hi_version & 0x0fff) << 48) |
323 (self.time_mid << 32) | self.time_low)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000324
Guido van Rossum65b6a802007-07-09 14:03:08 +0000325 @property
326 def clock_seq(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000327 return (((self.clock_seq_hi_variant & 0x3f) << 8) |
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000328 self.clock_seq_low)
329
Guido van Rossum65b6a802007-07-09 14:03:08 +0000330 @property
331 def node(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000332 return self.int & 0xffffffffffff
333
Guido van Rossum65b6a802007-07-09 14:03:08 +0000334 @property
335 def hex(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000336 return '%032x' % self.int
337
Guido van Rossum65b6a802007-07-09 14:03:08 +0000338 @property
339 def urn(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000340 return 'urn:uuid:' + str(self)
341
Guido van Rossum65b6a802007-07-09 14:03:08 +0000342 @property
343 def variant(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000344 if not self.int & (0x8000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000345 return RESERVED_NCS
Guido van Rossume2a383d2007-01-15 16:59:06 +0000346 elif not self.int & (0x4000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000347 return RFC_4122
Guido van Rossume2a383d2007-01-15 16:59:06 +0000348 elif not self.int & (0x2000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000349 return RESERVED_MICROSOFT
350 else:
351 return RESERVED_FUTURE
352
Guido van Rossum65b6a802007-07-09 14:03:08 +0000353 @property
354 def version(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000355 # The version bits are only meaningful for RFC 4122 UUIDs.
356 if self.variant == RFC_4122:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000357 return int((self.int >> 76) & 0xf)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000358
Michael Felt0bcbfa42019-09-26 20:43:15 +0100359
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))
R David Murray4be1e242013-12-17 21:13:16 -0500367 if executable is None:
368 return None
Michael Felt0bcbfa42019-09-26 20:43:15 +0100369 # 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 proc = subprocess.Popen((executable,) + args,
375 stdout=subprocess.PIPE,
376 stderr=subprocess.DEVNULL,
377 env=env)
378 if not proc:
379 return None
380 stdout, stderr = proc.communicate()
381 return io.BytesIO(stdout)
382 except (OSError, subprocess.SubprocessError):
383 return None
384
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000385
Barry Warsaw23df2d12017-11-28 17:26:04 -0500386# For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
387# bit of the first octet signifies whether the MAC address is universally (0)
388# or locally (1) administered. Network cards from hardware manufacturers will
389# always be universally administered to guarantee global uniqueness of the MAC
390# address, but any particular machine may have other interfaces which are
391# locally administered. An example of the latter is the bridge interface to
392# the Touch Bar on MacBook Pros.
393#
394# This bit works out to be the 42nd bit counting from 1 being the least
395# significant, or 1<<41. We'll prefer universally administered MAC addresses
396# over locally administered ones since the former are globally unique, but
397# we'll return the first of the latter found if that's all the machine has.
398#
399# See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
400
401def _is_universal(mac):
402 return not (mac & (1 << 41))
403
Michael Felt0bcbfa42019-09-26 20:43:15 +0100404
405def _find_mac_near_keyword(command, args, keywords, get_word_index):
406 """Searches a command's output for a MAC address near a keyword.
407
408 Each line of words in the output is case-insensitively searched for
409 any of the given keywords. Upon a match, get_word_index is invoked
410 to pick a word from the line, given the index of the match. For
411 example, lambda i: 0 would get the first word on the line, while
412 lambda i: i - 1 would get the word preceding the keyword.
413 """
414 stdout = _get_command_stdout(command, args)
415 if stdout is None:
416 return None
417
Barry Warsaw23df2d12017-11-28 17:26:04 -0500418 first_local_mac = None
Michael Felt0bcbfa42019-09-26 20:43:15 +0100419 for line in stdout:
420 words = line.lower().rstrip().split()
421 for i in range(len(words)):
422 if words[i] in keywords:
423 try:
424 word = words[get_word_index(i)]
425 mac = int(word.replace(_MAC_DELIM, b''), 16)
426 except (ValueError, IndexError):
427 # Virtual interfaces, such as those provided by
428 # VPNs, do not have a colon-delimited MAC address
429 # as expected, but a 16-byte HWAddr separated by
430 # dashes. These should be ignored in favor of a
431 # real MAC address
432 pass
433 else:
434 if _is_universal(mac):
435 return mac
436 first_local_mac = first_local_mac or mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500437 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000438
Michael Felt0bcbfa42019-09-26 20:43:15 +0100439
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100440def _parse_mac(word):
441 # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
442 # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8').
443 #
444 # Virtual interfaces, such as those provided by VPNs, do not have a
445 # colon-delimited MAC address as expected, but a 16-byte HWAddr separated
446 # by dashes. These should be ignored in favor of a real MAC address
447 parts = word.split(_MAC_DELIM)
448 if len(parts) != 6:
449 return
450 if _MAC_OMITS_LEADING_ZEROES:
451 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
452 # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
453 # not
454 # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
455 if not all(1 <= len(part) <= 2 for part in parts):
456 return
457 hexstr = b''.join(part.rjust(2, b'0') for part in parts)
458 else:
459 if not all(len(part) == 2 for part in parts):
460 return
461 hexstr = b''.join(parts)
462 try:
463 return int(hexstr, 16)
464 except ValueError:
465 return
466
467
Michael Felt0bcbfa42019-09-26 20:43:15 +0100468def _find_mac_under_heading(command, args, heading):
469 """Looks for a MAC address under a heading in a command's output.
470
471 The first line of words in the output is searched for the given
472 heading. Words at the same word index as the heading in subsequent
473 lines are then examined to see if they look like MAC addresses.
474 """
475 stdout = _get_command_stdout(command, args)
476 if stdout is None:
477 return None
478
479 keywords = stdout.readline().rstrip().split()
480 try:
481 column_index = keywords.index(heading)
482 except ValueError:
483 return None
484
485 first_local_mac = None
486 for line in stdout:
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100487 words = line.rstrip().split()
Michael Felt0bcbfa42019-09-26 20:43:15 +0100488 try:
Michael Felt0bcbfa42019-09-26 20:43:15 +0100489 word = words[column_index]
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100490 except IndexError:
491 continue
492
493 mac = _parse_mac(word)
494 if mac is None:
495 continue
496 if _is_universal(mac):
497 return mac
498 if first_local_mac is None:
499 first_local_mac = mac
500
501 return first_local_mac
Michael Felt0bcbfa42019-09-26 20:43:15 +0100502
503
504# The following functions call external programs to 'get' a macaddr value to
505# be used as basis for an uuid
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000506def _ifconfig_getnode():
507 """Get the hardware address on Unix by running ifconfig."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000508 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200509 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000510 for args in ('', '-a', '-av'):
Michael Felt0bcbfa42019-09-26 20:43:15 +0100511 mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000512 if mac:
513 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500514 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000515
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200516def _ip_getnode():
517 """Get the hardware address on Unix by running ip."""
518 # This works on Linux with iproute2.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100519 mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1)
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200520 if mac:
521 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500522 return None
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200523
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200524def _arp_getnode():
525 """Get the hardware address on Unix by running arp."""
526 import os, socket
Serhiy Storchaka525d5ae2014-11-21 21:55:39 +0200527 try:
528 ip_addr = socket.gethostbyname(socket.gethostname())
529 except OSError:
530 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000531
532 # Try getting the MAC addr from arp based on our IP address (Solaris).
Michael Felt0bcbfa42019-09-26 20:43:15 +0100533 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200534 if mac:
535 return mac
536
537 # This works on OpenBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100538 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200539 if mac:
540 return mac
541
542 # This works on Linux, FreeBSD and NetBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100543 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200544 lambda i: i+2)
Barry Warsaw23df2d12017-11-28 17:26:04 -0500545 # Return None instead of 0.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200546 if mac:
547 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500548 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000549
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200550def _lanscan_getnode():
551 """Get the hardware address on Unix by running lanscan."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000552 # This might work on HP-UX.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100553 return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000554
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200555def _netstat_getnode():
556 """Get the hardware address on Unix by running netstat."""
Michael Felt0bcbfa42019-09-26 20:43:15 +0100557 # This works on AIX and might work on Tru64 UNIX.
558 return _find_mac_under_heading('netstat', '-ian', b'Address')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000559
560def _ipconfig_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100561 """[DEPRECATED] Get the hardware address on Windows."""
562 # bpo-40501: UuidCreateSequential() is now the only supported approach
563 return _windll_getnode()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000564
565def _netbios_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100566 """[DEPRECATED] Get the hardware address on Windows."""
567 # bpo-40501: UuidCreateSequential() is now the only supported approach
568 return _windll_getnode()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000569
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000570
Antoine Pitroua106aec2017-09-28 23:03:06 +0200571# Import optional C extension at toplevel, to help disabling it when testing
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000572try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200573 import _uuid
Steve Dowerd6b727e2020-05-12 23:32:32 +0100574 _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
575 _UuidCreate = getattr(_uuid, "UuidCreate", None)
576 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
Antoine Pitroua106aec2017-09-28 23:03:06 +0200577except ImportError:
578 _uuid = None
Steve Dowerd6b727e2020-05-12 23:32:32 +0100579 _generate_time_safe = None
580 _UuidCreate = None
581 _has_uuid_generate_time_safe = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000582
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000583
Antoine Pitroua106aec2017-09-28 23:03:06 +0200584def _load_system_functions():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100585 """[DEPRECATED] Platform-specific functions loaded at import time"""
Antoine Pitroua106aec2017-09-28 23:03:06 +0200586
587
588def _unix_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100589 """Get the hardware address on Unix using the _uuid extension module."""
590 if _generate_time_safe:
591 uuid_time, _ = _generate_time_safe()
592 return UUID(bytes=uuid_time).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000593
594def _windll_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100595 """Get the hardware address on Windows using the _uuid extension module."""
596 if _UuidCreate:
597 uuid_bytes = _UuidCreate()
598 return UUID(bytes_le=uuid_bytes).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000599
600def _random_getnode():
Barry Warsaw23df2d12017-11-28 17:26:04 -0500601 """Get a random node ID."""
602 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
603 # pseudo-randomly generated value may be used; see Section 4.5. The
604 # multicast bit must be set in such addresses, in order that they will
605 # never conflict with addresses obtained from network cards."
606 #
607 # The "multicast bit" of a MAC address is defined to be "the least
608 # significant bit of the first octet". This works out to be the 41st bit
609 # counting from 1 being the least significant bit, or 1<<40.
610 #
611 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000612 import random
Barry Warsaw23df2d12017-11-28 17:26:04 -0500613 return random.getrandbits(48) | (1 << 40)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000614
Antoine Pitroua106aec2017-09-28 23:03:06 +0200615
Min ho Kim39d87b52019-08-31 06:21:19 +1000616# _OS_GETTERS, when known, are targeted for a specific OS or platform.
Michael Felt3a1d50e2019-06-15 17:52:29 +0200617# The order is by 'common practice' on the specified platform.
618# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
619# which, when successful, means none of these "external" methods are called.
620# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
621# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
622if _LINUX:
623 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
Steve Dowerbf2f76e2020-07-22 00:15:47 +0100624elif sys.platform == 'darwin':
Michael Felt3a1d50e2019-06-15 17:52:29 +0200625 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
Steve Dowerbf2f76e2020-07-22 00:15:47 +0100626elif sys.platform == 'win32':
Steve Dowerd6b727e2020-05-12 23:32:32 +0100627 # bpo-40201: _windll_getnode will always succeed, so these are not needed
628 _OS_GETTERS = []
Michael Felt3a1d50e2019-06-15 17:52:29 +0200629elif _AIX:
630 _OS_GETTERS = [_netstat_getnode]
631else:
632 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
633 _netstat_getnode, _lanscan_getnode]
634if os.name == 'posix':
635 _GETTERS = [_unix_getnode] + _OS_GETTERS
636elif os.name == 'nt':
637 _GETTERS = [_windll_getnode] + _OS_GETTERS
638else:
639 _GETTERS = _OS_GETTERS
640
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000641_node = None
642
Shantanu8b6f6522020-02-05 12:43:09 -0800643def getnode():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000644 """Get the hardware address as a 48-bit positive integer.
645
646 The first time this runs, it may launch a separate program, which could
647 be quite slow. If all attempts to obtain the hardware address fail, we
648 choose a random 48-bit number with its eighth bit set to 1 as recommended
649 in RFC 4122.
650 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000651 global _node
652 if _node is not None:
653 return _node
654
Michael Felt3a1d50e2019-06-15 17:52:29 +0200655 for getter in _GETTERS + [_random_getnode]:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000656 try:
657 _node = getter()
658 except:
659 continue
Bo Bayles6b273f72018-01-23 19:11:44 -0600660 if (_node is not None) and (0 <= _node < (1 << 48)):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000661 return _node
Bo Bayles6b273f72018-01-23 19:11:44 -0600662 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000663
Antoine Pitroua106aec2017-09-28 23:03:06 +0200664
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000665_last_timestamp = None
666
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000667def uuid1(node=None, clock_seq=None):
668 """Generate a UUID from a host ID, sequence number, and the current time.
669 If 'node' is not given, getnode() is used to obtain the hardware
670 address. If 'clock_seq' is given, it is used as the sequence number;
671 otherwise a random 14-bit sequence number is chosen."""
672
673 # When the system provides a version-1 UUID generator, use it (but don't
674 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
Antoine Pitroua106aec2017-09-28 23:03:06 +0200675 if _generate_time_safe is not None and node is clock_seq is None:
676 uuid_time, safely_generated = _generate_time_safe()
Barry Warsaw8c130d72017-02-18 15:45:49 -0500677 try:
678 is_safe = SafeUUID(safely_generated)
679 except ValueError:
680 is_safe = SafeUUID.unknown
Antoine Pitroua106aec2017-09-28 23:03:06 +0200681 return UUID(bytes=uuid_time, is_safe=is_safe)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000682
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000683 global _last_timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000684 import time
Victor Stinner62a68b72018-12-18 11:45:13 +0100685 nanoseconds = time.time_ns()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000686 # 0x01b21dd213814000 is the number of 100-ns intervals between the
687 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
Victor Stinner62a68b72018-12-18 11:45:13 +0100688 timestamp = nanoseconds // 100 + 0x01b21dd213814000
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000689 if _last_timestamp is not None and timestamp <= _last_timestamp:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000690 timestamp = _last_timestamp + 1
691 _last_timestamp = timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000692 if clock_seq is None:
693 import random
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300694 clock_seq = random.getrandbits(14) # instead of stable storage
Guido van Rossume2a383d2007-01-15 16:59:06 +0000695 time_low = timestamp & 0xffffffff
696 time_mid = (timestamp >> 32) & 0xffff
697 time_hi_version = (timestamp >> 48) & 0x0fff
698 clock_seq_low = clock_seq & 0xff
699 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000700 if node is None:
701 node = getnode()
702 return UUID(fields=(time_low, time_mid, time_hi_version,
703 clock_seq_hi_variant, clock_seq_low, node), version=1)
704
705def uuid3(namespace, name):
706 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000707 from hashlib import md5
Christian Heimes7cad53e2019-09-13 02:30:00 +0200708 digest = md5(
709 namespace.bytes + bytes(name, "utf-8"),
710 usedforsecurity=False
711 ).digest()
712 return UUID(bytes=digest[:16], version=3)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000713
714def uuid4():
715 """Generate a random UUID."""
Benjamin Peterson788cb522015-10-29 20:38:04 -0700716 return UUID(bytes=os.urandom(16), version=4)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000717
718def uuid5(namespace, name):
719 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000720 from hashlib import sha1
Guido van Rossum65b6a802007-07-09 14:03:08 +0000721 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
Guido van Rossum5ed033b2007-07-09 14:29:40 +0000722 return UUID(bytes=hash[:16], version=5)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000723
724# The following standard UUIDs are for use with uuid3() or uuid5().
725
726NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
727NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
728NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
729NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')