Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(13229)

Unified Diff: Lib/uuid.py

Issue 20519: ctypes.create_string_buffer creates reference cycles
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Lib/test/test_uuid.py ('k') | Modules/_uuidmodule.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
--- a/Lib/uuid.py Wed Feb 05 10:33:14 2014 -0500
+++ b/Lib/uuid.py Wed Oct 28 13:29:38 2015 +0000
@@ -425,23 +425,12 @@
# 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
- # 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
- if _uuid_generate_random is not None:
- break # found everything we were looking for
+import sys
+import os
+
+if sys.platform == "darwin" and int(os.uname().release.split('.')[0]) < 9:
# 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
@@ -449,28 +438,64 @@
#
# 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
+ _uuid = None
+else:
+ try:
+ import _uuid
+ except ImportError:
+ _uuid = 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.
+if _uuid is None:
try:
- lib = ctypes.windll.rpcrt4
- except:
- lib = None
- _UuidCreate = getattr(lib, 'UuidCreateSequential',
- getattr(lib, 'UuidCreate', None))
-except:
- pass
+ # If we couldn't find an extension module, try ctypes
+ import ctypes
+ 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
+ if _uuid_generate_random is not None:
+ break # found everything we were looking for
+
+ # 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_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
+ except:
+ lib = None
+ _UuidCreate = getattr(lib, 'UuidCreateSequential',
+ getattr(lib, 'UuidCreate', None))
+ except Exception as ex:
+ import warnings
+ warnings.warn("Could not find fallback ctypes uuid functions: {}"
+ .format(ex),
+ ImportWarning)
+
def _unixdll_getnode():
"""Get the hardware address on Unix using ctypes."""
@@ -478,12 +503,20 @@
_uuid_generate_time(_buffer)
return UUID(bytes=bytes_(_buffer.raw)).node
+
+def _unix_extmod_getnode():
+ """Get the hardware address on Unix using the _uuid extension module."""
+ uuid_time = _uuid.generate_time()
+ return UUID(bytes=uuid_time).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=bytes_(_buffer.raw)).node
+
def _random_getnode():
"""Get a random node ID, with eighth bit set as suggested by RFC 4122."""
import random
@@ -491,6 +524,7 @@
_node = None
+
def getnode():
"""Get the hardware address as a 48-bit positive integer.
@@ -508,7 +542,7 @@
if sys.platform == 'win32':
getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
else:
- getters = [_unixdll_getnode, _ifconfig_getnode]
+ getters = [_unix_extmod_getnode, _unixdll_getnode, _ifconfig_getnode]
for getter in getters + [_random_getnode]:
try:
@@ -520,6 +554,7 @@
_last_timestamp = None
+
def uuid1(node=None, clock_seq=None):
"""Generate a UUID from a host ID, sequence number, and the current time.
If 'node' is not given, getnode() is used to obtain the hardware
@@ -528,6 +563,8 @@
# 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 is not None and node is clock_seq is None:
+ return UUID(bytes=_uuid.generate_time())
if _uuid_generate_time and node is clock_seq is None:
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_time(_buffer)
@@ -555,16 +592,20 @@
return UUID(fields=(time_low, time_mid, time_hi_version,
clock_seq_hi_variant, clock_seq_low, node), version=1)
+
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 + bytes(name, "utf-8")).digest()
return UUID(bytes=hash[:16], version=3)
+
def uuid4():
"""Generate a random UUID."""
# When the system provides a version-4 UUID generator, use it.
+ if _uuid is not None:
+ return UUID(bytes=_uuid.generate_random())
if _uuid_generate_random:
_buffer = ctypes.create_string_buffer(16)
_uuid_generate_random(_buffer)
@@ -579,6 +620,7 @@
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
« no previous file with comments | « Lib/test/test_uuid.py ('k') | Modules/_uuidmodule.c » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+