Index: Lib/uuid.py =================================================================== --- Lib/uuid.py (revision 88332) +++ Lib/uuid.py (working copy) @@ -53,6 +53,9 @@ int_ = int # The built-in int type bytes_ = bytes # The built-in bytes type +import ctypes + + 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 +314,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']: @@ -362,7 +366,6 @@ import os, re dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] try: - import ctypes buffer = ctypes.create_string_buffer(300) ctypes.windll.kernel32.GetSystemDirectoryA(buffer, 300) dirs.insert(0, buffer.value.decode('mbcs')) @@ -410,66 +413,74 @@ 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. +def _uuid_generate(attr): + """Find system routines for UUID generation""" -# 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 + # Thanks to Thomas Heller for ctypes and for his help with its use here. + try: + import ctypes.util - # 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: - lib = ctypes.CDLL(ctypes.util.find_library(libname)) - 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 + 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: + lib = ctypes.CDLL(ctypes.util.find_library(libname)) + 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_generate_random = _uuid_generate_time = None + # 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 - # 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. +def _uuid_create(): + """Get random UUID on Windows platform.""" + try: - lib = ctypes.windll.rpcrt4 + # 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 + except: + 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.""" _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.""" _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 +527,10 @@ # 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: _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 +565,10 @@ """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: _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.