diff --git a/CHANGELOG b/CHANGELOG index 27a19ce8..d94ae2bb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,8 @@ jc changelog -20240618 v1.25.4 +20240906 v1.25.4 - Fix `mount` parser for cases where there are spaces in the filesystem name +- Fix `ip-address` parser for Python 3.13 changes to IPv4 mapped IPv6 addresses 20240609 v1.25.3 - Enhance `bluetoothctl` parser with added `battery_percentage` field diff --git a/jc/parsers/ip_address.py b/jc/parsers/ip_address.py index 7e6b37cb..3e44f7fe 100644 --- a/jc/parsers/ip_address.py +++ b/jc/parsers/ip_address.py @@ -533,7 +533,7 @@ class info(): """Provides parser metadata (version, author, etc.)""" - version = '1.4' + version = '1.5' description = 'IPv4 and IPv6 Address string parser' author = 'Kelly Brazil' author_email = 'kellyjonbrazil@gmail.com' @@ -661,8 +661,18 @@ def parse( if interface.version == 4: ip_split = ip_exploded.split('.') + else: - ip_split = ip_exploded.split(':') + # regular IPv6 + if not '.' in ip_exploded: + ip_split = ip_exploded.split(':') + + # IPv4 mapped IPv6 + else: + ip_split_v6 = ip_exploded.split(':')[:-1] + ip_split_v4_mapped_str = ip_exploded.split(':')[-1] + ip_split_v4_mapped = ip_split_v4_mapped_str.split('.') + ip_split = ip_split_v6 + ip_split_v4_mapped # fix for ipv6-only attributes scope_id = None diff --git a/tests/test_ip_address.py b/tests/test_ip_address.py index 99d7fd5f..0e46cd6b 100644 --- a/tests/test_ip_address.py +++ b/tests/test_ip_address.py @@ -90,7 +90,15 @@ def test_ip_address_ipv6_ipv4_mapped(self): Test ipv6 address with ipv4 mapped string """ data = r'::FFFF:192.168.1.35' - expected = json.loads(r'''{"version":6,"max_prefix_length":128,"ip":"::ffff:c0a8:123","ip_compressed":"::ffff:c0a8:123","ip_exploded":"0000:0000:0000:0000:0000:ffff:c0a8:0123","ip_split":["0000","0000","0000","0000","0000","ffff","c0a8","0123"],"scope_id":null,"ipv4_mapped":"192.168.1.35","six_to_four":null,"teredo_client":null,"teredo_server":null,"dns_ptr":"3.2.1.0.8.a.0.c.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa","network":"::ffff:c0a8:123","broadcast":"::ffff:c0a8:123","hostmask":"::","netmask":"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff","cidr_netmask":128,"hosts":1,"first_host":"::ffff:c0a8:123","last_host":"::ffff:c0a8:123","is_multicast":false,"is_private":true,"is_global":false,"is_link_local":false,"is_loopback":false,"is_reserved":true,"is_unspecified":false,"int":{"ip":281473913979171,"network":281473913979171,"broadcast":281473913979171,"first_host":281473913979171,"last_host":281473913979171},"hex":{"ip":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","network":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","broadcast":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","hostmask":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00","netmask":"ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff","first_host":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","last_host":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23"},"bin":{"ip":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","network":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","broadcast":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","hostmask":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","netmask":"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","first_host":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","last_host":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011"}}''') + if sys.version_info >= (3, 13, 0): + expected_ipv4 = '192.168.1.35' + expected_ipv4_exploded = '192.168.1.35' + expected_ipv4_split = '["0000", "0000", "0000", "0000", "0000", "ffff", "192", "168", "1", "35"]' + else: + expected_ipv4 = 'c0a8:123' + expected_ipv4_exploded = 'c0a8:0123' + expected_ipv4_split = '["0000", "0000", "0000", "0000", "0000", "ffff", "c0a8", "0123"]' + expected = json.loads(f'''{{"version":6,"max_prefix_length":128,"ip":"::ffff:{expected_ipv4}","ip_compressed":"::ffff:{expected_ipv4}","ip_exploded":"0000:0000:0000:0000:0000:ffff:{expected_ipv4_exploded}","ip_split":{expected_ipv4_split},"scope_id":null,"ipv4_mapped":"192.168.1.35","six_to_four":null,"teredo_client":null,"teredo_server":null,"dns_ptr":"3.2.1.0.8.a.0.c.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa","network":"::ffff:{expected_ipv4}","broadcast":"::ffff:{expected_ipv4}","hostmask":"::","netmask":"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff","cidr_netmask":128,"hosts":1,"first_host":"::ffff:{expected_ipv4}","last_host":"::ffff:{expected_ipv4}","is_multicast":false,"is_private":true,"is_global":false,"is_link_local":false,"is_loopback":false,"is_reserved":true,"is_unspecified":false,"int":{{"ip":281473913979171,"network":281473913979171,"broadcast":281473913979171,"first_host":281473913979171,"last_host":281473913979171}},"hex":{{"ip":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","network":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","broadcast":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","hostmask":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00","netmask":"ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff","first_host":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23","last_host":"00:00:00:00:00:00:00:00:00:00:ff:ff:c0:a8:01:23"}},"bin":{{"ip":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","network":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","broadcast":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","hostmask":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","netmask":"11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","first_host":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011","last_host":"00000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111000000101010000000000100100011"}}}}''') self.assertEqual(jc.parsers.ip_address.parse(data, quiet=True), expected)