tower_cli/cli/resource.py
def _format_human(self, payload):
        """Convert the payload into an ASCII table suitable for
        printing on screen and return it.
        """
        page = None
        total_pages = None

        # What are the columns we will show?
        columns = [field.name for field in self.resource.fields
                   if field.display or settings.description_on and
                   field.name == 'description']
        columns.insert(0, 'id')

        # Save a dictionary-by-name of fields for later use
        fields_by_name = {}
        for field in self.resource.fields:
            fields_by_name[field.name] = field

        # Sanity check: If there is a "changed" key in our payload
        # and little else, we print a short message and not a table.
        # this specifically applies to deletion
        if 'changed' in payload and 'id' not in payload:
            return 'OK. (changed: {0})'.format(
                six.text_type(payload['changed']).lower(),
            )

        # Sanity check: If there is no ID and no results, then this
        # is unusual output; keep our table formatting, but plow
        # over the columns-as-keys stuff above.
        # this originally applied to launch/status/update methods
        # but it may become deprecated
        if 'id' not in payload and 'results' not in payload:
            columns = [i for i in payload.keys()]

        # Get our raw rows into a standard format.
        if 'results' in payload:
            raw_rows = payload['results']
            if payload.get('count', 0) > len(payload['results']):
                prev = payload.get('previous', 0) or 0
                page = prev + 1
                count = payload['count']
                if payload.get('next', None):
                    total_pages = math.ceil(count / len(raw_rows))
                else:
                    total_pages = page
        else:
            raw_rows = [payload]

        # If we have no rows to display, return this information
        # and don't do any further processing.
        if not raw_rows:
            return 'No records found.'

        # Determine the width for each column.
        widths = {}
        for col in columns:
            widths[col] = max(
                len(col),
                *[len(self.get_print_value(i, col)) for i in raw_rows]
            )
            fd = fields_by_name.get(col, None)
            if fd is not None and fd.col_width is not None:
                widths[col] = fd.col_width

        # It's possible that the column widths will exceed our terminal
        # width; if so, reduce column widths accordingly.
        # TODO: Write this.

        # Put together the divider row.
        # This is easy and straightforward: it's simply a table divider
        # using the widths calculated.
        divider_row = ''
        for col in columns:
            divider_row += '=' * widths[col] + ' '
        divider_row.rstrip()

        # Put together the header row.
        # This is also easy and straightforward; simply center the
        # headers (which str.format does for us!).
        header_row = ''
        for col in columns:
            header_row += ('{0:^%d}' % widths[col]).format(col) + ' '
        header_row.rstrip()

        # Piece together each row of data.
        data_rows = []
        for raw_row in raw_rows:
            data_row = ''
            for col in columns:
                template = six.text_type('{0:%d}') % widths[col]
                value = self.get_print_value(raw_row, col)
                # Right-align certain native data types
                if isinstance(raw_row.get(col, 'N/A'), (bool, int)):
                    template = template.replace('{0:', '{0:>')
                # Truncate the cell entry if exceeds manually
                # specified column width limit
                fd = fields_by_name.get(col, None)
                if fd is not None and fd.col_width is not None:
                    str_value = template.format(value or '')
                    if len(str_value) > fd.col_width:
                        value = str_value[:fd.col_width]
                data_row += template.format(value or '') + ' '
            data_rows.append(data_row.rstrip())

        # Result the resulting table.
        response = '\n'.join((
            divider_row, header_row, divider_row,
            '\n'.join(data_rows),
            divider_row,
        ))
        # Don't print page numbers for 1 page results
        if page and total_pages != 1:
            response += '(Page %d of %d.)' % (page, total_pages)
        if payload.get('changed', False):
            response = 'Resource changed.\n' + response
        return response
