Skip to content

Commit 8e49e5a

Browse files
committed
table_display.py example now uses tableformatter instead of tabulate
Changed the table_display.py example to use the tableformatter module which resuls in nicer looking tables.
1 parent 63aa28c commit 8e49e5a

File tree

1 file changed

+60
-17
lines changed

1 file changed

+60
-17
lines changed

examples/table_display.py

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,78 @@
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
77
NOTE: IF the table does not entirely fit within the screen of your terminal, then it will be displayed using a pager.
88
You can use the arrow keys (left, right, up, and down) to scroll around the table as well as the PageUp/PageDown keys.
99
You 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
"""
1314
import functools
1415

1516
import 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

3678
class 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

62104
if __name__ == '__main__':
63105
app = TableDisplay()
106+
app.debug = True
64107
app.cmdloop()

0 commit comments

Comments
 (0)