1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehr"""UUID objects (universally unique identifiers) according to RFC 4122. 2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehThis module provides immutable UUID objects (class UUID) and the functions 4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehuuid1(), uuid3(), uuid4(), uuid5() for generating version 1, 3, 4, and 5 5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehUUIDs as specified in RFC 4122. 6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehIf all you want is a unique ID, you should probably call uuid1() or uuid4(). 8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNote that uuid1() may compromise privacy since it creates a UUID containing 9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehthe computer's network address. uuid4() creates a random UUID. 10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehTypical usage: 12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> import uuid 14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a UUID based on the host ID and current time 16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> uuid.uuid1() 17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') 18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a UUID using an MD5 hash of a namespace UUID and a name 20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') 21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') 22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a random UUID 24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> uuid.uuid4() 25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('16fd2706-8baf-433b-82eb-8c7fada847da') 26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a UUID using a SHA-1 hash of a namespace UUID and a name 28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') 29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') 30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a UUID from a string of hex digits (braces and hyphens ignored) 32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') 33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # convert a UUID to a string of hex digits in standard form 35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> str(x) 36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '00010203-0405-0607-0809-0a0b0c0d0e0f' 37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # get the raw 16 bytes of the UUID 39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> x.bytes 40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' 41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # make a UUID from a 16-byte string 43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh >>> uuid.UUID(bytes=x.bytes) 44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('00010203-0405-0607-0809-0a0b0c0d0e0f') 45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh""" 46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh__author__ = 'Ka-Ping Yee <ping@zesty.ca>' 48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehRESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ 50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'reserved for NCS compatibility', 'specified in RFC 4122', 51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 'reserved for Microsoft compatibility', 'reserved for future definition'] 52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass UUID(object): 54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Instances of the UUID class represent UUIDs as specified in RFC 4122. 55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID objects are immutable, hashable, and usable as dictionary keys. 56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Converting a UUID to a string with str() yields something in the form 57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '12345678-1234-1234-1234-123456789abc'. The UUID constructor accepts 58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh five possible forms: a similar string of hexadecimal digits, or a tuple 59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh of six integer fields (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 48-bit values respectively) as an argument named 'fields', or a string 61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh of 16 bytes (with all the integer fields in big-endian order) as an 62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh argument named 'bytes', or a string of 16 bytes (with the first three 63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fields in little-endian order) as an argument named 'bytes_le', or a 64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh single 128-bit integer as an argument named 'int'. 65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUIDs have these read-only attributes: 67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes the UUID as a 16-byte string (containing the six 69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh integer fields in big-endian byte order) 70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes_le the UUID as a 16-byte string (with time_low, time_mid, 72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh and time_hi_version in little-endian byte order) 73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fields a tuple of the six integer fields of the UUID, 75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh which are also available as six individual attributes 76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh and two derived attributes: 77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_low the first 32 bits of the UUID 79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_mid the next 16 bits of the UUID 80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_hi_version the next 16 bits of the UUID 81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_hi_variant the next 8 bits of the UUID 82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_low the next 8 bits of the UUID 83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh node the last 48 bits of the UUID 84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time the 60-bit timestamp 86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq the 14-bit sequence number 87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex the UUID as a 32-character hexadecimal string 89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int the UUID as a 128-bit integer 91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh urn the UUID as a URN as specified in RFC 4122 93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh variant the UUID variant (one of the constants RESERVED_NCS, 95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh RFC_4122, RESERVED_MICROSOFT, or RESERVED_FUTURE) 96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh version the UUID version number (1 through 5, meaningful only 98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh when the variant is RFC_4122) 99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None, 102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int=None, version=None): 103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh r"""Create a UUID from either a string of 32 hexadecimal digits, 104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh a string of 16 bytes as the 'bytes' argument, a string of 16 bytes 105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh in little-endian order as the 'bytes_le' argument, a tuple of six 106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version, 107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as 108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh the 'fields' argument, or a single 128-bit integer as the 'int' 109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh argument. When a string of hex digits is given, curly braces, 110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hyphens, and a URN prefix are all optional. For example, these 111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh expressions all yield the same UUID: 112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('{12345678-1234-5678-1234-567812345678}') 114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('12345678123456781234567812345678') 115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID('urn:uuid:12345678-1234-5678-1234-567812345678') 116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID(bytes='\x12\x34\x56\x78'*4) 117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' + 118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh '\x12\x34\x56\x78\x12\x34\x56\x78') 119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678)) 120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID(int=0x12345678123456781234567812345678) 121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must 123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh be given. The 'version' argument is optional; if given, the resulting 124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh UUID will have its variant and version set according to RFC 4122, 125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'. 126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if [hex, bytes, bytes_le, fields, int].count(None) != 4: 129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise TypeError('need one of hex, bytes, bytes_le, fields, or int') 130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hex is not None: 131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex = hex.replace('urn:', '').replace('uuid:', '') 132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex = hex.strip('{}').replace('-', '') 133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if len(hex) != 32: 134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('badly formed hexadecimal UUID string') 135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int = long(hex, 16) 136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if bytes_le is not None: 137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if len(bytes_le) != 16: 138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('bytes_le is not a 16-char string') 139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] + 140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] + 141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes_le[8:]) 142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if bytes is not None: 143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if len(bytes) != 16: 144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('bytes is not a 16-char string') 145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int = long(('%02x'*16) % tuple(map(ord, bytes)), 16) 146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if fields is not None: 147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if len(fields) != 6: 148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('fields is not a 6-tuple') 149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (time_low, time_mid, time_hi_version, 150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_hi_variant, clock_seq_low, node) = fields 151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= time_low < 1<<32L: 152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 1 out of range (need a 32-bit value)') 153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= time_mid < 1<<16L: 154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 2 out of range (need a 16-bit value)') 155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= time_hi_version < 1<<16L: 156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 3 out of range (need a 16-bit value)') 157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= clock_seq_hi_variant < 1<<8L: 158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 4 out of range (need an 8-bit value)') 159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= clock_seq_low < 1<<8L: 160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 5 out of range (need an 8-bit value)') 161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= node < 1<<48L: 162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('field 6 out of range (need a 48-bit value)') 163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low 164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int = ((time_low << 96L) | (time_mid << 80L) | 165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (time_hi_version << 64L) | (clock_seq << 48L) | node) 166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if int is not None: 167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 0 <= int < 1<<128L: 168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('int is out of range (need a 128-bit value)') 169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if version is not None: 170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not 1 <= version <= 5: 171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise ValueError('illegal version number') 172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Set the variant to RFC 4122. 173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int &= ~(0xc000 << 48L) 174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int |= 0x8000 << 48L 175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Set the version number. 176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int &= ~(0xf000 << 64L) 177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh int |= version << 76L 178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.__dict__['int'] = int 179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __cmp__(self, other): 181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if isinstance(other, UUID): 182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return cmp(self.int, other.int) 183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return NotImplemented 184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __hash__(self): 186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return hash(self.int) 187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __int__(self): 189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.int 190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __repr__(self): 192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'UUID(%r)' % str(self) 193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __setattr__(self, name, value): 195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh raise TypeError('UUID objects are immutable') 196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def __str__(self): 198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex = '%032x' % self.int 199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return '%s-%s-%s-%s-%s' % ( 200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:]) 201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_bytes(self): 203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = '' 204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for shift in range(0, 128, 8): 205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = chr((self.int >> shift) & 0xff) + bytes 206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return bytes 207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = property(get_bytes) 209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_bytes_le(self): 211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = self.bytes 212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (bytes[3] + bytes[2] + bytes[1] + bytes[0] + 213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:]) 214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes_le = property(get_bytes_le) 216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_fields(self): 218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (self.time_low, self.time_mid, self.time_hi_version, 219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.clock_seq_hi_variant, self.clock_seq_low, self.node) 220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh fields = property(get_fields) 222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_time_low(self): 224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.int >> 96L 225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_low = property(get_time_low) 227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_time_mid(self): 229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (self.int >> 80L) & 0xffff 230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_mid = property(get_time_mid) 232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_time_hi_version(self): 234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (self.int >> 64L) & 0xffff 235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_hi_version = property(get_time_hi_version) 237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_clock_seq_hi_variant(self): 239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (self.int >> 56L) & 0xff 240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_hi_variant = property(get_clock_seq_hi_variant) 242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_clock_seq_low(self): 244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (self.int >> 48L) & 0xff 245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_low = property(get_clock_seq_low) 247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_time(self): 249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (((self.time_hi_version & 0x0fffL) << 48L) | 250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (self.time_mid << 32L) | self.time_low) 251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time = property(get_time) 253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_clock_seq(self): 255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return (((self.clock_seq_hi_variant & 0x3fL) << 8L) | 256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh self.clock_seq_low) 257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq = property(get_clock_seq) 259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_node(self): 261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return self.int & 0xffffffffffff 262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh node = property(get_node) 264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_hex(self): 266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return '%032x' % self.int 267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hex = property(get_hex) 269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_urn(self): 271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 'urn:uuid:' + str(self) 272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh urn = property(get_urn) 274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_variant(self): 276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not self.int & (0x8000 << 48L): 277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return RESERVED_NCS 278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif not self.int & (0x4000 << 48L): 279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return RFC_4122 280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh elif not self.int & (0x2000 << 48L): 281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return RESERVED_MICROSOFT 282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return RESERVED_FUTURE 284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh variant = property(get_variant) 286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh def get_version(self): 288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The version bits are only meaningful for RFC 4122 UUIDs. 289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if self.variant == RFC_4122: 290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int((self.int >> 76L) & 0xf) 291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh version = property(get_version) 293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _find_mac(command, args, hw_identifiers, get_index): 295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import os 296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dir in ['', '/sbin/', '/usr/sbin']: 297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh executable = os.path.join(dir, command) 298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if not os.path.exists(executable): 299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # LC_ALL to get English output, 2>/dev/null to 303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # prevent output on stderr 304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args) 305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh with os.popen(cmd) as pipe: 306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for line in pipe: 307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh words = line.lower().split() 308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(len(words)): 309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if words[i] in hw_identifiers: 310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int( 311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh words[get_index(i)].replace(':', ''), 16) 312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError: 313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _ifconfig_getnode(): 317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address on Unix by running ifconfig.""" 318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes. 320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for args in ('', '-a', '-av'): 321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1) 322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if mac: 323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return mac 324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import socket 326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ip_addr = socket.gethostbyname(socket.gethostname()) 327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Try getting the MAC addr from arp based on our IP address (Solaris). 329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mac = _find_mac('arp', '-an', [ip_addr], lambda i: -1) 330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if mac: 331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return mac 332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # This might work on HP-UX. 334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh mac = _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0) 335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if mac: 336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return mac 337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return None 339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _ipconfig_getnode(): 341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address on Windows by running ipconfig.exe.""" 342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import os, re 343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] 344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import ctypes 346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh buffer = ctypes.create_string_buffer(300) 347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) 348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh dirs.insert(0, buffer.value.decode('mbcs')) 349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for dir in dirs: 352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') 354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except IOError: 355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for line in pipe: 358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh value = line.split(':')[-1].strip().lower() 359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): 360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return int(value.replace('-', ''), 16) 361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh finally: 362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pipe.close() 363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _netbios_getnode(): 365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address on Windows using NetBIOS calls. 366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh See http://support.microsoft.com/kb/118623 for details.""" 367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import win32wnet, netbios 368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb = netbios.NCB() 369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Command = netbios.NCBENUM 370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Buffer = adapters = netbios.LANA_ENUM() 371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh adapters._pack() 372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if win32wnet.Netbios(ncb) != 0: 373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return 374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh adapters._unpack() 375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for i in range(adapters.length): 376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Reset() 377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Command = netbios.NCBRESET 378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Lana_num = ord(adapters.lana[i]) 379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if win32wnet.Netbios(ncb) != 0: 380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Reset() 382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Command = netbios.NCBASTAT 383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Lana_num = ord(adapters.lana[i]) 384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Callname = '*'.ljust(16) 385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh ncb.Buffer = status = netbios.ADAPTER_STATUS() 386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if win32wnet.Netbios(ncb) != 0: 387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh status._unpack() 389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = map(ord, status.adapter_address) 390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) + 391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5]) 392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# Thanks to Thomas Heller for ctypes and for his help with its use here. 394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# If ctypes is available, use it to find system routines for UUID generation. 396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh_uuid_generate_random = _uuid_generate_time = _UuidCreate = None 397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehtry: 398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import ctypes, ctypes.util 399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The uuid_generate_* routines are provided by libuuid on at least 401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Linux and FreeBSD, and provided by libc on Mac OS X. 402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for libname in ['uuid', 'c']: 403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lib = ctypes.CDLL(ctypes.util.find_library(libname)) 405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(lib, 'uuid_generate_random'): 408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_random = lib.uuid_generate_random 409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if hasattr(lib, 'uuid_generate_time'): 410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_time = lib.uuid_generate_time 411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # The uuid_generate_* functions are broken on MacOS X 10.5, as noted 413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in issue #8621 the function generates the same sequence of values 414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # in the parent process and all children created using fork (unless 415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # those children use exec as well). 416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Assume that the uuid_generate functions are broken from 10.5 onward, 418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # the test can be adjusted when a later version is fixed. 419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import sys 420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform == 'darwin': 421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import os 422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if int(os.uname()[2].split('.')[0]) >= 9: 423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_random = _uuid_generate_time = None 424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # On Windows prior to 2000, UuidCreate gives a UUID containing the 426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # hardware address. On Windows 2000 and later, UuidCreate makes a 427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # random UUID and UuidCreateSequential gives a UUID containing the 428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # hardware address. These routines are provided by the RPC runtime. 429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last 430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 6 bytes returned by UuidCreateSequential are fixed, they don't appear 431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # to bear any relationship to the MAC address of any network device 432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # on the box. 433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lib = ctypes.windll.rpcrt4 435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh lib = None 437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _UuidCreate = getattr(lib, 'UuidCreateSequential', 438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh getattr(lib, 'UuidCreate', None)) 439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehexcept: 440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh pass 441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _unixdll_getnode(): 443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address on Unix using ctypes.""" 444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _buffer = ctypes.create_string_buffer(16) 445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_time(_buffer) 446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=_buffer.raw).node 447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _windll_getnode(): 449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address on Windows using ctypes.""" 450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _buffer = ctypes.create_string_buffer(16) 451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _UuidCreate(_buffer) == 0: 452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=_buffer.raw).node 453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef _random_getnode(): 455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get a random node ID, with eighth bit set as suggested by RFC 4122.""" 456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import random 457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return random.randrange(0, 1<<48L) | 0x010000000000L 458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh_node = None 460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef getnode(): 462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Get the hardware address as a 48-bit positive integer. 463ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 464ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh The first time this runs, it may launch a separate program, which could 465ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh be quite slow. If all attempts to obtain the hardware address fail, we 466ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh choose a random 48-bit number with its eighth bit set to 1 as recommended 467ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh in RFC 4122. 468ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """ 469ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 470ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh global _node 471ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _node is not None: 472ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return _node 473ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 474ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import sys 475ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if sys.platform == 'win32': 476ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] 477ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh else: 478ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh getters = [_unixdll_getnode, _ifconfig_getnode] 479ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 480ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh for getter in getters + [_random_getnode]: 481ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 482ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _node = getter() 483ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 484ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh continue 485ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _node is not None: 486ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return _node 487ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 488ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh_last_timestamp = None 489ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 490ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef uuid1(node=None, clock_seq=None): 491ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Generate a UUID from a host ID, sequence number, and the current time. 492ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh If 'node' is not given, getnode() is used to obtain the hardware 493ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh address. If 'clock_seq' is given, it is used as the sequence number; 494ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh otherwise a random 14-bit sequence number is chosen.""" 495ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 496ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # When the system provides a version-1 UUID generator, use it (but don't 497ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # use UuidCreate here because its UUIDs don't conform to RFC 4122). 498ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _uuid_generate_time and node is clock_seq is None: 499ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _buffer = ctypes.create_string_buffer(16) 500ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_time(_buffer) 501ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=_buffer.raw) 502ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 503ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh global _last_timestamp 504ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import time 505ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh nanoseconds = int(time.time() * 1e9) 506ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # 0x01b21dd213814000 is the number of 100-ns intervals between the 507ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. 508ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestamp = int(nanoseconds//100) + 0x01b21dd213814000L 509ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _last_timestamp is not None and timestamp <= _last_timestamp: 510ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh timestamp = _last_timestamp + 1 511ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _last_timestamp = timestamp 512ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if clock_seq is None: 513ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import random 514ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq = random.randrange(1<<14L) # instead of stable storage 515ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_low = timestamp & 0xffffffffL 516ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_mid = (timestamp >> 32L) & 0xffffL 517ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh time_hi_version = (timestamp >> 48L) & 0x0fffL 518ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_low = clock_seq & 0xffL 519ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL 520ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if node is None: 521ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh node = getnode() 522ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(fields=(time_low, time_mid, time_hi_version, 523ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh clock_seq_hi_variant, clock_seq_low, node), version=1) 524ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 525ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef uuid3(namespace, name): 526ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Generate a UUID from the MD5 hash of a namespace UUID and a name.""" 527ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from hashlib import md5 528ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hash = md5(namespace.bytes + name).digest() 529ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=hash[:16], version=3) 530ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 531ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef uuid4(): 532ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Generate a random UUID.""" 533ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 534ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # When the system provides a version-4 UUID generator, use it. 535ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh if _uuid_generate_random: 536ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _buffer = ctypes.create_string_buffer(16) 537ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh _uuid_generate_random(_buffer) 538ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=_buffer.raw) 539ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 540ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh # Otherwise, get randomness from urandom or the 'random' module. 541ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh try: 542ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import os 543ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=os.urandom(16), version=4) 544ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh except: 545ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh import random 546ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh bytes = [chr(random.randrange(256)) for i in range(16)] 547ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=bytes, version=4) 548ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 549ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef uuid5(namespace, name): 550ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh """Generate a UUID from the SHA-1 hash of a namespace UUID and a name.""" 551ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh from hashlib import sha1 552ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh hash = sha1(namespace.bytes + name).digest() 553ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh return UUID(bytes=hash[:16], version=5) 554ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 555ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh# The following standard UUIDs are for use with uuid3() or uuid5(). 556ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh 557ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNAMESPACE_DNS = UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8') 558ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNAMESPACE_URL = UUID('6ba7b811-9dad-11d1-80b4-00c04fd430c8') 559ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNAMESPACE_OID = UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8') 560ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehNAMESPACE_X500 = UUID('6ba7b814-9dad-11d1-80b4-00c04fd430c8') 561