summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorStefan Grönke <stefan@gronke.net>2017-09-20 22:36:29 (GMT)
committerStefan Grönke <stefan@gronke.net>2017-09-22 17:51:40 (GMT)
commit1eb5d208cdf20374bcad1b72632f1c01d6b1a0b3 (patch)
tree09deedbf9ad4b89bf5b155fb0f83c1cf84f47721 /Lib
parent74fdc42048b95698eeac36b2fdb35b3ff5d6a620 (diff)
downloadcpython-1eb5d208cdf20374bcad1b72632f1c01d6b1a0b3.zip
cpython-1eb5d208cdf20374bcad1b72632f1c01d6b1a0b3.tar.gz
cpython-1eb5d208cdf20374bcad1b72632f1c01d6b1a0b3.tar.bz2
lazy-load uuid_generate_time
_uuid_generate_time is lazy-loaded on first use to speed up initialization of applications depending on other uuid features
Diffstat (limited to 'Lib')
-rw-r--r--Lib/uuid.py143
1 files changed, 84 insertions, 59 deletions
diff --git a/Lib/uuid.py b/Lib/uuid.py
index 3dda13e..451d810 100644
--- a/Lib/uuid.py
+++ b/Lib/uuid.py
@@ -45,7 +45,7 @@ Typical usage:
"""
import os
-
+import sys
from enum import Enum
@@ -475,78 +475,101 @@ def _netbios_getnode():
continue
return int.from_bytes(bytes, 'big')
+def _is_darwin_greater_than_version(major_version_number):
+ """Checks if the operating system is Darwin newer than
+ the specified major version number."""
+ if sys.platform != "darwin":
+ return False
+ return int(os.uname().release.split(".")[0]) >= major_version_number
+
+# 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.
+_no_uuid_generate_time_lookup = _is_darwin_greater_than_version(9)
+_uuid_generate_time = _UuidCreate = None
+
# 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_time = _UuidCreate = None
-try:
- import sys
- # 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.
- if sys.platform == 'darwin':
- if int(os.uname().release.split('.')[0]) >= 9:
- _uuid_generate_time = None
- raise NotImplementedError("Not supported on OSX >= 10.5")
+def _get_uuid_generate_time():
+ """Lazy-loading of _uuid_generate_time."""
+ global _no_uuid_generate_time_lookup
+ global _uuid_generate_time
+
+ if _no_uuid_generate_time_lookup or (_uuid_generate_time is not None):
+ return _uuid_generate_time
+
+ # After looking up _uuid_generate_time once, the result is memoized
+ _no_uuid_generate_time_lookup = True
- import ctypes
- import ctypes.util
- # The uuid_generate_* routines are provided by libuuid - at least
- # on Linux. On FreeBSD and OS X they are provided by libc
- _libnames = ['uuid']
- if not sys.platform.startswith('win'):
- if 'bsd' in sys.platform:
- _libnames.insert(0, 'c')
- else:
- _libnames.append('c')
- for libname in _libnames:
- try:
- lib = ctypes.CDLL(ctypes.util.find_library(libname))
- except Exception: # pragma: nocover
- continue
- # Try to find the safe variety first.
- if hasattr(lib, 'uuid_generate_time_safe'):
- _uuid_generate_time = lib.uuid_generate_time_safe
- # int uuid_generate_time_safe(uuid_t out);
- break
- elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
- _uuid_generate_time = lib.uuid_generate_time
- # void uuid_generate_time(uuid_t out);
- _uuid_generate_time.restype = None
- break
- del _libnames
-
- # 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
+ import ctypes
+ import ctypes.util
+ # The uuid_generate_* routines are provided by libuuid - at least
+ # on Linux. On FreeBSD and OS X they are provided by libc
+ _libnames = ['uuid']
+ if not sys.platform.startswith('win'):
+ if 'bsd' in sys.platform:
+ _libnames.insert(0, 'c')
+ else:
+ _libnames.append('c')
+ for libname in _libnames:
+ try:
+ lib = ctypes.CDLL(ctypes.util.find_library(libname))
+ except Exception: # pragma: nocover
+ continue
+ # Try to find the safe variety first.
+ if hasattr(lib, 'uuid_generate_time_safe'):
+ _uuid_generate_time = lib.uuid_generate_time_safe
+ # int uuid_generate_time_safe(uuid_t out);
+ break
+ elif hasattr(lib, 'uuid_generate_time'): # pragma: nocover
+ _uuid_generate_time = lib.uuid_generate_time
+ # void uuid_generate_time(uuid_t out);
+ _uuid_generate_time.restype = None
+ break
+ del _libnames
+
+ # 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 AttributeError:
+ lib = None
+ _UuidCreate = getattr(
+ lib,
+ 'UuidCreateSequential',
+ getattr(lib, 'UuidCreate', None)
+ )
except:
- lib = None
- _UuidCreate = getattr(lib, 'UuidCreateSequential',
- getattr(lib, 'UuidCreate', None))
-except:
- pass
+ pass
+
+ return _uuid_generate_time
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 = _get_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)
+ _get_uuid_generate_time()
if _UuidCreate(_buffer) == 0:
return UUID(bytes=bytes_(_buffer.raw)).node
@@ -595,9 +618,11 @@ def uuid1(node=None, clock_seq=None):
# 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 = _get_uuid_generate_time()
+ if uuid_generate_time and node is clock_seq is None:
+ import ctypes
_buffer = ctypes.create_string_buffer(16)
- safely_generated = _uuid_generate_time(_buffer)
+ safely_generated = uuid_generate_time(_buffer)
try:
is_safe = SafeUUID(safely_generated)
except ValueError: