# Buggy code
def get_interfaces_ip(self):
    """
    Get interface IP details. Returns a dictionary of dictionaries.

    Sample output:
    {
        "Ethernet2/3": {
            "ipv4": {
                "4.4.4.4": {
                    "prefix_length": 16
                }
            },
            "ipv6": {
                "2001:db8::1": {
                    "prefix_length": 10
                },
                "fe80::2ec2:60ff:fe4f:feb2": {
                    "prefix_length": "128"
                }
            }
        },
        "Ethernet2/2": {
            "ipv4": {
                "2.2.2.2": {
                    "prefix_length": 27
                }
            }
        }
    }
    """
    interfaces_ip = {}
    ipv4_command = "show ip interface vrf all"
    ipv6_command = "show ipv6 interface vrf all"
    output_v4 = self._send_command(ipv4_command)
    output_v6 = self._send_command(ipv6_command)

    v4_interfaces = {}
    for line in output_v4.splitlines():
        # Ethernet2/2, Interface status: protocol-up/link-up/admin-up, iod: 38,
        # IP address: 2.2.2.2, IP subnet: 2.2.2.0/27 route-preference: 0, tag: 0
        # IP address: 3.3.3.3, IP subnet: 3.3.3.0/25 secondary route-preference: 0, tag: 0
        if "Interface status" in line:
            interface = line.split(",")[0]
            continue
        if "IP address" in line:
            ip_address = line.split(",")[0].split()[2]
            try:
                prefix_len = int(line.split()[5].split("/")[1])
            except ValueError:
                prefix_len = "N/A"
            val = {"prefix_length": prefix_len}
            v4_interfaces.setdefault(interface, {})[ip_address] = val

    v6_interfaces = {}
    for line in output_v6.splitlines():
        # Ethernet2/4, Interface status: protocol-up/link-up/admin-up, iod: 40
        # IPv6 address:
        #   2001:11:2233::a1/24 [VALID]
        #   2001:cc11:22bb:0:2ec2:60ff:fe4f:feb2/64 [VALID]
        # IPv6 subnet:  2001::/24
        # IPv6 link-local address: fe80::2ec2:60ff:fe4f:feb2 (default) [VALID]
        # IPv6 address: fe80::a293:51ff:fe5f:5ce9 [VALID]
        if "Interface status" in line:
            interface = line.split(",")[0]
            continue
        if "VALID" in line:
            line = line.strip()
            if "link-local address" in line:
                # match the following format:
                # IPv6 link-local address: fe80::2ec2:60ff:fe4f:feb2 (default) [VALID]
                ip_address = line.split()[3]
                prefix_len = "64"
            elif "IPv6 address" in line:
                # match the following format:
                # IPv6 address: fe80::a293:51ff:fe5f:5ce9 [VALID]
                ip_address = line.split()[2]
                prefix_len = "64"
            else:
                ip_address, prefix_len = line.split()[0].split("/")
            prefix_len = int(prefix_len)
            val = {"prefix_length": prefix_len}
            v6_interfaces.setdefault(interface, {})[ip_address] = val

    # Join data from intermediate dictionaries.
    for interface, data in v4_interfaces.items():
        interfaces_ip.setdefault(interface, {"ipv4": {}})["ipv4"] = data

    for interface, data in v6_interfaces.items():
        interfaces_ip.setdefault(interface, {"ipv6": {}})["ipv6"] = data

    return interfaces_ip


# Traceback (IndexError)
$ napalm -v nxos_ssh --user itifous --password ***** n9k-hostname call get_interfaces_ip
2019-07-16 13:51:56,644 - napalm - ERROR - method - Failed: list index out of range

================= Traceback =================

