ProvenPin Install

pandas + Pandera DataFrame schema validation: working versions (tested 2026-10-15)

Validate pandas DataFrames with Pandera DataFrameModel schemas: dtypes, coercion, value checks, custom dataframe checks and lazy error reports.

passed3 passed · 0 failed2026-10-15 13:32 UTC
Status
passed
Last passed
2026-10-15 13:32 UTC
Tests
3 / 3
Language
Python
Runtime
Python 3.13.16
pinned versions3
pandas@3.0.6pandera@0.34.1pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38742087302

The code

Exactly the files that passed. Your agent can pull them with get_recipe("pandas-pandera-validation") (install), or see them on GitHub.

requirements.txt
pandas==3.0.6
pandera==0.34.1
pytest==9.1.1
schemas.py
import pandas as pd
import pandera.pandas as pa
from pandera.typing.pandas import Series

class Orders(pa.DataFrameModel):
    order_id: Series[int] = pa.Field(unique=True, ge=1)
    email: Series[str] = pa.Field(str_matches=r"^[^@]+@[^@]+$")
    quantity: Series[int] = pa.Field(ge=1, le=1000)
    unit_price: Series[float] = pa.Field(gt=0)
    status: Series[str] = pa.Field(isin=["new", "paid", "shipped"])

    class Config:
        coerce = True   # "3" -> 3, etc.
        strict = True   # unknown columns are errors

    @pa.dataframe_check
    def shipped_orders_are_small(cls, df: pd.DataFrame) -> Series[bool]:
        return ~((df["status"] == "shipped") & (df["quantity"] > 500))

def clean_orders(df: pd.DataFrame) -> pd.DataFrame:
    return Orders.validate(df, lazy=True)  # lazy=True collects every failure
tests/test_schemas.py
import pandas as pd
import pandera.errors as pe
import pytest
from schemas import clean_orders

def frame(**over):
    base = {"order_id": [1, 2], "email": ["[email protected]", "[email protected]"], "quantity": ["3", "4"], "unit_price": [9.5, 1.0], "status": ["new", "paid"]}
    base.update(over)
    return pd.DataFrame(base)

def test_valid_and_coerced():
    out = clean_orders(frame())
    assert out["quantity"].tolist() == [3, 4]
    assert str(out["quantity"].dtype).startswith("int")

def test_lazy_collects_all_errors():
    with pytest.raises(pe.SchemaErrors) as e:
        clean_orders(frame(email=["bad", "[email protected]"], status=["new", "lost"], order_id=[1, 1]))
    cols = set(e.value.failure_cases["column"].dropna())
    assert {"email", "status", "order_id"} <= cols

def test_strict_and_dataframe_check():
    with pytest.raises(pe.SchemaErrors):
        clean_orders(frame(extra=[1, 2]))
    with pytest.raises(pe.SchemaErrors):
        clean_orders(frame(status=["shipped", "new"], quantity=[600, 1]))
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.