@@ -548,7 +548,9 @@ def format_value(
548548 console .print (f"[red]Error displaying table: { str (e )} [/red]" )
549549
550550
551- def _rich_print_gt_table (gt_table : Any , preview_info : dict | None = None ) -> None :
551+ def _rich_print_gt_table (
552+ gt_table : Any , preview_info : dict | None = None , show_summary : bool = True
553+ ) -> None :
552554 """Convert a GT table to Rich table and display it in the terminal.
553555
554556 Args:
@@ -558,6 +560,7 @@ def _rich_print_gt_table(gt_table: Any, preview_info: dict | None = None) -> Non
558560 - head_rows: Number of head rows shown
559561 - tail_rows: Number of tail rows shown
560562 - is_complete: Whether the entire dataset is shown
563+ show_summary: Whether to show the row count summary at the bottom
561564 """
562565 try :
563566 # Try to extract the underlying data from the GT table
@@ -861,44 +864,45 @@ def _rich_print_gt_table(gt_table: Any, preview_info: dict | None = None) -> Non
861864 console .print ()
862865 console .print (rich_table )
863866
864- # Show summary info
865- total_rows = len (rows )
867+ # Show summary info (conditionally)
868+ if show_summary :
869+ total_rows = len (rows )
866870
867- # Use preview info if available, otherwise fall back to old logic
868- if preview_info :
869- total_dataset_rows = preview_info .get ("total_rows" , total_rows )
870- head_rows = preview_info .get ("head_rows" , 0 )
871- tail_rows = preview_info .get ("tail_rows" , 0 )
872- is_complete = preview_info .get ("is_complete" , False )
871+ # Use preview info if available, otherwise fall back to old logic
872+ if preview_info :
873+ total_dataset_rows = preview_info .get ("total_rows" , total_rows )
874+ head_rows = preview_info .get ("head_rows" , 0 )
875+ tail_rows = preview_info .get ("tail_rows" , 0 )
876+ is_complete = preview_info .get ("is_complete" , False )
873877
874- if is_complete :
875- console .print (f"\n [dim]Showing all { total_rows } rows.[/dim]" )
876- elif head_rows > 0 and tail_rows > 0 :
877- console .print (
878- f"\n [dim]Showing first { head_rows } and last { tail_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
879- )
880- elif head_rows > 0 :
881- console .print (
882- f"\n [dim]Showing first { head_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
883- )
884- elif tail_rows > 0 :
885- console .print (
886- f"\n [dim]Showing last { tail_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
887- )
888- else :
889- # Fallback for other cases
890- console .print (
891- f"\n [dim]Showing { total_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
892- )
893- else :
894- # Original logic as fallback
895- max_rows = 50 # This should match the limit used above
896- if total_rows > max_rows :
897- console .print (
898- f"\n [dim]Showing first { max_rows } of { total_rows } rows. Use --output-html to see all data.[/dim]"
899- )
878+ if is_complete :
879+ console .print (f"\n [dim]Showing all { total_rows } rows.[/dim]" )
880+ elif head_rows > 0 and tail_rows > 0 :
881+ console .print (
882+ f"\n [dim]Showing first { head_rows } and last { tail_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
883+ )
884+ elif head_rows > 0 :
885+ console .print (
886+ f"\n [dim]Showing first { head_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
887+ )
888+ elif tail_rows > 0 :
889+ console .print (
890+ f"\n [dim]Showing last { tail_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
891+ )
892+ else :
893+ # Fallback for other cases
894+ console .print (
895+ f"\n [dim]Showing { total_rows } rows from { total_dataset_rows :,} total rows.[/dim]"
896+ )
900897 else :
901- console .print (f"\n [dim]Showing all { total_rows } rows.[/dim]" )
898+ # Original logic as fallback
899+ max_rows = 50 # This should match the limit used above
900+ if total_rows > max_rows :
901+ console .print (
902+ f"\n [dim]Showing first { max_rows } of { total_rows } rows. Use --output-html to see all data.[/dim]"
903+ )
904+ else :
905+ console .print (f"\n [dim]Showing all { total_rows } rows.[/dim]" )
902906
903907 else :
904908 # If we can't extract data, show the success message
@@ -1468,8 +1472,9 @@ def missing(data_source: str, output_html: str | None):
14681472 ]
14691473 ),
14701474 default = "rows-distinct" ,
1471- help = "Type of validation check to perform" ,
1475+ help = "Type of validation check to perform. Use --list-checks to see all options. " ,
14721476)
1477+ @click .option ("--list-checks" , is_flag = True , help = "List available validation checks and exit" )
14731478@click .option (
14741479 "--column" ,
14751480 help = "Column name to validate (required for col-vals-not-null, col-exists, col-vals-in-set, col-vals-gt, col-vals-ge, col-vals-lt, and col-vals-le checks)" ,
@@ -1481,7 +1486,7 @@ def missing(data_source: str, output_html: str | None):
14811486 help = "Numeric value for comparison (required for col-vals-gt, col-vals-ge, col-vals-lt, and col-vals-le checks)" ,
14821487)
14831488@click .option (
1484- "--show-extract" , is_flag = True , help = "Show preview of failing rows if validation fails"
1489+ "--show-extract" , is_flag = True , help = "Show extract of failing rows if validation fails"
14851490)
14861491@click .option (
14871492 "--write-extract" , type = str , help = "Save failing rows to folder. Provide base name for folder."
@@ -1490,7 +1495,9 @@ def missing(data_source: str, output_html: str | None):
14901495 "--limit" , "-l" , default = 10 , help = "Maximum number of failing rows to show/save (default: 10)"
14911496)
14921497@click .option ("--exit-code" , is_flag = True , help = "Exit with non-zero code if validation fails" )
1498+ @click .pass_context
14931499def validate (
1500+ ctx : click .Context ,
14941501 data_source : str ,
14951502 check : str ,
14961503 column : str | None ,
@@ -1500,6 +1507,7 @@ def validate(
15001507 write_extract : str | None ,
15011508 limit : int ,
15021509 exit_code : bool ,
1510+ list_checks : bool ,
15031511):
15041512 """
15051513 Perform simple, single-step data validations.
@@ -1517,6 +1525,10 @@ def validate(
15171525
15181526 AVAILABLE CHECKS:
15191527
1528+ Use --list-checks to see all available validation methods with examples.
1529+
1530+ The default check is 'rows-distinct' which checks for duplicate rows.
1531+
15201532 \b
15211533 - rows-distinct: Check if all rows in the dataset are unique (no duplicates)
15221534 - rows-complete: Check if all rows are complete (no missing values in any column)
@@ -1531,6 +1543,8 @@ def validate(
15311543 Examples:
15321544
15331545 \b
1546+ pb validate data.csv # Uses default validation (rows-distinct)
1547+ pb validate data.csv --list-checks # Show all available checks
15341548 pb validate data.csv --check rows-distinct
15351549 pb validate data.csv --check rows-distinct --show-extract
15361550 pb validate data.csv --check rows-distinct --write-extract failing_rows_folder
@@ -1542,6 +1556,67 @@ def validate(
15421556 pb validate data.csv --check col-vals-in-set --column status --set "active,inactive,pending"
15431557 """
15441558 try :
1559+ # Handle --list-checks option
1560+ if list_checks :
1561+ console .print ("[bold bright_cyan]Available Validation Checks:[/bold bright_cyan]" )
1562+ console .print ()
1563+ console .print ("[bold magenta]Basic checks:[/bold magenta]" )
1564+ console .print (
1565+ " • [bold cyan]rows-distinct[/bold cyan] Check for duplicate rows [yellow](default)[/yellow]"
1566+ )
1567+ console .print (
1568+ " • [bold cyan]rows-complete[/bold cyan] Check for missing values in any column"
1569+ )
1570+ console .print ()
1571+ console .print (
1572+ "[bold magenta]Column-specific checks [bright_black](require --column)[/bright_black]:[/bold magenta]"
1573+ )
1574+ console .print (" • [bold cyan]col-exists[/bold cyan] Check if a column exists" )
1575+ console .print (
1576+ " • [bold cyan]col-vals-not-null[/bold cyan] Check for null values in a column"
1577+ )
1578+ console .print ()
1579+ console .print (
1580+ "[bold magenta]Value comparison checks [bright_black](require --column and --value)[/bright_black]:[/bold magenta]"
1581+ )
1582+ console .print (
1583+ " • [bold cyan]col-vals-gt[/bold cyan] Values greater than threshold"
1584+ )
1585+ console .print (
1586+ " • [bold cyan]col-vals-ge[/bold cyan] Values greater than or equal to threshold"
1587+ )
1588+ console .print (" • [bold cyan]col-vals-lt[/bold cyan] Values less than threshold" )
1589+ console .print (
1590+ " • [bold cyan]col-vals-le[/bold cyan] Values less than or equal to threshold"
1591+ )
1592+ console .print ()
1593+ console .print (
1594+ "[bold magenta]Set validation check [bright_black](requires --column and --set)[/bright_black]:[/bold magenta]"
1595+ )
1596+ console .print (
1597+ " • [bold cyan]col-vals-in-set[/bold cyan] Values must be in allowed set"
1598+ )
1599+ console .print ()
1600+ console .print ("[bold bright_yellow]Examples:[/bold bright_yellow]" )
1601+ console .print (
1602+ f" [bright_blue]pb validate { data_source } --check rows-distinct[/bright_blue]"
1603+ )
1604+ console .print (
1605+ f" [bright_blue]pb validate { data_source } --check col-vals-not-null --column price[/bright_blue]"
1606+ )
1607+ console .print (
1608+ f" [bright_blue]pb validate { data_source } --check col-vals-gt --column age --value 18[/bright_blue]"
1609+ )
1610+ import sys
1611+
1612+ sys .exit (0 )
1613+
1614+ # Check if --check option was explicitly provided by the user
1615+ # If --check is not in the command line args, it means we're using the default
1616+ import sys
1617+
1618+ is_using_default_check = check == "rows-distinct" and "--check" not in sys .argv
1619+
15451620 # Validate required parameters for different check types
15461621 if check == "col-vals-not-null" and not column :
15471622 console .print (f"[red]Error:[/red] --column is required for { check } check" )
@@ -1640,7 +1715,12 @@ def validate(
16401715 # Get the result
16411716 all_passed = validation .all_passed ()
16421717
1643- console .print (f"[green]✓[/green] { check } validation completed" )
1718+ if is_using_default_check :
1719+ console .print (
1720+ f"[green]✓[/green] { check } validation completed [dim](default validation)[/dim]"
1721+ )
1722+ else :
1723+ console .print (f"[green]✓[/green] { check } validation completed" )
16441724 elif check == "col-vals-not-null" :
16451725 # Create validation for not null values in specified column
16461726 validation = (
@@ -1908,10 +1988,10 @@ def validate(
19081988
19091989 # Dynamic message based on check type
19101990 if check == "rows-distinct" :
1911- extract_message = "[yellow]Preview of failing rows (duplicates):[/yellow]"
1991+ extract_message = "[yellow]Extract of failing rows (duplicates):[/yellow]"
19121992 row_type = "duplicate rows"
19131993 elif check == "rows-complete" :
1914- extract_message = "[yellow]Preview of failing rows (incomplete rows):[/yellow]"
1994+ extract_message = "[yellow]Extract of failing rows (incomplete rows):[/yellow]"
19151995 row_type = "incomplete rows"
19161996 elif check == "col-exists" :
19171997 extract_message = (
@@ -1920,21 +2000,21 @@ def validate(
19202000 row_type = "missing column"
19212001 elif check == "col-vals-in-set" :
19222002 extract_message = (
1923- f"[yellow]Preview of failing rows (invalid values in '{ column } '):[/yellow]"
2003+ f"[yellow]Extract of failing rows (invalid values in '{ column } '):[/yellow]"
19242004 )
19252005 row_type = "rows with invalid values"
19262006 elif check == "col-vals-gt" :
19272007 extract_message = (
1928- f"[yellow]Preview of failing rows (values in '{ column } ' <= { value } ):[/yellow]"
2008+ f"[yellow]Extract of failing rows (values in '{ column } ' <= { value } ):[/yellow]"
19292009 )
19302010 row_type = f"rows with values <= { value } "
19312011 elif check == "col-vals-ge" :
19322012 extract_message = (
1933- f"[yellow]Preview of failing rows (values in '{ column } ' < { value } ):[/yellow]"
2013+ f"[yellow]Extract of failing rows (values in '{ column } ' < { value } ):[/yellow]"
19342014 )
19352015 row_type = f"rows with values < { value } "
19362016 else :
1937- extract_message = "[yellow]Preview of failing rows:[/yellow]"
2017+ extract_message = "[yellow]Extract of failing rows:[/yellow]"
19382018 row_type = "failing rows"
19392019
19402020 if show_extract :
@@ -1980,7 +2060,7 @@ def validate(
19802060 )
19812061
19822062 # Display using our Rich table function
1983- _rich_print_gt_table (preview_table )
2063+ _rich_print_gt_table (preview_table , show_summary = False )
19842064
19852065 if write_extract :
19862066 try :
@@ -2103,9 +2183,7 @@ def validate(
21032183
21042184 # Add hint about --show-extract if not already used (except for col-exists which has no rows to show)
21052185 if not show_extract and check != "col-exists" :
2106- failure_message += (
2107- "\n [dim]💡 Tip: Use --show-extract to see the failing rows[/dim]"
2108- )
2186+ failure_message += "\n [bright_blue]💡 Tip:[/bright_blue] [cyan]Use --show-extract to see the failing rows[/cyan]"
21092187
21102188 console .print (
21112189 Panel (
@@ -2129,9 +2207,7 @@ def validate(
21292207
21302208 # Add hint about --show-extract if not already used
21312209 if not show_extract :
2132- failure_message += (
2133- "\n [dim]💡 Tip: Use --show-extract to see the failing rows[/dim]"
2134- )
2210+ failure_message += "\n [bright_blue]💡 Tip:[/bright_blue] [cyan]Use --show-extract to see the failing rows[/cyan]"
21352211
21362212 console .print (
21372213 Panel (
@@ -2140,6 +2216,31 @@ def validate(
21402216 )
21412217 )
21422218
2219+ # Add informational hints when using default validation
2220+ if is_using_default_check :
2221+ console .print ()
2222+ console .print ("[bold blue]ℹ️ Information:[/bold blue] Using default validation method" )
2223+ console .print ("To specify a different validation, use the --check option." )
2224+ console .print ()
2225+ console .print ("[bold magenta]Common validation options:[/bold magenta]" )
2226+ console .print (
2227+ " • [bold cyan]--check rows-complete[/bold cyan] Check for rows with missing values"
2228+ )
2229+ console .print (
2230+ " • [bold cyan]--check col-vals-not-null[/bold cyan] Check for null values in a column [bright_black](requires --column)[/bright_black]"
2231+ )
2232+ console .print (
2233+ " • [bold cyan]--check col-exists[/bold cyan] Check if a column exists [bright_black](requires --column)[/bright_black]"
2234+ )
2235+ console .print ()
2236+ console .print ("[bold bright_yellow]Examples:[/bold bright_yellow]" )
2237+ console .print (
2238+ f" [bright_blue]pb validate { data_source } --check rows-complete[/bright_blue]"
2239+ )
2240+ console .print (
2241+ f" [bright_blue]pb validate { data_source } --check col-vals-not-null --column price[/bright_blue]"
2242+ )
2243+
21432244 # Exit with appropriate code if requested
21442245 if exit_code and not all_passed :
21452246 console .print ("[dim]Exiting with non-zero code due to validation failure[/dim]" )
@@ -2735,7 +2836,7 @@ def make_template(output_file: str):
27352836@click .option ("--output-html" , type = click .Path (), help = "Save HTML validation report to file" )
27362837@click .option ("--output-json" , type = click .Path (), help = "Save JSON validation summary to file" )
27372838@click .option (
2738- "--show-extract" , is_flag = True , help = "Show preview of failing rows if validation fails"
2839+ "--show-extract" , is_flag = True , help = "Show extract of failing rows if validation fails"
27392840)
27402841@click .option (
27412842 "--write-extract" ,
@@ -2892,7 +2993,7 @@ def run(
28922993 console .print ()
28932994
28942995 if show_extract :
2895- extract_title = "Preview of failing rows from validation steps"
2996+ extract_title = "Extract of failing rows from validation steps"
28962997 if len (validations ) > 1 :
28972998 extract_title += f" (Validation { i } )"
28982999 console .print (f"[yellow]{ extract_title } :[/yellow]" )
@@ -2928,7 +3029,7 @@ def run(
29283029 )
29293030
29303031 # Display using our Rich table function
2931- _rich_print_gt_table (preview_table )
3032+ _rich_print_gt_table (preview_table , show_summary = False )
29323033 else :
29333034 console .print (
29343035 f"\n [cyan]Step { step_num } :[/cyan] { step_info .assertion_type } "
0 commit comments