11#!/usr/bin/env python
22# coding=utf-8
33"""A simple example demonstrating the following:
4- 1) How to display tabular data within a cmd2 application
4+ 1) How to display tabular data
55 2) How to display output using a pager
66
77NOTE: IF the table does not entirely fit within the screen of your terminal, then it will be displayed using a pager.
88You can use the arrow keys (left, right, up, and down) to scroll around the table as well as the PageUp/PageDown keys.
99You can quit out of the pager by typing "q". You can also search for text within the pager using "/".
1010
11- WARNING: This example requires the tabulate module.
11+ WARNING: This example requires the tableformatter module: https://github.com/python-tableformatter/tableformatter
12+ - pip install tableformatter
1213"""
1314import functools
1415
1516import cmd2
16- import tabulate
17+ import tableformatter as tf
1718
18- # Format to use with tabulate module when displaying tables
19- TABLE_FORMAT = 'grid'
19+ try :
20+ from colored import bg
21+ BACK_PRI = bg (4 )
22+ BACK_ALT = bg (2 )
23+ except ImportError :
24+ try :
25+ from colorama import Back
26+ BACK_PRI = Back .LIGHTBLUE_EX
27+ BACK_ALT = Back .LIGHTYELLOW_EX
28+ except ImportError :
29+ BACK_PRI = ''
30+ BACK_ALT = ''
31+
32+ # Format to use for the grid style when displaying tables with the tableformatter module
33+ grid_style = tf .AlternatingRowGrid (BACK_PRI , BACK_ALT ) # Use rows of alternating color to assist as a visual guide
2034
2135# Create a function to format a fixed-width table for pretty-printing using the desired table format
22- table = functools .partial (tabulate .tabulate , tablefmt = TABLE_FORMAT )
36+ table = functools .partial (tf .generate_table , grid_style = grid_style )
37+
2338
2439# Population data from Wikipedia: https://en.wikipedia.org/wiki/List_of_cities_proper_by_population
25- EXAMPLE_DATA = [['Shanghai' , 'Shanghai' , 'China' , 'Asia' , 24183300 , 6340.5 , 3814 ],
26- ['Beijing' , 'Hebei' , 'China' , 'Asia' , 20794000 , 1749.57 , 11885 ],
27- ['Karachi' , 'Sindh' , 'Pakistan' , 'Asia' , 14910352 , 615.58 , 224221 ],
28- ['Shenzen' , 'Guangdong' , 'China' , 'Asia' , 13723000 , 1493.32 , 9190 ],
29- ['Guangzho' , 'Guangdong' , 'China' , 'Asia' , 13081000 , 1347.81 , 9705 ],
30- ['Mumbai' , ' Maharashtra' , 'India' , 'Asia' , 12442373 , 465.78 , 27223 ],
31- ['Istanbul' , 'Istanbul' , 'Turkey' , 'Eurasia' , 12661000 , 620.29 , 20411 ],
40+ EXAMPLE_DATA = [['Shanghai' , 'Shanghai' , 'China' , 'Asia' , 24183300 , 6340.5 ],
41+ ['Beijing' , 'Hebei' , 'China' , 'Asia' , 20794000 , 1749.57 ],
42+ ['Karachi' , 'Sindh' , 'Pakistan' , 'Asia' , 14910352 , 615.58 ],
43+ ['Shenzen' , 'Guangdong' , 'China' , 'Asia' , 13723000 , 1493.32 ],
44+ ['Guangzho' , 'Guangdong' , 'China' , 'Asia' , 13081000 , 1347.81 ],
45+ ['Mumbai' , 'Maharashtra' , 'India' , 'Asia' , 12442373 , 465.78 ],
46+ ['Istanbul' , 'Istanbul' , 'Turkey' , 'Eurasia' , 12661000 , 620.29 ],
3247 ]
33- EXAMPLE_HEADERS = ['City' , 'Province' , 'Country' , 'Continent' , 'Population' , 'Area (km^2)' , 'Pop. Density (/km^2)' ]
48+
49+ # Calculate population density
50+ for row in EXAMPLE_DATA :
51+ row .append (row [- 2 ]/ row [- 1 ])
52+
53+
54+ # TODO: Color row text foreground based on population density
55+
56+
57+ def no_dec (num : float ) -> str :
58+ """Format a floating point number with no decimal places."""
59+ return "{}" .format (round (num ))
60+
61+
62+ def two_dec (num : float ) -> str :
63+ """Format a floating point number with 2 decimal places."""
64+ return "{0:.2f}" .format (num )
65+
66+
67+ # # Column headers plus optional formatting info for each column
68+ columns = [tf .Column ('City' , header_halign = tf .ColumnAlignment .AlignCenter ),
69+ tf .Column ('Province' , header_halign = tf .ColumnAlignment .AlignCenter ),
70+ 'Country' , # NOTE: If you don't need any special effects, you can just pass a string
71+ tf .Column ('Continent' , cell_halign = tf .ColumnAlignment .AlignCenter ),
72+ tf .Column ('Population' , cell_halign = tf .ColumnAlignment .AlignRight , formatter = tf .FormatCommas ()),
73+ tf .Column ('Area (km^2)' , cell_halign = tf .ColumnAlignment .AlignRight , formatter = two_dec ),
74+ tf .Column ('Pop. Density (/km^2)' , width = 12 , cell_halign = tf .ColumnAlignment .AlignRight , formatter = no_dec ),
75+ ]
3476
3577
3678class TableDisplay (cmd2 .Cmd ):
@@ -51,14 +93,15 @@ def ptable(self, tabular_data, headers=()):
5193 - if `headers="keys"`, then dictionary keys or column indices are used
5294 - Otherwise, a headerless table is produced
5395 """
54- formatted_table = table (tabular_data , headers = headers )
55- self .ppaged (formatted_table )
96+ formatted_table = table (rows = tabular_data , columns = headers )
97+ self .ppaged (formatted_table , chop = True )
5698
5799 def do_table (self , _ ):
58100 """Display data on the Earth's most populated cities in a table."""
59- self .ptable (tabular_data = EXAMPLE_DATA , headers = EXAMPLE_HEADERS )
101+ self .ptable (EXAMPLE_DATA , columns )
60102
61103
62104if __name__ == '__main__' :
63105 app = TableDisplay ()
106+ app .debug = True
64107 app .cmdloop ()
0 commit comments