Coverage for /pythoncovmergedfiles/medio/medio/usr/lib/python3.9/uuid.py: 31%

364 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-10-20 07:00 +0000

1r"""UUID objects (universally unique identifiers) according to RFC 4122. 

2 

3This module provides immutable UUID objects (class UUID) and the functions 

4uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 

5UUIDs as specified in RFC 4122. 

6 

7If all you want is a unique ID, you should probably call uuid1() or uuid4(). 

8Note that uuid1() may compromise privacy since it creates a UUID containing 

9the computer's network address. uuid4() creates a random UUID. 

10 

11Typical usage: 

12 

13 >>> import uuid 

14 

15 # make a UUID based on the host ID and current time 

16 >>> uuid.uuid1() # doctest: +SKIP 

17 UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') 

18 

19 # make a UUID using an MD5 hash of a namespace UUID and a name 

20 >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') 

21 UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') 

22 

23 # make a random UUID 

24 >>> uuid.uuid4() # doctest: +SKIP 

25 UUID('16fd2706-8baf-433b-82eb-8c7fada847da') 

26 

27 # make a UUID using a SHA-1 hash of a namespace UUID and a name 

28 >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') 

29 UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') 

30 

31 # make a UUID from a string of hex digits (braces and hyphens ignored) 

32 >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') 

33 

34 # convert a UUID to a string of hex digits in standard form 

35 >>> str(x) 

36 '00010203-0405-0607-0809-0a0b0c0d0e0f' 

37 

38 # get the raw 16 bytes of the UUID 

39 >>> x.bytes 

40 b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' 

41 

42 # make a UUID from a 16-byte string 

43 >>> uuid.UUID(bytes=x.bytes) 

44 UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') 

45""" 

46 

47import os 

48import sys 

49 

50from enum import Enum 

51 

52 

53__author__ = 'Ka-Ping Yee <ping@zesty.ca>' 

54 

55# The recognized platforms - known behaviors 

56if sys.platform in ('win32', 'darwin'): 

57 _AIX = _LINUX = False 

58else: 

59 import platform 

60 _platform_system = platform.system() 

61 _AIX = _platform_system == 'AIX' 

62 _LINUX = _platform_system == 'Linux' 

63 

64_MAC_DELIM = b':' 

65_MAC_OMITS_LEADING_ZEROES = False 

66if _AIX: 

67 _MAC_DELIM = b'.' 

68 _MAC_OMITS_LEADING_ZEROES = True 

69 

70RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ 

71 'reserved for NCS compatibility', 'specified in RFC 4122', 

72 'reserved for Microsoft compatibility', 'reserved for future definition'] 

73 

74int_ = int # The built-in int type 

75bytes_ = bytes # The built-in bytes type 

76 

77 

78class SafeUUID(Enum): 

79 safe = 0 

80 unsafe = -1 

81 unknown = None 

82 

83 

84class UUID: 

85 """Instances of the UUID class represent UUIDs as specified in RFC 4122. 

86 UUID objects are immutable, hashable, and usable as dictionary keys. 

87 Converting a UUID to a string with str() yields something in the form 

88 '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts 

89 five possible forms: a similar string of hexadecimal digits, or a tuple 

90 of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 

91 48-bit values respectively) as an argument named 'fields', or a string 

92 of 16 bytes (with all the integer fields in big-endian order) as an 

93 argument named 'bytes', or a string of 16 bytes (with the first three 

94 fields in little-endian order) as an argument named 'bytes_le', or a 

95 single 128-bit integer as an argument named 'int'. 

96 

97 UUIDs have these read-only attributes: 

98 

99 bytes the UUID as a 16-byte string (containing the six 

100 integer fields in big-endian byte order) 

101 

102 bytes_le the UUID as a 16-byte string (with time_low, time_mid, 

103 and time_hi_version in little-endian byte order) 

104 

105 fields a tuple of the six integer fields of the UUID, 

106 which are also available as six individual attributes 

107 and two derived attributes: 

108 

109 time_low the first 32 bits of the UUID 

110 time_mid the next 16 bits of the UUID 

111 time_hi_version the next 16 bits of the UUID 

112 clock_seq_hi_variant the next 8 bits of the UUID 

113 clock_seq_low the next 8 bits of the UUID 

114 node the last 48 bits of the UUID 

115 

116 time the 60-bit timestamp 

117 clock_seq the 14-bit sequence number 

118 

119 hex the UUID as a 32-character hexadecimal string 

120 

121 int the UUID as a 128-bit integer 

122 

123 urn the UUID as a URN as specified in RFC 4122 

124 

125 variant the UUID variant (one of the constants RESERVED_NCS, 

126 RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) 

127 

128 version the UUID version number (1 through 5, meaningful only 

129 when the variant is RFC_4122) 

130 

131 is_safe An enum indicating whether the UUID has been generated in 

132 a way that is safe for multiprocessing applications, via 

133 uuid_generate_time_safe(3). 

134 """ 

