summaryrefslogtreecommitdiffstats
path: root/Lib/uuid.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/uuid.py')
-rw-r--r--Lib/uuid.py225
1 files changed, 123 insertions, 102 deletions
diff --git a/Lib/uuid.py b/Lib/uuid.py
index fdd0c5c..5684ad7 100644
--- a/Lib/uuid.py
+++ b/Lib/uuid.py
@@ -13,7 +13,7 @@ Typical usage:
>>> import uuid
# make a UUID based on the host ID and current time
- >>> uuid.uuid1()
+ >>> uuid.uuid1() # doctest: +SKIP
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
# make a UUID using an MD5 hash of a namespace UUID and a name
@@ -21,7 +21,7 @@ Typical usage:
UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
# make a random UUID
- >>> uuid.uuid4()
+ >>> uuid.uuid4() # doctest: +SKIP
UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
# make a UUID using a SHA-1 hash of a namespace UUID and a name
@@ -37,7 +37,7 @@ Typical usage:
# get the raw 16 bytes of the UUID
>>> x.bytes
- '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
+ b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'
# make a UUID from a 16-byte string
>>> uuid.UUID(bytes=x.bytes)
@@ -50,6 +50,9 @@ RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
'reserved for NCS compatibility', 'specified in RFC 4122',
'reserved for Microsoft compatibility', 'reserved for future definition']
+int_ = int # The built-in int type
+bytes_ = bytes # The built-in bytes type
+
class UUID(object):
"""Instances of the UUID class represent UUIDs as specified in RFC 4122.
UUID objects are immutable, hashable, and usable as dictionary keys.
@@ -132,54 +135,84 @@ class UUID(object):
hex = hex.strip('{}').replace('-', '')
if len(hex) != 32:
raise ValueError('badly formed hexadecimal UUID string')
- int = long(hex, 16)
+ int = int_(hex, 16)
if bytes_le is not None:
if len(bytes_le) != 16:
raise ValueError('bytes_le is not a 16-char string')
- bytes = (bytes_le[3] + bytes_le[2] + bytes_le[1] + bytes_le[0] +
- bytes_le[5] + bytes_le[4] + bytes_le[7] + bytes_le[6] +
+ bytes = (bytes_(reversed(bytes_le[0:4])) +
+ bytes_(reversed(bytes_le[4:6])) +
+ bytes_(reversed(bytes_le[6:8])) +
bytes_le[8:])
if bytes is not None:
if len(bytes) != 16:
raise ValueError('bytes is not a 16-char string')
- int = long(('%02x'*16) % tuple(map(ord, bytes)), 16)
+ assert isinstance(bytes, bytes_), repr(bytes)
+ int = int_(('%02x'*16) % tuple(bytes), 16)
if fields is not None:
if len(fields) != 6:
raise ValueError('fields is not a 6-tuple')
(time_low, time_mid, time_hi_version,
clock_seq_hi_variant, clock_seq_low, node) = fields
- if not 0 <= time_low < 1<<32L:
+ if not 0 <= time_low < 1<<32:
raise ValueError('field 1 out of range (need a 32-bit value)')
- if not 0 <= time_mid < 1<<16L:
+ if not 0 <= time_mid < 1<<16:
raise ValueError('field 2 out of range (need a 16-bit value)')
- if not 0 <= time_hi_version < 1<<16L:
+ if not 0 <= time_hi_version < 1<<16:
raise ValueError('field 3 out of range (need a 16-bit value)')
- if not 0 <= clock_seq_hi_variant < 1<<8L:
+ if not 0 <= clock_seq_hi_variant < 1<<8:
raise ValueError('field 4 out of range (need an 8-bit value)')
- if not 0 <= clock_seq_low < 1<<8L:
+ if not 0 <= clock_seq_low < 1<<8:
raise ValueError('field 5 out of range (need an 8-bit value)')
- if not 0 <= node < 1<<48L:
+ if not 0 <= node < 1<<48:
raise ValueError('field 6 out of range (need a 48-bit value)')
- clock_seq = (clock_seq_hi_variant << 8L) | clock_seq_low
- int = ((time_low << 96L) | (time_mid << 80L) |
- (time_hi_version << 64L) | (clock_seq << 48L) | node)
+ clock_seq = (clock_seq_hi_variant << 8) | clock_seq_low
+ int = ((time_low << 96) | (time_mid << 80) |
+ (time_hi_version << 64) | (clock_seq << 48) | node)
if int is not None:
- if not 0 <= int < 1<<128L:
+ if not 0 <= int < 1<<128:
raise ValueError('int is out of range (need a 128-bit value)')
if version is not None:
if not 1 <= version <= 5:
raise ValueError('illegal version number')
# Set the variant to RFC 4122.
- int &= ~(0xc000 << 48L)
- int |= 0x8000 << 48L
+ int &= ~(0xc000 << 48)
+ int |= 0x8000 << 48
# Set the version number.
- int &= ~(0xf000 << 64L)
- int |= version << 76L
+ int &= ~(0xf000 << 64)
+ int |= version << 76
self.__dict__['int'] = int
- def __cmp__(self, other):
+ def __eq__(self, other):
+ if isinstance(other, UUID):
+ return self.int == other.int
+ return NotImplemented
+
+ def __ne__(self, other):
+ if isinstance(other, UUID):
+ return self.int != other.int
+ return NotImplemented
+
+ # Q. What's the value of being able to sort UUIDs?
+ # A. Use them as keys in a B-Tree or similar mapping.
+
+ def __lt__(self, other):
+ if isinstance(other, UUID):
+ return self.int < other.int
+ return NotImplemented
+
+ def __gt__(self, other):
+ if isinstance(other, UUID):
+ return self.int > other.int
+ return NotImplemented
+
+ def __le__(self, other):
+ if isinstance(other, UUID):
+ return self.int <= other.int
+ return NotImplemented
+
+ def __ge__(self, other):
if isinstance(other, UUID):
- return cmp(self.int, other.int)
+ return self.int >= other.int
return NotImplemented
def __hash__(self):
@@ -199,97 +232,84 @@ class UUID(object):
return '%s-%s-%s-%s-%s' % (
hex[:8], hex[8:12], hex[12:16], hex[16:20], hex[20:])
- def get_bytes(self):
- bytes = ''
+ @property
+ def bytes(self):
+ bytes = bytearray()
for shift in range(0, 128, 8):
- bytes = chr((self.int >> shift) & 0xff) + bytes
- return bytes
-
- bytes = property(get_bytes)
+ bytes.insert(0, (self.int >> shift) & 0xff)
+ return bytes_(bytes)
- def get_bytes_le(self):
+ @property
+ def bytes_le(self):
bytes = self.bytes
- return (bytes[3] + bytes[2] + bytes[1] + bytes[0] +
- bytes[5] + bytes[4] + bytes[7] + bytes[6] + bytes[8:])
+ return (bytes_(reversed(bytes[0:4])) +
+ bytes_(reversed(bytes[4:6])) +
+ bytes_(reversed(bytes[6:8])) +
+ bytes[8:])
- bytes_le = property(get_bytes_le)
-
- def get_fields(self):
+ @property
+ def fields(self):
return (self.time_low, self.time_mid, self.time_hi_version,
self.clock_seq_hi_variant, self.clock_seq_low, self.node)
- fields = property(get_fields)
-
- def get_time_low(self):
- return self.int >> 96L
-
- time_low = property(get_time_low)
-
- def get_time_mid(self):
- return (self.int >> 80L) & 0xffff
-
- time_mid = property(get_time_mid)
-
- def get_time_hi_version(self):
- return (self.int >> 64L) & 0xffff
+ @property
+ def time_low(self):
+ return self.int >> 96
- time_hi_version = property(get_time_hi_version)
+ @property
+ def time_mid(self):
+ return (self.int >> 80) & 0xffff
- def get_clock_seq_hi_variant(self):
- return (self.int >> 56L) & 0xff
+ @property
+ def time_hi_version(self):
+ return (self.int >> 64) & 0xffff
- clock_seq_hi_variant = property(get_clock_seq_hi_variant)
+ @property
+ def clock_seq_hi_variant(self):
+ return (self.int >> 56) & 0xff
- def get_clock_seq_low(self):
- return (self.int >> 48L) & 0xff
+ @property
+ def clock_seq_low(self):
+ return (self.int >> 48) & 0xff
- clock_seq_low = property(get_clock_seq_low)
+ @property
+ def time(self):
+ return (((self.time_hi_version & 0x0fff) << 48) |
+ (self.time_mid << 32) | self.time_low)
- def get_time(self):
- return (((self.time_hi_version & 0x0fffL) << 48L) |
- (self.time_mid << 32L) | self.time_low)
-
- time = property(get_time)
-
- def get_clock_seq(self):
- return (((self.clock_seq_hi_variant & 0x3fL) << 8L) |
+ @property
+ def clock_seq(self):
+ return (((self.clock_seq_hi_variant & 0x3f) << 8) |
self.clock_seq_low)
- clock_seq = property(get_clock_seq)
-
- def get_node(self):
+ @property
+ def node(self):
return self.int & 0xffffffffffff
- node = property(get_node)
-
- def get_hex(self):
+ @property
+ def hex(self):
return '%032x' % self.int
- hex = property(get_hex)
-
- def get_urn(self):
+ @property
+ def urn(self):
return 'urn:uuid:' + str(self)
- urn = property(get_urn)
-
- def get_variant(self):
- if not self.int & (0x8000 << 48L):
+ @property
+ def variant(self):
+ if not self.int & (0x8000 << 48):
return RESERVED_NCS
- elif not self.int & (0x4000 << 48L):
+ elif not self.int & (0x4000 << 48):
return RFC_4122
- elif not self.int & (0x2000 << 48L):
+ elif not self.int & (0x2000 << 48):
return RESERVED_MICROSOFT
else:
return RESERVED_FUTURE
- variant = property(get_variant)
-
- def get_version(self):
+ @property
+ def version(self):
# The version bits are only meaningful for RFC 4122 UUIDs.
if self.variant == RFC_4122:
- return int((self.int >> 76L) & 0xf)
-
- version = property(get_version)
+ return int((self.int >> 76) & 0xf)
def _find_mac(command, args, hw_identifiers, get_index):
import os
@@ -387,12 +407,13 @@ def _netbios_getnode():
continue
status._unpack()
bytes = map(ord, status.adapter_address)
- return ((bytes[0]<<40L) + (bytes[1]<<32L) + (bytes[2]<<24L) +
- (bytes[3]<<16L) + (bytes[4]<<8L) + bytes[5])
+ return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) +
+ (bytes[3]<<16) + (bytes[4]<<8) + bytes[5])
# Thanks to Thomas Heller for ctypes and for his help with its use here.
# If ctypes is available, use it to find system routines for UUID generation.
+# XXX This makes the module non-thread-safe!
_uuid_generate_random = _uuid_generate_time = _UuidCreate = None
try:
import ctypes, ctypes.util
@@ -443,18 +464,18 @@ def _unixdll_getnode():
"""Get the hardware address on Unix using ctypes."""
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw).node
+ return UUID(bytes=bytes_(_buffer.raw)).node
def _windll_getnode():
"""Get the hardware address on Windows using ctypes."""
_buffer = ctypes.create_string_buffer(16)
if _UuidCreate(_buffer) == 0:
- return UUID(bytes=_buffer.raw).node
+ return UUID(bytes=bytes_(_buffer.raw)).node
def _random_getnode():
"""Get a random node ID, with eighth bit set as suggested by RFC 4122."""
import random
- return random.randrange(0, 1<<48L) | 0x010000000000L
+ return random.randrange(0, 1<<48) | 0x010000000000
_node = None
@@ -498,25 +519,25 @@ def uuid1(node=None, clock_seq=None):
if _uuid_generate_time and node is clock_seq is None:
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_time(_buffer)
- return UUID(bytes=_buffer.raw)
+ return UUID(bytes=bytes_(_buffer.raw))
global _last_timestamp
import time
nanoseconds = int(time.time() * 1e9)
# 0x01b21dd213814000 is the number of 100-ns intervals between the
# UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
- timestamp = int(nanoseconds//100) + 0x01b21dd213814000L
+ timestamp = int(nanoseconds/100) + 0x01b21dd213814000
if _last_timestamp is not None and timestamp <= _last_timestamp:
timestamp = _last_timestamp + 1
_last_timestamp = timestamp
if clock_seq is None:
import random
- clock_seq = random.randrange(1<<14L) # instead of stable storage
- time_low = timestamp & 0xffffffffL
- time_mid = (timestamp >> 32L) & 0xffffL
- time_hi_version = (timestamp >> 48L) & 0x0fffL
- clock_seq_low = clock_seq & 0xffL
- clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
+ clock_seq = random.randrange(1<<14) # instead of stable storage
+ time_low = timestamp & 0xffffffff
+ time_mid = (timestamp >> 32) & 0xffff
+ time_hi_version = (timestamp >> 48) & 0x0fff
+ clock_seq_low = clock_seq & 0xff
+ clock_seq_hi_variant = (clock_seq >> 8) & 0x3f
if node is None:
node = getnode()
return UUID(fields=(time_low, time_mid, time_hi_version,
@@ -525,7 +546,7 @@ def uuid1(node=None, clock_seq=None):
def uuid3(namespace, name):
"""Generate a UUID from the MD5 hash of a namespace UUID and a name."""
from hashlib import md5
- hash = md5(namespace.bytes + name).digest()
+ hash = md5(namespace.bytes + bytes(name, "utf-8")).digest()
return UUID(bytes=hash[:16], version=3)
def uuid4():
@@ -535,7 +556,7 @@ def uuid4():
if _uuid_generate_random:
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_random(_buffer)
- return UUID(bytes=_buffer.raw)
+ return UUID(bytes=bytes_(_buffer.raw))
# Otherwise, get randomness from urandom or the 'random' module.
try:
@@ -543,13 +564,13 @@ def uuid4():
return UUID(bytes=os.urandom(16), version=4)
except:
import random
- bytes = [chr(random.randrange(256)) for i in range(16)]
+ bytes = bytes_(random.randrange(256) for i in range(16))
return UUID(bytes=bytes, version=4)
def uuid5(namespace, name):
"""Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
from hashlib import sha1
- hash = sha1(namespace.bytes + name).digest()
+ hash = sha1(namespace.bytes + bytes(name, "utf-8")).digest()
return UUID(bytes=hash[:16], version=5)
# The following standard UUIDs are for use with uuid3() or uuid5().