Spaces:
Sleeping
Sleeping
| """ | |
| 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 |