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