Skip to content

Commit d5036f3

Browse files
authored
Merge pull request #227 from posit-dev/fix-cli-scan-improve-display
fix: improve display of tables in CLI utility
2 parents 4cfecd6 + f2d2c6d commit d5036f3

1 file changed

Lines changed: 30 additions & 49 deletions

File tree

pointblank/cli.py

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,13 @@ def _rich_print_gt_table(gt_table: Any, preview_info: dict | None = None) -> Non
284284
table_type = preview_info["table_type"]
285285
table_title = f"Data Preview / {source_type} / {table_type}"
286286

287+
# Add dimensions subtitle in gray if available
288+
if "total_rows" in preview_info and "total_columns" in preview_info:
289+
total_rows = preview_info["total_rows"]
290+
total_columns = preview_info["total_columns"]
291+
if total_rows is not None and total_columns is not None:
292+
table_title += f"\n[dim]{total_rows:,} rows / {total_columns} columns[/dim]"
293+
287294
rich_table = Table(
288295
title=table_title,
289296
show_header=True,
@@ -951,6 +958,7 @@ def preview(
951958
processed_data = data
952959

953960
total_dataset_rows = pb.get_row_count(processed_data)
961+
total_dataset_columns = pb.get_column_count(processed_data)
954962

955963
# Determine source type and table type for enhanced preview title
956964
if data_source in ["small_table", "game_revenue", "nycflights", "global_sales"]:
@@ -962,6 +970,7 @@ def preview(
962970
except Exception:
963971
# If we can't get metadata, set defaults
964972
total_dataset_rows = None
973+
total_dataset_columns = None
965974
source_type = f"Data source: {data_source}"
966975
table_type = "unknown"
967976

@@ -992,6 +1001,7 @@ def preview(
9921001

9931002
preview_info = {
9941003
"total_rows": total_dataset_rows,
1004+
"total_columns": total_dataset_columns,
9951005
"head_rows": head,
9961006
"tail_rows": tail,
9971007
"is_complete": is_complete,
@@ -1118,11 +1128,13 @@ def scan(
11181128
source_type = f"External source: {data_source}"
11191129

11201130
table_type = _get_tbl_type(data)
1121-
# Get row count for footer
1131+
# Get row count and column count for header
11221132
try:
11231133
total_rows = pb.get_row_count(data)
1134+
total_columns = pb.get_column_count(data)
11241135
except Exception:
11251136
total_rows = None
1137+
total_columns = None
11261138

11271139
scan_time = time.time() - start_time
11281140

@@ -1142,7 +1154,7 @@ def scan(
11421154
# Display detailed column summary using rich formatting
11431155
try:
11441156
_rich_print_scan_table(
1145-
scan_result, data_source, source_type, table_type, total_rows
1157+
scan_result, data_source, source_type, table_type, total_rows, total_columns
11461158
)
11471159

11481160
except Exception as e:
@@ -1756,6 +1768,7 @@ def _rich_print_scan_table(
17561768
source_type: str,
17571769
table_type: str,
17581770
total_rows: int | None = None,
1771+
total_columns: int | None = None,
17591772
) -> None:
17601773
"""
17611774
Display scan results as a Rich table in the terminal with statistical measures.
@@ -1766,6 +1779,7 @@ def _rich_print_scan_table(
17661779
source_type: Type of data source (e.g., "Pointblank dataset: small_table")
17671780
table_type: Type of table (e.g., "polars.LazyFrame")
17681781
total_rows: Total number of rows in the dataset
1782+
total_columns: Total number of columns in the dataset
17691783
"""
17701784
try:
17711785
import re
@@ -1787,6 +1801,10 @@ def _rich_print_scan_table(
17871801
# Create a comprehensive title with data source, source type, and table type
17881802
title_text = f"Column Summary / {source_type} / {table_type}"
17891803

1804+
# Add dimensions subtitle in gray if available
1805+
if total_rows is not None and total_columns is not None:
1806+
title_text += f"\n[dim]{total_rows:,} rows / {total_columns} columns[/dim]"
1807+
17901808
scan_table = Table(
17911809
title=title_text,
17921810
show_header=True,
@@ -2003,26 +2021,7 @@ def format_value(
20032021

20042022
# Display the results
20052023
console.print()
2006-
console.print(scan_table) # Add informational footer about the scan scope
2007-
try:
2008-
if total_rows is not None:
2009-
# Full table scan
2010-
footer_text = f"[dim]Scan from all {total_rows:,} rows in the table.[/dim]"
2011-
2012-
# Create a simple footer
2013-
footer_table = Table(
2014-
show_header=False,
2015-
show_lines=False,
2016-
box=None,
2017-
padding=(0, 0),
2018-
)
2019-
footer_table.add_column("", style="dim", width=80)
2020-
footer_table.add_row(footer_text)
2021-
console.print(footer_table)
2022-
2023-
except Exception:
2024-
# If we can't determine the scan scope, don't show a footer
2025-
pass
2024+
console.print(scan_table)
20262025

20272026
except Exception as e:
20282027
# Fallback to simple message if table creation fails
@@ -2225,9 +2224,7 @@ def validate_simple(
22252224
# Get the result
22262225
all_passed = validation.all_passed()
22272226

2228-
console.print(
2229-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2230-
)
2227+
console.print(f"[green]✓[/green] {check} validation completed")
22312228
elif check == "col-vals-not-null":
22322229
# Create validation for not null values in specified column
22332230
validation = (
@@ -2243,9 +2240,7 @@ def validate_simple(
22432240
# Get the result
22442241
all_passed = validation.all_passed()
22452242

2246-
console.print(
2247-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2248-
)
2243+
console.print(f"[green]✓[/green] {check} validation completed")
22492244
elif check == "rows-complete":
22502245
# Create validation for complete rows (no missing values in any column)
22512246
validation = (
@@ -2261,9 +2256,7 @@ def validate_simple(
22612256
# Get the result
22622257
all_passed = validation.all_passed()
22632258

2264-
console.print(
2265-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2266-
)
2259+
console.print(f"[green]✓[/green] {check} validation completed")
22672260
elif check == "col-exists":
22682261
# Create validation for column existence
22692262
validation = (
@@ -2279,9 +2272,7 @@ def validate_simple(
22792272
# Get the result
22802273
all_passed = validation.all_passed()
22812274

2282-
console.print(
2283-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2284-
)
2275+
console.print(f"[green]✓[/green] {check} validation completed")
22852276
elif check == "col-vals-in-set":
22862277
# Parse the comma-separated set values
22872278
allowed_values = [value.strip() for value in set.split(",")]
@@ -2300,9 +2291,7 @@ def validate_simple(
23002291
# Get the result
23012292
all_passed = validation.all_passed()
23022293

2303-
console.print(
2304-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2305-
)
2294+
console.print(f"[green]✓[/green] {check} validation completed")
23062295
elif check == "col-vals-gt":
23072296
# Create validation for values greater than threshold
23082297
validation = (
@@ -2318,9 +2307,7 @@ def validate_simple(
23182307
# Get the result
23192308
all_passed = validation.all_passed()
23202309

2321-
console.print(
2322-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2323-
)
2310+
console.print(f"[green]✓[/green] {check} validation completed")
23242311
elif check == "col-vals-ge":
23252312
# Create validation for values greater than or equal to threshold
23262313
validation = (
@@ -2336,9 +2323,7 @@ def validate_simple(
23362323
# Get the result
23372324
all_passed = validation.all_passed()
23382325

2339-
console.print(
2340-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2341-
)
2326+
console.print(f"[green]✓[/green] {check} validation completed")
23422327
elif check == "col-vals-lt":
23432328
# Create validation for values less than threshold
23442329
validation = (
@@ -2354,9 +2339,7 @@ def validate_simple(
23542339
# Get the result
23552340
all_passed = validation.all_passed()
23562341

2357-
console.print(
2358-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2359-
)
2342+
console.print(f"[green]✓[/green] {check} validation completed")
23602343
elif check == "col-vals-le":
23612344
# Create validation for values less than or equal to threshold
23622345
validation = (
@@ -2372,9 +2355,7 @@ def validate_simple(
23722355
# Get the result
23732356
all_passed = validation.all_passed()
23742357

2375-
console.print(
2376-
f"[green]✓[/green] {check.replace('-', ' ').title()} validation completed"
2377-
)
2358+
console.print(f"[green]✓[/green] {check} validation completed")
23782359
else:
23792360
# This shouldn't happen due to click.Choice, but just in case
23802361
console.print(f"[red]Error:[/red] Unknown check type: {check}")

0 commit comments

Comments
 (0)