List prefixes matching 'arg'

def list_prefix(arg, opts, shell_opts):
    """ List prefixes matching 'arg'
    """

    search_string = ''
    if type(arg) == list or type(arg) == tuple:
        search_string = ' '.join(arg)

    v = get_vrf(opts.get('vrf_rt'), default_var='default_list_vrf_rt', abort=True)

    if v.rt == 'all':
        vrf_text = 'any VRF'
        vrf_q = None
    else:
        vrf_text = vrf_format(v)
        vrf_q = {
            'operator': 'equals',
            'val1': 'vrf_rt',
            'val2': v.rt
        }
    print("Searching for prefixes in %s..." % vrf_text)

    col_def = {
            'added': { 'title': 'Added' },
            'alarm_priority': { 'title': 'Alarm Prio' },
            'authoritative_source': { 'title': 'Auth source' },
            'children': { 'title': 'Children' },
            'comment': { 'title': 'Comment' },
            'customer_id': { 'title': 'Customer ID' },
            'description': { 'title': 'Description' },
            'expires': { 'title': 'Expires' },
            'free_addresses': { 'title': 'Free addresses' },
            'monitor': { 'title': 'Monitor' },
            'last_modified': { 'title': 'Last mod' },
            'node': { 'title': 'Node' },
            'order_id': { 'title': 'Order ID' },
            'pool_name': { 'title': 'Pool name' },
            'prefix': { 'title': 'Prefix' },
            'status': { 'title': 'Status' },
            'tags': { 'title': '#' },
            'total_addresses': { 'title': 'Total addresses' },
            'type': { 'title': '' },
            'used_addresses': { 'title': 'Used addresses' },
            'vlan': { 'title': 'VLAN' },
            'vrf_rt': { 'title': 'VRF RT' },
            }
    # default columns
    columns = [ 'vrf_rt', 'prefix', 'type', 'tags', 'node', 'order_id', 'customer_id', 'description' ]

    # custom columns? prefer shell opts, then look in config file
    custom_columns = None
    if shell_opts.columns and len(shell_opts.columns) > 0:
        custom_columns = shell_opts.columns
    elif cfg.get('global', 'prefix_list_columns'):
        custom_columns = cfg.get('global', 'prefix_list_columns')

    # parse custom columns
    if custom_columns:
        # Clear out default columns, unless user whishes to append
        if custom_columns[0] != '+':
            columns = []

        # read in custom columns
        for col in list(csv.reader([custom_columns.lstrip('+') or ''], escapechar='\\'))[0]:
            col = col.strip()
            if col not in col_def:
                print("Invalid column:", col, file=sys.stderr)
                sys.exit(1)
            columns.append(col)

    offset = 0
    # small initial limit for "instant" result
    limit = 50
    prefix_str = ""
    while True:
        res = Prefix.smart_search(search_string, { 'parents_depth': -1,
            'include_neighbors': True, 'offset': offset, 'max_result': limit },
            vrf_q)

        if offset == 0: # first time in loop?
            if shell_opts.show_interpretation:
                print("Query interpretation:")
                _parse_interp_prefix(res['interpretation'])

            if res['error']:
                print("Query failed: %s" % res['error_message'])
                return

            if len(res['result']) == 0:
                print("No addresses matching '%s' found." % search_string)
                return

            # guess column width by looking at the initial result set
            for p in res['result']:
                for colname, col in col_def.items():
                    val = getattr(p, colname, '')
                    col['width'] = max(len(colname), col.get('width', 0),
                                       len(str(val)))

                # special handling of a few columns
                col_def['vrf_rt']['width'] = max(col_def['vrf_rt'].get('width', 8),
                                                 len(str(p.vrf.rt)))
                col_def['prefix']['width'] = max(col_def['prefix'].get('width', 0)-12,
                                                 p.indent * 2 + len(p.prefix)) + 12
                try:
                    col_def['pool_name']['width'] = max(col_def['pool_name'].get('width', 8),
                                                        len(str(p.pool.name)))
                except:
                    pass
            # override certain column widths
            col_def['type']['width'] = 1
            col_def['tags']['width'] = 2

            col_header_data = {}
            # build prefix formatting string
            for colname, col in [(k, col_def[k]) for k in columns]:
                prefix_str += "{%s:<%d}  " % (colname, col['width'])
                col_header_data[colname] = col['title']

            column_header = prefix_str.format(**col_header_data)
            print(column_header)
            print("".join("=" for i in range(len(column_header))))

        for p in res['result']:
            if p.display == False:
                continue

            col_data = {}
            try:
                for colname, col in col_def.items():
                    col_data[colname] = str(getattr(p, colname, None))

                # overwrite some columns due to special handling
                col_data['tags'] = '-'
                if len(p.tags) > 0:
                    col_data['tags'] = '#%d' % len(p.tags)

                try: 
                    col_data['pool_name'] = p.pool.name
                except:
                    pass

                col_data['prefix'] = "".join("  " for i in range(p.indent)) + p.display_prefix
                col_data['type'] = p.type[0].upper()
                col_data['vrf_rt'] = p.vrf.rt or '-'

                print(prefix_str.format(**col_data))

            except UnicodeEncodeError as e:
                print("\nCrazy encoding for prefix %s\n" % p.prefix, file=sys.stderr)

        if len(res['result']) < limit:
            break
        offset += limit

        # let consecutive limit be higher to tax the XML-RPC backend less
        limit = 200