Spaces:
Sleeping
Sleeping
File size: 3,071 Bytes
b336134 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | """
Pre-execution validator.
Checks that a resolved intent is compatible with the dataframe schema
before any data gets touched. This is the safety net that stops
"increase the name column" from ever reaching Polars.
"""
from __future__ import annotations
from typing import Optional
import polars as pl
from config import DATA_DIR
from core.column_registry import column_registry
# Operations that REQUIRE numeric dtype on the target column
NUMERIC_ONLY_OPS = {"increase", "decrease", "sum", "average", "min", "max"}
def get_schema(session_id: str) -> Optional[pl.Schema]:
"""Read just the Parquet metadata to get column dtypes β no data loaded."""
import os
from services.session_manager import session_manager
pq_path = session_manager.get_filepath(session_id)
if not os.path.exists(pq_path):
return None
try:
schema = pl.scan_parquet(pq_path).collect_schema()
return schema
except Exception:
return None
def validate_intent(session_id: str, intent: dict) -> Optional[str]:
"""Return an error string if the intent is invalid, else ``None``."""
schema = get_schema(session_id)
if schema is None:
return "Session ka data nahi mila β dobara upload karo"
col = intent.get("column")
op = intent.get("operation", "")
# ββ Column existence (skip for operations that don't target a column) ββ
no_column_ops = {"remove_duplicates"}
if op not in no_column_ops and col:
if col not in schema:
return f"'{col}' column nahi hai file mein"
# ββ Numeric dtype check ββββββββββββββββββββββββββββββββββββββββββββ
if op in NUMERIC_ONLY_OPS and col:
dtype = schema[col]
if dtype not in (pl.Float64, pl.Int64, pl.Int32, pl.Float32, pl.UInt64, pl.UInt32):
return f"'{col}' numeric column nahi hai ({dtype}), ye operation apply nahi ho sakta"
# ββ Filter: need condition + value ββββββββββββββββββββββββββββββββββ
if op == "filter":
if intent.get("condition") is None or intent.get("filter_value") is None:
return "Filter ke liye condition aur value dono chahiye, jaise: 'salary > 50000 dikhao'"
# ββ Find & Replace: need old + new ββββββββββββββββββββββββββββββββββ
if op == "find_replace":
if not intent.get("old_value") or not intent.get("new_value"):
return "Find & Replace ke liye purana aur naya value dono chahiye, jaise: 'Active ko Inactive se badlo'"
# ββ Rename: need new_name βββββββββββββββββββββββββββββββββββββββββββ
if op == "rename_column":
if not intent.get("new_name"):
return "Rename ke liye naya naam chahiye, jaise: 'name ko full_name rename karo'"
return None # All good |