mirror of
https://github.com/python/cpython.git
synced 2025-09-28 03:13:48 +00:00
bpo-28009: Fix uuid SkipUnless logic to be based on platform programs capable of introspection (GH-12777)
uuid could try fallback methods that had no chance of working on a particular platform, and this could cause spurious test failures, as well as degraded performance as fallback options were tried and failed. This fixes both the uuid module and its test's SkipUnless logic to use a prefiltered list of techniques that may at least potentially work on that platform. Patch by Michael Felt (aixtools).
This commit is contained in:
parent
7a68f8c28b
commit
3a1d50e7e5
3 changed files with 47 additions and 19 deletions
|
@ -462,8 +462,7 @@ class BaseTestUUID:
|
||||||
with unittest.mock.patch.multiple(
|
with unittest.mock.patch.multiple(
|
||||||
self.uuid,
|
self.uuid,
|
||||||
_node=None, # Ignore any cached node value.
|
_node=None, # Ignore any cached node value.
|
||||||
_NODE_GETTERS_WIN32=[too_large_getter],
|
_GETTERS=[too_large_getter],
|
||||||
_NODE_GETTERS_UNIX=[too_large_getter],
|
|
||||||
):
|
):
|
||||||
node = self.uuid.getnode()
|
node = self.uuid.getnode()
|
||||||
self.assertTrue(0 < node < (1 << 48), '%012x' % node)
|
self.assertTrue(0 < node < (1 << 48), '%012x' % node)
|
||||||
|
@ -673,7 +672,7 @@ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class BaseTestInternals:
|
class BaseTestInternals:
|
||||||
uuid = None
|
_uuid = py_uuid
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
||||||
def test_find_mac(self):
|
def test_find_mac(self):
|
||||||
|
@ -708,27 +707,32 @@ eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab
|
||||||
self.assertTrue(0 < node < (1 << 48),
|
self.assertTrue(0 < node < (1 << 48),
|
||||||
"%s is not an RFC 4122 node ID" % hex)
|
"%s is not an RFC 4122 node ID" % hex)
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS,
|
||||||
|
"ifconfig is not used for introspection on this platform")
|
||||||
def test_ifconfig_getnode(self):
|
def test_ifconfig_getnode(self):
|
||||||
node = self.uuid._ifconfig_getnode()
|
node = self.uuid._ifconfig_getnode()
|
||||||
self.check_node(node, 'ifconfig')
|
self.check_node(node, 'ifconfig')
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(_uuid._ip_getnode in _uuid._GETTERS,
|
||||||
|
"ip is not used for introspection on this platform")
|
||||||
def test_ip_getnode(self):
|
def test_ip_getnode(self):
|
||||||
node = self.uuid._ip_getnode()
|
node = self.uuid._ip_getnode()
|
||||||
self.check_node(node, 'ip')
|
self.check_node(node, 'ip')
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(_uuid._arp_getnode in _uuid._GETTERS,
|
||||||
|
"arp is not used for introspection on this platform")
|
||||||
def test_arp_getnode(self):
|
def test_arp_getnode(self):
|
||||||
node = self.uuid._arp_getnode()
|
node = self.uuid._arp_getnode()
|
||||||
self.check_node(node, 'arp')
|
self.check_node(node, 'arp')
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(_uuid._lanscan_getnode in _uuid._GETTERS,
|
||||||
|
"lanscan is not used for introspection on this platform")
|
||||||
def test_lanscan_getnode(self):
|
def test_lanscan_getnode(self):
|
||||||
node = self.uuid._lanscan_getnode()
|
node = self.uuid._lanscan_getnode()
|
||||||
self.check_node(node, 'lanscan')
|
self.check_node(node, 'lanscan')
|
||||||
|
|
||||||
@unittest.skipUnless(os.name == 'posix', 'requires Posix')
|
@unittest.skipUnless(_uuid._netstat_getnode in _uuid._GETTERS,
|
||||||
|
"netstat is not used for introspection on this platform")
|
||||||
def test_netstat_getnode(self):
|
def test_netstat_getnode(self):
|
||||||
node = self.uuid._netstat_getnode()
|
node = self.uuid._netstat_getnode()
|
||||||
self.check_node(node, 'netstat')
|
self.check_node(node, 'netstat')
|
||||||
|
|
43
Lib/uuid.py
43
Lib/uuid.py
|
@ -45,6 +45,7 @@ Typical usage:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
@ -52,6 +53,12 @@ from enum import Enum
|
||||||
|
|
||||||
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
|
__author__ = 'Ka-Ping Yee <ping@zesty.ca>'
|
||||||
|
|
||||||
|
# The recognized platforms - known behaviors
|
||||||
|
_AIX = platform.system() == 'AIX'
|
||||||
|
_DARWIN = platform.system() == 'Darwin'
|
||||||
|
_LINUX = platform.system() == 'Linux'
|
||||||
|
_WINDOWS = platform.system() == 'Windows'
|
||||||
|
|
||||||
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
|
RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
|
||||||
'reserved for NCS compatibility', 'specified in RFC 4122',
|
'reserved for NCS compatibility', 'specified in RFC 4122',
|
||||||
'reserved for Microsoft compatibility', 'reserved for future definition']
|
'reserved for Microsoft compatibility', 'reserved for future definition']
|
||||||
|
@ -673,13 +680,32 @@ def _random_getnode():
|
||||||
return random.getrandbits(48) | (1 << 40)
|
return random.getrandbits(48) | (1 << 40)
|
||||||
|
|
||||||
|
|
||||||
|
# _OS_GETTERS, when known, are targetted for a specific OS or platform.
|
||||||
|
# The order is by 'common practice' on the specified platform.
|
||||||
|
# Note: 'posix' and 'windows' _OS_GETTERS are prefixed by a dll/dlload() method
|
||||||
|
# which, when successful, means none of these "external" methods are called.
|
||||||
|
# _GETTERS is (also) used by test_uuid.py to SkipUnless(), e.g.,
|
||||||
|
# @unittest.skipUnless(_uuid._ifconfig_getnode in _uuid._GETTERS, ...)
|
||||||
|
if _LINUX:
|
||||||
|
_OS_GETTERS = [_ip_getnode, _ifconfig_getnode]
|
||||||
|
elif _DARWIN:
|
||||||
|
_OS_GETTERS = [_ifconfig_getnode, _arp_getnode, _netstat_getnode]
|
||||||
|
elif _WINDOWS:
|
||||||
|
_OS_GETTERS = [_netbios_getnode, _ipconfig_getnode]
|
||||||
|
elif _AIX:
|
||||||
|
_OS_GETTERS = [_netstat_getnode]
|
||||||
|
else:
|
||||||
|
_OS_GETTERS = [_ifconfig_getnode, _ip_getnode, _arp_getnode,
|
||||||
|
_netstat_getnode, _lanscan_getnode]
|
||||||
|
if os.name == 'posix':
|
||||||
|
_GETTERS = [_unix_getnode] + _OS_GETTERS
|
||||||
|
elif os.name == 'nt':
|
||||||
|
_GETTERS = [_windll_getnode] + _OS_GETTERS
|
||||||
|
else:
|
||||||
|
_GETTERS = _OS_GETTERS
|
||||||
|
|
||||||
_node = None
|
_node = None
|
||||||
|
|
||||||
_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]
|
|
||||||
|
|
||||||
_NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
|
|
||||||
_arp_getnode, _lanscan_getnode, _netstat_getnode]
|
|
||||||
|
|
||||||
def getnode(*, getters=None):
|
def getnode(*, getters=None):
|
||||||
"""Get the hardware address as a 48-bit positive integer.
|
"""Get the hardware address as a 48-bit positive integer.
|
||||||
|
|
||||||
|
@ -692,12 +718,7 @@ def getnode(*, getters=None):
|
||||||
if _node is not None:
|
if _node is not None:
|
||||||
return _node
|
return _node
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
for getter in _GETTERS + [_random_getnode]:
|
||||||
getters = _NODE_GETTERS_WIN32
|
|
||||||
else:
|
|
||||||
getters = _NODE_GETTERS_UNIX
|
|
||||||
|
|
||||||
for getter in getters + [_random_getnode]:
|
|
||||||
try:
|
try:
|
||||||
_node = getter()
|
_node = getter()
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Modify the test_uuid logic to test when a program is available
|
||||||
|
AND can be used to obtain a MACADDR as basis for an UUID.
|
||||||
|
Patch by M. Felt
|
Loading…
Add table
Add a link
Reference in a new issue