# Contributing ## Local setup ```bash git clone https://github.com/ChunSikPark/TeamOverbyeWeather.git cd TeamOverbyeWeather pip install -e package/ # the SDK, editable pip install -r docs/requirements.txt ``` Run the backend locally if you are changing it: ```bash cd backend pip install -r requirements.txt uvicorn main:app --reload ``` Point the client at it: ```python client = WeatherClient(base_url="http://localhost:8000") ``` The backend needs `GDRIVE_CREDENTIALS_JSON_CONTENT` set to a service-account JSON with Viewer access on the data folders. Without it the catalog will be empty but the app still starts. ## Building the docs ```bash sphinx-build -b html docs docs/_build/html ``` Open `docs/_build/html/index.html`. Pushing to `main` rebuilds and publishes the site to via `.github/workflows/docs.yml`. A `.readthedocs.yaml` is also checked in if you would rather host on Read the Docs, which adds versioned docs and PDF output. ## Adding a data source Five places, in this order: 1. `backend/catalog.py` — add the folder id to `_DEFAULT_FOLDERS`, write a `_build_()`, call it from `build_catalog()`, add the key to `_empty_catalog()` 2. `backend/download.py` — add `_SOURCE_LOOKUP` and `_FILENAME_PATTERNS` entries 3. `package/TeamOverbyeWeather/registry.py` — add to `_API_KEYS` and `_TYPES` 4. `frontend/main.js` — add to `TYPE_DEFS` and `getApiSourceKey()` 5. `docs/guides/catalog.md` — document the new type and its date-key format Check the real filenames before writing a regex: ```bash curl "/api/debug/folder?folder_id=&limit=50" ``` Filename conventions vary between folders more than you would expect. Guessing wastes time; the debug endpoint takes seconds. ## Things that will bite you **`pww_io.py` exists twice.** `backend/pww_io.py` is the original; `package/TeamOverbyeWeather/pww_io.py` is a copy. Change one, copy to the other. **Bounding box ordering is `(lat_max, lon_min, lat_min, lon_max)`** everywhere — north, west, south, east. Not the ordering most GIS libraries use. **The longitude axis descends.** Index 0 is `lon_max`. Latitude ascends. **Always `.copy()` after slicing** before writing a PWW. Numpy slices are views. **`255` is the missing-data sentinel**, not a value. **Times are OLE Automation days in the file, Unix epoch seconds in the API.** `crop_to_timerange` takes epoch seconds; `header["date_min"]` is OLE days. Do not pass one where the other is expected — they are both floats, so nothing will stop you, and the result is a nonsensical date rather than an error. **HRRR history regexes are loose on the extension** on purpose. Older archives are `.pww.gz`; do not tighten to `\.zip$`. **Do not reintroduce `get_file_url`** in `download.py`. Fetching large Drive files by URL hits a virus-scan interstitial and silently returns HTML instead of data. Everything goes through the service account. ## Testing a change to the crop path Compare server output against local output — they should agree exactly: ```python from TeamOverbyeWeather import WeatherClient, pww_io, localcrop client = WeatherClient(show_progress=False) bbox = (36.5, -106.6, 25.8, -93.5) server = client.download("hrrr", type="current", dates="2026-07-21", region="TX", dest="./tmp")[0] raw = client._plain("hrrr_history_current", "2026-07-21", __import__("pathlib").Path("./tmp"), False) local = localcrop.crop_file(raw, "./tmp/local.pww", bbox=bbox) for p in (server, local): _, _, arr = pww_io.read_pww(open(p, "rb").read()) print(p.name, arr.shape) ``` Both must report 96 time steps for a 15-minute day. A result of 24 means the four quarter files were not stitched. ## Publishing **Package** — bump `version` in `package/pyproject.toml` and `__version__` in `__init__.py` (keep them equal), then build and upload: ```bash cd package rm -rf dist build python -m build python -m twine check dist/* python -m twine upload dist/* ``` A version number on PyPI can never be reused, so run `twine check` first and confirm the metadata (especially `[project.urls]`) is right before uploading. Verify afterwards in a clean environment: ```bash python -m venv /tmp/check && /tmp/check/bin/pip install TeamOverbyeWeather ``` **Backend and frontend** — push to `main`; both auto-deploy. Refresh the catalog afterwards: ```bash curl /api/catalog/refresh ``` ## Style Match the surrounding code. Google-style docstrings — they are what the API reference is generated from, so a function without one shows up bare in the docs.