135 

136 __slots__ = ('int', 'is_safe', '__weakref__') 

137 

138 def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, 

139 int=None, version=None, 

140 *, is_safe=SafeUUID.unknown): 

141 r"""Create a UUID from either a string of 32 hexadecimal digits, 

142 a string of 16 bytes as the 'bytes' argument, a string of 16 bytes 

143 in little-endian order as the 'bytes_le' argument, a tuple of six 

144 integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 

145 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as 

146 the 'fields' argument, or a single 128-bit integer as the 'int' 

147 argument. When a string of hex digits is given, curly braces, 

148 hyphens, and a URN prefix are all optional. For example, these 

149 expressions all yield the same UUID: 

150 

151 UUID('{12345678-1234-5678-1234-567812345678}') 

152 UUID('12345678123456781234567812345678') 

153 UUID('urn:uuid:12345678-1234-5678-1234-567812345678') 

154 UUID(bytes='\x12\x34\x56\x78'*4) 

155 UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' + 

156 '\x12\x34\x56\x78\x12\x34\x56\x78') 

157 UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) 

158 UUID(int=0x12345678123456781234567812345678) 

159 

160 Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must 

161 be given. The 'version' argument is optional; if given, the resulting 

162 UUID will have its variant and version set according to RFC 4122, 

163 overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'. 

164 

165 is_safe is an enum exposed as an attribute on the instance. It 

166 indicates whether the UUID has been generated in a way that is safe 

167 for multiprocessing applications, via uuid_generate_time_safe(3). 

168 """ 

169 

170 if [hex, bytes, bytes_le, fields, int].count(None) != 4: 

171 raise TypeError('one of the hex, bytes, bytes_le, fields, ' 

172 'or int arguments must be given') 

173 if hex is not None: 

174 hex = hex.replace('urn:', '').replace('uuid:', '') 

175 hex = hex.strip('{}').replace('-', '') 

176 if len(hex) != 32: 

177 raise ValueError('badly formed hexadecimal UUID string') 

178 int = int_(hex, 16) 

179 if bytes_le is not None: 

180 if len(bytes_le) != 16: 

181 raise ValueError('bytes_le is not a 16-char string') 

182 bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] + 

183 bytes_le[8-1:6-1:-1] + bytes_le[8:]) 

184 if bytes is not None: 

185 if len(bytes) != 16: 

186 raise ValueError('bytes is not a 16-char string') 

187 assert isinstance(bytes, bytes_), repr(bytes) 

188 int = int_.from_bytes(bytes, byteorder='big') 

189 if fields is not None: 

190 if len(fields) != 6: 

191 raise ValueError('fields is not a 6-tuple') 

192 (time_low, time_mid, time_hi_version, 

193 clock_seq_hi_variant, clock_seq_low, node) = fields 

194 if not 0 <= time_low < 1<<32: 

195 raise ValueError('field 1 out of range (need a 32-bit value)') 

196 if not 0 <= time_mid < 1<<16: 

197 raise ValueError('field 2 out of range (need a 16-bit value)') 

198 if not 0 <= time_hi_version < 1<<16: 

199 raise ValueError('field 3 out of range (need a 16-bit value)') 

200 if not 0 <= clock_seq_hi_variant < 1<<8: 

201 raise ValueError('field 4 out of range (need an 8-bit value)') 

202 if not 0 <= clock_seq_low < 1<<8: 

203 raise ValueError('field 5 out of range (need an 8-bit value)') 

204 if not 0 <= node < 1<<48: 

205 raise ValueError('field 6 out of range (need a 48-bit value)') 

206 clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low 

207 int = ((time_low << 96) | (time_mid << 80) | 

208 (time_hi_version << 64) | (clock_seq << 48) | node) 

209 if int is not None: 

210 if not 0 <= int < 1<<128: 

211 raise ValueError('int is out of range (need a 128-bit value)') 

212 if version is not None: 

213 if not 1 <= version <= 5: 

214 raise ValueError('illegal version number') 

215 # Set the variant to RFC 4122. 

216 int &= ~(0xc000 << 48) 

217 int |= 0x8000 << 48 

218 # Set the version number. 

219 int &= ~(0xf000 << 64) 

220 int |= version << 76 

221 object.__setattr__(self, 'int', int) 

222 object.__setattr__(self, 'is_safe', is_safe) 

223 

224 def __getstate__(self): 

225 d = {'int': self.int} 

226 if self.is_safe != SafeUUID.unknown: 

227 # is_safe is a SafeUUID instance. Return just its value, so that 

228 # it can be un-pickled in older Python versions without SafeUUID. 

229 d['is_safe'] = self.is_safe.value 

230 return d 

231 

232 def __setstate__(self, state): 

233 object.__setattr__(self, 'int', state['int']) 

234 # is_safe was added in 3.7; it is also omitted when it is "unknown" 

235 object.__setattr__(self, 'is_safe', 

236 SafeUUID(state['is_safe']) 

237 if 'is_safe' in state else SafeUUID.unknown) 

238 

239 def __eq__(self, other): 

240 if isinstance(other, UUID): 

241 return self.int == other.int 

242 return NotImplemented 

243 

244 # Q. What's the value of being able to sort UUIDs? 

245 # A. Use them as keys in a B-Tree or similar mapping. 

246 

247 def __lt__(self, other): 

248 if isinstance(other, UUID): 

249 return self.int < other.int 

250 return NotImplemented 

251 

252 def __gt__(self, other): 

253 if isinstance(other, UUID): 

254 return self.int > other.int 

255 return NotImplemented 

256 

257 def __le__(self, other): 

258 if isinstance(other, UUID): 

259 return self.int <= other.int 

260 return NotImplemented 

261 

262 def __ge__(self, other): 

263 if isinstance(other, UUID): 

264 return self.int >= other.int 

265 return NotImplemented 

266 

267 def __hash__(self): 

268 return hash(self.int) 

269 

270 def __int__(self): 

271 return self.int 

272 

273 def __repr__(self): 

274 return '%s(%r)' % (self.__class__.__name__, str(self)) 

275 

276 def __setattr__(self, name, value): 

277 raise TypeError('UUID objects are immutable') 

278 

279 def __str__(self): 

280 hex = '%032x' % self.int 

281 return '%s-%s-%s-%s-%s' % ( 

282 hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) 

283 

284 @property 

285 def bytes(self): 

286 return self.int.to_bytes(16, 'big') 

287 

288 @property 

289 def bytes_le(self): 

290 bytes = self.bytes 

291 return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] + 

292 bytes[8:]) 

293 

294 @property 

295 def fields(self): 

296 return (self.time_low, self.time_mid, self.time_hi_version, 

297 self.clock_seq_hi_variant, self.clock_seq_low, self.node) 

298 

299 @property 

300 def time_low(self): 

301 return self.int >> 96 

302 

303 @property 

304 def time_mid(self): 

305 return (self.int >> 80) & 0xffff 

306 

307 @property 

308 def time_hi_version(self): 

309 return (self.int >> 64) & 0xffff 

310 

311 @property 

312 def clock_seq_hi_variant(self): 

313 return (self.int >> 56) & 0xff 

314 

315 @property 

316 def clock_seq_low(self): 

317 return (self.int >> 48) & 0xff 

318 

319 @property 

320 def time(self): 

321 return (((self.time_hi_version & 0x0fff) << 48) | 

322 (self.time_mid << 32) | self.time_low) 

323 

324 @property 

325 def clock_seq(self): 

326 return (((self.clock_seq_hi_variant & 0x3f) << 8) | 

327 self.clock_seq_low) 

328 

329 @property 

330 def node(self): 

331 return self.int & 0xffffffffffff 

332 

333 @property 

334 def hex(self): 

335 return '%032x' % self.int 

336 

337 @property 

338 def urn(self): 

339 return 'urn:uuid:' + str(self) 

340 

341 @property 

342 def variant(self): 

343 if not self.int & (0x8000 << 48): 

344 return RESERVED_NCS 

345 elif not self.int & (0x4000 << 48): 

346 return RFC_4122 

347 elif not self.int & (0x2000 << 48): 

348 return RESERVED_MICROSOFT 

349 else: 

350 return RESERVED_FUTURE 

351 

352 @property 

353 def version(self): 

354 # The version bits are only meaningful for RFC 4122 UUIDs. 

355 if self.variant == RFC_4122: 

356 return int((self.int >> 76) & 0xf) 

357 

358 

359def _get_command_stdout(command, *args): 

360 import io, os, shutil, subprocess 

361 

362 try: 

363 path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep) 

364 path_dirs.extend(['/sbin', '/usr/sbin']) 

365 executable = shutil.which(command, path=os.pathsep.join(path_dirs)) 

366 if executable is None: 

367 return None 

368 # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output 

369 # on stderr (Note: we don't have an example where the words we search 

370 # for are actually localized, but in theory some system could do so.) 

371 env = dict(os.environ) 

372 env['LC_ALL'] = 'C' 

373 proc = subprocess.Popen((executable,) + args, 

374 stdout=subprocess.PIPE, 

375 stderr=subprocess.DEVNULL, 

376 env=env) 

377 if not proc: 

378 return None 

379 stdout, stderr = proc.communicate() 

380 return io.BytesIO(stdout) 

381 except (OSError, subprocess.SubprocessError): 

382 return None 

383 

384 

385# For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant 

386# bit of the first octet signifies whether the MAC address is universally (0) 

387# or locally (1) administered. Network cards from hardware manufacturers will 

388# always be universally administered to guarantee global uniqueness of the MAC 

389# address, but any particular machine may have other interfaces which are 

390# locally administered. An example of the latter is the bridge interface to 

391# the Touch Bar on MacBook Pros. 

392# 

393# This bit works out to be the 42nd bit counting from 1 being the least 

394# significant, or 1<<41. We'll prefer universally administered MAC addresses 

395# over locally administered ones since the former are globally unique, but 

396# we'll return the first of the latter found if that's all the machine has. 

397# 

398# See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local 

399 

400def _is_universal(mac): 

401 return not (mac & (1 << 41)) 

402 

403 

404def _find_mac_near_keyword(command, args, keywords, get_word_index): 

405 """Searches a command's output for a MAC address near a keyword. 

406 

407 Each line of words in the output is case-insensitively searched for 

408 any of the given keywords. Upon a match, get_word_index is invoked 

409 to pick a word from the line, given the index of the match. For 

410 example, lambda i: 0 would get the first word on the line, while 

411 lambda i: i - 1 would get the word preceding the keyword. 

412 """ 

413 stdout = _get_command_stdout(command, args) 

414 if stdout is None: 

415 return None 

416 

417 first_local_mac = None 

418 for line in stdout: 

419 words = line.lower().rstrip().split() 

420 for i in range(len(words)): 

421 if words[i] in keywords: 

422 try: 

423 word = words[get_word_index(i)] 

424 mac = int(word.replace(_MAC_DELIM, b''), 16) 

425 except (ValueError, IndexError): 

426 # Virtual interfaces, such as those provided by 

427 # VPNs, do not have a colon-delimited MAC address 

428 # as expected, but a 16-byte HWAddr separated by 

429 # dashes. These should be ignored in favor of a 

430 # real MAC address 

431 pass 

432 else: 

433 if _is_universal(mac): 

434 return mac 

435 first_local_mac = first_local_mac or mac 

436 return first_local_mac or None 

437 

438 

439def _parse_mac(word): 

440 # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'), 

441 # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8'). 

442 # 

443 # Virtual interfaces, such as those provided by VPNs, do not have a 

444 # colon-delimited MAC address as expected, but a 16-byte HWAddr separated 

445 # by dashes. These should be ignored in favor of a real MAC address 

446 parts = word.split(_MAC_DELIM) 

447 if len(parts) != 6: 

448 return 

449 if _MAC_OMITS_LEADING_ZEROES: 

450 # (Only) on AIX the macaddr value given is not prefixed by 0, e.g. 

451 # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0 

452 # not 

453 # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0 

454 if not all(1 <= len(part) <= 2 for part in parts): 

455 return 

456 hexstr = b''.join(part.rjust(2, b'0') for part in parts) 

457 else: 

458 if not all(len(part) == 2 for part in parts): 

459 return 

460 hexstr = b''.join(parts) 

461 try: 

462 return int(hexstr, 16) 

463 except ValueError: 

464 return 

465 

466 

467def _find_mac_under_heading(command, args, heading): 

468 """Looks for a MAC address under a heading in a command's output. 

469 

470 The first line of words in the output is searched for the given 

471 heading. Words at the same word index as the heading in subsequent 

472 lines are then examined to see if they look like MAC addresses. 

473 """ 

474 stdout = _get_command_stdout(command, args) 

475 if stdout is None: 

476 return None 

477 

478 keywords = stdout.readline().rstrip().split() 

479 try: 

480 column_index = keywords.index(heading) 

481 except ValueError: 

482 return None 

483 

484 first_local_mac = None 

485 for line in stdout: 

486 words = line.rstrip().split() 

487 try: 

488 word = words[column_index] 

489 except IndexError: 

490 continue 

491 

492 mac = _parse_mac(word) 

493 if mac is None: 

494 continue 

495 if _is_universal(mac): 

496 return mac 

497 if first_local_mac is None: 

498 first_local_mac = mac 

499 

500 return first_local_mac 

501 

502 

503# The following functions call external programs to 'get' a macaddr value to 

504# be used as basis for an uuid 

505def _ifconfig_getnode(): 

506 """Get the hardware address on Unix by running ifconfig.""" 

507 # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes. 

508 keywords = (b'hwaddr', b'ether', b'address:', b'lladdr') 

509 for args in ('', '-a', '-av'): 

510 mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1) 

511 if mac: 

512 return mac 

513 return None 

514 

515def _ip_getnode(): 

516 """Get the hardware address on Unix by running ip.""" 

517 # This works on Linux with iproute2. 

518 mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1) 

519 if mac: 

520 return mac 

521 return None 

522 

523def _arp_getnode(): 

524 """Get the hardware address on Unix by running arp.""" 

525 import os, socket 

526 try: 

527 ip_addr = socket.gethostbyname(socket.gethostname()) 

528 except OSError: 

529 return None 

530 

531 # Try getting the MAC addr from arp based on our IP address (Solaris). 

532 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1) 

533 if mac: 

534 return mac 

535 

536 # This works on OpenBSD 

537 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1) 

538 if mac: 

539 return mac 

540 

541 # This works on Linux, FreeBSD and NetBSD 

542 mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)], 

543 lambda i: i+2) 

544 # Return None instead of 0. 

545 if mac: 

546 return mac 

547 return None 

548 

549def _lanscan_getnode(): 

550 """Get the hardware address on Unix by running lanscan.""" 

551 # This might work on HP-UX. 

552 return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0) 

553 

554def _netstat_getnode(): 

555 """Get the hardware address on Unix by running netstat.""" 

556 # This works on AIX and might work on Tru64 UNIX. 

557 return _find_mac_under_heading('netstat', '-ian', b'Address') 

558 

559def _ipconfig_getnode(): 

560 """[DEPRECATED] Get the hardware address on Windows.""" 

561 # bpo-40501: UuidCreateSequential() is now the only supported approach 

562 return _windll_getnode() 

563 

564def _netbios_getnode(): 

565 """[DEPRECATED] Get the hardware address on Windows.""" 

566 # bpo-40501: UuidCreateSequential() is now the only supported approach 

567 return _windll_getnode() 

568 

569 

570# Import optional C extension at toplevel, to help disabling it when testing 

571try: 

572 import _uuid 

573 _generate_time_safe = getattr(_uuid, "generate_time_safe", None) 

574 _UuidCreate = getattr(_uuid, "UuidCreate", None) 

575 _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe 

576except ImportError: 

577 _uuid = None 

578 _generate_time_safe = None 

579 _UuidCreate = None 

580 _has_uuid_generate_time_safe = None 

581 

582 

583def _load_system_functions(): 

584 """[DEPRECATED] Platform-specific functions loaded at import time""" 

585 

586 

587def _unix_getnode(): 

588 """Get the hardware address on Unix using the _uuid extension module.""" 

589 if _generate_time_safe: 

590 uuid_time, _ = _generate_time_safe() 

591 return UUID(bytes=uuid_time).node 

592 

593def _windll_getnode(): 

594 """Get the hardware address on Windows using the _uuid extension module.""" 

595 if _UuidCreate: 

596 uuid_bytes = _UuidCreate() 

597 return UUID(bytes_le=uuid_bytes).node 

598 

599def _random_getnode(): 

600 """Get a random node ID.""" 

601 # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or 

602 # pseudo-randomly generated value may be used; see Section 4.5. The 

603 # multicast bit must be set in such addresses, in order that they will 

604 # never conflict with addresses obtained from network cards." 

605 # 

606 # The "multicast bit" of a MAC address is defined to be "the least 

607 # significant bit of the first octet". This works out to be the 41st bit 

608 # counting from 1 being the least significant bit, or 1<<40. 

609 # 

610 # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast 

611 import random 

612 return random.getrandbits(48) | (1 << 40) 

613 

