Spaces:
Configuration error
Configuration error
| """Kaggle PaySim dataset download script (SETUP-02). | |
| Downloads the `ealaxi/paysim1` dataset from Kaggle into `data/` and | |
| unzips it so the PaySim CSV lands directly under `data/`. | |
| Note: the dataset originally lived at `ntnu-testimon/paysim1`; that slug now | |
| returns HTTP 403 (dataset moved/retired under the old owner). `ealaxi/paysim1` | |
| is the current live mirror of the same PaySim simulation output (same | |
| ~6.36M-row schema: step, type, amount, nameOrig/nameDest, balances, isFraud, | |
| isFlaggedFraud). | |
| Reads `KAGGLE_USERNAME`/`KAGGLE_KEY` from the environment (via `.env`, | |
| loaded with python-dotenv) and fails loud -- naming the missing variable(s) | |
| -- BEFORE attempting any network call or importing the `kaggle` package. | |
| This check must run before `import kaggle`: the installed `kaggle` client | |
| authenticates eagerly as a side effect of importing the package (any | |
| submodule import triggers it), which would otherwise surface its own, | |
| less specific error before our validation ever runs. | |
| Idempotent: if a PaySim CSV already exists under `data/`, the download is | |
| skipped and the existing path is reported. | |
| Usage: | |
| python training/fetch_data.py | |
| """ | |
| from __future__ import annotations | |
| import sys | |
| from pathlib import Path | |
| from dotenv import load_dotenv | |
| DATASET = "ealaxi/paysim1" | |
| DATA_DIR = Path(__file__).resolve().parent.parent / "data" | |
| class FetchDataError(RuntimeError): | |
| """Raised when the PaySim dataset cannot be fetched. | |
| Messages never include credential values -- only variable names. | |
| """ | |
| def _require_kaggle_credentials() -> None: | |
| """Fail loud, naming any missing/empty Kaggle credential env var. | |
| Runs before any network call and before `kaggle` is imported. | |
| """ | |
| import os | |
| missing = [ | |
| name | |
| for name in ("KAGGLE_USERNAME", "KAGGLE_KEY") | |
| if not os.environ.get(name, "").strip() | |
| ] | |
| if missing: | |
| raise FetchDataError( | |
| "Missing required Kaggle credential(s) in the environment: " | |
| f"{', '.join(missing)}. Set them in .env (see README) before " | |
| "running training/fetch_data.py. No network call was made." | |
| ) | |
| def _existing_csv() -> Path | None: | |
| if not DATA_DIR.exists(): | |
| return None | |
| csvs = sorted(DATA_DIR.glob("*.csv")) | |
| return csvs[0] if csvs else None | |
| def main() -> Path: | |
| load_dotenv() | |
| _require_kaggle_credentials() | |
| existing = _existing_csv() | |
| if existing is not None: | |
| print(f"PaySim CSV already present, skipping download: {existing}") | |
| return existing | |
| # Imported lazily, after credential validation above: importing the | |
| # `kaggle` package (any submodule) triggers its own eager | |
| # authentication check as a side effect of import. | |
| from kaggle.api.kaggle_api_extended import KaggleApi | |
| from requests.exceptions import HTTPError | |
| DATA_DIR.mkdir(parents=True, exist_ok=True) | |
| try: | |
| api = KaggleApi() | |
| api.authenticate() | |
| print(f"Downloading {DATASET} into {DATA_DIR} ...") | |
| api.dataset_download_files(DATASET, path=str(DATA_DIR), unzip=True) | |
| except HTTPError as exc: | |
| status = exc.response.status_code if exc.response is not None else "unknown" | |
| raise FetchDataError( | |
| f"Kaggle API request failed (HTTP {status}) while downloading " | |
| f"'{DATASET}'. This is a Kaggle-side authorization/response " | |
| "issue, not a missing-credential problem -- KAGGLE_USERNAME/" | |
| "KAGGLE_KEY were present and accepted by the auth step. " | |
| "Verify the API token is current (regenerate at " | |
| "https://www.kaggle.com/settings/api if needed) and that the " | |
| "account has access to this dataset." | |
| ) from exc | |
| csv_path = _existing_csv() | |
| if csv_path is None: | |
| raise FetchDataError( | |
| f"Download completed but no .csv file was found under {DATA_DIR}. " | |
| "Check the Kaggle dataset contents." | |
| ) | |
| print(f"PaySim CSV available at: {csv_path}") | |
| return csv_path | |
| if __name__ == "__main__": | |
| try: | |
| main() | |
| except FetchDataError as exc: | |
| print(f"ERROR: {exc}", file=sys.stderr) | |
| sys.exit(1) | |