1212- pip install tableformatter
1313"""
1414import argparse
15+ from typing import Tuple
1516
1617import cmd2
1718import tableformatter as tf
@@ -93,12 +94,11 @@ def get_area(self):
9394 return self ._area
9495
9596
96- def pop_density (data : CityInfo ):
97+ def pop_density (data : CityInfo ) -> str :
9798 """Calculate the population density from the data entry"""
98- if isinstance (data , CityInfo ):
99- return no_dec (data .get_population () / data .get_area ())
100-
101- return ''
99+ if not isinstance (data , CityInfo ):
100+ raise AttributeError ("Argument to pop_density() must be an instance of CityInfo" )
101+ return no_dec (data .get_population () / data .get_area ())
102102
103103
104104# Convert the Iterable of Iterables data to an Iterable of non-iterable objects for demonstration purposes
@@ -122,7 +122,24 @@ def pop_density(data: CityInfo):
122122 cell_halign = tf .ColumnAlignment .AlignRight , obj_formatter = pop_density ),
123123 ]
124124
125- # TODO: Color row text foreground based on population density
125+
126+ EXTREMELY_HIGH_POULATION_DENSITY = 25000
127+
128+
129+ def high_density_tuples (row_tuple : Tuple ) -> dict :
130+ """Color rows with extremely high population density red."""
131+ opts = dict ()
132+ if len (row_tuple ) >= 7 and row_tuple [6 ] > EXTREMELY_HIGH_POULATION_DENSITY :
133+ opts [tf .TableFormatter .ROW_OPT_TEXT_COLOR ] = tf .TableColors .TEXT_COLOR_RED
134+ return opts
135+
136+
137+ def high_density_objs (row_obj : CityInfo ) -> dict :
138+ """Color rows with extremely high population density red."""
139+ opts = dict ()
140+ if float (pop_density (row_obj )) > EXTREMELY_HIGH_POULATION_DENSITY :
141+ opts [tf .TableFormatter .ROW_OPT_TEXT_COLOR ] = tf .TableColors .TEXT_COLOR_RED
142+ return opts
126143
127144
128145class TableDisplay (cmd2 .Cmd ):
@@ -131,13 +148,14 @@ class TableDisplay(cmd2.Cmd):
131148 def __init__ (self ):
132149 super ().__init__ ()
133150
134- def ptable (self , rows , columns , grid_args ):
151+ def ptable (self , rows , columns , grid_args , row_stylist ):
135152 """Format tabular data for pretty-printing as a fixed-width table and then display it using a pager.
136153
137154 :param rows: required argument - can be a list-of-lists (or another iterable of iterables), a two-dimensional
138155 NumPy array, or an Iterable of non-iterable objects
139156 :param columns: column headers and formatting options per column
140157 :param grid_args: argparse arguments for formatting the grid
158+ :param row_stylist: function to determine how each row gets styled
141159 """
142160 if grid_args .color :
143161 grid = tf .AlternatingRowGrid (BACK_PRI , BACK_ALT )
@@ -148,7 +166,7 @@ def ptable(self, rows, columns, grid_args):
148166 else :
149167 grid = None
150168
151- formatted_table = tf .generate_table (rows = rows , columns = columns , grid_style = grid )
169+ formatted_table = tf .generate_table (rows = rows , columns = columns , grid_style = grid , row_tagger = row_stylist )
152170 self .ppaged (formatted_table , chop = True )
153171
154172 table_parser = argparse .ArgumentParser ()
@@ -160,12 +178,12 @@ def ptable(self, rows, columns, grid_args):
160178 @cmd2 .with_argparser (table_parser )
161179 def do_table (self , args ):
162180 """Display data in iterable form on the Earth's most populated cities in a table."""
163- self .ptable (EXAMPLE_ITERABLE_DATA , COLUMNS , args )
181+ self .ptable (EXAMPLE_ITERABLE_DATA , COLUMNS , args , high_density_tuples )
164182
165183 @cmd2 .with_argparser (table_parser )
166184 def do_object_table (self , args ):
167185 """Display data in object form on the Earth's most populated cities in a table."""
168- self .ptable (EXAMPLE_OBJECT_DATA , OBJ_COLS , args )
186+ self .ptable (EXAMPLE_OBJECT_DATA , OBJ_COLS , args , high_density_objs )
169187
170188
171189if __name__ == '__main__' :
0 commit comments