Data Validation Expectations
skyulf.profiling.expect is a lightweight, dependency-free data-validation
helper — a tiny subset of what Great Expectations offers, but with zero extra
dependencies. Each expect_* function checks a single condition and raises
ExpectationError with a precise
message when the condition is violated.
It is engine-agnostic: Pandas frames are used directly; raw and wrapped
Polars frames stay native for simple predicates. Boolean range checks and
other frames exposing to_pandas() use Pandas conversion.
When to use it
These are manual assertions — they are not wired into profiling or CI automatically. You call them yourself in two main places:
- In tests / CI — guard a dataset contract so a bad upstream change fails the build.
- In a pipeline — assert preconditions before an expensive step, so you get a clear error instead of a deep traceback later.
Available expectations
| Function | Checks |
|---|---|
expect_columns_exist(df, columns) |
Every name in columns is present. |
expect_no_nulls(df, columns=None, *, allow_empty=False) |
Given columns (default: all) have no nulls. |
expect_value_range(df, column, *, minimum=None, maximum=None, inclusive=True, allow_empty=False) |
All non-null values fall within the optional bounds. |
expect_unique(df, columns, *, allow_empty=False) |
The combination of columns has no duplicate rows. |
Empty datasets
The null, range and uniqueness checks require at least one row by default.
An ingestion that unexpectedly returns zero rows therefore raises
ExpectationError, even if the expected columns are present.
If empty partitions are valid in your workflow, explicitly opt in on each check:
import pandas as pd
from skyulf import expect_no_nulls, expect_unique, expect_value_range
empty = pd.DataFrame({"age": pd.Series(dtype="float64")})
expect_no_nulls(empty, ["age"], allow_empty=True)
expect_value_range(empty, "age", minimum=0, maximum=120, allow_empty=True)
expect_unique(empty, ["age"], allow_empty=True)
Previously these checks accepted empty frames automatically; existing callers
that rely on that behavior must add allow_empty=True. Requested columns must
still exist. expect_columns_exist only checks the schema and accepts zero rows.
Range checks continue to ignore null values, including an all-null column in a
frame that has rows; combine them with expect_no_nulls when nulls are invalid.
Example: a dataset contract in CI
import pandas as pd
from skyulf import (
ExpectationError,
expect_columns_exist,
expect_no_nulls,
expect_unique,
expect_value_range,
)
def validate_customers(df: pd.DataFrame) -> None:
"""Raises ExpectationError if the customers frame breaks its contract."""
expect_columns_exist(df, ["customer_id", "age", "signup_date"])
expect_unique(df, ["customer_id"])
expect_no_nulls(df, ["customer_id", "signup_date"])
expect_value_range(df, "age", minimum=0, maximum=120)
Wire it into a test so CI enforces it:
def test_customers_contract():
df = pd.read_parquet("data/customers.parquet")
validate_customers(df) # raises ExpectationError on violation → test fails
Example: a pipeline guard
from skyulf import expect_no_nulls
def run(df):
# Fail fast with a clear message before an expensive fit.
expect_no_nulls(df, ["target"])
...
API reference
skyulf.profiling.expect
Lightweight data-validation expectations (no Great Expectations dependency).
Each expect_* function checks a single condition on a DataFrame and raises
:class:ExpectationError with a precise message when the condition is violated.
Pure-Python and engine-agnostic: Pandas frames are used directly; raw and wrapped
Polars frames stay native for simple predicates; other frames exposing
to_pandas() fall back to Pandas conversion.
Example
import pandas as pd from skyulf.profiling.expect import expect_no_nulls, expect_value_range df = pd.DataFrame({"age": [21, 35, 40]}) expect_no_nulls(df) expect_value_range(df, "age", minimum=0, maximum=120)
ExpectationError
Bases: ValueError
Raised when a data-validation expectation is not met.
Source code in skyulf-core/skyulf/profiling/expect.py
34 35 | |
expect_columns_exist(df, columns)
Assert that every name in columns is present in df.
Source code in skyulf-core/skyulf/profiling/expect.py
92 93 94 95 96 97 98 | |
expect_no_nulls(df, columns=None, *, allow_empty=False)
Assert that the given columns (default: all) contain no null values.
Zero-row frames fail unless allow_empty=True is explicitly requested.
Source code in skyulf-core/skyulf/profiling/expect.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
expect_unique(df, columns, *, allow_empty=False)
Assert that the combination of columns has no duplicate rows.
Zero-row frames fail unless allow_empty=True is explicitly requested.
Source code in skyulf-core/skyulf/profiling/expect.py
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | |
expect_value_range(df, column, *, minimum=None, maximum=None, inclusive=True, allow_empty=False)
Assert that all values in column fall within [minimum, maximum].
minimum / maximum are optional (open-ended on the unset side).
Null values are ignored. Set inclusive=False for a strict comparison.
Zero-row frames fail unless allow_empty=True is explicitly requested;
a frame containing only null values still has rows and passes this check.
Source code in skyulf-core/skyulf/profiling/expect.py
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |