uuid.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. r"""UUID objects (universally unique identifiers) according to RFC 4122.
  2. This module provides immutable UUID objects (class UUID) and the functions
  3. uuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5
  4. UUIDs as specified in RFC 4122.
  5. If all you want is a unique ID, you should probably call uuid1() or uuid4().
  6. Note that uuid1() may compromise privacy since it creates a UUID containing
  7. the computer's network address. uuid4() creates a random UUID.
  8. Typical usage:
  9. >>> import uuid
  10. # make a UUID based on the host ID and current time
  11. >>> uuid.uuid1() # doctest: +SKIP
  12. UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
  13. # make a UUID using an MD5 hash of a namespace UUID and a name
  14. >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
  15. UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
  16. # make a random UUID
  17. >>> uuid.uuid4() # doctest: +SKIP
  18. UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
  19. # make a UUID using a SHA-1 hash of a namespace UUID and a name
  20. >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
  21. UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
  22. # make a UUID from a string of hex digits (braces and hyphens ignored)
  23. >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
  24. # convert a UUID to a string of hex digits in standard form
  25. >>> str(x)
  26. '00010203-0405-0607-0809-0a0b0c0d0e0f'
  27. # get the raw 16 bytes of the UUID
  28. >>> x.bytes
  29. b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
  30. # make a UUID from a 16-byte string
  31. >>> uuid.UUID(bytes=x.bytes)
  32. UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
  33. """
  34. import os
  35. import sys
  36. from enum import Enum
  37. __author__ = 'Ka-Ping Yee <ping@zesty.ca>'
  38. RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
  39. 'reserved for NCS compatibility', 'specified in RFC 4122',
  40. 'reserved for Microsoft compatibility', 'reserved for future definition']
  41. int_ = int # The built-in int type
  42. bytes_ = bytes # The built-in bytes type
  43. class SafeUUID(Enum):
  44. safe = 0
  45. unsafe = -1
  46. unknown = None
  47. class UUID:
  48. """Instances of the UUID class represent UUIDs as specified in RFC 4122.
  49. UUID objects are immutable, hashable, and usable as dictionary keys.
  50. Converting a UUID to a string with str() yields something in the form
  51. '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts
  52. five possible forms: a similar string of hexadecimal digits, or a tuple
  53. of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and
  54. 48-bit values respectively) as an argument named 'fields', or a string
  55. of 16 bytes (with all the integer fields in big-endian order) as an
  56. argument named 'bytes', or a string of 16 bytes (with the first three
  57. fields in little-endian order) as an argument named 'bytes_le', or a
  58. single 128-bit integer as an argument named 'int'.
  59. UUIDs have these read-only attributes:
  60. bytes the UUID as a 16-byte string (containing the six
  61. integer fields in big-endian byte order)
  62. bytes_le the UUID as a 16-byte string (with time_low, time_mid,
  63. and time_hi_version in little-endian byte order)
  64. fields a tuple of the six integer fields of the UUID,
  65. which are also available as six individual attributes
  66. and two derived attributes:
  67. time_low the first 32 bits of the UUID
  68. time_mid the next 16 bits of the UUID
  69. time_hi_version the next 16 bits of the UUID
  70. clock_seq_hi_variant the next 8 bits of the UUID
  71. clock_seq_low the next 8 bits of the UUID
  72. node the last 48 bits of the UUID
  73. time the 60-bit timestamp
  74. clock_seq the 14-bit sequence number
  75. hex the UUID as a 32-character hexadecimal string
  76. int the UUID as a 128-bit integer
  77. urn the UUID as a URN as specified in RFC 4122
  78. variant the UUID variant (one of the constants RESERVED_NCS,
  79. RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE)
  80. version the UUID version number (1 through 5, meaningful only
  81. when the variant is RFC_4122)
  82. is_safe An enum indicating whether the UUID has been generated in
  83. a way that is safe for multiprocessing applications, via
  84. uuid_generate_time_safe(3).
  85. """
  86. def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
  87. int=None, version=None,
  88. *, is_safe=SafeUUID.unknown):
  89. r"""Create a UUID from either a string of 32 hexadecimal digits,
  90. a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
  91. in little-endian order as the 'bytes_le' argument, a tuple of six
  92. integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
  93. 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
  94. the 'fields' argument, or a single 128-bit integer as the 'int'
  95. argument. When a string of hex digits is given, curly braces,
  96. hyphens, and a URN prefix are all optional. For example, these
  97. expressions all yield the same UUID:
  98. UUID('{12345678-1234-5678-1234-567812345678}')
  99. UUID('12345678123456781234567812345678')
  100. UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
  101. UUID(bytes='\x12\x34\x56\x78'*4)
  102. UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
  103. '\x12\x34\x56\x78\x12\x34\x56\x78')
  104. UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
  105. UUID(int=0x12345678123456781234567812345678)
  106. Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
  107. be given. The 'version' argument is optional; if given, the resulting
  108. UUID will have its variant and version set according to RFC 4122,
  109. overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
  110. is_safe is an enum exposed as an attribute on the instance. It
  111. indicates whether the UUID has been generated in a way that is safe
  112. for multiprocessing applications, via uuid_generate_time_safe(3).
  113. """
  114. if [hex, bytes, bytes_le, fields, int].count(None) != 4:
  115. raise TypeError('one of the hex, bytes, bytes_le, fields, '
  116. 'or int arguments must be given')
  117. if hex is not None:
  118. hex = hex.replace('urn:', '').replace('uuid:', '')
  119. hex = hex.strip('{}').replace('-', '')
  120. if len(hex) != 32:
  121. raise ValueError('badly formed hexadecimal UUID string')
  122. int = int_(hex, 16)
  123. if bytes_le is not None:
  124. if len(bytes_le) != 16:
  125. raise ValueError('bytes_le is not a 16-char string')
  126. bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] +
  127. bytes_le[8-1:6-1:-1] + bytes_le[8:])
  128. if bytes is not None:
  129. if len(bytes) != 16:
  130. raise ValueError('bytes is not a 16-char string')
  131. assert isinstance(bytes, bytes_), repr(bytes)
  132. int = int_.from_bytes(bytes, byteorder='big')
  133. if fields is not None:
  134. if len(fields) != 6:
  135. raise ValueError('fields is not a 6-tuple')
  136. (time_low, time_mid, time_hi_version,
  137. clock_seq_hi_variant, clock_seq_low, node) = fields
  138. if not 0 <= time_low < 1<<32:
  139. raise ValueError('field 1 out of range (need a 32-bit value)')
  140. if not 0 <= time_mid < 1<<16:
  141. raise ValueError('field 2 out of range (need a 16-bit value)')
  142. if not 0 <= time_hi_version < 1<<16:
  143. raise ValueError('field 3 out of range (need a 16-bit value)')
  144. if not 0 <= clock_seq_hi_variant < 1<<8:
  145. raise ValueError('field 4 out of range (need an 8-bit value)')
  146. if not 0 <= clock_seq_low < 1<<8:
  147. raise ValueError('field 5 out of range (need an 8-bit value)')
  148. if not 0 <= node < 1<<48:
  149. raise ValueError('field 6 out of range (need a 48-bit value)')
  150. clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
  151. int = ((time_low << 96) | (time_mid << 80) |
  152. (time_hi_version << 64) | (clock_seq << 48) | node)
  153. if int is not None:
  154. if not 0 <= int < 1<<128:
  155. raise ValueError('int is out of range (need a 128-bit value)')
  156. if version is not None:
  157. if not 1 <= version <= 5:
  158. raise ValueError('illegal version number')
  159. # Set the variant to RFC 4122.
  160. int &= ~(0xc000 << 48)
  161. int |= 0x8000 << 48
  162. # Set the version number.
  163. int &= ~(0xf000 << 64)
  164. int |= version << 76
  165. self.__dict__['int'] = int
  166. self.__dict__['is_safe'] = is_safe
  167. def __getstate__(self):
  168. state = self.__dict__.copy()
  169. if self.is_safe != SafeUUID.unknown:
  170. # is_safe is a SafeUUID instance. Return just its value, so that
  171. # it can be un-pickled in older Python versions without SafeUUID.
  172. state['is_safe'] = self.is_safe.value
  173. else:
  174. # omit is_safe when it is "unknown"
  175. del state['is_safe']
  176. return state
  177. def __setstate__(self, state):
  178. self.__dict__.update(state)
  179. # is_safe was added in 3.7; it is also omitted when it is "unknown"
  180. self.__dict__['is_safe'] = (
  181. SafeUUID(state['is_safe'])
  182. if 'is_safe' in state else SafeUUID.unknown
  183. )
  184. def __eq__(self, other):
  185. if isinstance(other, UUID):
  186. return self.int == other.int
  187. return NotImplemented
  188. # Q. What's the value of being able to sort UUIDs?
  189. # A. Use them as keys in a B-Tree or similar mapping.
  190. def __lt__(self, other):
  191. if isinstance(other, UUID):
  192. return self.int < other.int
  193. return NotImplemented
  194. def __gt__(self, other):
  195. if isinstance(other, UUID):
  196. return self.int > other.int
  197. return NotImplemented
  198. def __le__(self, other):
  199. if isinstance(other, UUID):
  200. return self.int <= other.int
  201. return NotImplemented
  202. def __ge__(self, other):
  203. if isinstance(other, UUID):
  204. return self.int >= other.int
  205. return NotImplemented
  206. def __hash__(self):
  207. return hash(self.int)
  208. def __int__(self):
  209. return self.int
  210. def __repr__(self):
  211. return '%s(%r)' % (self.__class__.__name__, str(self))
  212. def __setattr__(self, name, value):
  213. raise TypeError('UUID objects are immutable')
  214. def __str__(self):
  215. hex = '%032x' % self.int
  216. return '%s-%s-%s-%s-%s' % (
  217. hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
  218. @property
  219. def bytes(self):
  220. return self.int.to_bytes(16, 'big')
  221. @property
  222. def bytes_le(self):
  223. bytes = self.bytes
  224. return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] +
  225. bytes[8:])
  226. @property
  227. def fields(self):
  228. return (self.time_low, self.time_mid, self.time_hi_version,
  229. self.clock_seq_hi_variant, self.clock_seq_low, self.node)
  230. @property
  231. def time_low(self):
  232. return self.int >> 96
  233. @property
  234. def time_mid(self):
  235. return (self.int >> 80) & 0xffff
  236. @property
  237. def time_hi_version(self):
  238. return (self.int >> 64) & 0xffff
  239. @property
  240. def clock_seq_hi_variant(self):
  241. return (self.int >> 56) & 0xff
  242. @property
  243. def clock_seq_low(self):
  244. return (self.int >> 48) & 0xff
  245. @property
  246. def time(self):
  247. return (((self.time_hi_version & 0x0fff) << 48) |
  248. (self.time_mid << 32) | self.time_low)
  249. @property
  250. def clock_seq(self):
  251. return (((self.clock_seq_hi_variant & 0x3f) << 8) |
  252. self.clock_seq_low)
  253. @property
  254. def node(self):
  255. return self.int & 0xffffffffffff
  256. @property
  257. def hex(self):
  258. return '%032x' % self.int
  259. @property
  260. def urn(self):
  261. return 'urn:uuid:' + str(self)
  262. @property
  263. def variant(self):
  264. if not self.int & (0x8000 << 48):
  265. return RESERVED_NCS
  266. elif not self.int & (0x4000 << 48):
  267. return RFC_4122
  268. elif not self.int & (0x2000 << 48):
  269. return RESERVED_MICROSOFT
  270. else:
  271. return RESERVED_FUTURE
  272. @property
  273. def version(self):
  274. # The version bits are only meaningful for RFC 4122 UUIDs.
  275. if self.variant == RFC_4122:
  276. return int((self.int >> 76) & 0xf)
  277. def _popen(command, *args):
  278. import os, shutil, subprocess
  279. executable = shutil.which(command)
  280. if executable is None:
  281. path = os.pathsep.join(('/sbin', '/usr/sbin'))
  282. executable = shutil.which(command, path=path)
  283. if executable is None:
  284. return None
  285. # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output
  286. # on stderr (Note: we don't have an example where the words we search
  287. # for are actually localized, but in theory some system could do so.)
  288. env = dict(os.environ)
  289. env['LC_ALL'] = 'C'
  290. proc = subprocess.Popen((executable,) + args,
  291. stdout=subprocess.PIPE,
  292. stderr=subprocess.DEVNULL,
  293. env=env)
  294. return proc
  295. # For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant
  296. # bit of the first octet signifies whether the MAC address is universally (0)
  297. # or locally (1) administered. Network cards from hardware manufacturers will
  298. # always be universally administered to guarantee global uniqueness of the MAC
  299. # address, but any particular machine may have other interfaces which are
  300. # locally administered. An example of the latter is the bridge interface to
  301. # the Touch Bar on MacBook Pros.
  302. #
  303. # This bit works out to be the 42nd bit counting from 1 being the least
  304. # significant, or 1<<41. We'll prefer universally administered MAC addresses
  305. # over locally administered ones since the former are globally unique, but
  306. # we'll return the first of the latter found if that's all the machine has.
  307. #
  308. # See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local
  309. def _is_universal(mac):
  310. return not (mac & (1 << 41))
  311. def _find_mac(command, args, hw_identifiers, get_index):
  312. first_local_mac = None
  313. try:
  314. proc = _popen(command, *args.split())
  315. if not proc:
  316. return None
  317. with proc:
  318. for line in proc.stdout:
  319. words = line.lower().rstrip().split()
  320. for i in range(len(words)):
  321. if words[i] in hw_identifiers:
  322. try:
  323. word = words[get_index(i)]
  324. mac = int(word.replace(b':', b''), 16)
  325. if _is_universal(mac):
  326. return mac
  327. first_local_mac = first_local_mac or mac
  328. except (ValueError, IndexError):
  329. # Virtual interfaces, such as those provided by
  330. # VPNs, do not have a colon-delimited MAC address
  331. # as expected, but a 16-byte HWAddr separated by
  332. # dashes. These should be ignored in favor of a
  333. # real MAC address
  334. pass
  335. except OSError:
  336. pass
  337. return first_local_mac or None
  338. def _ifconfig_getnode():
  339. """Get the hardware address on Unix by running ifconfig."""
  340. # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes.
  341. keywords = (b'hwaddr', b'ether', b'address:', b'lladdr')
  342. for args in ('', '-a', '-av'):
  343. mac = _find_mac('ifconfig', args, keywords, lambda i: i+1)
  344. if mac:
  345. return mac
  346. return None
  347. def _ip_getnode():
  348. """Get the hardware address on Unix by running ip."""
  349. # This works on Linux with iproute2.
  350. mac = _find_mac('ip', 'link', [b'link/ether'], lambda i: i+1)
  351. if mac:
  352. return mac
  353. return None
  354. def _arp_getnode():
  355. """Get the hardware address on Unix by running arp."""
  356. import os, socket
  357. try:
  358. ip_addr = socket.gethostbyname(socket.gethostname())
  359. except OSError:
  360. return None
  361. # Try getting the MAC addr from arp based on our IP address (Solaris).
  362. mac = _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1)
  363. if mac:
  364. return mac
  365. # This works on OpenBSD
  366. mac = _find_mac('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1)
  367. if mac:
  368. return mac
  369. # This works on Linux, FreeBSD and NetBSD
  370. mac = _find_mac('arp', '-an', [os.fsencode('(%s)' % ip_addr)],
  371. lambda i: i+2)
  372. # Return None instead of 0.
  373. if mac:
  374. return mac
  375. return None
  376. def _lanscan_getnode():
  377. """Get the hardware address on Unix by running lanscan."""
  378. # This might work on HP-UX.
  379. return _find_mac('lanscan', '-ai', [b'lan0'], lambda i: 0)
  380. def _netstat_getnode():
  381. """Get the hardware address on Unix by running netstat."""
  382. # This might work on AIX, Tru64 UNIX.
  383. first_local_mac = None
  384. try:
  385. proc = _popen('netstat', '-ia')
  386. if not proc:
  387. return None
  388. with proc:
  389. words = proc.stdout.readline().rstrip().split()
  390. try:
  391. i = words.index(b'Address')
  392. except ValueError:
  393. return None
  394. for line in proc.stdout:
  395. try:
  396. words = line.rstrip().split()
  397. word = words[i]
  398. if len(word) == 17 and word.count(b':') == 5:
  399. mac = int(word.replace(b':', b''), 16)
  400. if _is_universal(mac):
  401. return mac
  402. first_local_mac = first_local_mac or mac
  403. except (ValueError, IndexError):
  404. pass
  405. except OSError:
  406. pass
  407. return first_local_mac or None
  408. def _ipconfig_getnode():
  409. """Get the hardware address on Windows by running ipconfig.exe."""
  410. import os, re, subprocess
  411. first_local_mac = None
  412. dirs = ['', r'c:\windows\system32', r'c:\winnt\system32']
  413. try:
  414. import ctypes
  415. buffer = ctypes.create_string_buffer(300)
  416. ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300)
  417. dirs.insert(0, buffer.value.decode('mbcs'))
  418. except:
  419. pass
  420. for dir in dirs:
  421. try:
  422. proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'],
  423. stdout=subprocess.PIPE,
  424. encoding="oem")
  425. except OSError:
  426. continue
  427. with proc:
  428. for line in proc.stdout:
  429. value = line.split(':')[-1].strip().lower()
  430. if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value):
  431. mac = int(value.replace('-', ''), 16)
  432. if _is_universal(mac):
  433. return mac
  434. first_local_mac = first_local_mac or mac
  435. return first_local_mac or None
  436. def _netbios_getnode():
  437. """Get the hardware address on Windows using NetBIOS calls.
  438. See http://support.microsoft.com/kb/118623 for details."""
  439. import win32wnet, netbios
  440. first_local_mac = None
  441. ncb = netbios.NCB()
  442. ncb.Command = netbios.NCBENUM
  443. ncb.Buffer = adapters = netbios.LANA_ENUM()
  444. adapters._pack()
  445. if win32wnet.Netbios(ncb) != 0:
  446. return None
  447. adapters._unpack()
  448. for i in range(adapters.length):
  449. ncb.Reset()
  450. ncb.Command = netbios.NCBRESET
  451. ncb.Lana_num = ord(adapters.lana[i])
  452. if win32wnet.Netbios(ncb) != 0:
  453. continue
  454. ncb.Reset()
  455. ncb.Command = netbios.NCBASTAT
  456. ncb.Lana_num = ord(adapters.lana[i])
  457. ncb.Callname = '*'.ljust(16)
  458. ncb.Buffer = status = netbios.ADAPTER_STATUS()
  459. if win32wnet.Netbios(ncb) != 0:
  460. continue
  461. status._unpack()
  462. bytes = status.adapter_address[:6]
  463. if len(bytes) != 6:
  464. continue
  465. mac = int.from_bytes(bytes, 'big')
  466. if _is_universal(mac):
  467. return mac
  468. first_local_mac = first_local_mac or mac
  469. return first_local_mac or None
  470. _generate_time_safe = _UuidCreate = None
  471. _has_uuid_generate_time_safe = None
  472. # Import optional C extension at toplevel, to help disabling it when testing
  473. try:
  474. import _uuid
  475. except ImportError:
  476. _uuid = None
  477. def _load_system_functions():
  478. """
  479. Try to load platform-specific functions for generating uuids.
  480. """
  481. global _generate_time_safe, _UuidCreate, _has_uuid_generate_time_safe
  482. if _has_uuid_generate_time_safe is not None:
  483. return
  484. _has_uuid_generate_time_safe = False
  485. if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
  486. # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
  487. # in issue #8621 the function generates the same sequence of values
  488. # in the parent process and all children created using fork (unless
  489. # those children use exec as well).
  490. #
  491. # Assume that the uuid_generate functions are broken from 10.5 onward,
  492. # the test can be adjusted when a later version is fixed.
  493. pass
  494. elif _uuid is not None:
  495. _generate_time_safe = _uuid.generate_time_safe
  496. _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe
  497. return
  498. try:
  499. # If we couldn't find an extension module, try ctypes to find
  500. # system routines for UUID generation.
  501. # Thanks to Thomas Heller for ctypes and for his help with its use here.
  502. import ctypes
  503. import ctypes.util
  504. # The uuid_generate_* routines are provided by libuuid on at least
  505. # Linux and FreeBSD, and provided by libc on Mac OS X.
  506. _libnames = ['uuid']
  507. if not sys.platform.startswith('win'):
  508. _libnames.append('c')
  509. for libname in _libnames:
  510. try:
  511. lib = ctypes.CDLL(ctypes.util.find_library(libname))
  512. except Exception: # pragma: nocover
  513. continue
  514. # Try to find the safe variety first.
  515. if hasattr(lib, 'uuid_generate_time_safe'):
  516. _uuid_generate_time_safe = lib.uuid_generate_time_safe
  517. # int uuid_generate_time_safe(uuid_t out);
  518. def _generate_time_safe():
  519. _buffer = ctypes.create_string_buffer(16)
  520. res = _uuid_generate_time_safe(_buffer)
  521. return bytes(_buffer.raw), res
  522. _has_uuid_generate_time_safe = True
  523. break
  524. elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
  525. _uuid_generate_time = lib.uuid_generate_time
  526. # void uuid_generate_time(uuid_t out);
  527. _uuid_generate_time.restype = None
  528. def _generate_time_safe():
  529. _buffer = ctypes.create_string_buffer(16)
  530. _uuid_generate_time(_buffer)
  531. return bytes(_buffer.raw), None
  532. break
  533. # On Windows prior to 2000, UuidCreate gives a UUID containing the
  534. # hardware address. On Windows 2000 and later, UuidCreate makes a
  535. # random UUID and UuidCreateSequential gives a UUID containing the
  536. # hardware address. These routines are provided by the RPC runtime.
  537. # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last
  538. # 6 bytes returned by UuidCreateSequential are fixed, they don't appear
  539. # to bear any relationship to the MAC address of any network device
  540. # on the box.
  541. try:
  542. lib = ctypes.windll.rpcrt4
  543. except:
  544. lib = None
  545. _UuidCreate = getattr(lib, 'UuidCreateSequential',
  546. getattr(lib, 'UuidCreate', None))
  547. except Exception as exc:
  548. import warnings
  549. warnings.warn(f"Could not find fallback ctypes uuid functions: {exc}",
  550. ImportWarning)
  551. def _unix_getnode():
  552. """Get the hardware address on Unix using the _uuid extension module
  553. or ctypes."""
  554. _load_system_functions()
  555. uuid_time, _ = _generate_time_safe()
  556. return UUID(bytes=uuid_time).node
  557. def _windll_getnode():
  558. """Get the hardware address on Windows using ctypes."""
  559. import ctypes
  560. _load_system_functions()
  561. _buffer = ctypes.create_string_buffer(16)
  562. if _UuidCreate(_buffer) == 0:
  563. return UUID(bytes=bytes_(_buffer.raw)).node
  564. def _random_getnode():
  565. """Get a random node ID."""
  566. # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or
  567. # pseudo-randomly generated value may be used; see Section 4.5. The
  568. # multicast bit must be set in such addresses, in order that they will
  569. # never conflict with addresses obtained from network cards."
  570. #
  571. # The "multicast bit" of a MAC address is defined to be "the least
  572. # significant bit of the first octet". This works out to be the 41st bit
  573. # counting from 1 being the least significant bit, or 1<<40.
  574. #
  575. # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
  576. import random
  577. return random.getrandbits(48) | (1 << 40)
  578. _node = None
  579. _NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
  580. _NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
  581. _arp_getnode, _lanscan_getnode, _netstat_getnode]
  582. def getnode(*, getters=None):
  583. """Get the hardware address as a 48-bit positive integer.
  584. The first time this runs, it may launch a separate program, which could
  585. be quite slow. If all attempts to obtain the hardware address fail, we
  586. choose a random 48-bit number with its eighth bit set to 1 as recommended
  587. in RFC 4122.
  588. """
  589. global _node
  590. if _node is not None:
  591. return _node
  592. if sys.platform == 'win32':
  593. getters = _NODE_GETTERS_WIN32
  594. else:
  595. getters = _NODE_GETTERS_UNIX
  596. for getter in getters + [_random_getnode]:
  597. try:
  598. _node = getter()
  599. except:
  600. continue
  601. if (_node is not None) and (0 <= _node < (1 << 48)):
  602. return _node
  603. assert False, '_random_getnode() returned invalid value: {}'.format(_node)
  604. _last_timestamp = None
  605. def uuid1(node=None, clock_seq=None):
  606. """Generate a UUID from a host ID, sequence number, and the current time.
  607. If 'node' is not given, getnode() is used to obtain the hardware
  608. address. If 'clock_seq' is given, it is used as the sequence number;
  609. otherwise a random 14-bit sequence number is chosen."""
  610. # When the system provides a version-1 UUID generator, use it (but don't
  611. # use UuidCreate here because its UUIDs don't conform to RFC 4122).
  612. _load_system_functions()
  613. if _generate_time_safe is not None and node is clock_seq is None:
  614. uuid_time, safely_generated = _generate_time_safe()
  615. try:
  616. is_safe = SafeUUID(safely_generated)
  617. except ValueError:
  618. is_safe = SafeUUID.unknown
  619. return UUID(bytes=uuid_time, is_safe=is_safe)
  620. global _last_timestamp
  621. import time
  622. nanoseconds = int(time.time() * 1e9)
  623. # 0x01b21dd213814000 is the number of 100-ns intervals between the
  624. # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
  625. timestamp = int(nanoseconds/100) + 0x01b21dd213814000
  626. if _last_timestamp is not None and timestamp <= _last_timestamp:
  627. timestamp = _last_timestamp + 1
  628. _last_timestamp = timestamp
  629. if clock_seq is None:
  630. import random
  631. clock_seq = random.getrandbits(14) # instead of stable storage
  632. time_low = timestamp & 0xffffffff
  633. time_mid = (timestamp >> 32) & 0xffff
  634. time_hi_version = (timestamp >> 48) & 0x0fff
  635. clock_seq_low = clock_seq & 0xff
  636. clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
  637. if node is None:
  638. node = getnode()
  639. return UUID(fields=(time_low, time_mid, time_hi_version,
  640. clock_seq_hi_variant, clock_seq_low, node), version=1)
  641. def uuid3(namespace, name):
  642. """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
  643. from hashlib import md5
  644. hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()
  645. return UUID(bytes=hash[:16], version=3)
  646. def uuid4():
  647. """Generate a random UUID."""
  648. return UUID(bytes=os.urandom(16), version=4)
  649. def uuid5(namespace, name):
  650. """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
  651. from hashlib import sha1
  652. hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
  653. return UUID(bytes=hash[:16], version=5)
  654. # The following standard UUIDs are for use with uuid3() or uuid5().
  655. NAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
  656. NAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8')
  657. NAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')
  658. NAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8')