diff -r 8145f25f26aa Lib/test/test_uuid.py --- a/Lib/test/test_uuid.py Tue Sep 30 11:00:46 2014 -0400 +++ b/Lib/test/test_uuid.py Wed Oct 01 22:29:30 2014 +0300 @@ -319,6 +319,24 @@ class TestUUID(unittest.TestCase): if node is not None: self.check_node(node, 'ifconfig') + @unittest.skipUnless(os.name == 'posix', 'requires Posix') + def test_arp_getnode(self): + node = uuid._arp_getnode() + if node is not None: + self.check_node(node, 'arp') + + @unittest.skipUnless(os.name == 'posix', 'requires Posix') + def test_lanscan_getnode(self): + node = uuid._lanscan_getnode() + if node is not None: + self.check_node(node, 'lanscan') + + @unittest.skipUnless(os.name == 'posix', 'requires Posix') + def test_netstat_getnode(self): + node = uuid._netstat_getnode() + if node is not None: + self.check_node(node, 'netstat') + @unittest.skipUnless(os.name == 'nt', 'requires Windows') def test_ipconfig_getnode(self): node = uuid._ipconfig_getnode() diff -r 8145f25f26aa Lib/uuid.py --- a/Lib/uuid.py Tue Sep 30 11:00:46 2014 -0400 +++ b/Lib/uuid.py Wed Oct 01 22:29:30 2014 +0300 @@ -304,20 +304,28 @@ class UUID(object): if self.variant == RFC_4122: return int((self.int >> 76) & 0xf) -def _find_mac(command, args, hw_identifiers, get_index): +# See how to find MAC address on Linux/Unix: +# http://www.coffer.com/mac_info/locate-unix.html + +def _find_executable(command): import os, shutil executable = shutil.which(command) if executable is None: path = os.pathsep.join(('/sbin', '/usr/sbin')) executable = shutil.which(command, path=path) - if executable is None: - return None + return executable +def _find_mac(command, args, hw_identifiers, get_index): + import os + executable = _find_executable(command) + if not executable: + return None + + # LC_ALL to ensure English output, 2>/dev/null to prevent output on + # stderr (Note: we don't have an example where the words we search for + # are actually localized, but in theory some system could do so.) + cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args) try: - # LC_ALL to ensure English output, 2>/dev/null to prevent output on - # stderr (Note: we don't have an example where the words we search for - # are actually localized, but in theory some system could do so.) - 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() @@ -338,13 +346,14 @@ def _find_mac(command, args, hw_identifi def _ifconfig_getnode(): """Get the hardware address on Unix by running ifconfig.""" - # This works on Linux ('' or '-a'), Tru64 ('-av'), but not all Unixes. for args in ('', '-a', '-av'): mac = _find_mac('ifconfig', args, ['hwaddr', 'ether'], lambda i: i+1) if mac: return mac +def _arp_getnode(): + """Get the hardware address on Unix by running arp.""" import socket ip_addr = socket.gethostbyname(socket.gethostname()) @@ -353,12 +362,36 @@ def _ifconfig_getnode(): if mac: return mac +def _lanscan_getnode(): + """Get the hardware address on Unix by running lanscan.""" # This might work on HP-UX. mac = _find_mac('lanscan', '-ai', ['lan0'], lambda i: 0) if mac: return mac - return None +def _netstat_getnode(): + """Get the hardware address on Unix by running netstat.""" + # This might work on AIX, Tru64 UNIX and presumably on IRIX. + import os + executable = _find_executable('netstat') + if not executable: + return None + + cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, '-ia') + try: + with os.popen(cmd) as pipe: + words = pipe.readline().split() + i = words.index('Address') + for line in pipe: + try: + words = line.split() + word = words[i] + if len(word) == 17 and word.count(':') == 5: + return int(word.replace(':', ''), 16) + except (ValueError, IndexError): + pass + except (OSError, ValueError): + pass def _ipconfig_getnode(): """Get the hardware address on Windows by running ipconfig.exe.""" @@ -500,7 +533,8 @@ def getnode(): if sys.platform == 'win32': getters = [_windll_getnode, _netbios_getnode, _ipconfig_getnode] else: - getters = [_unixdll_getnode, _ifconfig_getnode] + getters = [_unixdll_getnode, _ifconfig_getnode, _arp_getnode, + _lanscan_getnode, _netstat_getnode] for getter in getters + [_random_getnode]: try: