blob: 3b3abc2a4554373f221f3d59ec1de6802615902a [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
437def _find_mac_under_heading(command, args, heading):
438 """Looks for a MAC address under a heading in a command's output.
439
440 The first line of words in the output is searched for the given
441 heading. Words at the same word index as the heading in subsequent
442 lines are then examined to see if they look like MAC addresses.
443 """
444 stdout = _get_command_stdout(command, args)
445 if stdout is None:
446 return None
447
448 keywords = stdout.readline().rstrip().split()
449 try:
450 column_index = keywords.index(heading)
451 except ValueError:
452 return None
453
454 first_local_mac = None
455 for line in stdout:
456 try:
457 words = line.rstrip().split()
458 word = words[column_index]
Victor Stinnereb886db2020-03-17 15:51:42 +0100459 # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'),
460 # but reject IPv6 address (ex: 'fe80::5054:ff:fe9') detected
461 # by '::' pattern.
462 if len(word) == 17 and b'::' not in word:
Michael Felt0bcbfa42019-09-26 20:43:15 +0100463 mac = int(word.replace(_MAC_DELIM, b''), 16)
464 elif _MAC_OMITS_LEADING_ZEROES:
465 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g.
466 # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0
467 # not
468 # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0
469 parts = word.split(_MAC_DELIM)
470 if len(parts) == 6 and all(0 < len(p) <= 2 for p in parts):
471 hexstr = b''.join(p.rjust(2, b'0') for p in parts)
472 mac = int(hexstr, 16)
473 else:
474 continue
475 else:
476 continue
477 except (ValueError, IndexError):
478 # Virtual interfaces, such as those provided by
479 # VPNs, do not have a colon-delimited MAC address
480 # as expected, but a 16-byte HWAddr separated by
481 # dashes. These should be ignored in favor of a
482 # real MAC address
483 pass
484 else:
485 if _is_universal(mac):
486 return mac
487 first_local_mac = first_local_mac or mac
488 return first_local_mac or None
489
490
491# The following functions call external programs to 'get' a macaddr value to
492# be used as basis for an uuid
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000493def _ifconfig_getnode():
494 """Get the hardware address on Unix by running ifconfig."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000495 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200496 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000497 for args in ('', '-a', '-av'):
Michael Felt0bcbfa42019-09-26 20:43:15 +0100498 mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000499 if mac:
500 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500501 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000502
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200503def _ip_getnode():
504 """Get the hardware address on Unix by running ip."""
505 # This works on Linux with iproute2.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100506 mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1)
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200507 if mac:
508 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500509 return None
Serhiy Storchakaac4aa7b2014-11-30 20:39:04 +0200510
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200511def _arp_getnode():
512 """Get the hardware address on Unix by running arp."""
513 import os, socket
Serhiy Storchaka525d5ae2014-11-21 21:55:39 +0200514 try:
515 ip_addr = socket.gethostbyname(socket.gethostname())
516 except OSError:
517 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000518
519 # Try getting the MAC addr from arp based on our IP address (Solaris).
Michael Felt0bcbfa42019-09-26 20:43:15 +0100520 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200521 if mac:
522 return mac
523
524 # This works on OpenBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100525 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200526 if mac:
527 return mac
528
529 # This works on Linux, FreeBSD and NetBSD
Michael Felt0bcbfa42019-09-26 20:43:15 +0100530 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200531 lambda i: i+2)
Barry Warsaw23df2d12017-11-28 17:26:04 -0500532 # Return None instead of 0.
Serhiy Storchakaee1a9a22017-11-04 09:37:32 +0200533 if mac:
534 return mac
Barry Warsaw23df2d12017-11-28 17:26:04 -0500535 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000536
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200537def _lanscan_getnode():
538 """Get the hardware address on Unix by running lanscan."""
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000539 # This might work on HP-UX.
Michael Felt0bcbfa42019-09-26 20:43:15 +0100540 return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000541
Serhiy Storchakae66bb962014-11-07 12:19:40 +0200542def _netstat_getnode():
543 """Get the hardware address on Unix by running netstat."""
Michael Felt0bcbfa42019-09-26 20:43:15 +0100544 # This works on AIX and might work on Tru64 UNIX.
545 return _find_mac_under_heading('netstat', '-ian', b'Address')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000546
547def _ipconfig_getnode():
548 """Get the hardware address on Windows by running ipconfig.exe."""
Segev Finerda6c3da2018-02-13 08:29:54 +0200549 import os, re, subprocess
Barry Warsaw23df2d12017-11-28 17:26:04 -0500550 first_local_mac = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000551 dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
552 try:
553 import ctypes
554 buffer = ctypes.create_string_buffer(300)
555 ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
556 dirs.insert(0, buffer.value.decode('mbcs'))
557 except:
558 pass
559 for dir in dirs:
560 try:
Segev Finerda6c3da2018-02-13 08:29:54 +0200561 proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'],
562 stdout=subprocess.PIPE,
563 encoding="oem")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200564 except OSError:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 continue
Segev Finerda6c3da2018-02-13 08:29:54 +0200566 with proc:
567 for line in proc.stdout:
Brian Curtin69cd87b2010-11-05 14:48:35 +0000568 value = line.split(':')[-1].strip().lower()
CtrlZvic66c3422018-05-20 08:03:25 -0700569 if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
Barry Warsaw23df2d12017-11-28 17:26:04 -0500570 mac = int(value.replace('-', ''), 16)
571 if _is_universal(mac):
572 return mac
573 first_local_mac = first_local_mac or mac
574 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000575
576def _netbios_getnode():
577 """Get the hardware address on Windows using NetBIOS calls.
578 See http://support.microsoft.com/kb/118623 for details."""
579 import win32wnet, netbios
Barry Warsaw23df2d12017-11-28 17:26:04 -0500580 first_local_mac = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000581 ncb = netbios.NCB()
582 ncb.Command = netbios.NCBENUM
583 ncb.Buffer = adapters = netbios.LANA_ENUM()
584 adapters._pack()
585 if win32wnet.Netbios(ncb) != 0:
Barry Warsaw23df2d12017-11-28 17:26:04 -0500586 return None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000587 adapters._unpack()
588 for i in range(adapters.length):
589 ncb.Reset()
590 ncb.Command = netbios.NCBRESET
591 ncb.Lana_num = ord(adapters.lana[i])
592 if win32wnet.Netbios(ncb) != 0:
593 continue
594 ncb.Reset()
595 ncb.Command = netbios.NCBASTAT
596 ncb.Lana_num = ord(adapters.lana[i])
597 ncb.Callname = '*'.ljust(16)
598 ncb.Buffer = status = netbios.ADAPTER_STATUS()
599 if win32wnet.Netbios(ncb) != 0:
600 continue
601 status._unpack()
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300602 bytes = status.adapter_address[:6]
603 if len(bytes) != 6:
604 continue
Barry Warsaw23df2d12017-11-28 17:26:04 -0500605 mac = int.from_bytes(bytes, 'big')
606 if _is_universal(mac):
607 return mac
608 first_local_mac = first_local_mac or mac
609 return first_local_mac or None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000610
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000611
Antoine Pitroua106aec2017-09-28 23:03:06 +0200612_generate_time_safe = _UuidCreate = None
613_has_uuid_generate_time_safe = None
614
615# Import optional C extension at toplevel, to help disabling it when testing
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000616try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200617 import _uuid
618except ImportError:
619 _uuid = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000620
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000621
Antoine Pitroua106aec2017-09-28 23:03:06 +0200622def _load_system_functions():
623 """
624 Try to load platform-specific functions for generating uuids.
625 """
626 global _generate_time_safe, _UuidCreate, _has_uuid_generate_time_safe
Ronald Oussorenac764d32010-05-05 15:32:33 +0000627
Antoine Pitroua106aec2017-09-28 23:03:06 +0200628 if _has_uuid_generate_time_safe is not None:
629 return
630
631 _has_uuid_generate_time_safe = False
632
633 if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
634 # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
635 # in issue #8621 the function generates the same sequence of values
636 # in the parent process and all children created using fork (unless
637 # those children use exec as well).
638 #
639 # Assume that the uuid_generate functions are broken from 10.5 onward,
640 # the test can be adjusted when a later version is fixed.
641 pass
642 elif _uuid is not None:
643 _generate_time_safe = _uuid.generate_time_safe
Victor Stinner4337a0d2017-10-02 07:57:59 -0700644 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
Antoine Pitroua106aec2017-09-28 23:03:06 +0200645 return
646
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000647 try:
Antoine Pitroua106aec2017-09-28 23:03:06 +0200648 # If we couldn't find an extension module, try ctypes to find
649 # system routines for UUID generation.
650 # Thanks to Thomas Heller for ctypes and for his help with its use here.
651 import ctypes
652 import ctypes.util
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000653
Antoine Pitroua106aec2017-09-28 23:03:06 +0200654 # The uuid_generate_* routines are provided by libuuid on at least
655 # Linux and FreeBSD, and provided by libc on Mac OS X.
656 _libnames = ['uuid']
657 if not sys.platform.startswith('win'):
658 _libnames.append('c')
659 for libname in _libnames:
660 try:
661 lib = ctypes.CDLL(ctypes.util.find_library(libname))
662 except Exception: # pragma: nocover
663 continue
664 # Try to find the safe variety first.
665 if hasattr(lib, 'uuid_generate_time_safe'):
666 _uuid_generate_time_safe = lib.uuid_generate_time_safe
667 # int uuid_generate_time_safe(uuid_t out);
668 def _generate_time_safe():
669 _buffer = ctypes.create_string_buffer(16)
670 res = _uuid_generate_time_safe(_buffer)
671 return bytes(_buffer.raw), res
672 _has_uuid_generate_time_safe = True
673 break
674
675 elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
676 _uuid_generate_time = lib.uuid_generate_time
677 # void uuid_generate_time(uuid_t out);
678 _uuid_generate_time.restype = None
679 def _generate_time_safe():
680 _buffer = ctypes.create_string_buffer(16)
681 _uuid_generate_time(_buffer)
682 return bytes(_buffer.raw), None
683 break
684
685 # On Windows prior to 2000, UuidCreate gives a UUID containing the
686 # hardware address. On Windows 2000 and later, UuidCreate makes a
687 # random UUID and UuidCreateSequential gives a UUID containing the
688 # hardware address. These routines are provided by the RPC runtime.
689 # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
690 # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
691 # to bear any relationship to the MAC address of any network device
692 # on the box.
693 try:
694 lib = ctypes.windll.rpcrt4
695 except:
696 lib = None
697 _UuidCreate = getattr(lib, 'UuidCreateSequential',
698 getattr(lib, 'UuidCreate', None))
699
700 except Exception as exc:
701 import warnings
702 warnings.warn(f"Could not find fallback ctypes uuid functions: {exc}",
703 ImportWarning)
704
705
706def _unix_getnode():
707 """Get the hardware address on Unix using the _uuid extension module
708 or ctypes."""
709 _load_system_functions()
710 uuid_time, _ = _generate_time_safe()
711 return UUID(bytes=uuid_time).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000712
713def _windll_getnode():
714 """Get the hardware address on Windows using ctypes."""
Antoine Pitroua106aec2017-09-28 23:03:06 +0200715 import ctypes
716 _load_system_functions()
Guido van Rossum37410aa2007-08-24 04:13:42 +0000717 _buffer = ctypes.create_string_buffer(16)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000718 if _UuidCreate(_buffer) == 0:
Guido van Rossumfb56d8f2007-07-20 17:45:09 +0000719 return UUID(bytes=bytes_(_buffer.raw)).node
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000720
721def _random_getnode():
Barry Warsaw23df2d12017-11-28 17:26:04 -0500722 """Get a random node ID."""
723 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
724 # pseudo-randomly generated value may be used; see Section 4.5. The
725 # multicast bit must be set in such addresses, in order that they will
726 # never conflict with addresses obtained from network cards."
727 #
728 # The "multicast bit" of a MAC address is defined to be "the least
729 # significant bit of the first octet". This works out to be the 41st bit
730 # counting from 1 being the least significant bit, or 1<<40.
731 #
732 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000733 import random
Barry Warsaw23df2d12017-11-28 17:26:04 -0500734 return random.getrandbits(48) | (1 << 40)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000735
Antoine Pitroua106aec2017-09-28 23:03:06 +0200736
Min ho Kim39d87b52019-08-31 06:21:19 +1000737# _OS_GETTERS, when known, are targeted for a specific OS or platform.
Michael Felt3a1d50e2019-06-15 17:52:29 +0200738# The order is by 'common practice' on the specified platform.
739# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
740# which, when successful, means none of these "external" methods are called.
741# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
742# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
743if _LINUX:
744 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
745elif _DARWIN:
746 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
747elif _WINDOWS:
748 _OS_GETTERS = [_netbios_getnode, _ipconfig_getnode]
749elif _AIX:
750 _OS_GETTERS = [_netstat_getnode]
751else:
752 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
753 _netstat_getnode, _lanscan_getnode]
754if os.name == 'posix':
755 _GETTERS = [_unix_getnode] + _OS_GETTERS
756elif os.name == 'nt':
757 _GETTERS = [_windll_getnode] + _OS_GETTERS
758else:
759 _GETTERS = _OS_GETTERS
760
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000761_node = None
762
Shantanu8b6f6522020-02-05 12:43:09 -0800763def getnode():
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000764 """Get the hardware address as a 48-bit positive integer.
765
766 The first time this runs, it may launch a separate program, which could
767 be quite slow. If all attempts to obtain the hardware address fail, we
768 choose a random 48-bit number with its eighth bit set to 1 as recommended
769 in RFC 4122.
770 """
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000771 global _node
772 if _node is not None:
773 return _node
774
Michael Felt3a1d50e2019-06-15 17:52:29 +0200775 for getter in _GETTERS + [_random_getnode]:
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000776 try:
777 _node = getter()
778 except:
779 continue
Bo Bayles6b273f72018-01-23 19:11:44 -0600780 if (_node is not None) and (0 <= _node < (1 << 48)):
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000781 return _node
Bo Bayles6b273f72018-01-23 19:11:44 -0600782 assert False, '_random_getnode() returned invalid value: {}'.format(_node)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000783
Antoine Pitroua106aec2017-09-28 23:03:06 +0200784
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000785_last_timestamp = None
786
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000787def uuid1(node=None, clock_seq=None):
788 """Generate a UUID from a host ID, sequence number, and the current time.
789 If 'node' is not given, getnode() is used to obtain the hardware
790 address. If 'clock_seq' is given, it is used as the sequence number;
791 otherwise a random 14-bit sequence number is chosen."""
792
793 # When the system provides a version-1 UUID generator, use it (but don't
794 # use UuidCreate here because its UUIDs don't conform to RFC 4122).
Antoine Pitroua106aec2017-09-28 23:03:06 +0200795 _load_system_functions()
796 if _generate_time_safe is not None and node is clock_seq is None:
797 uuid_time, safely_generated = _generate_time_safe()
Barry Warsaw8c130d72017-02-18 15:45:49 -0500798 try:
799 is_safe = SafeUUID(safely_generated)
800 except ValueError:
801 is_safe = SafeUUID.unknown
Antoine Pitroua106aec2017-09-28 23:03:06 +0200802 return UUID(bytes=uuid_time, is_safe=is_safe)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000803
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000804 global _last_timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000805 import time
Victor Stinner62a68b72018-12-18 11:45:13 +0100806 nanoseconds = time.time_ns()
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000807 # 0x01b21dd213814000 is the number of 100-ns intervals between the
808 # 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 +0100809 timestamp = nanoseconds // 100 + 0x01b21dd213814000
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000810 if _last_timestamp is not None and timestamp <= _last_timestamp:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000811 timestamp = _last_timestamp + 1
812 _last_timestamp = timestamp
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000813 if clock_seq is None:
814 import random
Serhiy Storchakafa9be4f2014-09-06 22:14:04 +0300815 clock_seq = random.getrandbits(14) # instead of stable storage
Guido van Rossume2a383d2007-01-15 16:59:06 +0000816 time_low = timestamp & 0xffffffff
817 time_mid = (timestamp >> 32) & 0xffff
818 time_hi_version = (timestamp >> 48) & 0x0fff
819 clock_seq_low = clock_seq & 0xff
820 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000821 if node is None:
822 node = getnode()
823 return UUID(fields=(time_low, time_mid, time_hi_version,
824 clock_seq_hi_variant, clock_seq_low, node), version=1)
825
826def uuid3(namespace, name):
827 """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000828 from hashlib import md5
Christian Heimes7cad53e2019-09-13 02:30:00 +0200829 digest = md5(
830 namespace.bytes + bytes(name, "utf-8"),
831 usedforsecurity=False
832 ).digest()
833 return UUID(bytes=digest[:16], version=3)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000834
835def uuid4():
836 """Generate a random UUID."""
Benjamin Peterson788cb522015-10-29 20:38:04 -0700837 return UUID(bytes=os.urandom(16), version=4)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000838
839def uuid5(namespace, name):
840 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
Guido van Rossume7ba4952007-06-06 23:52:48 +0000841 from hashlib import sha1
Guido van Rossum65b6a802007-07-09 14:03:08 +0000842 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
Guido van Rossum5ed033b2007-07-09 14:29:40 +0000843 return UUID(bytes=hash[:16], version=5)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000844
845# The following standard UUIDs are for use with uuid3() or uuid5().
846
847NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
848NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
849NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
850NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')