<s> import os <EOL> import sys <EOL> import struct <EOL> import colorama <EOL> from awscli . compat import six <EOL> def determine_terminal_width ( default_width = <NUM_LIT> ) : <EOL> try : <EOL> from termios import TIOCGWINSZ <EOL> from fcntl import ioctl <EOL> except ImportError : <EOL> return default_width <EOL> try : <EOL> height , width = struct . unpack ( '<STR_LIT>' , ioctl ( sys . stdout , <EOL> TIOCGWINSZ , '<STR_LIT>' * <NUM_LIT:8> ) ) [ <NUM_LIT:0> : <NUM_LIT:2> ] <EOL> except Exception : <EOL> return default_width <EOL> else : <EOL> return width <EOL> def is_a_tty ( ) : <EOL> try : <EOL> return os . isatty ( sys . stdout . fileno ( ) ) <EOL> except Exception : <EOL> return False <EOL> def center_text ( text , length = <NUM_LIT> , left_edge = '<STR_LIT:|>' , right_edge = '<STR_LIT:|>' , <EOL> text_length = None ) : <EOL> """<STR_LIT>""" <EOL> if text_length is None : <EOL> text_length = len ( text ) <EOL> output = [ ] <EOL> char_start = ( length // <NUM_LIT:2> ) - ( text_length // <NUM_LIT:2> ) - <NUM_LIT:1> <EOL> output . append ( left_edge + '<STR_LIT:U+0020>' * char_start + text ) <EOL> length_so_far = len ( left_edge ) + char_start + text_length <EOL> right_side_spaces = length - len ( right_edge ) - length_so_far <EOL> output . append ( '<STR_LIT:U+0020>' * right_side_spaces ) <EOL> output . append ( right_edge ) <EOL> final = '<STR_LIT>' . join ( output ) <EOL> return final <EOL> def align_left ( text , length , left_edge = '<STR_LIT:|>' , right_edge = '<STR_LIT:|>' , text_length = None , <EOL> left_padding = <NUM_LIT:2> ) : <EOL> """<STR_LIT>""" <EOL> if text_length is None : <EOL> text_length = len ( text ) <EOL> computed_length = ( <EOL> text_length + left_padding + len ( left_edge ) + len ( right_edge ) ) <EOL> if length - computed_length >= <NUM_LIT:0> : <EOL> padding = left_padding <EOL> else : <EOL> padding = <NUM_LIT:0> <EOL> output = [ ] <EOL> length_so_far = <NUM_LIT:0> <EOL> output . append ( left_edge ) <EOL> length_so_far += len ( left_edge ) <EOL> output . append ( '<STR_LIT:U+0020>' * padding ) <EOL> length_so_far += padding <EOL> output . append ( text ) <EOL> length_so_far += text_length <EOL> output . append ( '<STR_LIT:U+0020>' * ( length - length_so_far - len ( right_edge ) ) ) <EOL> output . append ( right_edge ) <EOL> return '<STR_LIT>' . join ( output ) <EOL> def convert_to_vertical_table ( sections ) : <EOL> for i , section in enumerate ( sections ) : <EOL> if len ( section . rows ) == <NUM_LIT:1> and section . headers : <EOL> headers = section . headers <EOL> new_section = Section ( ) <EOL> new_section . title = section . title <EOL> new_section . indent_level = section . indent_level <EOL> for header , element in zip ( headers , section . rows [ <NUM_LIT:0> ] ) : <EOL> new_section . add_row ( [ header , element ] ) <EOL> sections [ i ] = new_section <EOL> class IndentedStream ( object ) : <EOL> def __init__ ( self , stream , indent_level , left_indent_char = '<STR_LIT:|>' , <EOL> right_indent_char = '<STR_LIT:|>' ) : <EOL> self . _stream = stream <EOL> self . _indent_level = indent_level <EOL> self . _left_indent_char = left_indent_char <EOL> self . _right_indent_char = right_indent_char <EOL> def write ( self , text ) : <EOL> self . _stream . write ( self . _left_indent_char * self . _indent_level ) <EOL> if text . endswith ( '<STR_LIT:\n>' ) : <EOL> self . _stream . write ( text [ : - <NUM_LIT:1> ] ) <EOL> self . _stream . write ( self . _right_indent_char * self . _indent_level ) <EOL> self . _stream . write ( '<STR_LIT:\n>' ) <EOL> else : <EOL> self . _stream . write ( text ) <EOL> def __getattr__ ( self , attr ) : <EOL> return getattr ( self . _stream , attr ) <EOL> class Styler ( object ) : <EOL> def style_title ( self , text ) : <EOL> return text <EOL> def style_header_column ( self , text ) : <EOL> return text <EOL> def style_row_element ( self , text ) : <EOL> return text <EOL> def style_indentation_char ( self , text ) : <EOL> return text <EOL> class ColorizedStyler ( Styler ) : <EOL> def __init__ ( self ) : <EOL> colorama . init ( autoreset = True ) <EOL> def style_title ( self , text ) : <EOL> return text <EOL> def style_header_column ( self , text ) : <EOL> return text <EOL> def style_row_element ( self , text ) : <EOL> return ( colorama . Style . BRIGHT + colorama . Fore . BLUE + <EOL> text + colorama . Style . RESET_ALL ) <EOL> def style_indentation_char ( self , text ) : <EOL> return ( colorama . Style . DIM + colorama . Fore . YELLOW + <EOL> text + colorama . Style . RESET_ALL ) <EOL> class MultiTable ( object ) : <EOL> def __init__ ( self , terminal_width = None , initial_section = True , <EOL> column_separator = '<STR_LIT:|>' , terminal = None , <EOL> styler = None , auto_reformat = True ) : <EOL> self . _auto_reformat = auto_reformat <EOL> if initial_section : <EOL> self . _current_section = Section ( ) <EOL> self . _sections = [ self . _current_section ] <EOL> else : <EOL> self . _current_section = None <EOL> self . _sections = [ ] <EOL> if styler is None : <EOL> if is_a_tty ( ) : <EOL> self . _styler = ColorizedStyler ( ) <EOL> else : <EOL> self . _styler = Styler ( ) <EOL> else : <EOL> self . _styler = styler <EOL> self . _rendering_index = <NUM_LIT:0> <EOL> self . _column_separator = column_separator <EOL> if terminal_width is None : <EOL> self . _terminal_width = determine_terminal_width ( ) <EOL> def add_title ( self , title ) : <EOL> self . _current_section . add_title ( title ) <EOL> def add_row_header ( self , headers ) : <EOL> self . _current_section . add_header ( headers ) <EOL> def add_row ( self , row_elements ) : <EOL> self . _current_section . add_row ( row_elements ) <EOL> def new_section ( self , title , indent_level = <NUM_LIT:0> ) : <EOL> self . _current_section = Section ( ) <EOL> self . _sections . append ( self . _current_section ) <EOL> self . _current_section . add_title ( title ) <EOL> self . _current_section . indent_level = indent_level <EOL> def render ( self , stream ) : <EOL> max_width = self . _calculate_max_width ( ) <EOL> should_convert_table = self . _determine_conversion_needed ( max_width ) <EOL> if should_convert_table : <EOL> convert_to_vertical_table ( self . _sections ) <EOL> max_width = self . _calculate_max_width ( ) <EOL> stream . write ( '<STR_LIT:->' * max_width + '<STR_LIT:\n>' ) <EOL> for section in self . _sections : <EOL> self . _render_section ( section , max_width , stream ) <EOL> def _determine_conversion_needed ( self , max_width ) : <EOL> if max_width > self . _terminal_width : <EOL> return self . _auto_reformat <EOL> def _calculate_max_width ( self ) : <EOL> max_width = max ( s . total_width ( padding = <NUM_LIT:4> , with_border = True , <EOL> outer_padding = s . indent_level ) <EOL> for s in self . _sections ) <EOL> return max_width <EOL> def _render_section ( self , section , max_width , stream ) : <EOL> stream = IndentedStream ( stream , section . indent_level , <EOL> self . _styler . style_indentation_char ( '<STR_LIT:|>' ) , <EOL> self . _styler . style_indentation_char ( '<STR_LIT:|>' ) ) <EOL> max_width -= ( section . indent_level * <NUM_LIT:2> ) <EOL> self . _render_title ( section , max_width , stream ) <EOL> self . _render_column_titles ( section , max_width , stream ) <EOL> self . _render_rows ( section , max_width , stream ) <EOL> def _render_title ( self , section , max_width , stream ) : <EOL> if section . title : <EOL> title = self . _styler . style_title ( section . title ) <EOL> stream . write ( center_text ( title , max_width , '<STR_LIT:|>' , '<STR_LIT:|>' , <EOL> len ( section . title ) ) + '<STR_LIT:\n>' ) <EOL> if not section . headers and not section . rows : <EOL> stream . write ( '<STR_LIT>' % ( '<STR_LIT:->' * ( max_width - <NUM_LIT:2> ) ) + '<STR_LIT:\n>' ) <EOL> def _render_column_titles ( self , section , max_width , stream ) : <EOL> if not section . headers : <EOL> return <EOL> widths = section . calculate_column_widths ( padding = <NUM_LIT:4> , <EOL> max_width = max_width ) <EOL> current = '<STR_LIT>' <EOL> length_so_far = <NUM_LIT:0> <EOL> first = True <EOL> for width , header in zip ( widths , section . headers ) : <EOL> stylized_header = self . _styler . style_header_column ( header ) <EOL> if first : <EOL> left_edge = '<STR_LIT:|>' <EOL> first = False <EOL> else : <EOL> left_edge = '<STR_LIT>' <EOL> current += center_text ( text = stylized_header , length = width , <EOL> left_edge = left_edge , right_edge = '<STR_LIT:|>' , <EOL> text_length = len ( header ) ) <EOL> length_so_far += width <EOL> self . _write_line_break ( stream , widths ) <EOL> stream . write ( current + '<STR_LIT:\n>' ) <EOL> def _write_line_break ( self , stream , widths ) : <EOL> parts = [ ] <EOL> first = True <EOL> for width in widths : <EOL> if first : <EOL> parts . append ( '<STR_LIT>' % ( '<STR_LIT:->' * ( width - <NUM_LIT:2> ) ) ) <EOL> first = False <EOL> else : <EOL> parts . append ( '<STR_LIT>' % ( '<STR_LIT:->' * ( width - <NUM_LIT:1> ) ) ) <EOL> parts . append ( '<STR_LIT:\n>' ) <EOL> stream . write ( '<STR_LIT>' . join ( parts ) ) <EOL> def _render_rows ( self , section , max_width , stream ) : <EOL> if not section . rows : <EOL> return <EOL> widths = section . calculate_column_widths ( padding = <NUM_LIT:4> , <EOL> max_width = max_width ) <EOL> if not widths : <EOL> return <EOL> self . _write_line_break ( stream , widths ) <EOL> for row in section . rows : <EOL> current = '<STR_LIT>' <EOL> length_so_far = <NUM_LIT:0> <EOL> first = True <EOL> for width , element in zip ( widths , row ) : <EOL> if first : <EOL> left_edge = '<STR_LIT:|>' <EOL> first = False <EOL> else : <EOL> left_edge = '<STR_LIT>' <EOL> stylized = self . _styler . style_row_element ( element ) <EOL> current += align_left ( text = stylized , length = width , <EOL> left_edge = left_edge , <EOL> right_edge = self . _column_separator , <EOL> text_length = len ( element ) ) <EOL> length_so_far += width <EOL> stream . write ( current + '<STR_LIT:\n>' ) <EOL> self . _write_line_break ( stream , widths ) <EOL> class Section ( object ) : <EOL> def __init__ ( self ) : <EOL> self . title = '<STR_LIT>' <EOL> self . headers = [ ] <EOL> self . rows = [ ] <EOL> self . indent_level = <NUM_LIT:0> <EOL> self . _num_cols = None <EOL> self . _max_widths = [ ] <EOL> def __repr__ ( self ) : <EOL> return ( "<STR_LIT>" % <EOL> ( self . title , self . headers , self . indent_level , len ( self . rows ) ) ) <EOL> def calculate_column_widths ( self , padding = <NUM_LIT:0> , max_width = None ) : <EOL> unscaled_widths = [ w + padding for w in self . _max_widths ] <EOL> if max_width is None : <EOL> return unscaled_widths <EOL> if not unscaled_widths : <EOL> return unscaled_widths <EOL> else : <EOL> scale_factor = max_width / float ( sum ( unscaled_widths ) ) <EOL> scaled = [ int ( round ( scale_factor * w ) ) for w in unscaled_widths ] <EOL> off_by = sum ( scaled ) - max_width <EOL> while off_by != <NUM_LIT:0> : <EOL> iter_order = range ( len ( scaled ) ) <EOL> if off_by < <NUM_LIT:0> : <EOL> iter_order = reversed ( iter_order ) <EOL> for i in iter_order : <EOL> if off_by > <NUM_LIT:0> : <EOL> scaled [ i ] -= <NUM_LIT:1> <EOL> off_by -= <NUM_LIT:1> <EOL> else : <EOL> scaled [ i ] += <NUM_LIT:1> <EOL> off_by += <NUM_LIT:1> <EOL> if off_by == <NUM_LIT:0> : <EOL> break <EOL> return scaled <EOL> def total_width ( self , padding = <NUM_LIT:0> , with_border = False , outer_padding = <NUM_LIT:0> ) : <EOL> total = <NUM_LIT:0> <EOL> border_padding = <NUM_LIT:2> <EOL> for w in self . calculate_column_widths ( ) : <EOL> total += w + padding <EOL> if with_border : <EOL> total += border_padding <EOL> total += outer_padding + outer_padding <EOL> return max ( len ( self . title ) + border_padding + outer_padding + <EOL> outer_padding , total ) <EOL> def add_title ( self , title ) : <EOL> self . title = title <EOL> def add_header ( self , headers ) : <EOL> self . _update_max_widths ( headers ) <EOL> if self . _num_cols is None : <EOL> self . _num_cols = len ( headers ) <EOL> self . headers = self . _format_headers ( headers ) <EOL> def _format_headers ( self , headers ) : <EOL> return headers <EOL> def add_row ( self , row ) : <EOL> if self . _num_cols is None : <EOL> self . _num_cols = len ( row ) <EOL> if len ( row ) != self . _num_cols : <EOL> raise ValueError ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( self . _num_cols , len ( row ) ) ) <EOL> row = self . _format_row ( row ) <EOL> self . rows . append ( row ) <EOL> self . _update_max_widths ( row ) <EOL> def _format_row ( self , row ) : <EOL> return [ six . text_type ( r ) for r in row ] <EOL> def _update_max_widths ( self , row ) : <EOL> if not self . _max_widths : <EOL> self . _max_widths = [ len ( el ) for el in row ] <EOL> else : <EOL> for i , el in enumerate ( row ) : <EOL> self . _max_widths [ i ] = max ( len ( el ) , self . _max_widths [ i ] ) </s>
