Skip to content

Commit 812c440

Browse files
authored
Merge pull request #273 from posit-dev/feat-step-report-col-vals-expr
fix: show a `col_vals_expr()`-based step with the `get_step_report()` method
2 parents 180d14b + 7cad830 commit 812c440

File tree

3 files changed

+121
-8
lines changed

3 files changed

+121
-8
lines changed

pointblank/_constants_translations.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,33 @@
18431843
"hi": "{column} Null नहीं है",
18441844
"el": "{column} δεν είναι Null",
18451845
},
1846+
"column_expr": {
1847+
"en": "The following column expression holds: {values}",
1848+
"fr": "L'expression de colonne suivante est vraie : {values}",
1849+
"de": "Der folgende Spaltenausdruck gilt: {values}",
1850+
"it": "La seguente espressione di colonna è valida: {values}",
1851+
"es": "La siguiente expresión de columna se cumple: {values}",
1852+
"pt": "A seguinte expressão de coluna é válida: {values}",
1853+
"ro": "Următoarea expresie de coloană este validă: {values}",
1854+
"tr": "Aşağıdaki sütun ifadesi geçerlidir: {values}",
1855+
"zh-Hans": "以下列表达式成立:{values}",
1856+
"zh-Hant": "以下欄位表達式成立:{values}",
1857+
"ja": "次の列式が成り立ちます:{values}",
1858+
"ko": "다음 열 표현식이 성립합니다: {values}",
1859+
"vi": "Biểu thức cột sau đây đúng: {values}",
1860+
"ru": "Следующее выражение для столбца выполняется: {values}",
1861+
"cs": "Následující výraz sloupce platí: {values}",
1862+
"pl": "Następujące wyrażenie kolumny jest spełnione: {values}",
1863+
"da": "Følgende kolonneudtryk gælder: {values}",
1864+
"sv": "Följande kolumnuttryck gäller: {values}",
1865+
"nb": "Følgende kolonneuttrykk gjelder: {values}",
1866+
"nl": "De volgende kolomuitdrukking geldt: {values}",
1867+
"fi": "Seuraava sarake-lauseke pätee: {values}",
1868+
"is": "Eftirfarandi dálktjáning gildir: {values}",
1869+
"ar": "التعبير التالي للعمود صحيح: {values}",
1870+
"hi": "निम्नलिखित स्तंभ अभिव्यक्ति सत्य है: {values}",
1871+
"el": "Η ακόλουθη έκφραση στήλης ισχύει: {values}",
1872+
},
18461873
"rows_distinct_all": {
18471874
"en": "All rows are distinct",
18481875
"fr": "Toutes les lignes sont distinctes",
@@ -2032,6 +2059,33 @@
20322059
"hi": "कॉलम <strong>{column_position}</strong> में {failure_rate} परीक्षण इकाई विफलताएँ",
20332060
"el": "{failure_rate} ΑΠΟΤΥΧΙΕΣ ΜΟΝΑΔΩΝ ΔΟΚΙΜΗΣ ΣΤΗ ΣΤΗΛΗ <strong>{column_position}</strong>",
20342061
},
2062+
"failure_rate_summary_no_column": {
2063+
"en": "{failure_rate} TEST UNIT FAILURES",
2064+
"fr": "{failure_rate} ÉCHECS D'UNITÉS DE TEST",
2065+
"de": "{failure_rate} TESTEINHEITENFEHLER",
2066+
"it": "{failure_rate} FALLIMENTI DI UNITÀ DI TEST",
2067+
"es": "{failure_rate} FALLOS DE UNIDAD DE PRUEBA",
2068+
"pt": "{failure_rate} FALHAS DE UNIDADE DE TESTE",
2069+
"ro": "{failure_rate} EȘECURI ALE UNITĂȚILOR DE TEST",
2070+
"tr": "{failure_rate} TEST BİRİMİ HATALARI",
2071+
"zh-Hans": "{failure_rate} 个测试单元失败",
2072+
"zh-Hant": "{failure_rate} 個測試單元失敗",
2073+
"ja": "{failure_rate} テストユニットの失敗",
2074+
"ko": "{failure_rate} 테스트 단위 실패",
2075+
"vi": "{failure_rate} LỖI ĐƠN VỊ KIỂM TRA",
2076+
"ru": "{failure_rate} СБОЕВ ТЕСТОВЫХ ЕДИНИЦ",
2077+
"cs": "{failure_rate} SELHÁNÍ TESTOVACÍCH JEDNOTEK",
2078+
"pl": "{failure_rate} NIEPOWODZEŃ JEDNOSTEK TESTOWYCH",
2079+
"da": "{failure_rate} TEST ENHED FEJL",
2080+
"sv": "{failure_rate} TESTENHETSFEL",
2081+
"nb": "{failure_rate} TESTENHETSFEIL",
2082+
"nl": "{failure_rate} TESTEENHEID FOUTEN",
2083+
"fi": "{failure_rate} TESTIYKSIKÖN VIRHEITÄ",
2084+
"is": "{failure_rate} PRÓFUNAREININGAR VILLUR",
2085+
"ar": "{failure_rate} فشل وحدات الاختبار",
2086+
"hi": "{failure_rate} परीक्षण इकाई विफलताएँ",
2087+
"el": "{failure_rate} ΑΠΟΤΥΧΙΕΣ ΜΟΝΑΔΩΝ ΔΟΚΙΜΗΣ",
2088+
},
20352089
"not_shown": {
20362090
"en": "(NOT SHOWN)",
20372091
"fr": "(NON AFFICHÉ)",

pointblank/validate.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15338,6 +15338,8 @@ def _step_report_row_based(
1533815338
text = STEP_REPORT_TEXT["column_is_null"][lang].format(column=column)
1533915339
elif assertion_type == "col_vals_not_null":
1534015340
text = STEP_REPORT_TEXT["column_is_not_null"][lang].format(column=column)
15341+
elif assertion_type == "col_vals_expr":
15342+
text = STEP_REPORT_TEXT["column_expr"][lang].format(values=values)
1534115343
elif assertion_type == "rows_complete":
1534215344
if column is None:
1534315345
text = STEP_REPORT_TEXT["rows_complete_all"][lang]
@@ -15384,10 +15386,14 @@ def _step_report_row_based(
1538415386
title = STEP_REPORT_TEXT["report_for_step_i"][lang].format(i=i) + " " + CHECK_MARK_SPAN
1538515387
assertion_header_text = STEP_REPORT_TEXT["assertion_header_text"][lang]
1538615388

15387-
success_stmt = STEP_REPORT_TEXT["success_statement"][lang].format(
15388-
n=n,
15389-
column_position=column_position,
15390-
)
15389+
# Use success_statement_no_column for col_vals_expr since it doesn't target a specific column
15390+
if assertion_type == "col_vals_expr":
15391+
success_stmt = STEP_REPORT_TEXT["success_statement_no_column"][lang].format(n=n)
15392+
else:
15393+
success_stmt = STEP_REPORT_TEXT["success_statement"][lang].format(
15394+
n=n,
15395+
column_position=column_position,
15396+
)
1539115397
preview_stmt = STEP_REPORT_TEXT["preview_statement"][lang]
1539215398

1539315399
details = (
@@ -15467,10 +15473,16 @@ def _step_report_row_based(
1546715473
assertion_header_text = STEP_REPORT_TEXT["assertion_header_text"][lang]
1546815474
failure_rate_metrics = f"<strong>{n_failed}</strong> / <strong>{n}</strong>"
1546915475

15470-
failure_rate_stmt = STEP_REPORT_TEXT["failure_rate_summary"][lang].format(
15471-
failure_rate=failure_rate_metrics,
15472-
column_position=column_position,
15473-
)
15476+
# Use failure_rate_summary_no_column for col_vals_expr since it doesn't target a specific column
15477+
if assertion_type == "col_vals_expr":
15478+
failure_rate_stmt = STEP_REPORT_TEXT["failure_rate_summary_no_column"][lang].format(
15479+
failure_rate=failure_rate_metrics
15480+
)
15481+
else:
15482+
failure_rate_stmt = STEP_REPORT_TEXT["failure_rate_summary"][lang].format(
15483+
failure_rate=failure_rate_metrics,
15484+
column_position=column_position,
15485+
)
1547415486

1547515487
if limit < extract_length:
1547615488
extract_length_resolved = limit

tests/test_validate.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4669,6 +4669,53 @@ def test_col_vals_expr_pandas_tbl():
46694669
)
46704670

46714671

4672+
def test_col_vals_expr_step_report():
4673+
"""Test that `get_step_report()` works for `col_vals_expr()` validations."""
4674+
4675+
# Polars test
4676+
df_pl = pl.DataFrame({"a": ["foo"], "b": ["bar"]})
4677+
validation_pl = Validate(data=df_pl).col_vals_expr(pl.col("a") == pl.col("b")).interrogate()
4678+
4679+
# This should not throw an exception (the original issue)
4680+
result_pl = validation_pl.get_step_report(1)
4681+
assert result_pl is not None
4682+
4683+
# Check that the expression is shown in the report
4684+
html_pl = result_pl.as_raw_html()
4685+
assert "The following column expression holds:" in html_pl
4686+
4687+
# Pandas test
4688+
df_pd = pd.DataFrame({"a": ["foo"], "b": ["bar"]})
4689+
validation_pd = Validate(data=df_pd).col_vals_expr(lambda df: df["a"] == df["b"]).interrogate()
4690+
4691+
# This should not throw an exception
4692+
result_pd = validation_pd.get_step_report(1)
4693+
assert result_pd is not None
4694+
4695+
4696+
def test_col_vals_expr_display_text_formatting():
4697+
"""Test that `col_vals_expr()` step reports don't show 'IN COLUMN None' text."""
4698+
4699+
# Create test data where expression will fail for some rows
4700+
df = pl.DataFrame(
4701+
{
4702+
"a": [1, 2, 3, 4, 5, 6],
4703+
"b": [2, 3, 4, 5, 6, 7],
4704+
}
4705+
)
4706+
4707+
# Test failing case, which should not show "IN COLUMN None"
4708+
validator_fail = Validate(df).col_vals_expr(pl.col("a") > pl.col("b")).interrogate()
4709+
report_html_fail = validator_fail.get_step_report(i=1).as_raw_html()
4710+
4711+
# Main assertions: no column references for expression validations
4712+
assert "IN COLUMN None" not in report_html_fail
4713+
assert "IN COLUMN" not in report_html_fail
4714+
4715+
# Verify it has the basic failure structure
4716+
assert "TEST UNIT FAILURES" in report_html_fail
4717+
4718+
46724719
@pytest.mark.parametrize("tbl_fixture", TBL_LIST)
46734720
def test_rows_distinct(request, tbl_fixture):
46744721
tbl = request.getfixturevalue(tbl_fixture)

0 commit comments

Comments
 (0)