def _format_human(self, payload):
        """Convert the payload into an ASCII table suitable for
        printing on screen and return it.
        """
        page = None
        total_pages = None

        # What are the columns we will show?
        columns = [field.name for field in self.resource.fields
                   if field.display or settings.description_on and
                   field.name == 'description']
        columns.insert(0, 'id')

        # Save a dictionary-by-name of fields for later use
        fields_by_name = {}
        for field in self.resource.fields:
            fields_by_name[field.name] = field

        # Sanity check: If there is a "changed" key in our payload
        # and little else, we print a short message and not a table.
        # this specifically applies to deletion
        if 'changed' in payload and 'id' not in payload:
            return 'OK. (changed: {0})'.format(
                six.text_type(payload['changed']).lower(),
            )

        # Sanity check: If there is no ID and no results, then this
        # is unusual output; keep our table formatting, but plow
        # over the columns-as-keys stuff above.
        # this originally applied to launch/status/update methods
        # but it may become deprecated
        if 'id' not in payload and 'results' not in payload:
            columns = [i for i in payload.keys()]

        # Get our raw rows into a standard format.
        if 'results' in payload:
            raw_rows = payload['results']
            if payload.get('count', 0) > len(payload['results']):
                prev = payload.get('previous', 0) or 0
                page = prev + 1
                count = payload['count']
                if payload.get('next', None):
                    total_pages = math.ceil(count / len(raw_rows))
                else:
                    total_pages = page
        else:
            raw_rows = [payload]

        # If we have no rows to display, return this information
        # and don't do any further processing.
        if not raw_rows:
            return 'No records found.'

        # Determine the width for each column.
        widths = {}
        for col in columns:
            widths[col] = max(
                len(col),
                *[len(self.get_print_value(i, col)) for i in raw_rows]
            )
            fd = fields_by_name.get(col, None)
            if fd is not None and fd.col_width is not None:
                widths[col] = fd.col_width

        # It's possible that the column widths will exceed our terminal
        # width; if so, reduce column widths accordingly.
        # TODO: Write this.

        # Put together the divider row.
        # This is easy and straightforward: it's simply a table divider
        # using the widths calculated.
        divider_row = ''
        for col in columns:
            divider_row += '=' * widths[col] + ' '
        divider_row.rstrip()

        # Put together the header row.
        # This is also easy and straightforward; simply center the
        # headers (which str.format does for us!).
        header_row = ''
        for col in columns:
            header_row += ('{0:^%d}' % widths[col]).format(col) + ' '
        header_row.rstrip()

        # Piece together each row of data.
        data_rows = []
        for raw_row in raw_rows:
            data_row = ''
            for col in columns:
                template = six.text_type('{0:%d}') % widths[col]
                value = self.get_print_value(raw_row, col)
                # Right-align certain native data types
                if isinstance(raw_row.get(col, 'N/A'), (bool, int)):
                    template = template.replace('{0:', '{0:>')
                # Truncate the cell entry if exceeds manually
                # specified column width limit
                fd = fields_by_name.get(col, None)
                if fd is not None and fd.col_width is not None:
                    str_value = template.format(value or '')
                    if len(str_value) > fd.col_width:
                        value = str_value[:fd.col_width]
                data_row += template.format(value or '') + ' '
            data_rows.append(data_row.rstrip())

        # Result the resulting table.
        response = '\n'.join((
            divider_row, header_row, divider_row,
            '\n'.join(data_rows),
            divider_row,
        ))
        # Don't print page numbers for 1 page results
        if page and total_pages != 1:
            response += '(Page %d of %d.)' % (page, total_pages)
        if payload.get('changed', False):
            response = 'Resource changed.\n' + response
        return response
def _format_human ( self , payload ) : page = None total_pages = None # What are the columns we will show? columns = [ field . name for field in self . resource . fields if field . display or settings . description_on and field . name == 'description' ] columns . insert ( 0 , 'id' ) # Save a dictionary-by-name of fields for later use fields_by_name = { } for field in self . resource . fields : fields_by_name [ field . name ] = field # Sanity check: If there is a "changed" key in our payload # and little else, we print a short message and not a table. # this specifically applies to deletion if 'changed' in payload and 'id' not in payload : return 'OK. (changed: {0})' . format ( six . text_type ( payload [ 'changed' ] ) . lower ( ) , ) # Sanity check: If there is no ID and no results, then this # is unusual output; keep our table formatting, but plow # over the columns-as-keys stuff above. # this originally applied to launch/status/update methods # but it may become deprecated if 'id' not in payload and 'results' not in payload : columns = [ i for i in payload . keys ( ) ] # Get our raw rows into a standard format. if 'results' in payload : raw_rows = payload [ 'results' ] if payload . get ( 'count' , 0 ) > len ( payload [ 'results' ] ) : prev = payload . get ( 'previous' , 0 ) or 0 page = prev + 1 count = payload [ 'count' ] if payload . get ( 'next' , None ) : total_pages = math . ceil ( count / len ( raw_rows ) ) else : total_pages = page else : raw_rows = [ payload ] # If we have no rows to display, return this information # and don't do any further processing. if not raw_rows : return 'No records found.' # Determine the width for each column. widths = { } for col in columns : widths [ col ] = max ( len ( col ) , * [ len ( self . get_print_value ( i , col ) ) for i in raw_rows ] ) fd = fields_by_name . get ( col , None ) if fd is not None and fd . col_width is not None : widths [ col ] = fd . col_width # It's possible that the column widths will exceed our terminal # width; if so, reduce column widths accordingly. # TODO: Write this. # Put together the divider row. # This is easy and straightforward: it's simply a table divider # using the widths calculated. divider_row = '' for col in columns : divider_row += '=' * widths [ col ] + ' ' divider_row . rstrip ( ) # Put together the header row. # This is also easy and straightforward; simply center the # headers (which str.format does for us!). header_row = '' for col in columns : header_row += ( '{0:^%d}' % widths [ col ] ) . format ( col ) + ' ' header_row . rstrip ( ) # Piece together each row of data. data_rows = [ ] for raw_row in raw_rows : data_row = '' for col in columns : template = six . text_type ( '{0:%d}' ) % widths [ col ] value = self . get_print_value ( raw_row , col ) # Right-align certain native data types if isinstance ( raw_row . get ( col , 'N/A' ) , ( bool , int ) ) : template = template . replace ( '{0:' , '{0:>' ) # Truncate the cell entry if exceeds manually # specified column width limit fd = fields_by_name . get ( col , None ) if fd is not None and fd . col_width is not None : str_value = template . format ( value or '' ) if len ( str_value ) > fd . col_width : value = str_value [ : fd . col_width ] data_row += template . format ( value or '' ) + ' ' data_rows . append ( data_row . rstrip ( ) ) # Result the resulting table. response = '\n' . join ( ( divider_row , header_row , divider_row , '\n' . join ( data_rows ) , divider_row , ) ) # Don't print page numbers for 1 page results if page and total_pages != 1 : response += '(Page %d of %d.)' % ( page , total_pages ) if payload . get ( 'changed' , False ) : response = 'Resource changed.\n' + response return response
Convert the payload into an ASCII table suitable for
        printing on screen and return it.
Convert the payload into an ASCII table suitable for printing on screen and return it .