diff -r 96f08a22f562 Lib/test/test_uuid.py --- a/Lib/test/test_uuid.py Sat Feb 23 22:21:48 2013 -0500 +++ b/Lib/test/test_uuid.py Sun Feb 24 14:16:31 2013 +0100 @@ -376,6 +376,7 @@ # Make sure the generated UUIDs are actually unique. uuids = {} + for u in [uuid.uuid1() for i in range(1000)]: uuids[u] = 1 equal(len(uuids.keys()), 1000) diff -r 96f08a22f562 Lib/uuid.py --- a/Lib/uuid.py Sat Feb 23 22:21:48 2013 -0500 +++ b/Lib/uuid.py Sun Feb 24 14:16:31 2013 +0100 @@ -53,6 +53,7 @@ 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. @@ -311,6 +312,7 @@ if self.variant == RFC_4122: return int((self.int >> 76) & 0xf) + def _find_mac(command, args, hw_identifiers, get_index): import os for dir in ['', '/sbin/', '/usr/sbin']: @@ -410,66 +412,87 @@ 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 +_ctypes_lib = None - # The uuid_generate_* routines are provided by libuuid on at least - # Linux and FreeBSD, and provided by libc on Mac OS X. - for libname in ['uuid', 'c']: + +def _uuid_generate(attr): + """Find system routines for UUID generation""" + + # Thanks to Thomas Heller for ctypes and for his help with its use here. + try: + import ctypes + import ctypes.util + + global _ctypes_lib + + uuid = None + # The uuid_generate_* routines are provided by libuuid on at least + # Linux and FreeBSD, and provided by libc on Mac OS X. + for libname in ['uuid', 'c']: + try: + if _ctypes_lib is None: + _ctypes_lib = ctypes.CDLL(ctypes.util.find_library(libname)) + lib = _ctypes_lib + except: + continue + if hasattr(lib, attr): + uuid = getattr(lib, attr) + + # The uuid_generate_* functions are broken on MacOS X 10.5, as noted + # in issue #8621 the function generates the same sequence of values + # in the parent process and all children created using fork (unless + # those children use exec as well). + # + # Assume that the uuid_generate functions are broken from 10.5 onward, + # the test can be adjusted when a later version is fixed. + import sys + if sys.platform == 'darwin': + import os + if int(os.uname()[2].split('.')[0]) >= 9: + uuid = None + return uuid + except: + pass + + +def _uuid_create(): + """Get random UUID on Windows platform.""" + + try: + # On Windows prior to 2000, UuidCreate gives a UUID containing the + # hardware address. On Windows 2000 and later, UuidCreate makes a + # random UUID and UuidCreateSequential gives a UUID containing the + # hardware address. These routines are provided by the RPC runtime. + # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last + # 6 bytes returned by UuidCreateSequential are fixed, they don't appear + # to bear any relationship to the MAC address of any network device + # on the box. try: - lib = ctypes.CDLL(ctypes.util.find_library(libname)) + import ctypes + lib = ctypes.windll.rpcrt4 except: - continue - if hasattr(lib, 'uuid_generate_random'): - _uuid_generate_random = lib.uuid_generate_random - if hasattr(lib, 'uuid_generate_time'): - _uuid_generate_time = lib.uuid_generate_time - - # The uuid_generate_* functions are broken on MacOS X 10.5, as noted - # in issue #8621 the function generates the same sequence of values - # in the parent process and all children created using fork (unless - # those children use exec as well). - # - # Assume that the uuid_generate functions are broken from 10.5 onward, - # the test can be adjusted when a later version is fixed. - import sys - if sys.platform == 'darwin': - import os - if int(os.uname().release.split('.')[0]) >= 9: - _uuid_generate_random = _uuid_generate_time = None - - # On Windows prior to 2000, UuidCreate gives a UUID containing the - # hardware address. On Windows 2000 and later, UuidCreate makes a - # random UUID and UuidCreateSequential gives a UUID containing the - # hardware address. These routines are provided by the RPC runtime. - # NOTE: at least on Tim's WinXP Pro SP2 desktop box, while the last - # 6 bytes returned by UuidCreateSequential are fixed, they don't appear - # to bear any relationship to the MAC address of any network device - # on the box. - try: - lib = ctypes.windll.rpcrt4 + lib = None + uuid = getattr(lib, 'UuidCreateSequential', + getattr(lib, 'UuidCreate', None)) + return uuid except: - lib = None - _UuidCreate = getattr(lib, 'UuidCreateSequential', - getattr(lib, 'UuidCreate', None)) -except: - pass + pass def _unixdll_getnode(): """Get the hardware address on Unix using ctypes.""" + import ctypes _buffer = ctypes.create_string_buffer(16) - _uuid_generate_time(_buffer) + uuid_generate_time = _uuid_generate("uuid_generate_time") + uuid_generate_time(_buffer) return UUID(bytes=bytes_(_buffer.raw)).node def _windll_getnode(): """Get the hardware address on Windows using ctypes.""" + import ctypes _buffer = ctypes.create_string_buffer(16) - if _UuidCreate(_buffer) == 0: + UuidCreate = _uuid_create() + if UuidCreate(_buffer) == 0: return UUID(bytes=bytes_(_buffer.raw)).node def _random_getnode(): @@ -516,9 +539,12 @@ # When the system provides a version-1 UUID generator, use it (but don't # use UuidCreate here because its UUIDs don't conform to RFC 4122). - if _uuid_generate_time and node is clock_seq is None: + uuid_generate_time = _uuid_generate("uuid_generate_time") + + if uuid_generate_time and node is clock_seq is None: + import ctypes _buffer = ctypes.create_string_buffer(16) - _uuid_generate_time(_buffer) + uuid_generate_time(_buffer) return UUID(bytes=bytes_(_buffer.raw)) global _last_timestamp @@ -553,9 +579,11 @@ """Generate a random UUID.""" # When the system provides a version-4 UUID generator, use it. - if _uuid_generate_random: + uuid_generate_random = _uuid_generate("uuid_generate_random") + if uuid_generate_random: + import ctypes _buffer = ctypes.create_string_buffer(16) - _uuid_generate_random(_buffer) + uuid_generate_random(_buffer) return UUID(bytes=bytes_(_buffer.raw)) # Otherwise, get randomness from urandom or the 'random' module.