blob: 9ddce813fc4692fe42f12d1c4e04d26236a69ee7 [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
Michael Felt3a1d50e2019-06-15 17:52:29 +020048import platform
Antoine Pitroua106aec2017-09-28 23:03:06 +020049import sys
Benjamin Peterson788cb522015-10-29 20:38:04 -070050
Barry Warsaw8c130d72017-02-18 15:45:49 -050051from enum import Enum
52
53
Thomas Wouters0e3f5912006-08-11 14:57:12 +000054__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
Thomas Wouters0e3f5912006-08-11 14:57:12 +000055
Michael Felt3a1d50e2019-06-15 17:52:29 +020056# The recognized platforms - known behaviors
57_AIX = platform.system() == 'AIX'
58_DARWIN = platform.system() == 'Darwin'
59_LINUX = platform.system() == 'Linux'
60_WINDOWS = platform.system() == 'Windows'
61
Michael Felt0bcbfa42019-09-26 20:43:15 +010062_MAC_DELIM = b':'
63_MAC_OMITS_LEADING_ZEROES = False
64if _AIX:
65 _MAC_DELIM = b'.'
66 _MAC_OMITS_LEADING_ZEROES = True
67
Thomas Wouters0e3f5912006-08-11 14:57:12 +000068RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
69 'reserved for NCS compatibility', 'specified in RFC 4122',
70 'reserved for Microsoft compatibility', 'reserved for future definition']
71
Guido van Rossum65b6a802007-07-09 14:03:08 +000072int_ = int # The built-in int type
73bytes_ = bytes # The built-in bytes type
Guido van Rossume2a383d2007-01-15 16:59:06 +000074
Barry Warsaw8c130d72017-02-18 15:45:49 -050075
76class SafeUUID(Enum):
77 safe = 0
78 unsafe = -1
79 unknown = None
80
81
82class UUID:
Thomas Wouters0e3f5912006-08-11 14:57:12 +000083 """Instances of the UUID class represent UUIDs as specified in RFC 4122.
84 UUID objects are immutable, hashable, and usable as dictionary keys.
85 Converting a UUID to a string with str() yields something in the form
86 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000087 five possible forms: a similar string of hexadecimal digits, or a tuple
88 of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
89 48-bit values respectively) as an argument named 'fields', or a string
90 of 16 bytes (with all the integer fields in big-endian order) as an
91 argument named 'bytes', or a string of 16 bytes (with the first three
92 fields in little-endian order) as an argument named 'bytes_le', or a
93 single 128-bit integer as an argument named 'int'.
Thomas Wouters0e3f5912006-08-11 14:57:12 +000094
95 UUIDs have these read-only attributes:
96
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000097 bytes the UUID as a 16-byte string (containing the six
98 integer fields in big-endian byte order)
99
100 bytes_le the UUID as a 16-byte string (with time_low, time_mid,
101 and time_hi_version in little-endian byte order)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000102
103 fields a tuple of the six integer fields of the UUID,
104 which are also available as six individual attributes
105 and two derived attributes:
106
107 time_low the first 32 bits of the UUID
108 time_mid the next 16 bits of the UUID
109 time_hi_version the next 16 bits of the UUID
110 clock_seq_hi_variant the next 8 bits of the UUID
111 clock_seq_low the next 8 bits of the UUID
112 node the last 48 bits of the UUID
113
114 time the 60-bit timestamp
115 clock_seq the 14-bit sequence number
116
117 hex the UUID as a 32-character hexadecimal string
118
119 int the UUID as a 128-bit integer
120
121 urn the UUID as a URN as specified in RFC 4122
122
123 variant the UUID variant (one of the constants RESERVED_NCS,
124 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
125
126 version the UUID version number (1 through 5, meaningful only
127 when the variant is RFC_4122)
Barry Warsaw8c130d72017-02-18 15:45:49 -0500128
129 is_safe An enum indicating whether the UUID has been generated in
130 a way that is safe for multiprocessing applications, via
131 uuid_generate_time_safe(3).
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000132 """
133
David Hf1d8e7c2019-01-17 13:16:51 +0100134 __slots__ = ('int', 'is_safe', '__weakref__')
Tal Einat3e2b29d2018-09-06 14:34:25 +0300135
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000136 def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
Barry Warsaw8c130d72017-02-18 15:45:49 -0500137 int=None, version=None,
138 *, is_safe=SafeUUID.unknown):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000139 r"""Create a UUID from either a string of 32 hexadecimal digits,
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000140 a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
141 in little-endian order as the 'bytes_le' argument, a tuple of six
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000142 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
143 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
144 the 'fields' argument, or a single 128-bit integer as the 'int'
145 argument. When a string of hex digits is given, curly braces,
146 hyphens, and a URN prefix are all optional. For example, these
147 expressions all yield the same UUID:
148
149 UUID('{12345678-1234-5678-1234-567812345678}')
150 UUID('12345678123456781234567812345678')
151 UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
152 UUID(bytes='\x12\x34\x56\x78'*4)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000153 UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
154 '\x12\x34\x56\x78\x12\x34\x56\x78')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000155 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
156 UUID(int=0x12345678123456781234567812345678)
157
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000158 Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
159 be given. The 'version' argument is optional; if given, the resulting
160 UUID will have its variant and version set according to RFC 4122,
161 overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
Barry Warsaw8c130d72017-02-18 15:45:49 -0500162
163 is_safe is an enum exposed as an attribute on the instance. It
164 indicates whether the UUID has been generated in a way that is safe
165 for multiprocessing applications, via uuid_generate_time_safe(3).
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000166 """
167
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000168 if [hex, bytes, bytes_le, fields, int].count(None) != 4:
Berker Peksagd02eb8a2016-03-20 16:49:10 +0200169 raise TypeError('one of the hex, bytes, bytes_le, fields, '
170 'or int arguments must be given')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000171 if hex is not None:
172 hex = hex.replace('urn:', '').replace('uuid:', '')
173 hex = hex.strip('{}').replace('-', '')
174 if len(hex) != 32:
175 raise ValueError('badly formed hexadecimal UUID string')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000176 int = int_(hex, 16)
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000177 if bytes_le is not None:
178 if len(bytes_le) != 16:
179 raise ValueError('bytes_le is not a 16-char string')
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300180 bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
181 bytes_le[8-1:6-1:-1] + bytes_le[8:])
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000182 if bytes is not None:
183 if len(bytes) != 16:
184 raise ValueError('bytes is not a 16-char string')
Guido van Rossum65b6a802007-07-09 14:03:08 +0000185 assert isinstance(bytes, bytes_), repr(bytes)
Philip Jenvey1221f6b2013-08-29 18:33:50 -0700186 int = int_.from_bytes(bytes, byteorder='big')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000187 if fields is not None:
188 if len(fields) != 6:
189 raise ValueError('fields is not a 6-tuple')
190 (time_low, time_mid, time_hi_version,
191 clock_seq_hi_variant, clock_seq_low, node) = fields
Guido van Rossume2a383d2007-01-15 16:59:06 +0000192 if not 0 <= time_low < 1<<32:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000193 raise ValueError('field 1 out of range (need a 32-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000194 if not 0 <= time_mid < 1<<16:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000195 raise ValueError('field 2 out of range (need a 16-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000196 if not 0 <= time_hi_version < 1<<16:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000197 raise ValueError('field 3 out of range (need a 16-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000198 if not 0 <= clock_seq_hi_variant < 1<<8:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000199 raise ValueError('field 4 out of range (need an 8-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000200 if not 0 <= clock_seq_low < 1<<8:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000201 raise ValueError('field 5 out of range (need an 8-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000202 if not 0 <= node < 1<<48:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000203 raise ValueError('field 6 out of range (need a 48-bit value)')
Guido van Rossume2a383d2007-01-15 16:59:06 +0000204 clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
205 int = ((time_low << 96) | (time_mid << 80) |
206 (time_hi_version << 64) | (clock_seq << 48) | node)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000207 if int is not None:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000208 if not 0 <= int < 1<<128:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000209 raise ValueError('int is out of range (need a 128-bit value)')
210 if version is not None:
211 if not 1 <= version <= 5:
212 raise ValueError('illegal version number')
213 # Set the variant to RFC 4122.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000214 int &= ~(0xc000 << 48)
215 int |= 0x8000 << 48
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000216 # Set the version number.
Guido van Rossume2a383d2007-01-15 16:59:06 +0000217 int &= ~(0xf000 << 64)
218 int |= version << 76
Tal Einat3e2b29d2018-09-06 14:34:25 +0300219 object.__setattr__(self, 'int', int)
220 object.__setattr__(self, 'is_safe', is_safe)
221
222 def __getstate__(self):
Tal Einat54752532018-09-10 16:11:04 +0300223 d = {'int': self.int}
224 if self.is_safe != SafeUUID.unknown:
225 # is_safe is a SafeUUID instance. Return just its value, so that
226 # it can be un-pickled in older Python versions without SafeUUID.
227 d['is_safe'] = self.is_safe.value
Tal Einat3e2b29d2018-09-06 14:34:25 +0300228 return d
229
230 def __setstate__(self, state):
Tal Einat54752532018-09-10 16:11:04 +0300231 object.__setattr__(self, 'int', state['int'])
232 # is_safe was added in 3.7; it is also omitted when it is "unknown"
233 object.__setattr__(self, 'is_safe',
234 SafeUUID(state['is_safe'])
235 if 'is_safe' in state else SafeUUID.unknown)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000236
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000237 def __eq__(self, other):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000238 if isinstance(other, UUID):
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000239 return self.int == other.int
240 return NotImplemented
241
Guido van Rossum65b6a802007-07-09 14:03:08 +0000242 # Q. What's the value of being able to sort UUIDs?
243 # A. Use them as keys in a B-Tree or similar mapping.
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000244
245 def __lt__(self, other):
246 if isinstance(other, UUID):
247 return self.int < other.int
248 return NotImplemented
249
250 def __gt__(self, other):
251 if isinstance(other, UUID):
252 return self.int > other.int
253 return NotImplemented
254
255 def __le__(self, other):
256 if isinstance(other, UUID):
257 return self.int <= other.int
258 return NotImplemented
259
260 def __ge__(self, other):
261 if isinstance(other, UUID):
262 return self.int >= other.int
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000263 return NotImplemented
264
265 def __hash__(self):
266 return hash(self.int)
267
268 def __int__(self):
269 return self.int
270
271 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300272 return '%s(%r)' % (self.__class__.__name__, str(self))
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000273
274 def __setattr__(self, name, value):
275 raise TypeError('UUID objects are immutable')
276
277 def __str__(self):
278 hex = '%032x' % self.int
279 return '%s-%s-%s-%s-%s' % (
280 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
281
Guido van Rossum65b6a802007-07-09 14:03:08 +0000282 @property
283 def bytes(self):
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300284 return self.int.to_bytes(16, 'big')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000285
Guido van Rossum65b6a802007-07-09 14:03:08 +0000286 @property
287 def bytes_le(self):
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000288 bytes = self.bytes
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300289 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 +0000290 bytes[8:])
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000291
Guido van Rossum65b6a802007-07-09 14:03:08 +0000292 @property
293 def fields(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000294 return (self.time_low, self.time_mid, self.time_hi_version,
295 self.clock_seq_hi_variant, self.clock_seq_low, self.node)
296
Guido van Rossum65b6a802007-07-09 14:03:08 +0000297 @property
298 def time_low(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000299 return self.int >> 96
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000300
Guido van Rossum65b6a802007-07-09 14:03:08 +0000301 @property
302 def time_mid(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000303 return (self.int >> 80) & 0xffff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000304
Guido van Rossum65b6a802007-07-09 14:03:08 +0000305 @property
306 def time_hi_version(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000307 return (self.int >> 64) & 0xffff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000308
Guido van Rossum65b6a802007-07-09 14:03:08 +0000309 @property
310 def clock_seq_hi_variant(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000311 return (self.int >> 56) & 0xff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000312
Guido van Rossum65b6a802007-07-09 14:03:08 +0000313 @property
314 def clock_seq_low(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000315 return (self.int >> 48) & 0xff
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000316
Guido van Rossum65b6a802007-07-09 14:03:08 +0000317 @property
318 def time(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000319 return (((self.time_hi_version & 0x0fff) << 48) |
320 (self.time_mid << 32) | self.time_low)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000321
Guido van Rossum65b6a802007-07-09 14:03:08 +0000322 @property
323 def clock_seq(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000324 return (((self.clock_seq_hi_variant & 0x3f) << 8) |
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000325 self.clock_seq_low)
326
Guido van Rossum65b6a802007-07-09 14:03:08 +0000327 @property
328 def node(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000329 return self.int & 0xffffffffffff
330
Guido van Rossum65b6a802007-07-09 14:03:08 +0000331 @property
332 def hex(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000333 return '%032x' % self.int
334
Guido van Rossum65b6a802007-07-09 14:03:08 +0000335 @property
336 def urn(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000337 return 'urn:uuid:' + str(self)
338
Guido van Rossum65b6a802007-07-09 14:03:08 +0000339 @property
340 def variant(self):
Guido van Rossume2a383d2007-01-15 16:59:06 +0000341 if not self.int & (0x8000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000342 return RESERVED_NCS
Guido van Rossume2a383d2007-01-15 16:59:06 +0000343 elif not self.int & (0x4000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000344 return RFC_4122
Guido van Rossume2a383d2007-01-15 16:59:06 +0000345 elif not self.int & (0x2000 << 48):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000346 return RESERVED_MICROSOFT
347 else:
348 return RESERVED_FUTURE
349
Guido van Rossum65b6a802007-07-09 14:03:08 +0000350 @property
351 def version(self):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000352 # The version bits are only meaningful for RFC 4122 UUIDs.
353 if self.variant == RFC_4122:
Guido van Rossume2a383d2007-01-15 16:59:06 +0000354 return int((self.int >> 76) & 0xf)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000355
Michael Felt0bcbfa42019-09-26 20:43:15 +0100356
357def _get_command_stdout(command, *args):
358 import io, os, shutil, subprocess
359
360 try:
361 path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep)
362 path_dirs.extend(['/sbin', '/usr/sbin'])
363 executable = shutil.which(command, path=os.pathsep.join(path_dirs))
R David Murray4be1e242013-12-17 21:13:16 -0500364 if executable is None:
365 return None
Michael Felt0bcbfa42019-09-26 20:43:15 +0100366 # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
367 # on stderr (Note: we don't have an example where the words we search
368 # for are actually localized, but in theory some system could do so.)
369 env = dict(os.environ)
370 env['LC_ALL'] = 'C'
371 proc = subprocess.Popen((executable,) + args,
372 stdout=subprocess.PIPE,
373 stderr=subprocess.DEVNULL,
374 env=env)
375 if not proc:
376 return None
377 stdout, stderr = proc.communicate()
378 return io.BytesIO(stdout)
379 except (OSError, subprocess.SubprocessError):
380 return None
381
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000382
Barry Warsaw23df2d12017-11-28 17:26:04 -0500383# For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
384# bit of the first octet signifies whether the MAC address is universally (0)
385# or locally (1) administered. Network cards from hardware manufacturers will
386# always be universally administered to guarantee global uniqueness of the MAC
387# address, but any particular machine may have other interfaces which are
388# locally administered. An example of the latter is the bridge interface to
389# the Touch Bar on MacBook Pros.
390#
391# This bit works out to be the 42nd bit counting from 1 being the least
392# significant, or 1<<41. We'll prefer universally administered MAC addresses
393# over locally administered ones since the former are globally unique, but
394# we'll return the first of the latter found if that's all the machine has.
395#
396# See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
397
398def _is_universal(mac):
399 return not (mac & (1 << 41))
400
Michael Felt0bcbfa42019-09-26 20:43:15 +0100401
402def _find_mac_near_keyword(command, args, keywords, get_word_index):
403 """Searches a command's output for a MAC address near a keyword.
404
405 Each line of words in the output is case-insensitively searched for
406 any of the given keywords. Upon a match, get_word_index is invoked
407 to pick a word from the line, given the index of the match. For
408 example, lambda i: 0 would get the first word on the line, while
409 lambda i: i - 1 would get the word preceding the keyword.
410 """
411 stdout = _get_command_stdout(command, args)
412 if stdout is None:
413 return None
414
Barry Warsaw23df2d12017-11-28 17:26:04 -0500415 first_local_mac = None
Michael Felt0bcbfa42019-09-26 20:43:15 +0100416 for line in stdout:
417 words = line.lower().rstrip().split()
418 for i in range(len(words)):
419 if words[i] in keywords:
420 try:
421 word = words[get_word_index(i)]
422 mac = int(word.replace(_MAC_DELIM, b''), 16)
423 except (ValueError, IndexError):
424 # Virtual interfaces, such as those provided by
425 # VPNs, do not have a colon-delimited MAC address
426 # as expected, but a 16-byte HWAddr separated by
427 # dashes. These should be ignored in favor of a
428 # real MAC address
429 pass
430 else:
431 if _is_universal(mac):
432 return mac
433 first_local_mac = first_local_mac or mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500434 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000435
Michael Felt0bcbfa42019-09-26 20:43:15 +0100436
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100437def _parse_mac(word):
438 # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
439 # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8').
440 #
441 # Virtual interfaces, such as those provided by VPNs, do not have a
442 # colon-delimited MAC address as expected, but a 16-byte HWAddr separated
443 # by dashes. These should be ignored in favor of a real MAC address
444 parts = word.split(_MAC_DELIM)
445 if len(parts) != 6:
446 return
447 if _MAC_OMITS_LEADING_ZEROES:
448 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
449 # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
450 # not
451 # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
452 if not all(1 <= len(part) <= 2 for part in parts):
453 return
454 hexstr = b''.join(part.rjust(2, b'0') for part in parts)
455 else:
456 if not all(len(part) == 2 for part in parts):
457 return
458 hexstr = b''.join(parts)
459 try:
460 return int(hexstr, 16)
461 except ValueError:
462 return
463
464
Michael Felt0bcbfa42019-09-26 20:43:15 +0100465def _find_mac_under_heading(command, args, heading):
466 """Looks for a MAC address under a heading in a command's output.
467
468 The first line of words in the output is searched for the given
469 heading. Words at the same word index as the heading in subsequent
470 lines are then examined to see if they look like MAC addresses.
471 """
472 stdout = _get_command_stdout(command, args)
473 if stdout is None:
474 return None
475
476 keywords = stdout.readline().rstrip().split()
477 try:
478 column_index = keywords.index(heading)
479 except ValueError:
480 return None
481
482 first_local_mac = None
483 for line in stdout:
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100484 words = line.rstrip().split()
Michael Felt0bcbfa42019-09-26 20:43:15 +0100485 try:
Michael Felt0bcbfa42019-09-26 20:43:15 +0100486 word = words[column_index]
Victor Stinnerebf6bb92020-03-17 18:36:44 +0100487 except IndexError:
488 continue
489
490 mac = _parse_mac(word)
491 if mac is None:
492 continue
493 if _is_universal(mac):
494 return mac
495 if first_local_mac is None:
496 first_local_mac = mac
497
498 return first_local_mac
Michael Felt0bcbfa42019-09-26 20:43:15 +0100499
500
501# The following functions call external programs to 'get' a macaddr value to
502# be used as basis for an uuid
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000503def _ifconfig_getnode():
504 """Get the hardware address on Unix by running ifconfig."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000505 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200506 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000507 for args in ('', '-a', '-av'):
Michael Felt0bcbfa42019-09-26 20:43:15 +0100508 mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000509 if mac:
510 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500511 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000512
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200513def _ip_getnode():
514 """Get the hardware address on Unix by running ip."""
515 # This works on Linux with iproute2.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100516 mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1)
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200517 if mac:
518 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500519 return None
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200520
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200521def _arp_getnode():
522 """Get the hardware address on Unix by running arp."""
523 import os, socket
Serhiy Storchaka525d5ae2014-11-21 21:55:39 +0200524 try:
525 ip_addr = socket.gethostbyname(socket.gethostname())
526 except OSError:
527 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000528
529 # Try getting the MAC addr from arp based on our IP address (Solaris).
Michael Felt0bcbfa42019-09-26 20:43:15 +0100530 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200531 if mac:
532 return mac
533
534 # This works on OpenBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100535 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200536 if mac:
537 return mac
538
539 # This works on Linux, FreeBSD and NetBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100540 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200541 lambda i: i+2)
Barry Warsaw23df2d12017-11-28 17:26:04 -0500542 # Return None instead of 0.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200543 if mac:
544 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500545 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000546
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200547def _lanscan_getnode():
548 """Get the hardware address on Unix by running lanscan."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000549 # This might work on HP-UX.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100550 return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000551
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200552def _netstat_getnode():
553 """Get the hardware address on Unix by running netstat."""
Michael Felt0bcbfa42019-09-26 20:43:15 +0100554 # This works on AIX and might work on Tru64 UNIX.
555 return _find_mac_under_heading('netstat', '-ian', b'Address')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000556
557def _ipconfig_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100558 """[DEPRECATED] Get the hardware address on Windows."""
559 # bpo-40501: UuidCreateSequential() is now the only supported approach
560 return _windll_getnode()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561
562def _netbios_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100563 """[DEPRECATED] Get the hardware address on Windows."""
564 # bpo-40501: UuidCreateSequential() is now the only supported approach
565 return _windll_getnode()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000566
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000567
Antoine Pitroua106aec2017-09-28 23:03:06 +0200568# Import optional C extension at toplevel, to help disabling it when testing
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000569try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200570 import _uuid
Steve Dowerd6b727e2020-05-12 23:32:32 +0100571 _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
572 _UuidCreate = getattr(_uuid, "UuidCreate", None)
573 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
Antoine Pitroua106aec2017-09-28 23:03:06 +0200574except ImportError:
575 _uuid = None
Steve Dowerd6b727e2020-05-12 23:32:32 +0100576 _generate_time_safe = None
577 _UuidCreate = None
578 _has_uuid_generate_time_safe = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000579
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000580
Antoine Pitroua106aec2017-09-28 23:03:06 +0200581def _load_system_functions():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100582 """[DEPRECATED] Platform-specific functions loaded at import time"""
Antoine Pitroua106aec2017-09-28 23:03:06 +0200583
584
585def _unix_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100586 """Get the hardware address on Unix using the _uuid extension module."""
587 if _generate_time_safe:
588 uuid_time, _ = _generate_time_safe()
589 return UUID(bytes=uuid_time).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000590
591def _windll_getnode():
Steve Dowerd6b727e2020-05-12 23:32:32 +0100592 """Get the hardware address on Windows using the _uuid extension module."""
593 if _UuidCreate:
594 uuid_bytes = _UuidCreate()
595 return UUID(bytes_le=uuid_bytes).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000596
597def _random_getnode():
Barry Warsaw23df2d12017-11-28 17:26:04 -0500598 """Get a random node ID."""
599 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
600 # pseudo-randomly generated value may be used; see Section 4.5. The
601 # multicast bit must be set in such addresses, in order that they will
602 # never conflict with addresses obtained from network cards."
603 #
604 # The "multicast bit" of a MAC address is defined to be "the least
605 # significant bit of the first octet". This works out to be the 41st bit
606 # counting from 1 being the least significant bit, or 1<<40.
607 #
608 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000609 import random
Barry Warsaw23df2d12017-11-28 17:26:04 -0500610 return random.getrandbits(48) | (1 << 40)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000611
Antoine Pitroua106aec2017-09-28 23:03:06 +0200612
Min ho Kim39d87b52019-08-31 06:21:19 +1000613# _OS_GETTERS, when known, are targeted for a specific OS or platform.
Michael Felt3a1d50e2019-06-15 17:52:29 +0200614# The order is by 'common practice' on the specified platform.
615# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
616# which, when successful, means none of these "external" methods are called.
617# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
618# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
619if _LINUX:
620 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
621elif _DARWIN:
622 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
623elif _WINDOWS:
Steve Dowerd6b727e2020-05-12 23:32:32 +0100624 # bpo-40201: _windll_getnode will always succeed, so these are not needed
625 _OS_GETTERS = []
Michael Felt3a1d50e2019-06-15 17:52:29 +0200626elif _AIX:
627 _OS_GETTERS = [_netstat_getnode]
628else:
629 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
630 _netstat_getnode, _lanscan_getnode]
631if os.name == 'posix':
632 _GETTERS = [_unix_getnode] + _OS_GETTERS
633elif os.name == 'nt':
634 _GETTERS = [_windll_getnode] + _OS_GETTERS
635else:
636 _GETTERS = _OS_GETTERS
637
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000638_node = None
639
Shantanu8b6f6522020-02-05 12:43:09 -0800640def getnode():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000641 """Get the hardware address as a 48-bit positive integer.
642
643 The first time this runs, it may launch a separate program, which could
644 be quite slow. If all attempts to obtain the hardware address fail, we
645 choose a random 48-bit number with its eighth bit set to 1 as recommended
646 in RFC 4122.
647 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000648 global _node
649 if _node is not None:
650 return _node
651
Michael Felt3a1d50e2019-06-15 17:52:29 +0200652 for getter in _GETTERS + [_random_getnode]:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000653 try:
654 _node = getter()
655 except:
656 continue
Bo Bayles6b273f72018-01-23 19:11:44 -0600657 if (_node is not None) and (0 <= _node < (1 << 48)):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000658 return _node
Bo Bayles6b273f72018-01-23 19:11:44 -0600659 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000660
Antoine Pitroua106aec2017-09-28 23:03:06 +0200661
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000662_last_timestamp = None
663
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000664def uuid1(node=None, clock_seq=None):
665 """Generate a UUID from a host ID, sequence number, and the current time.
666 If 'node' is not given, getnode() is used to obtain the hardware
667 address. If 'clock_seq' is given, it is used as the sequence number;
668 otherwise a random 14-bit sequence number is chosen."""
669
670 # When the system provides a version-1 UUID generator, use it (but don't
671 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
Antoine Pitroua106aec2017-09-28 23:03:06 +0200672 if _generate_time_safe is not None and node is clock_seq is None:
673 uuid_time, safely_generated = _generate_time_safe()
Barry Warsaw8c130d72017-02-18 15:45:49 -0500674 try:
675 is_safe = SafeUUID(safely_generated)
676 except ValueError:
677 is_safe = SafeUUID.unknown
Antoine Pitroua106aec2017-09-28 23:03:06 +0200678 return UUID(bytes=uuid_time, is_safe=is_safe)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000679
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000680 global _last_timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000681 import time
Victor Stinner62a68b72018-12-18 11:45:13 +0100682 nanoseconds = time.time_ns()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000683 # 0x01b21dd213814000 is the number of 100-ns intervals between the
684 # 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 +0100685 timestamp = nanoseconds // 100 + 0x01b21dd213814000
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000686 if _last_timestamp is not None and timestamp <= _last_timestamp:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000687 timestamp = _last_timestamp + 1
688 _last_timestamp = timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000689 if clock_seq is None:
690 import random
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300691 clock_seq = random.getrandbits(14) # instead of stable storage
Guido van Rossume2a383d2007-01-15 16:59:06 +0000692 time_low = timestamp & 0xffffffff
693 time_mid = (timestamp >> 32) & 0xffff
694 time_hi_version = (timestamp >> 48) & 0x0fff
695 clock_seq_low = clock_seq & 0xff
696 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000697 if node is None:
698 node = getnode()
699 return UUID(fields=(time_low, time_mid, time_hi_version,
700 clock_seq_hi_variant, clock_seq_low, node), version=1)
701
702def uuid3(namespace, name):
703 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000704 from hashlib import md5
Christian Heimes7cad53e2019-09-13 02:30:00 +0200705 digest = md5(
706 namespace.bytes + bytes(name, "utf-8"),
707 usedforsecurity=False
708 ).digest()
709 return UUID(bytes=digest[:16], version=3)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000710
711def uuid4():
712 """Generate a random UUID."""
Benjamin Peterson788cb522015-10-29 20:38:04 -0700713 return UUID(bytes=os.urandom(16), version=4)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000714
715def uuid5(namespace, name):
716 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000717 from hashlib import sha1
Guido van Rossum65b6a802007-07-09 14:03:08 +0000718 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
Guido van Rossum5ed033b2007-07-09 14:29:40 +0000719 return UUID(bytes=hash[:16], version=5)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000720
721# The following standard UUIDs are for use with uuid3() or uuid5().
722
723NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
724NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
725NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
726NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')