diff -r 634f3fe8cbde Lib/test/test_uuid.py --- a/Lib/test/test_uuid.py Sun Aug 03 14:54:11 2014 -0400 +++ b/Lib/test/test_uuid.py Tue Sep 30 19:54:29 2014 +0300 @@ -1,6 +1,8 @@ from unittest import TestCase from test import support import builtins +import io +import os import uuid def importable(name): @@ -360,6 +362,25 @@ class TestUUID(TestCase): self.assertEqual(node1, node2) + def test_find_mac(self): + data = '''\ + +fake hwaddr +cscotun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 +eth0 Link encap:Ethernet HWaddr 12:34:56:78:90:ab +''' + def mock_popen(cmd): + return io.StringIO(data) + + with support.swap_attr(os, 'popen', mock_popen): + mac = uuid._find_mac( + command='ifconfig', + args='', + hw_identifiers=['hwaddr'], + get_index=lambda x: x + 1, + ) + self.assertEqual(mac, 0x1234567890ab) + def test_uuid1(self): # uuid1 requires ctypes. try: diff -r 634f3fe8cbde Lib/uuid.py --- a/Lib/uuid.py Sun Aug 03 14:54:11 2014 -0400 +++ b/Lib/uuid.py Tue Sep 30 19:54:29 2014 +0300 @@ -313,25 +313,38 @@ class UUID(object): def _find_mac(command, args, hw_identifiers, get_index): import os - for dir in ['', '/sbin/', '/usr/sbin']: + path = os.environ.get("PATH", os.defpath).split(os.pathsep) + path.extend(('/sbin', '/usr/sbin')) + for dir in path: executable = os.path.join(dir, command) - if not os.path.exists(executable): - continue + if (os.path.exists(executable) and + os.access(executable, os.F_OK | os.X_OK) and + not os.path.isdir(executable)): + break + else: + return None - try: - # LC_ALL to get English output, 2>/dev/null to - # prevent output on stderr - cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args) - with os.popen(cmd) as pipe: - for line in pipe: - words = line.lower().split() - for i in range(len(words)): - if words[i] in hw_identifiers: + try: + # LC_ALL to ensure English output, 2>/dev/null to + # prevent output on stderr + cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args) + with os.popen(cmd) as pipe: + for line in pipe: + words = line.lower().split() + for i in range(len(words)): + if words[i] in hw_identifiers: + try: return int( words[get_index(i)].replace(':', ''), 16) - except IOError: - continue - return None + except (ValueError, IndexError): + # Virtual interfaces, such as those provided by + # VPNs, do not have a colon-delimited MAC address + # as expected, but a 16-byte HWAddr separated by + # dashes. These should be ignored in favor of a + # real MAC address + pass + except IOError: + pass def _ifconfig_getnode(): """Get the hardware address on Unix by running ifconfig.""" @@ -406,7 +419,7 @@ def _netbios_getnode(): if win32wnet.Netbios(ncb) != 0: continue status._unpack() - bytes = map(ord, status.adapter_address) + bytes = status.adapter_address return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) + (bytes[3]<<16) + (bytes[4]<<8) + bytes[5]) @@ -429,6 +442,8 @@ try: _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 diff -r 634f3fe8cbde Misc/ACKS --- a/Misc/ACKS Sun Aug 03 14:54:11 2014 -0400 +++ b/Misc/ACKS Tue Sep 30 19:54:29 2014 +0300 @@ -351,6 +351,7 @@ Doug Fort John Fouhy Stefan Franke Martin Franklin +Kent Frazier Robin Friedrich Bradley Froehle Ivan Frohne @@ -1026,6 +1027,7 @@ Ryan Smith-Roberts Rafal Smotrzyk Dirk Soede Paul Sokolovsky +Evgeny Sologubov Cody Somerville Clay Spence Stefan Sperling diff -r 634f3fe8cbde Misc/NEWS --- a/Misc/NEWS Sun Aug 03 14:54:11 2014 -0400 +++ b/Misc/NEWS Tue Sep 30 19:54:29 2014 +0300 @@ -10,6 +10,19 @@ What's New in Python 3.2.6? Library ------- +- Issue #19855: uuid.getnode() on Unix now looks on the PATH for the + executables used to find the mac address, with /sbin and /usr/sbin as + fallbacks. + +- Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with + virtual interface. Original patch by Kent Frazier. + +- Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL, + if all necessary functions are already found in libuuid. + Patch by Evgeny Sologubov. + +- Issue #16102: Make uuid._netbios_getnode() work again on Python 3. + - Issue #21766: Prevent a security hole in CGIHTTPServer by URL unquoting paths before checking for a CGI script at that path.