17db96d56Sopenharmony_cir"""UUID objects (universally unique identifiers) according to RFC 4122. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciThis module provides immutable UUID objects (class UUID) and the functions 47db96d56Sopenharmony_ciuuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 57db96d56Sopenharmony_ciUUIDs as specified in RFC 4122. 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ciIf all you want is a unique ID, you should probably call uuid1() or uuid4(). 87db96d56Sopenharmony_ciNote that uuid1() may compromise privacy since it creates a UUID containing 97db96d56Sopenharmony_cithe computer's network address. uuid4() creates a random UUID. 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ciTypical usage: 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci >>> import uuid 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci # make a UUID based on the host ID and current time 167db96d56Sopenharmony_ci >>> uuid.uuid1() # doctest: +SKIP 177db96d56Sopenharmony_ci UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci # make a UUID using an MD5 hash of a namespace UUID and a name 207db96d56Sopenharmony_ci >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') 217db96d56Sopenharmony_ci UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci # make a random UUID 247db96d56Sopenharmony_ci >>> uuid.uuid4() # doctest: +SKIP 257db96d56Sopenharmony_ci UUID('16fd2706-8baf-433b-82eb-8c7fada847da') 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci # make a UUID using a SHA-1 hash of a namespace UUID and a name 287db96d56Sopenharmony_ci >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') 297db96d56Sopenharmony_ci UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci # make a UUID from a string of hex digits (braces and hyphens ignored) 327db96d56Sopenharmony_ci >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci # convert a UUID to a string of hex digits in standard form 357db96d56Sopenharmony_ci >>> str(x) 367db96d56Sopenharmony_ci '00010203-0405-0607-0809-0a0b0c0d0e0f' 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci # get the raw 16 bytes of the UUID 397db96d56Sopenharmony_ci >>> x.bytes 407db96d56Sopenharmony_ci b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci # make a UUID from a 16-byte string 437db96d56Sopenharmony_ci >>> uuid.UUID(bytes=x.bytes) 447db96d56Sopenharmony_ci UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') 457db96d56Sopenharmony_ci""" 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ciimport os 487db96d56Sopenharmony_ciimport sys 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_cifrom enum import Enum, _simple_enum 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci__author__ = 'Ka-Ping Yee <ping@zesty.ca>' 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci# The recognized platforms - known behaviors 567db96d56Sopenharmony_ciif sys.platform in ('win32', 'darwin'): 577db96d56Sopenharmony_ci _AIX = _LINUX = False 587db96d56Sopenharmony_cielse: 597db96d56Sopenharmony_ci import platform 607db96d56Sopenharmony_ci _platform_system = platform.system() 617db96d56Sopenharmony_ci _AIX = _platform_system == 'AIX' 627db96d56Sopenharmony_ci _LINUX = _platform_system == 'Linux' 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci_MAC_DELIM = b':' 657db96d56Sopenharmony_ci_MAC_OMITS_LEADING_ZEROES = False 667db96d56Sopenharmony_ciif _AIX: 677db96d56Sopenharmony_ci _MAC_DELIM = b'.' 687db96d56Sopenharmony_ci _MAC_OMITS_LEADING_ZEROES = True 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ciRESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ 717db96d56Sopenharmony_ci 'reserved for NCS compatibility', 'specified in RFC 4122', 727db96d56Sopenharmony_ci 'reserved for Microsoft compatibility', 'reserved for future definition'] 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ciint_ = int # The built-in int type 757db96d56Sopenharmony_cibytes_ = bytes # The built-in bytes type 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci@_simple_enum(Enum) 797db96d56Sopenharmony_ciclass SafeUUID: 807db96d56Sopenharmony_ci safe = 0 817db96d56Sopenharmony_ci unsafe = -1 827db96d56Sopenharmony_ci unknown = None 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ciclass UUID: 867db96d56Sopenharmony_ci """Instances of the UUID class represent UUIDs as specified in RFC 4122. 877db96d56Sopenharmony_ci UUID objects are immutable, hashable, and usable as dictionary keys. 887db96d56Sopenharmony_ci Converting a UUID to a string with str() yields something in the form 897db96d56Sopenharmony_ci '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts 907db96d56Sopenharmony_ci five possible forms: a similar string of hexadecimal digits, or a tuple 917db96d56Sopenharmony_ci of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 927db96d56Sopenharmony_ci 48-bit values respectively) as an argument named 'fields', or a string 937db96d56Sopenharmony_ci of 16 bytes (with all the integer fields in big-endian order) as an 947db96d56Sopenharmony_ci argument named 'bytes', or a string of 16 bytes (with the first three 957db96d56Sopenharmony_ci fields in little-endian order) as an argument named 'bytes_le', or a 967db96d56Sopenharmony_ci single 128-bit integer as an argument named 'int'. 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci UUIDs have these read-only attributes: 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci bytes the UUID as a 16-byte string (containing the six 1017db96d56Sopenharmony_ci integer fields in big-endian byte order) 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci bytes_le the UUID as a 16-byte string (with time_low, time_mid, 1047db96d56Sopenharmony_ci and time_hi_version in little-endian byte order) 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci fields a tuple of the six integer fields of the UUID, 1077db96d56Sopenharmony_ci which are also available as six individual attributes 1087db96d56Sopenharmony_ci and two derived attributes: 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci time_low the first 32 bits of the UUID 1117db96d56Sopenharmony_ci time_mid the next 16 bits of the UUID 1127db96d56Sopenharmony_ci time_hi_version the next 16 bits of the UUID 1137db96d56Sopenharmony_ci clock_seq_hi_variant the next 8 bits of the UUID 1147db96d56Sopenharmony_ci clock_seq_low the next 8 bits of the UUID 1157db96d56Sopenharmony_ci node the last 48 bits of the UUID 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci time the 60-bit timestamp 1187db96d56Sopenharmony_ci clock_seq the 14-bit sequence number 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci hex the UUID as a 32-character hexadecimal string 1217db96d56Sopenharmony_ci 1227db96d56Sopenharmony_ci int the UUID as a 128-bit integer 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci urn the UUID as a URN as specified in RFC 4122 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_ci variant the UUID variant (one of the constants RESERVED_NCS, 1277db96d56Sopenharmony_ci RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci version the UUID version number (1 through 5, meaningful only 1307db96d56Sopenharmony_ci when the variant is RFC_4122) 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci is_safe An enum indicating whether the UUID has been generated in 1337db96d56Sopenharmony_ci a way that is safe for multiprocessing applications, via 1347db96d56Sopenharmony_ci uuid_generate_time_safe(3). 1357db96d56Sopenharmony_ci """ 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci __slots__ = ('int', 'is_safe', '__weakref__') 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, 1407db96d56Sopenharmony_ci int=None, version=None, 1417db96d56Sopenharmony_ci *, is_safe=SafeUUID.unknown): 1427db96d56Sopenharmony_ci r"""Create a UUID from either a string of 32 hexadecimal digits, 1437db96d56Sopenharmony_ci a string of 16 bytes as the 'bytes' argument, a string of 16 bytes 1447db96d56Sopenharmony_ci in little-endian order as the 'bytes_le' argument, a tuple of six 1457db96d56Sopenharmony_ci integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 1467db96d56Sopenharmony_ci 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as 1477db96d56Sopenharmony_ci the 'fields' argument, or a single 128-bit integer as the 'int' 1487db96d56Sopenharmony_ci argument. When a string of hex digits is given, curly braces, 1497db96d56Sopenharmony_ci hyphens, and a URN prefix are all optional. For example, these 1507db96d56Sopenharmony_ci expressions all yield the same UUID: 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci UUID('{12345678-1234-5678-1234-567812345678}') 1537db96d56Sopenharmony_ci UUID('12345678123456781234567812345678') 1547db96d56Sopenharmony_ci UUID('urn:uuid:12345678-1234-5678-1234-567812345678') 1557db96d56Sopenharmony_ci UUID(bytes='\x12\x34\x56\x78'*4) 1567db96d56Sopenharmony_ci UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' + 1577db96d56Sopenharmony_ci '\x12\x34\x56\x78\x12\x34\x56\x78') 1587db96d56Sopenharmony_ci UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) 1597db96d56Sopenharmony_ci UUID(int=0x12345678123456781234567812345678) 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must 1627db96d56Sopenharmony_ci be given. The 'version' argument is optional; if given, the resulting 1637db96d56Sopenharmony_ci UUID will have its variant and version set according to RFC 4122, 1647db96d56Sopenharmony_ci overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'. 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci is_safe is an enum exposed as an attribute on the instance. It 1677db96d56Sopenharmony_ci indicates whether the UUID has been generated in a way that is safe 1687db96d56Sopenharmony_ci for multiprocessing applications, via uuid_generate_time_safe(3). 1697db96d56Sopenharmony_ci """ 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci if [hex, bytes, bytes_le, fields, int].count(None) != 4: 1727db96d56Sopenharmony_ci raise TypeError('one of the hex, bytes, bytes_le, fields, ' 1737db96d56Sopenharmony_ci 'or int arguments must be given') 1747db96d56Sopenharmony_ci if hex is not None: 1757db96d56Sopenharmony_ci hex = hex.replace('urn:', '').replace('uuid:', '') 1767db96d56Sopenharmony_ci hex = hex.strip('{}').replace('-', '') 1777db96d56Sopenharmony_ci if len(hex) != 32: 1787db96d56Sopenharmony_ci raise ValueError('badly formed hexadecimal UUID string') 1797db96d56Sopenharmony_ci int = int_(hex, 16) 1807db96d56Sopenharmony_ci if bytes_le is not None: 1817db96d56Sopenharmony_ci if len(bytes_le) != 16: 1827db96d56Sopenharmony_ci raise ValueError('bytes_le is not a 16-char string') 1837db96d56Sopenharmony_ci bytes = (bytes_le[4-1::-1] + bytes_le[6-1:4-1:-1] + 1847db96d56Sopenharmony_ci bytes_le[8-1:6-1:-1] + bytes_le[8:]) 1857db96d56Sopenharmony_ci if bytes is not None: 1867db96d56Sopenharmony_ci if len(bytes) != 16: 1877db96d56Sopenharmony_ci raise ValueError('bytes is not a 16-char string') 1887db96d56Sopenharmony_ci assert isinstance(bytes, bytes_), repr(bytes) 1897db96d56Sopenharmony_ci int = int_.from_bytes(bytes) # big endian 1907db96d56Sopenharmony_ci if fields is not None: 1917db96d56Sopenharmony_ci if len(fields) != 6: 1927db96d56Sopenharmony_ci raise ValueError('fields is not a 6-tuple') 1937db96d56Sopenharmony_ci (time_low, time_mid, time_hi_version, 1947db96d56Sopenharmony_ci clock_seq_hi_variant, clock_seq_low, node) = fields 1957db96d56Sopenharmony_ci if not 0 <= time_low < 1<<32: 1967db96d56Sopenharmony_ci raise ValueError('field 1 out of range (need a 32-bit value)') 1977db96d56Sopenharmony_ci if not 0 <= time_mid < 1<<16: 1987db96d56Sopenharmony_ci raise ValueError('field 2 out of range (need a 16-bit value)') 1997db96d56Sopenharmony_ci if not 0 <= time_hi_version < 1<<16: 2007db96d56Sopenharmony_ci raise ValueError('field 3 out of range (need a 16-bit value)') 2017db96d56Sopenharmony_ci if not 0 <= clock_seq_hi_variant < 1<<8: 2027db96d56Sopenharmony_ci raise ValueError('field 4 out of range (need an 8-bit value)') 2037db96d56Sopenharmony_ci if not 0 <= clock_seq_low < 1<<8: 2047db96d56Sopenharmony_ci raise ValueError('field 5 out of range (need an 8-bit value)') 2057db96d56Sopenharmony_ci if not 0 <= node < 1<<48: 2067db96d56Sopenharmony_ci raise ValueError('field 6 out of range (need a 48-bit value)') 2077db96d56Sopenharmony_ci clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low 2087db96d56Sopenharmony_ci int = ((time_low << 96) | (time_mid << 80) | 2097db96d56Sopenharmony_ci (time_hi_version << 64) | (clock_seq << 48) | node) 2107db96d56Sopenharmony_ci if int is not None: 2117db96d56Sopenharmony_ci if not 0 <= int < 1<<128: 2127db96d56Sopenharmony_ci raise ValueError('int is out of range (need a 128-bit value)') 2137db96d56Sopenharmony_ci if version is not None: 2147db96d56Sopenharmony_ci if not 1 <= version <= 5: 2157db96d56Sopenharmony_ci raise ValueError('illegal version number') 2167db96d56Sopenharmony_ci # Set the variant to RFC 4122. 2177db96d56Sopenharmony_ci int &= ~(0xc000 << 48) 2187db96d56Sopenharmony_ci int |= 0x8000 << 48 2197db96d56Sopenharmony_ci # Set the version number. 2207db96d56Sopenharmony_ci int &= ~(0xf000 << 64) 2217db96d56Sopenharmony_ci int |= version << 76 2227db96d56Sopenharmony_ci object.__setattr__(self, 'int', int) 2237db96d56Sopenharmony_ci object.__setattr__(self, 'is_safe', is_safe) 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci def __getstate__(self): 2267db96d56Sopenharmony_ci d = {'int': self.int} 2277db96d56Sopenharmony_ci if self.is_safe != SafeUUID.unknown: 2287db96d56Sopenharmony_ci # is_safe is a SafeUUID instance. Return just its value, so that 2297db96d56Sopenharmony_ci # it can be un-pickled in older Python versions without SafeUUID. 2307db96d56Sopenharmony_ci d['is_safe'] = self.is_safe.value 2317db96d56Sopenharmony_ci return d 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci def __setstate__(self, state): 2347db96d56Sopenharmony_ci object.__setattr__(self, 'int', state['int']) 2357db96d56Sopenharmony_ci # is_safe was added in 3.7; it is also omitted when it is "unknown" 2367db96d56Sopenharmony_ci object.__setattr__(self, 'is_safe', 2377db96d56Sopenharmony_ci SafeUUID(state['is_safe']) 2387db96d56Sopenharmony_ci if 'is_safe' in state else SafeUUID.unknown) 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci def __eq__(self, other): 2417db96d56Sopenharmony_ci if isinstance(other, UUID): 2427db96d56Sopenharmony_ci return self.int == other.int 2437db96d56Sopenharmony_ci return NotImplemented 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci # Q. What's the value of being able to sort UUIDs? 2467db96d56Sopenharmony_ci # A. Use them as keys in a B-Tree or similar mapping. 2477db96d56Sopenharmony_ci 2487db96d56Sopenharmony_ci def __lt__(self, other): 2497db96d56Sopenharmony_ci if isinstance(other, UUID): 2507db96d56Sopenharmony_ci return self.int < other.int 2517db96d56Sopenharmony_ci return NotImplemented 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci def __gt__(self, other): 2547db96d56Sopenharmony_ci if isinstance(other, UUID): 2557db96d56Sopenharmony_ci return self.int > other.int 2567db96d56Sopenharmony_ci return NotImplemented 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_ci def __le__(self, other): 2597db96d56Sopenharmony_ci if isinstance(other, UUID): 2607db96d56Sopenharmony_ci return self.int <= other.int 2617db96d56Sopenharmony_ci return NotImplemented 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_ci def __ge__(self, other): 2647db96d56Sopenharmony_ci if isinstance(other, UUID): 2657db96d56Sopenharmony_ci return self.int >= other.int 2667db96d56Sopenharmony_ci return NotImplemented 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci def __hash__(self): 2697db96d56Sopenharmony_ci return hash(self.int) 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci def __int__(self): 2727db96d56Sopenharmony_ci return self.int 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci def __repr__(self): 2757db96d56Sopenharmony_ci return '%s(%r)' % (self.__class__.__name__, str(self)) 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci def __setattr__(self, name, value): 2787db96d56Sopenharmony_ci raise TypeError('UUID objects are immutable') 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci def __str__(self): 2817db96d56Sopenharmony_ci hex = '%032x' % self.int 2827db96d56Sopenharmony_ci return '%s-%s-%s-%s-%s' % ( 2837db96d56Sopenharmony_ci hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_ci @property 2867db96d56Sopenharmony_ci def bytes(self): 2877db96d56Sopenharmony_ci return self.int.to_bytes(16) # big endian 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci @property 2907db96d56Sopenharmony_ci def bytes_le(self): 2917db96d56Sopenharmony_ci bytes = self.bytes 2927db96d56Sopenharmony_ci return (bytes[4-1::-1] + bytes[6-1:4-1:-1] + bytes[8-1:6-1:-1] + 2937db96d56Sopenharmony_ci bytes[8:]) 2947db96d56Sopenharmony_ci 2957db96d56Sopenharmony_ci @property 2967db96d56Sopenharmony_ci def fields(self): 2977db96d56Sopenharmony_ci return (self.time_low, self.time_mid, self.time_hi_version, 2987db96d56Sopenharmony_ci self.clock_seq_hi_variant, self.clock_seq_low, self.node) 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci @property 3017db96d56Sopenharmony_ci def time_low(self): 3027db96d56Sopenharmony_ci return self.int >> 96 3037db96d56Sopenharmony_ci 3047db96d56Sopenharmony_ci @property 3057db96d56Sopenharmony_ci def time_mid(self): 3067db96d56Sopenharmony_ci return (self.int >> 80) & 0xffff 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci @property 3097db96d56Sopenharmony_ci def time_hi_version(self): 3107db96d56Sopenharmony_ci return (self.int >> 64) & 0xffff 3117db96d56Sopenharmony_ci 3127db96d56Sopenharmony_ci @property 3137db96d56Sopenharmony_ci def clock_seq_hi_variant(self): 3147db96d56Sopenharmony_ci return (self.int >> 56) & 0xff 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci @property 3177db96d56Sopenharmony_ci def clock_seq_low(self): 3187db96d56Sopenharmony_ci return (self.int >> 48) & 0xff 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci @property 3217db96d56Sopenharmony_ci def time(self): 3227db96d56Sopenharmony_ci return (((self.time_hi_version & 0x0fff) << 48) | 3237db96d56Sopenharmony_ci (self.time_mid << 32) | self.time_low) 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci @property 3267db96d56Sopenharmony_ci def clock_seq(self): 3277db96d56Sopenharmony_ci return (((self.clock_seq_hi_variant & 0x3f) << 8) | 3287db96d56Sopenharmony_ci self.clock_seq_low) 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci @property 3317db96d56Sopenharmony_ci def node(self): 3327db96d56Sopenharmony_ci return self.int & 0xffffffffffff 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_ci @property 3357db96d56Sopenharmony_ci def hex(self): 3367db96d56Sopenharmony_ci return '%032x' % self.int 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci @property 3397db96d56Sopenharmony_ci def urn(self): 3407db96d56Sopenharmony_ci return 'urn:uuid:' + str(self) 3417db96d56Sopenharmony_ci 3427db96d56Sopenharmony_ci @property 3437db96d56Sopenharmony_ci def variant(self): 3447db96d56Sopenharmony_ci if not self.int & (0x8000 << 48): 3457db96d56Sopenharmony_ci return RESERVED_NCS 3467db96d56Sopenharmony_ci elif not self.int & (0x4000 << 48): 3477db96d56Sopenharmony_ci return RFC_4122 3487db96d56Sopenharmony_ci elif not self.int & (0x2000 << 48): 3497db96d56Sopenharmony_ci return RESERVED_MICROSOFT 3507db96d56Sopenharmony_ci else: 3517db96d56Sopenharmony_ci return RESERVED_FUTURE 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci @property 3547db96d56Sopenharmony_ci def version(self): 3557db96d56Sopenharmony_ci # The version bits are only meaningful for RFC 4122 UUIDs. 3567db96d56Sopenharmony_ci if self.variant == RFC_4122: 3577db96d56Sopenharmony_ci return int((self.int >> 76) & 0xf) 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci 3607db96d56Sopenharmony_cidef _get_command_stdout(command, *args): 3617db96d56Sopenharmony_ci import io, os, shutil, subprocess 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci try: 3647db96d56Sopenharmony_ci path_dirs = os.environ.get('PATH', os.defpath).split(os.pathsep) 3657db96d56Sopenharmony_ci path_dirs.extend(['/sbin', '/usr/sbin']) 3667db96d56Sopenharmony_ci executable = shutil.which(command, path=os.pathsep.join(path_dirs)) 3677db96d56Sopenharmony_ci if executable is None: 3687db96d56Sopenharmony_ci return None 3697db96d56Sopenharmony_ci # LC_ALL=C to ensure English output, stderr=DEVNULL to prevent output 3707db96d56Sopenharmony_ci # on stderr (Note: we don't have an example where the words we search 3717db96d56Sopenharmony_ci # for are actually localized, but in theory some system could do so.) 3727db96d56Sopenharmony_ci env = dict(os.environ) 3737db96d56Sopenharmony_ci env['LC_ALL'] = 'C' 3747db96d56Sopenharmony_ci # Empty strings will be quoted by popen so we should just ommit it 3757db96d56Sopenharmony_ci if args != ('',): 3767db96d56Sopenharmony_ci command = (executable, *args) 3777db96d56Sopenharmony_ci else: 3787db96d56Sopenharmony_ci command = (executable,) 3797db96d56Sopenharmony_ci proc = subprocess.Popen(command, 3807db96d56Sopenharmony_ci stdout=subprocess.PIPE, 3817db96d56Sopenharmony_ci stderr=subprocess.DEVNULL, 3827db96d56Sopenharmony_ci env=env) 3837db96d56Sopenharmony_ci if not proc: 3847db96d56Sopenharmony_ci return None 3857db96d56Sopenharmony_ci stdout, stderr = proc.communicate() 3867db96d56Sopenharmony_ci return io.BytesIO(stdout) 3877db96d56Sopenharmony_ci except (OSError, subprocess.SubprocessError): 3887db96d56Sopenharmony_ci return None 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci 3917db96d56Sopenharmony_ci# For MAC (a.k.a. IEEE 802, or EUI-48) addresses, the second least significant 3927db96d56Sopenharmony_ci# bit of the first octet signifies whether the MAC address is universally (0) 3937db96d56Sopenharmony_ci# or locally (1) administered. Network cards from hardware manufacturers will 3947db96d56Sopenharmony_ci# always be universally administered to guarantee global uniqueness of the MAC 3957db96d56Sopenharmony_ci# address, but any particular machine may have other interfaces which are 3967db96d56Sopenharmony_ci# locally administered. An example of the latter is the bridge interface to 3977db96d56Sopenharmony_ci# the Touch Bar on MacBook Pros. 3987db96d56Sopenharmony_ci# 3997db96d56Sopenharmony_ci# This bit works out to be the 42nd bit counting from 1 being the least 4007db96d56Sopenharmony_ci# significant, or 1<<41. We'll prefer universally administered MAC addresses 4017db96d56Sopenharmony_ci# over locally administered ones since the former are globally unique, but 4027db96d56Sopenharmony_ci# we'll return the first of the latter found if that's all the machine has. 4037db96d56Sopenharmony_ci# 4047db96d56Sopenharmony_ci# See https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local 4057db96d56Sopenharmony_ci 4067db96d56Sopenharmony_cidef _is_universal(mac): 4077db96d56Sopenharmony_ci return not (mac & (1 << 41)) 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_cidef _find_mac_near_keyword(command, args, keywords, get_word_index): 4117db96d56Sopenharmony_ci """Searches a command's output for a MAC address near a keyword. 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci Each line of words in the output is case-insensitively searched for 4147db96d56Sopenharmony_ci any of the given keywords. Upon a match, get_word_index is invoked 4157db96d56Sopenharmony_ci to pick a word from the line, given the index of the match. For 4167db96d56Sopenharmony_ci example, lambda i: 0 would get the first word on the line, while 4177db96d56Sopenharmony_ci lambda i: i - 1 would get the word preceding the keyword. 4187db96d56Sopenharmony_ci """ 4197db96d56Sopenharmony_ci stdout = _get_command_stdout(command, args) 4207db96d56Sopenharmony_ci if stdout is None: 4217db96d56Sopenharmony_ci return None 4227db96d56Sopenharmony_ci 4237db96d56Sopenharmony_ci first_local_mac = None 4247db96d56Sopenharmony_ci for line in stdout: 4257db96d56Sopenharmony_ci words = line.lower().rstrip().split() 4267db96d56Sopenharmony_ci for i in range(len(words)): 4277db96d56Sopenharmony_ci if words[i] in keywords: 4287db96d56Sopenharmony_ci try: 4297db96d56Sopenharmony_ci word = words[get_word_index(i)] 4307db96d56Sopenharmony_ci mac = int(word.replace(_MAC_DELIM, b''), 16) 4317db96d56Sopenharmony_ci except (ValueError, IndexError): 4327db96d56Sopenharmony_ci # Virtual interfaces, such as those provided by 4337db96d56Sopenharmony_ci # VPNs, do not have a colon-delimited MAC address 4347db96d56Sopenharmony_ci # as expected, but a 16-byte HWAddr separated by 4357db96d56Sopenharmony_ci # dashes. These should be ignored in favor of a 4367db96d56Sopenharmony_ci # real MAC address 4377db96d56Sopenharmony_ci pass 4387db96d56Sopenharmony_ci else: 4397db96d56Sopenharmony_ci if _is_universal(mac): 4407db96d56Sopenharmony_ci return mac 4417db96d56Sopenharmony_ci first_local_mac = first_local_mac or mac 4427db96d56Sopenharmony_ci return first_local_mac or None 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_cidef _parse_mac(word): 4467db96d56Sopenharmony_ci # Accept 'HH:HH:HH:HH:HH:HH' MAC address (ex: '52:54:00:9d:0e:67'), 4477db96d56Sopenharmony_ci # but reject IPv6 address (ex: 'fe80::5054:ff:fe9' or '123:2:3:4:5:6:7:8'). 4487db96d56Sopenharmony_ci # 4497db96d56Sopenharmony_ci # Virtual interfaces, such as those provided by VPNs, do not have a 4507db96d56Sopenharmony_ci # colon-delimited MAC address as expected, but a 16-byte HWAddr separated 4517db96d56Sopenharmony_ci # by dashes. These should be ignored in favor of a real MAC address 4527db96d56Sopenharmony_ci parts = word.split(_MAC_DELIM) 4537db96d56Sopenharmony_ci if len(parts) != 6: 4547db96d56Sopenharmony_ci return 4557db96d56Sopenharmony_ci if _MAC_OMITS_LEADING_ZEROES: 4567db96d56Sopenharmony_ci # (Only) on AIX the macaddr value given is not prefixed by 0, e.g. 4577db96d56Sopenharmony_ci # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0 4587db96d56Sopenharmony_ci # not 4597db96d56Sopenharmony_ci # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0 4607db96d56Sopenharmony_ci if not all(1 <= len(part) <= 2 for part in parts): 4617db96d56Sopenharmony_ci return 4627db96d56Sopenharmony_ci hexstr = b''.join(part.rjust(2, b'0') for part in parts) 4637db96d56Sopenharmony_ci else: 4647db96d56Sopenharmony_ci if not all(len(part) == 2 for part in parts): 4657db96d56Sopenharmony_ci return 4667db96d56Sopenharmony_ci hexstr = b''.join(parts) 4677db96d56Sopenharmony_ci try: 4687db96d56Sopenharmony_ci return int(hexstr, 16) 4697db96d56Sopenharmony_ci except ValueError: 4707db96d56Sopenharmony_ci return 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci 4737db96d56Sopenharmony_cidef _find_mac_under_heading(command, args, heading): 4747db96d56Sopenharmony_ci """Looks for a MAC address under a heading in a command's output. 4757db96d56Sopenharmony_ci 4767db96d56Sopenharmony_ci The first line of words in the output is searched for the given 4777db96d56Sopenharmony_ci heading. Words at the same word index as the heading in subsequent 4787db96d56Sopenharmony_ci lines are then examined to see if they look like MAC addresses. 4797db96d56Sopenharmony_ci """ 4807db96d56Sopenharmony_ci stdout = _get_command_stdout(command, args) 4817db96d56Sopenharmony_ci if stdout is None: 4827db96d56Sopenharmony_ci return None 4837db96d56Sopenharmony_ci 4847db96d56Sopenharmony_ci keywords = stdout.readline().rstrip().split() 4857db96d56Sopenharmony_ci try: 4867db96d56Sopenharmony_ci column_index = keywords.index(heading) 4877db96d56Sopenharmony_ci except ValueError: 4887db96d56Sopenharmony_ci return None 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci first_local_mac = None 4917db96d56Sopenharmony_ci for line in stdout: 4927db96d56Sopenharmony_ci words = line.rstrip().split() 4937db96d56Sopenharmony_ci try: 4947db96d56Sopenharmony_ci word = words[column_index] 4957db96d56Sopenharmony_ci except IndexError: 4967db96d56Sopenharmony_ci continue 4977db96d56Sopenharmony_ci 4987db96d56Sopenharmony_ci mac = _parse_mac(word) 4997db96d56Sopenharmony_ci if mac is None: 5007db96d56Sopenharmony_ci continue 5017db96d56Sopenharmony_ci if _is_universal(mac): 5027db96d56Sopenharmony_ci return mac 5037db96d56Sopenharmony_ci if first_local_mac is None: 5047db96d56Sopenharmony_ci first_local_mac = mac 5057db96d56Sopenharmony_ci 5067db96d56Sopenharmony_ci return first_local_mac 5077db96d56Sopenharmony_ci 5087db96d56Sopenharmony_ci 5097db96d56Sopenharmony_ci# The following functions call external programs to 'get' a macaddr value to 5107db96d56Sopenharmony_ci# be used as basis for an uuid 5117db96d56Sopenharmony_cidef _ifconfig_getnode(): 5127db96d56Sopenharmony_ci """Get the hardware address on Unix by running ifconfig.""" 5137db96d56Sopenharmony_ci # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes. 5147db96d56Sopenharmony_ci keywords = (b'hwaddr', b'ether', b'address:', b'lladdr') 5157db96d56Sopenharmony_ci for args in ('', '-a', '-av'): 5167db96d56Sopenharmony_ci mac = _find_mac_near_keyword('ifconfig', args, keywords, lambda i: i+1) 5177db96d56Sopenharmony_ci if mac: 5187db96d56Sopenharmony_ci return mac 5197db96d56Sopenharmony_ci return None 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_cidef _ip_getnode(): 5227db96d56Sopenharmony_ci """Get the hardware address on Unix by running ip.""" 5237db96d56Sopenharmony_ci # This works on Linux with iproute2. 5247db96d56Sopenharmony_ci mac = _find_mac_near_keyword('ip', 'link', [b'link/ether'], lambda i: i+1) 5257db96d56Sopenharmony_ci if mac: 5267db96d56Sopenharmony_ci return mac 5277db96d56Sopenharmony_ci return None 5287db96d56Sopenharmony_ci 5297db96d56Sopenharmony_cidef _arp_getnode(): 5307db96d56Sopenharmony_ci """Get the hardware address on Unix by running arp.""" 5317db96d56Sopenharmony_ci import os, socket 5327db96d56Sopenharmony_ci if not hasattr(socket, "gethostbyname"): 5337db96d56Sopenharmony_ci return None 5347db96d56Sopenharmony_ci try: 5357db96d56Sopenharmony_ci ip_addr = socket.gethostbyname(socket.gethostname()) 5367db96d56Sopenharmony_ci except OSError: 5377db96d56Sopenharmony_ci return None 5387db96d56Sopenharmony_ci 5397db96d56Sopenharmony_ci # Try getting the MAC addr from arp based on our IP address (Solaris). 5407db96d56Sopenharmony_ci mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: -1) 5417db96d56Sopenharmony_ci if mac: 5427db96d56Sopenharmony_ci return mac 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_ci # This works on OpenBSD 5457db96d56Sopenharmony_ci mac = _find_mac_near_keyword('arp', '-an', [os.fsencode(ip_addr)], lambda i: i+1) 5467db96d56Sopenharmony_ci if mac: 5477db96d56Sopenharmony_ci return mac 5487db96d56Sopenharmony_ci 5497db96d56Sopenharmony_ci # This works on Linux, FreeBSD and NetBSD 5507db96d56Sopenharmony_ci mac = _find_mac_near_keyword('arp', '-an', [os.fsencode('(%s)' % ip_addr)], 5517db96d56Sopenharmony_ci lambda i: i+2) 5527db96d56Sopenharmony_ci # Return None instead of 0. 5537db96d56Sopenharmony_ci if mac: 5547db96d56Sopenharmony_ci return mac 5557db96d56Sopenharmony_ci return None 5567db96d56Sopenharmony_ci 5577db96d56Sopenharmony_cidef _lanscan_getnode(): 5587db96d56Sopenharmony_ci """Get the hardware address on Unix by running lanscan.""" 5597db96d56Sopenharmony_ci # This might work on HP-UX. 5607db96d56Sopenharmony_ci return _find_mac_near_keyword('lanscan', '-ai', [b'lan0'], lambda i: 0) 5617db96d56Sopenharmony_ci 5627db96d56Sopenharmony_cidef _netstat_getnode(): 5637db96d56Sopenharmony_ci """Get the hardware address on Unix by running netstat.""" 5647db96d56Sopenharmony_ci # This works on AIX and might work on Tru64 UNIX. 5657db96d56Sopenharmony_ci return _find_mac_under_heading('netstat', '-ian', b'Address') 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_cidef _ipconfig_getnode(): 5687db96d56Sopenharmony_ci """[DEPRECATED] Get the hardware address on Windows.""" 5697db96d56Sopenharmony_ci # bpo-40501: UuidCreateSequential() is now the only supported approach 5707db96d56Sopenharmony_ci return _windll_getnode() 5717db96d56Sopenharmony_ci 5727db96d56Sopenharmony_cidef _netbios_getnode(): 5737db96d56Sopenharmony_ci """[DEPRECATED] Get the hardware address on Windows.""" 5747db96d56Sopenharmony_ci # bpo-40501: UuidCreateSequential() is now the only supported approach 5757db96d56Sopenharmony_ci return _windll_getnode() 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_ci 5787db96d56Sopenharmony_ci# Import optional C extension at toplevel, to help disabling it when testing 5797db96d56Sopenharmony_citry: 5807db96d56Sopenharmony_ci import _uuid 5817db96d56Sopenharmony_ci _generate_time_safe = getattr(_uuid, "generate_time_safe", None) 5827db96d56Sopenharmony_ci _UuidCreate = getattr(_uuid, "UuidCreate", None) 5837db96d56Sopenharmony_ci _has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe 5847db96d56Sopenharmony_ciexcept ImportError: 5857db96d56Sopenharmony_ci _uuid = None 5867db96d56Sopenharmony_ci _generate_time_safe = None 5877db96d56Sopenharmony_ci _UuidCreate = None 5887db96d56Sopenharmony_ci _has_uuid_generate_time_safe = None 5897db96d56Sopenharmony_ci 5907db96d56Sopenharmony_ci 5917db96d56Sopenharmony_cidef _load_system_functions(): 5927db96d56Sopenharmony_ci """[DEPRECATED] Platform-specific functions loaded at import time""" 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci 5957db96d56Sopenharmony_cidef _unix_getnode(): 5967db96d56Sopenharmony_ci """Get the hardware address on Unix using the _uuid extension module.""" 5977db96d56Sopenharmony_ci if _generate_time_safe: 5987db96d56Sopenharmony_ci uuid_time, _ = _generate_time_safe() 5997db96d56Sopenharmony_ci return UUID(bytes=uuid_time).node 6007db96d56Sopenharmony_ci 6017db96d56Sopenharmony_cidef _windll_getnode(): 6027db96d56Sopenharmony_ci """Get the hardware address on Windows using the _uuid extension module.""" 6037db96d56Sopenharmony_ci if _UuidCreate: 6047db96d56Sopenharmony_ci uuid_bytes = _UuidCreate() 6057db96d56Sopenharmony_ci return UUID(bytes_le=uuid_bytes).node 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_cidef _random_getnode(): 6087db96d56Sopenharmony_ci """Get a random node ID.""" 6097db96d56Sopenharmony_ci # RFC 4122, $4.1.6 says "For systems with no IEEE address, a randomly or 6107db96d56Sopenharmony_ci # pseudo-randomly generated value may be used; see Section 4.5. The 6117db96d56Sopenharmony_ci # multicast bit must be set in such addresses, in order that they will 6127db96d56Sopenharmony_ci # never conflict with addresses obtained from network cards." 6137db96d56Sopenharmony_ci # 6147db96d56Sopenharmony_ci # The "multicast bit" of a MAC address is defined to be "the least 6157db96d56Sopenharmony_ci # significant bit of the first octet". This works out to be the 41st bit 6167db96d56Sopenharmony_ci # counting from 1 being the least significant bit, or 1<<40. 6177db96d56Sopenharmony_ci # 6187db96d56Sopenharmony_ci # See https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast 6197db96d56Sopenharmony_ci import random 6207db96d56Sopenharmony_ci return random.getrandbits(48) | (1 << 40) 6217db96d56Sopenharmony_ci 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_ci# _OS_GETTERS, when known, are targeted for a specific OS or platform. 6247db96d56Sopenharmony_ci# The order is by 'common practice' on the specified platform. 6257db96d56Sopenharmony_ci# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method 6267db96d56Sopenharmony_ci# which, when successful, means none of these "external" methods are called. 6277db96d56Sopenharmony_ci# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g., 6287db96d56Sopenharmony_ci# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...) 6297db96d56Sopenharmony_ciif _LINUX: 6307db96d56Sopenharmony_ci _OS_GETTERS = [_ip_getnode, _ifconfig_getnode] 6317db96d56Sopenharmony_cielif sys.platform == 'darwin': 6327db96d56Sopenharmony_ci _OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode] 6337db96d56Sopenharmony_cielif sys.platform == 'win32': 6347db96d56Sopenharmony_ci # bpo-40201: _windll_getnode will always succeed, so these are not needed 6357db96d56Sopenharmony_ci _OS_GETTERS = [] 6367db96d56Sopenharmony_cielif _AIX: 6377db96d56Sopenharmony_ci _OS_GETTERS = [_netstat_getnode] 6387db96d56Sopenharmony_cielse: 6397db96d56Sopenharmony_ci _OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode, 6407db96d56Sopenharmony_ci _netstat_getnode, _lanscan_getnode] 6417db96d56Sopenharmony_ciif os.name == 'posix': 6427db96d56Sopenharmony_ci _GETTERS = [_unix_getnode] + _OS_GETTERS 6437db96d56Sopenharmony_cielif os.name == 'nt': 6447db96d56Sopenharmony_ci _GETTERS = [_windll_getnode] + _OS_GETTERS 6457db96d56Sopenharmony_cielse: 6467db96d56Sopenharmony_ci _GETTERS = _OS_GETTERS 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ci_node = None 6497db96d56Sopenharmony_ci 6507db96d56Sopenharmony_cidef getnode(): 6517db96d56Sopenharmony_ci """Get the hardware address as a 48-bit positive integer. 6527db96d56Sopenharmony_ci 6537db96d56Sopenharmony_ci The first time this runs, it may launch a separate program, which could 6547db96d56Sopenharmony_ci be quite slow. If all attempts to obtain the hardware address fail, we 6557db96d56Sopenharmony_ci choose a random 48-bit number with its eighth bit set to 1 as recommended 6567db96d56Sopenharmony_ci in RFC 4122. 6577db96d56Sopenharmony_ci """ 6587db96d56Sopenharmony_ci global _node 6597db96d56Sopenharmony_ci if _node is not None: 6607db96d56Sopenharmony_ci return _node 6617db96d56Sopenharmony_ci 6627db96d56Sopenharmony_ci for getter in _GETTERS + [_random_getnode]: 6637db96d56Sopenharmony_ci try: 6647db96d56Sopenharmony_ci _node = getter() 6657db96d56Sopenharmony_ci except: 6667db96d56Sopenharmony_ci continue 6677db96d56Sopenharmony_ci if (_node is not None) and (0 <= _node < (1 << 48)): 6687db96d56Sopenharmony_ci return _node 6697db96d56Sopenharmony_ci assert False, '_random_getnode() returned invalid value: {}'.format(_node) 6707db96d56Sopenharmony_ci 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci_last_timestamp = None 6737db96d56Sopenharmony_ci 6747db96d56Sopenharmony_cidef uuid1(node=None, clock_seq=None): 6757db96d56Sopenharmony_ci """Generate a UUID from a host ID, sequence number, and the current time. 6767db96d56Sopenharmony_ci If 'node' is not given, getnode() is used to obtain the hardware 6777db96d56Sopenharmony_ci address. If 'clock_seq' is given, it is used as the sequence number; 6787db96d56Sopenharmony_ci otherwise a random 14-bit sequence number is chosen.""" 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci # When the system provides a version-1 UUID generator, use it (but don't 6817db96d56Sopenharmony_ci # use UuidCreate here because its UUIDs don't conform to RFC 4122). 6827db96d56Sopenharmony_ci if _generate_time_safe is not None and node is clock_seq is None: 6837db96d56Sopenharmony_ci uuid_time, safely_generated = _generate_time_safe() 6847db96d56Sopenharmony_ci try: 6857db96d56Sopenharmony_ci is_safe = SafeUUID(safely_generated) 6867db96d56Sopenharmony_ci except ValueError: 6877db96d56Sopenharmony_ci is_safe = SafeUUID.unknown 6887db96d56Sopenharmony_ci return UUID(bytes=uuid_time, is_safe=is_safe) 6897db96d56Sopenharmony_ci 6907db96d56Sopenharmony_ci global _last_timestamp 6917db96d56Sopenharmony_ci import time 6927db96d56Sopenharmony_ci nanoseconds = time.time_ns() 6937db96d56Sopenharmony_ci # 0x01b21dd213814000 is the number of 100-ns intervals between the 6947db96d56Sopenharmony_ci # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. 6957db96d56Sopenharmony_ci timestamp = nanoseconds // 100 + 0x01b21dd213814000 6967db96d56Sopenharmony_ci if _last_timestamp is not None and timestamp <= _last_timestamp: 6977db96d56Sopenharmony_ci timestamp = _last_timestamp + 1 6987db96d56Sopenharmony_ci _last_timestamp = timestamp 6997db96d56Sopenharmony_ci if clock_seq is None: 7007db96d56Sopenharmony_ci import random 7017db96d56Sopenharmony_ci clock_seq = random.getrandbits(14) # instead of stable storage 7027db96d56Sopenharmony_ci time_low = timestamp & 0xffffffff 7037db96d56Sopenharmony_ci time_mid = (timestamp >> 32) & 0xffff 7047db96d56Sopenharmony_ci time_hi_version = (timestamp >> 48) & 0x0fff 7057db96d56Sopenharmony_ci clock_seq_low = clock_seq & 0xff 7067db96d56Sopenharmony_ci clock_seq_hi_variant = (clock_seq >> 8) & 0x3f 7077db96d56Sopenharmony_ci if node is None: 7087db96d56Sopenharmony_ci node = getnode() 7097db96d56Sopenharmony_ci return UUID(fields=(time_low, time_mid, time_hi_version, 7107db96d56Sopenharmony_ci clock_seq_hi_variant, clock_seq_low, node), version=1) 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_cidef uuid3(namespace, name): 7137db96d56Sopenharmony_ci """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" 7147db96d56Sopenharmony_ci from hashlib import md5 7157db96d56Sopenharmony_ci digest = md5( 7167db96d56Sopenharmony_ci namespace.bytes + bytes(name, "utf-8"), 7177db96d56Sopenharmony_ci usedforsecurity=False 7187db96d56Sopenharmony_ci ).digest() 7197db96d56Sopenharmony_ci return UUID(bytes=digest[:16], version=3) 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_cidef uuid4(): 7227db96d56Sopenharmony_ci """Generate a random UUID.""" 7237db96d56Sopenharmony_ci return UUID(bytes=os.urandom(16), version=4) 7247db96d56Sopenharmony_ci 7257db96d56Sopenharmony_cidef uuid5(namespace, name): 7267db96d56Sopenharmony_ci """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" 7277db96d56Sopenharmony_ci from hashlib import sha1 7287db96d56Sopenharmony_ci hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest() 7297db96d56Sopenharmony_ci return UUID(bytes=hash[:16], version=5) 7307db96d56Sopenharmony_ci 7317db96d56Sopenharmony_ci# The following standard UUIDs are for use with uuid3() or uuid5(). 7327db96d56Sopenharmony_ci 7337db96d56Sopenharmony_ciNAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') 7347db96d56Sopenharmony_ciNAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') 7357db96d56Sopenharmony_ciNAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') 7367db96d56Sopenharmony_ciNAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') 737