blob: 2799c75ba6a1ad3e478af77c7ea4d3f40c86b0b0 [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():
558 """Get the hardware address on Windows by running ipconfig.exe."""
Segev Finerda6c3da2018-02-13 08:29:54 +0200559 import os, re, subprocess
Barry Warsaw23df2d12017-11-28 17:26:04 -0500560 first_local_mac = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
562 try:
563 import ctypes
564 buffer = ctypes.create_string_buffer(300)
565 ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
566 dirs.insert(0, buffer.value.decode('mbcs'))
567 except:
568 pass
569 for dir in dirs:
570 try:
Segev Finerda6c3da2018-02-13 08:29:54 +0200571 proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'],
572 stdout=subprocess.PIPE,
573 encoding="oem")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200574 except OSError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000575 continue
Segev Finerda6c3da2018-02-13 08:29:54 +0200576 with proc:
577 for line in proc.stdout:
Brian Curtin69cd87b2010-11-05 14:48:35 +0000578 value = line.split(':')[-1].strip().lower()
CtrlZvic66c3422018-05-20 08:03:25 -0700579 if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
Barry Warsaw23df2d12017-11-28 17:26:04 -0500580 mac = int(value.replace('-', ''), 16)
581 if _is_universal(mac):
582 return mac
583 first_local_mac = first_local_mac or mac
584 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000585
586def _netbios_getnode():
587 """Get the hardware address on Windows using NetBIOS calls.
588 See http://support.microsoft.com/kb/118623 for details."""
589 import win32wnet, netbios
Barry Warsaw23df2d12017-11-28 17:26:04 -0500590 first_local_mac = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000591 ncb = netbios.NCB()
592 ncb.Command = netbios.NCBENUM
593 ncb.Buffer = adapters = netbios.LANA_ENUM()
594 adapters._pack()
595 if win32wnet.Netbios(ncb) != 0:
Barry Warsaw23df2d12017-11-28 17:26:04 -0500596 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000597 adapters._unpack()
598 for i in range(adapters.length):
599 ncb.Reset()
600 ncb.Command = netbios.NCBRESET
601 ncb.Lana_num = ord(adapters.lana[i])
602 if win32wnet.Netbios(ncb) != 0:
603 continue
604 ncb.Reset()
605 ncb.Command = netbios.NCBASTAT
606 ncb.Lana_num = ord(adapters.lana[i])
607 ncb.Callname = '*'.ljust(16)
608 ncb.Buffer = status = netbios.ADAPTER_STATUS()
609 if win32wnet.Netbios(ncb) != 0:
610 continue
611 status._unpack()
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300612 bytes = status.adapter_address[:6]
613 if len(bytes) != 6:
614 continue
Barry Warsaw23df2d12017-11-28 17:26:04 -0500615 mac = int.from_bytes(bytes, 'big')
616 if _is_universal(mac):
617 return mac
618 first_local_mac = first_local_mac or mac
619 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000620
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000621
Antoine Pitroua106aec2017-09-28 23:03:06 +0200622_generate_time_safe = _UuidCreate = None
623_has_uuid_generate_time_safe = None
624
625# Import optional C extension at toplevel, to help disabling it when testing
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000626try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200627 import _uuid
628except ImportError:
629 _uuid = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000630
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000631
Antoine Pitroua106aec2017-09-28 23:03:06 +0200632def _load_system_functions():
633 """
634 Try to load platform-specific functions for generating uuids.
635 """
636 global _generate_time_safe, _UuidCreate, _has_uuid_generate_time_safe
Ronald Oussorenac764d32010-05-05 15:32:33 +0000637
Antoine Pitroua106aec2017-09-28 23:03:06 +0200638 if _has_uuid_generate_time_safe is not None:
639 return
640
641 _has_uuid_generate_time_safe = False
642
643 if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
644 # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
645 # in issue #8621 the function generates the same sequence of values
646 # in the parent process and all children created using fork (unless
647 # those children use exec as well).
648 #
649 # Assume that the uuid_generate functions are broken from 10.5 onward,
650 # the test can be adjusted when a later version is fixed.
651 pass
652 elif _uuid is not None:
653 _generate_time_safe = _uuid.generate_time_safe
Victor Stinner4337a0d2017-10-02 07:57:59 -0700654 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
Antoine Pitroua106aec2017-09-28 23:03:06 +0200655 return
656
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000657 try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200658 # If we couldn't find an extension module, try ctypes to find
659 # system routines for UUID generation.
660 # Thanks to Thomas Heller for ctypes and for his help with its use here.
661 import ctypes
662 import ctypes.util
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000663
Antoine Pitroua106aec2017-09-28 23:03:06 +0200664 # The uuid_generate_* routines are provided by libuuid on at least
665 # Linux and FreeBSD, and provided by libc on Mac OS X.
666 _libnames = ['uuid']
667 if not sys.platform.startswith('win'):
668 _libnames.append('c')
669 for libname in _libnames:
670 try:
671 lib = ctypes.CDLL(ctypes.util.find_library(libname))
672 except Exception: # pragma: nocover
673 continue
674 # Try to find the safe variety first.
675 if hasattr(lib, 'uuid_generate_time_safe'):
676 _uuid_generate_time_safe = lib.uuid_generate_time_safe
677 # int uuid_generate_time_safe(uuid_t out);
678 def _generate_time_safe():
679 _buffer = ctypes.create_string_buffer(16)
680 res = _uuid_generate_time_safe(_buffer)
681 return bytes(_buffer.raw), res
682 _has_uuid_generate_time_safe = True
683 break
684
685 elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
686 _uuid_generate_time = lib.uuid_generate_time
687 # void uuid_generate_time(uuid_t out);
688 _uuid_generate_time.restype = None
689 def _generate_time_safe():
690 _buffer = ctypes.create_string_buffer(16)
691 _uuid_generate_time(_buffer)
692 return bytes(_buffer.raw), None
693 break
694
695 # On Windows prior to 2000, UuidCreate gives a UUID containing the
696 # hardware address. On Windows 2000 and later, UuidCreate makes a
697 # random UUID and UuidCreateSequential gives a UUID containing the
698 # hardware address. These routines are provided by the RPC runtime.
699 # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
700 # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
701 # to bear any relationship to the MAC address of any network device
702 # on the box.
703 try:
704 lib = ctypes.windll.rpcrt4
705 except:
706 lib = None
707 _UuidCreate = getattr(lib, 'UuidCreateSequential',
708 getattr(lib, 'UuidCreate', None))
709
710 except Exception as exc:
711 import warnings
712 warnings.warn(f"Could not find fallback ctypes uuid functions: {exc}",
713 ImportWarning)
714
715
716def _unix_getnode():
717 """Get the hardware address on Unix using the _uuid extension module
718 or ctypes."""
719 _load_system_functions()
720 uuid_time, _ = _generate_time_safe()
721 return UUID(bytes=uuid_time).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000722
723def _windll_getnode():
724 """Get the hardware address on Windows using ctypes."""
Antoine Pitroua106aec2017-09-28 23:03:06 +0200725 import ctypes
726 _load_system_functions()
Guido van Rossum37410aa2007-08-24 04:13:42 +0000727 _buffer = ctypes.create_string_buffer(16)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000728 if _UuidCreate(_buffer) == 0:
Guido van Rossumfb56d8f2007-07-20 17:45:09 +0000729 return UUID(bytes=bytes_(_buffer.raw)).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000730
731def _random_getnode():
Barry Warsaw23df2d12017-11-28 17:26:04 -0500732 """Get a random node ID."""
733 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
734 # pseudo-randomly generated value may be used; see Section 4.5. The
735 # multicast bit must be set in such addresses, in order that they will
736 # never conflict with addresses obtained from network cards."
737 #
738 # The "multicast bit" of a MAC address is defined to be "the least
739 # significant bit of the first octet". This works out to be the 41st bit
740 # counting from 1 being the least significant bit, or 1<<40.
741 #
742 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000743 import random
Barry Warsaw23df2d12017-11-28 17:26:04 -0500744 return random.getrandbits(48) | (1 << 40)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000745
Antoine Pitroua106aec2017-09-28 23:03:06 +0200746
Min ho Kim39d87b52019-08-31 06:21:19 +1000747# _OS_GETTERS, when known, are targeted for a specific OS or platform.
Michael Felt3a1d50e2019-06-15 17:52:29 +0200748# The order is by 'common practice' on the specified platform.
749# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
750# which, when successful, means none of these "external" methods are called.
751# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
752# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
753if _LINUX:
754 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
755elif _DARWIN:
756 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
757elif _WINDOWS:
758 _OS_GETTERS = [_netbios_getnode, _ipconfig_getnode]
759elif _AIX:
760 _OS_GETTERS = [_netstat_getnode]
761else:
762 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
763 _netstat_getnode, _lanscan_getnode]
764if os.name == 'posix':
765 _GETTERS = [_unix_getnode] + _OS_GETTERS
766elif os.name == 'nt':
767 _GETTERS = [_windll_getnode] + _OS_GETTERS
768else:
769 _GETTERS = _OS_GETTERS
770
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000771_node = None
772
Shantanu8b6f6522020-02-05 12:43:09 -0800773def getnode():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000774 """Get the hardware address as a 48-bit positive integer.
775
776 The first time this runs, it may launch a separate program, which could
777 be quite slow. If all attempts to obtain the hardware address fail, we
778 choose a random 48-bit number with its eighth bit set to 1 as recommended
779 in RFC 4122.
780 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000781 global _node
782 if _node is not None:
783 return _node
784
Michael Felt3a1d50e2019-06-15 17:52:29 +0200785 for getter in _GETTERS + [_random_getnode]:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000786 try:
787 _node = getter()
788 except:
789 continue
Bo Bayles6b273f72018-01-23 19:11:44 -0600790 if (_node is not None) and (0 <= _node < (1 << 48)):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000791 return _node
Bo Bayles6b273f72018-01-23 19:11:44 -0600792 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000793
Antoine Pitroua106aec2017-09-28 23:03:06 +0200794
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000795_last_timestamp = None
796
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000797def uuid1(node=None, clock_seq=None):
798 """Generate a UUID from a host ID, sequence number, and the current time.
799 If 'node' is not given, getnode() is used to obtain the hardware
800 address. If 'clock_seq' is given, it is used as the sequence number;
801 otherwise a random 14-bit sequence number is chosen."""
802
803 # When the system provides a version-1 UUID generator, use it (but don't
804 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
Antoine Pitroua106aec2017-09-28 23:03:06 +0200805 _load_system_functions()
806 if _generate_time_safe is not None and node is clock_seq is None:
807 uuid_time, safely_generated = _generate_time_safe()
Barry Warsaw8c130d72017-02-18 15:45:49 -0500808 try:
809 is_safe = SafeUUID(safely_generated)
810 except ValueError:
811 is_safe = SafeUUID.unknown
Antoine Pitroua106aec2017-09-28 23:03:06 +0200812 return UUID(bytes=uuid_time, is_safe=is_safe)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000813
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000814 global _last_timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000815 import time
Victor Stinner62a68b72018-12-18 11:45:13 +0100816 nanoseconds = time.time_ns()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000817 # 0x01b21dd213814000 is the number of 100-ns intervals between the
818 # 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 +0100819 timestamp = nanoseconds // 100 + 0x01b21dd213814000
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000820 if _last_timestamp is not None and timestamp <= _last_timestamp:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000821 timestamp = _last_timestamp + 1
822 _last_timestamp = timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000823 if clock_seq is None:
824 import random
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300825 clock_seq = random.getrandbits(14) # instead of stable storage
Guido van Rossume2a383d2007-01-15 16:59:06 +0000826 time_low = timestamp & 0xffffffff
827 time_mid = (timestamp >> 32) & 0xffff
828 time_hi_version = (timestamp >> 48) & 0x0fff
829 clock_seq_low = clock_seq & 0xff
830 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000831 if node is None:
832 node = getnode()
833 return UUID(fields=(time_low, time_mid, time_hi_version,
834 clock_seq_hi_variant, clock_seq_low, node), version=1)
835
836def uuid3(namespace, name):
837 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000838 from hashlib import md5
Christian Heimes7cad53e2019-09-13 02:30:00 +0200839 digest = md5(
840 namespace.bytes + bytes(name, "utf-8"),
841 usedforsecurity=False
842 ).digest()
843 return UUID(bytes=digest[:16], version=3)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000844
845def uuid4():
846 """Generate a random UUID."""
Benjamin Peterson788cb522015-10-29 20:38:04 -0700847 return UUID(bytes=os.urandom(16), version=4)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000848
849def uuid5(namespace, name):
850 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000851 from hashlib import sha1
Guido van Rossum65b6a802007-07-09 14:03:08 +0000852 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
Guido van Rossum5ed033b2007-07-09 14:29:40 +0000853 return UUID(bytes=hash[:16], version=5)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000854
855# The following standard UUIDs are for use with uuid3() or uuid5().
856
857NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
858NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
859NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
860NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')