Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 127 additions & 78 deletions pointblank/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8886,9 +8886,12 @@ def get_step_report(
column selector expressions don't resolve to any columns.
header
Options for customizing the header of the step report. The default is the `":default:"`
value which produces a generic header. Aside from this default, text can be provided for
the header. This will be interpreted as Markdown text and transformed internally to
HTML.
value which produces a header with a standard title and set of details underneath. Aside
from this default, free text can be provided for the header. This will be interpreted as
Markdown text and transformed internally to HTML. You can provide one of two templating
elements: `{title}` and `{details}`. The default header has the template
`"{title}{details}"` so you can easily start from that and modify as you see fit. If you
don't want a header at all, you can set `header=None` to remove it entirely.
limit
The number of rows to display for those validation steps that check values in rows (the
`col_vals_*()` validation steps). The default is `10` rows and the limit can be removed
Expand Down Expand Up @@ -10362,7 +10365,12 @@ def _step_report_row_based(
else:
step_report = tbl_preview

if header == ":default:":
# TODO: localize all text fragments according to `lang=` parameter

if header is None:
pass

elif header == ":default:":
step_report = step_report.tab_header(
title=html(f"Report for Validation Step {i} {CHECK_MARK_SPAN}"),
subtitle=html(
Expand Down Expand Up @@ -10435,27 +10443,41 @@ def _step_report_row_based(
not_shown = " (NOT SHOWN)"
shown_failures = ""

title = f"Report for Validation Step {i}"
details = (
"<div style='font-size: 13.6px;'>"
"<div style='padding-top: 7px;'>"
"ASSERTION <span style='border-style: solid; border-width: thin; "
"border-color: lightblue; padding-left: 2px; padding-right: 2px;'>"
f"<code style='color: #303030;'>{text}</code></span>"
"</div>"
"<div style='padding-top: 7px;'>"
f"<strong>{n_failed}</strong> / "
f"<strong>{n}</strong> TEST UNIT FAILURES "
f"IN COLUMN <strong>{column_position}</strong>{not_shown}"
"</div>"
f"<div>EXTRACT OF {extract_of_x_rows} "
f"<strong>{extract_length_resolved}</strong> ROWS {shown_failures}:"
"</div>"
"</div>"
)

# If `header` is None then don't add a header and just return the step report
if header is None:
return step_report

# Generate the default template text for the header when `":default:"` is used
if header == ":default:":
step_report = step_report.tab_header(
title=f"Report for Validation Step {i}",
subtitle=html(
"<div>"
"ASSERTION <span style='border-style: solid; border-width: thin; "
"border-color: lightblue; padding-left: 2px; padding-right: 2px;'>"
f"<code style='color: #303030;'>{text}</code></span><br>"
f"<div style='padding-top: 3px;'><strong>{n_failed}</strong> / "
f"<strong>{n}</strong> TEST UNIT FAILURES "
f"IN COLUMN <strong>{column_position}</strong>{not_shown}</div>"
f"<div style='padding-top: 10px;'>EXTRACT OF {extract_of_x_rows} "
f"<strong>{extract_length_resolved}</strong> ROWS {shown_failures}:"
"</div></div>"
),
)
header = "{title}{details}"

else:
step_report = step_report.tab_header(
title=md(header),
)
# Use commonmark to convert the header text to HTML
header = commonmark.commonmark(header)

# Place any templated text in the header
header = header.format(title=title, details=details)

# Create the header with `header` string
step_report = step_report.tab_header(title=md(header))

return step_report

Expand Down Expand Up @@ -10620,23 +10642,6 @@ def _step_report_schema_in_order(
if debug_return_df:
return schema_combined

# Get the other parameters for the `col_schema_match()` function
case_sensitive_colnames = schema_info["params"]["case_sensitive_colnames"]
case_sensitive_dtypes = schema_info["params"]["case_sensitive_dtypes"]
full_match_dtypes = schema_info["params"]["full_match_dtypes"]

# Generate text for the `col_schema_match()` parameters
col_schema_match_params_html = _create_col_schema_match_params_html(
complete=complete,
in_order=True,
case_sensitive_colnames=case_sensitive_colnames,
case_sensitive_dtypes=case_sensitive_dtypes,
full_match_dtypes=full_match_dtypes,
)

# Get the passing symbol for the step
passing_symbol = CHECK_MARK_SPAN if all_passed else CROSS_MARK_SPAN

step_report = (
GT(schema_combined, id="pb_step_tbl")
.fmt_markdown(columns=None)
Expand Down Expand Up @@ -10725,15 +10730,6 @@ def _step_report_schema_in_order(
.tab_options(source_notes_font_size="12px")
)

if header == ":default:":
step_report = step_report.tab_header(
title=html(f"Report for Validation Step {step} {passing_symbol}"),
subtitle=html(col_schema_match_params_html),
)

else:
step_report = step_report.tab_header(title=md(header))

if schema_length == "shorter":
# Add background color to the missing column on the exp side
step_report = step_report.tab_style(
Expand Down Expand Up @@ -10774,6 +10770,43 @@ def _step_report_schema_in_order(
if version("great_tables") >= "0.17.0":
step_report = step_report.tab_options(quarto_disable_processing=True)

# If `header` is None then don't add a header and just return the step report
if header is None:
return step_report

# Get the other parameters for the `col_schema_match()` function
case_sensitive_colnames = schema_info["params"]["case_sensitive_colnames"]
case_sensitive_dtypes = schema_info["params"]["case_sensitive_dtypes"]
full_match_dtypes = schema_info["params"]["full_match_dtypes"]

# Get the passing symbol for the step
passing_symbol = CHECK_MARK_SPAN if all_passed else CROSS_MARK_SPAN

# Generate the title for the step report
title = f"Report for Validation Step {step} {passing_symbol}"

# Generate the details for the step report
details = _create_col_schema_match_params_html(
complete=complete,
in_order=True,
case_sensitive_colnames=case_sensitive_colnames,
case_sensitive_dtypes=case_sensitive_dtypes,
full_match_dtypes=full_match_dtypes,
)

# Generate the default template text for the header when `":default:"` is used
if header == ":default:":
header = "{title}{details}"

# Use commonmark to convert the header text to HTML
header = commonmark.commonmark(header)

# Place any templated text in the header
header = header.format(title=title, details=details)

# Create the header with `header` string
step_report = step_report.tab_header(title=md(header))

return step_report


Expand Down Expand Up @@ -11039,23 +11072,6 @@ def _step_report_schema_any_order(
if debug_return_df:
return schema_combined

# Get the other parameters for the `col_schema_match()` function
case_sensitive_colnames = schema_info["params"]["case_sensitive_colnames"]
case_sensitive_dtypes = schema_info["params"]["case_sensitive_dtypes"]
full_match_dtypes = schema_info["params"]["full_match_dtypes"]

# Generate text for the `col_schema_match()` parameters
col_schema_match_params_html = _create_col_schema_match_params_html(
complete=complete,
in_order=False,
case_sensitive_colnames=case_sensitive_colnames,
case_sensitive_dtypes=case_sensitive_dtypes,
full_match_dtypes=full_match_dtypes,
)

# Get the passing symbol for the step
passing_symbol = CHECK_MARK_SPAN if all_passed else CROSS_MARK_SPAN

step_report = (
GT(schema_combined, id="pb_step_tbl")
.fmt_markdown(columns=None)
Expand Down Expand Up @@ -11145,15 +11161,6 @@ def _step_report_schema_any_order(
.tab_options(source_notes_font_size="12px")
)

if header == ":default:":
step_report = step_report.tab_header(
title=html(f"Report for Validation Step {step} {passing_symbol}"),
subtitle=html(col_schema_match_params_html),
)

else:
step_report = step_report.tab_header(title=md(header))

# Add background color to signify limits of target table schema (on LHS side)
if len(colnames_exp_unmatched) > 0:
step_report = step_report.tab_style(
Expand All @@ -11172,6 +11179,43 @@ def _step_report_schema_any_order(
if version("great_tables") >= "0.17.0":
step_report = step_report.tab_options(quarto_disable_processing=True)

# If `header` is None then don't add a header and just return the step report
if header is None:
return step_report

# Get the other parameters for the `col_schema_match()` function
case_sensitive_colnames = schema_info["params"]["case_sensitive_colnames"]
case_sensitive_dtypes = schema_info["params"]["case_sensitive_dtypes"]
full_match_dtypes = schema_info["params"]["full_match_dtypes"]

# Get the passing symbol for the step
passing_symbol = CHECK_MARK_SPAN if all_passed else CROSS_MARK_SPAN

# Generate the title for the step report
title = f"Report for Validation Step {step} {passing_symbol}"

# Generate the details for the step report
details = _create_col_schema_match_params_html(
complete=complete,
in_order=False,
case_sensitive_colnames=case_sensitive_colnames,
case_sensitive_dtypes=case_sensitive_dtypes,
full_match_dtypes=full_match_dtypes,
)

# Generate the default template text for the header when `":default:"` is used
if header == ":default:":
header = "{title}{details}"

# Use commonmark to convert the header text to HTML
header = commonmark.commonmark(header)

# Place any templated text in the header
header = header.format(title=title, details=details)

# Create the header with `header` string
step_report = step_report.tab_header(title=md(header))

return step_report


Expand Down Expand Up @@ -11247,7 +11291,12 @@ def _create_col_schema_match_params_html(
)

return (
'<div style="display: flex;"><div style="margin-right: 5px;">COLUMN SCHEMA MATCH</div>'
f"{complete_text}{in_order_text}{case_sensitive_colnames_text}{case_sensitive_dtypes_text}"
f"{full_match_dtypes_text}</div>"
'<div style="display: flex; font-size: 13.7px; padding-top: 7px;">'
'<div style="margin-right: 5px;">COLUMN SCHEMA MATCH</div>'
f"{complete_text}"
f"{in_order_text}"
f"{case_sensitive_colnames_text}"
f"{case_sensitive_dtypes_text}"
f"{full_match_dtypes_text}"
"</div>"
)
10 changes: 9 additions & 1 deletion tests/test_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6640,10 +6640,18 @@ def test_get_step_report_no_fail(tbl_type):
for i in range(1, 18):
assert isinstance(validation.get_step_report(i=i, limit=None), GT.GT)

# Test with a custom header
# Test with a custom header using static text
for i in range(1, 18):
assert isinstance(validation.get_step_report(i=i, header="Custom header"), GT.GT)

# Test with a custom header using templating elements
for i in range(1, 18):
assert isinstance(validation.get_step_report(i=i, header="Title {title} {details}"), GT.GT)

# Test with header removal
for i in range(1, 18):
assert isinstance(validation.get_step_report(i=i, header=None), GT.GT)

#
# Tests with a subset of columns
#
Expand Down