614 

615# _OS_GETTERS, when known, are targeted for a specific OS or platform. 

616# The order is by 'common practice' on the specified platform. 

617# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method 

618# which, when successful, means none of these "external" methods are called. 

619# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g., 

620# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...) 

621if _LINUX: 

622 _OS_GETTERS = [_ip_getnode, _ifconfig_getnode] 

623elif sys.platform == 'darwin': 

624 _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode] 

625elif sys.platform == 'win32': 

626 # bpo-40201: _windll_getnode will always succeed, so these are not needed 

627 _OS_GETTERS = [] 

628elif _AIX: 

629 _OS_GETTERS = [_netstat_getnode] 

630else: 

631 _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode, 

632 _netstat_getnode, _lanscan_getnode] 

633if os.name == 'posix': 

634 _GETTERS = [_unix_getnode] + _OS_GETTERS 

635elif os.name == 'nt': 

636 _GETTERS = [_windll_getnode] + _OS_GETTERS 

637else: 

638 _GETTERS = _OS_GETTERS 

639 

640_node = None 

641 

642def getnode(): 

643 """Get the hardware address as a 48-bit positive integer. 

644 

645 The first time this runs, it may launch a separate program, which could 

646 be quite slow. If all attempts to obtain the hardware address fail, we 

647 choose a random 48-bit number with its eighth bit set to 1 as recommended 

648 in RFC 4122. 

649 """ 

650 global _node 

651 if _node is not None: 

652 return _node 

653 

654 for getter in _GETTERS + [_random_getnode]: 

655 try: 

656 _node = getter() 

657 except: 

658 continue 

659 if (_node is not None) and (0 <= _node < (1 << 48)): 

660 return _node 

661 assert False, '_random_getnode() returned invalid value: {}'.format(_node) 

662 

663 

664_last_timestamp = None 

665 

666def uuid1(node=None, clock_seq=None): 

667 """Generate a UUID from a host ID, sequence number, and the current time. 

668 If 'node' is not given, getnode() is used to obtain the hardware 

669 address. If 'clock_seq' is given, it is used as the sequence number; 

670 otherwise a random 14-bit sequence number is chosen.""" 

671 

672 # When the system provides a version-1 UUID generator, use it (but don't 

673 # use UuidCreate here because its UUIDs don't conform to RFC 4122). 

674 if _generate_time_safe is not None and node is clock_seq is None: 

675 uuid_time, safely_generated = _generate_time_safe() 

676 try: 

677 is_safe = SafeUUID(safely_generated) 

678 except ValueError: 

679 is_safe = SafeUUID.unknown 

680 return UUID(bytes=uuid_time, is_safe=is_safe) 

681 

682 global _last_timestamp 

683 import time 

684 nanoseconds = time.time_ns() 

685 # 0x01b21dd213814000 is the number of 100-ns intervals between the 

686 # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. 

687 timestamp = nanoseconds // 100 + 0x01b21dd213814000 

688 if _last_timestamp is not None and timestamp <= _last_timestamp: 

689 timestamp = _last_timestamp + 1 

690 _last_timestamp = timestamp 

691 if clock_seq is None: 

692 import random 

693 clock_seq = random.getrandbits(14) # instead of stable storage 

694 time_low = timestamp & 0xffffffff 

695 time_mid = (timestamp >> 32) & 0xffff 

696 time_hi_version = (timestamp >> 48) & 0x0fff 

697 clock_seq_low = clock_seq & 0xff 

698 clock_seq_hi_variant = (clock_seq >> 8) & 0x3f 

699 if node is None: 

700 node = getnode() 

701 return UUID(fields=(time_low, time_mid, time_hi_version, 

702 clock_seq_hi_variant, clock_seq_low, node), version=1) 

703 

704def uuid3(namespace, name): 

705 """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" 

706 from hashlib import md5 

707 digest = md5( 

708 namespace.bytes + bytes(name, "utf-8"), 

709 usedforsecurity=False 

710 ).digest() 

711 return UUID(bytes=digest[:16], version=3) 

712 

713def uuid4(): 

714 """Generate a random UUID.""" 

715 return UUID(bytes=os.urandom(16), version=4) 

716 

717def uuid5(namespace, name): 

718 """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" 

719 from hashlib import sha1 

720 hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest() 

721 return UUID(bytes=hash[:16], version=5) 

722 

723# The following standard UUIDs are for use with uuid3() or uuid5(). 

724 

725NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') 

726NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') 

727NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') 

728NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')