diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index e177464c00f7a6..291efa031986d8 100755 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -781,29 +781,14 @@ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase): class BaseTestInternals: _uuid = py_uuid - def check_parse_mac(self, aix): - if not aix: - patch = mock.patch.multiple(self.uuid, - _MAC_DELIM=b':', - _MAC_OMITS_LEADING_ZEROES=False) - else: - patch = mock.patch.multiple(self.uuid, - _MAC_DELIM=b'.', - _MAC_OMITS_LEADING_ZEROES=True) + def check_parse_mac(self, valid_macs, delim=b':', omits_leading_zeros=False): + patch = mock.patch.multiple(self.uuid, + _MAC_DELIM=delim, + _MAC_OMITS_LEADING_ZEROES=omits_leading_zeros) with patch: # Valid MAC addresses - if not aix: - tests = ( - (b'52:54:00:9d:0e:67', 0x5254009d0e67), - (b'12:34:56:78:90:ab', 0x1234567890ab), - ) - else: - # AIX format - tests = ( - (b'fe.ad.c.1.23.4', 0xfead0c012304), - ) - for mac, expected in tests: + for mac, expected in valid_macs: self.assertEqual(self.uuid._parse_mac(mac), expected) # Invalid MAC addresses @@ -822,16 +807,38 @@ def check_parse_mac(self, aix): # dash separator b'52-54-00-9d-0e-67', ): - if aix: - mac = mac.replace(b':', b'.') + if delim != b':': + mac = mac.replace(b':', delim) with self.subTest(mac=mac): self.assertIsNone(self.uuid._parse_mac(mac)) def test_parse_mac(self): - self.check_parse_mac(False) + self.check_parse_mac( + valid_macs=( + (b'52:54:00:9d:0e:67', 0x5254009d0e67), + (b'12:34:56:78:90:ab', 0x1234567890ab), + ), + delim=b':', + omits_leading_zeros=False, + ) def test_parse_mac_aix(self): - self.check_parse_mac(True) + self.check_parse_mac( + valid_macs=( + (b'fe.ad.c.1.23.4', 0xfead0c012304), + ), + delim=b'.', + omits_leading_zeros=True, + ) + + def test_parse_mac_macos(self): + self.check_parse_mac( + valid_macs=( + (b'1:0:5e:0:c:fb', 0x01005e000cfb), + ), + delim=b':', + omits_leading_zeros=True, + ) def test_find_under_heading(self): data = '''\ @@ -917,6 +924,25 @@ def test_find_mac_near_keyword(self): self.assertEqual(mac, 0x1234567890ab) + def test_find_mac_near_keyword_macos(self): + data = ''' +? (224.0.0.251) at 1:0:5e:0:0:fb on en0 ifscope permanent [ethernet] +''' + + with mock.patch.multiple(self.uuid, + _MAC_DELIM=b':', + _MAC_OMITS_LEADING_ZEROES=True, + _get_command_stdout=mock_get_command_stdout(data)): + + mac = self.uuid._find_mac_near_keyword( + command='arp', + args='-an', + keywords=[os.fsencode('(%s)' % '224.0.0.251')], + get_word_index=lambda x: x + 2, + ) + + self.assertEqual(mac, 0x01005e0000fb) + def check_node(self, node, requires=None): if requires and node is None: self.skipTest('requires ' + requires) diff --git a/Lib/uuid.py b/Lib/uuid.py index c286eac38e1ef4..1dd7b7998be13c 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -69,6 +69,8 @@ if _AIX: _MAC_DELIM = b'.' _MAC_OMITS_LEADING_ZEROES = True +if sys.platform == 'darwin': + _MAC_OMITS_LEADING_ZEROES = True RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [ 'reserved for NCS compatibility', 'specified in RFC 4122', @@ -430,8 +432,8 @@ def _find_mac_near_keyword(command, args, keywords, get_word_index): if words[i] in keywords: try: word = words[get_word_index(i)] - mac = int(word.replace(_MAC_DELIM, b''), 16) - except (ValueError, IndexError): + mac = _parse_mac(word) + except 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 @@ -439,7 +441,7 @@ def _find_mac_near_keyword(command, args, keywords, get_word_index): # real MAC address pass else: - if _is_universal(mac): + if mac and _is_universal(mac): return mac first_local_mac = first_local_mac or mac return first_local_mac or None @@ -456,10 +458,12 @@ def _parse_mac(word): if len(parts) != 6: return if _MAC_OMITS_LEADING_ZEROES: - # (Only) on AIX the macaddr value given is not prefixed by 0, e.g. + # on AIX and darwin the macaddr value given is not prefixed by 0, e.g. on AIX # en0 1500 link#2 fa.bc.de.f7.62.4 110854824 0 160133733 0 0 # not # en0 1500 link#2 fa.bc.de.f7.62.04 110854824 0 160133733 0 0 + # and on darwin + # ? (224.0.0.251) at 1:0:5e:0:0:fb on en0 ifscope permanent [ethernet] if not all(1 <= len(part) <= 2 for part in parts): return hexstr = b''.join(part.rjust(2, b'0') for part in parts) diff --git a/Misc/NEWS.d/next/macOS/2023-05-26-17-07-23.gh-issue-101531.xTMHTk.rst b/Misc/NEWS.d/next/macOS/2023-05-26-17-07-23.gh-issue-101531.xTMHTk.rst new file mode 100644 index 00000000000000..20de87652fe86d --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2023-05-26-17-07-23.gh-issue-101531.xTMHTk.rst @@ -0,0 +1 @@ +Handle omitted leading zeroes in mac address on Darwin