Traceback (most recent call last):
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/bin/napalm", line 11, in <module>
load_entry_point('napalm', 'console_scripts', 'napalm')()
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/lib/python3.7/site-packages/napalm-2.4.0-py3.7.egg/napalm/base/clitools/cl_napalm.py", line 309, in main
run_tests(args)
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/lib/python3.7/site-packages/napalm-2.4.0-py3.7.egg/napalm/base/clitools/cl_napalm.py", line 292, in run_tests
call_getter(device, args.method, **method_kwargs)
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/lib/python3.7/site-packages/napalm-2.4.0-py3.7.egg/napalm/base/clitools/cl_napalm.py", line 31, in wrapper
r = func(*args, **kwargs)
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/lib/python3.7/site-packages/napalm-2.4.0-py3.7.egg/napalm/base/clitools/cl_napalm.py", line 256, in call_getter
r = func(**kwargs)
File "/home/itifous/.local/share/virtualenvs/netbox-netprod-importer-1U3vzfIV/lib/python3.7/site-packages/napalm-2.4.0-py3.7.egg/napalm/nxos_ssh/nxos_ssh.py", line 892, in get_interfaces_ip
prefix_len = int(line.split()[5].split("/")[1])
IndexError: list index out of range

# Fixed code
def get_interfaces_ip(self):
    """
    Get interface IP details. Returns a dictionary of dictionaries.

    Sample output:
    {
        "Ethernet2/3": {
            "ipv4": {
                "4.4.4.4": {
                    "prefix_length": 16
                }
            },
            "ipv6": {
                "2001:db8::1": {
                    "prefix_length": 10
                },
                "fe80::2ec2:60ff:fe4f:feb2": {
                    "prefix_length": "128"
                }
            }
        },
        "Ethernet2/2": {
            "ipv4": {
                "2.2.2.2": {
                    "prefix_length": 27
                }
            }
        }
    }
    """
    interfaces_ip = {}
    ipv4_command = "show ip interface vrf all"
    ipv6_command = "show ipv6 interface vrf all"
    output_v4 = self._send_command(ipv4_command)
    output_v6 = self._send_command(ipv6_command)

    v4_interfaces = {}
    for line in output_v4.splitlines():
        # Ethernet2/2, Interface status: protocol-up/link-up/admin-up, iod: 38,
        # IP address: 2.2.2.2, IP subnet: 2.2.2.0/27 route-preference: 0, tag: 0
        # IP address: 3.3.3.3, IP subnet: 3.3.3.0/25 secondary route-preference: 0, tag: 0
        if "Interface status" in line:
            interface = line.split(",")[0]
            continue
        if "IP address" in line:
            ip_address = line.split(",")[0].split()[2]
            try:
                prefix_len = int(line.split()[5].split("/")[1])
            except (ValueError, IndexError):
                prefix_len = "N/A"

            if ip_address == "none":
                v4_interfaces.setdefault(interface, {})
            else:
                val = {"prefix_length": prefix_len}
                v4_interfaces.setdefault(interface, {})[ip_address] = val

    v6_interfaces = {}
    for line in output_v6.splitlines():
        # Ethernet2/4, Interface status: protocol-up/link-up/admin-up, iod: 40
        # IPv6 address:
        #   2001:11:2233::a1/24 [VALID]
        #   2001:cc11:22bb:0:2ec2:60ff:fe4f:feb2/64 [VALID]
        # IPv6 subnet:  2001::/24
        # IPv6 link-local address: fe80::2ec2:60ff:fe4f:feb2 (default) [VALID]
        # IPv6 address: fe80::a293:51ff:fe5f:5ce9 [VALID]
        if "Interface status" in line:
            interface = line.split(",")[0]
            continue
        if "VALID" in line:
            line = line.strip()
            if "link-local address" in line:
                # match the following format:
                # IPv6 link-local address: fe80::2ec2:60ff:fe4f:feb2 (default) [VALID]
                ip_address = line.split()[3]
                prefix_len = "64"
            elif "IPv6 address" in line:
                # match the following format:
                # IPv6 address: fe80::a293:51ff:fe5f:5ce9 [VALID]
                ip_address = line.split()[2]
                prefix_len = "64"
            else:
                ip_address, prefix_len = line.split()[0].split("/")
            prefix_len = int(prefix_len)
            val = {"prefix_length": prefix_len}
            v6_interfaces.setdefault(interface, {})[ip_address] = val
        else:
            # match the following format:
            # IPv6 address: none
            v6_interfaces.setdefault(interface, {})

    # Join data from intermediate dictionaries.
    for interface, data in v4_interfaces.items():
        interfaces_ip.setdefault(interface, {"ipv4": {}})["ipv4"] = data

    for interface, data in v6_interfaces.items():
        interfaces_ip.setdefault(interface, {"ipv6": {}})["ipv6"] = data

    return interfaces_ip