def format_ports(ports):

    def format_port_list(l):
        if isinstance(l, list):
            return ', '.join([format_port(x) for x in l])
        return '{0}'.format(l)

    def format_port(port):
        """
        Format port dictionary and return string.
        """
        if 'PublicPort' in port:
            return '{0}:{1}->{2}/{3}'.format(
                port.get('IP', '0.0.0.0'),
                port.get('PublicPort', '0000'),
                port.get('PrivatePort', '0000'),
                port.get('Type', 'type'))
        if 'HostPort' in port:
            return "{0}:{1}".format(
                port.get('HostIp', '0.0.0.0'),
                port.get('HostPort', '0000')
            )
        if 'PrivatePort' in port:
            return '{0}/{1}'.format(
                port.get('PrivatePort', '0000'),
                port.get('Type', 'type'))
        # Fallback to formatting "as is"
        return "{0}".format(port)

    if isinstance(ports, dict):
        return ', '.join(['{0}->{1}'.format(k, format_port_list(v))
                          for k, v in ports.items()])
    return ', '.join(format_port(x) for x in ports)
Remove data related to any cloud that changed signature.
dataset/ETHPy150Open j-bennet/wharfee/wharfee/formatter.py/format_ports--crossover with--dataset/ETHPy150Open MirantisWorkloadMobility/CloudFerry/cloudferry/lib/os/discovery/stages.py/DiscoverStage.invalidate