Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .claude/hooks/format.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
"""PostToolUse hook: format files Claude edits.

.py -> ruff format (config in backend/pyproject.toml)
Expand Down
3 changes: 0 additions & 3 deletions backend/api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# ruff: noqa: F401


from .request_models import (
DPSeriesRequest,
FilterRequest,
Expand Down
4 changes: 3 additions & 1 deletion backend/api/models/request_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

from pydantic import BaseModel, model_validator

MAX_YEAR = datetime.now().year - 2
from query.clock import EASTERN_STD_TIME

MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 2


class RangeFilter(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion backend/api/routes/get_routes/get_wholedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async def read_flood_data():

# VT Municipalities Endpoint
@router.get("/data/vermont/municipalities")
async def read_municipalities_data():
def read_municipalities_data():
with open(
DATA_DIR / "vermont" / "municipalities.json", "r", encoding="utf-8"
) as file:
Expand Down
11 changes: 6 additions & 5 deletions backend/data_collection/acs5.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

from data_collection.base import ALL_GEOS
from data_collection.census import tidy_census
from query.clock import EASTERN_STD_TIME

# Define API key through the .env file
API_KEY = os.environ.get("CENSUS_API_KEY")
Expand All @@ -36,7 +37,7 @@
STORAGE_LOCATION = "Data/Census/ACS_5"
ID_VARS = ["year", "geo_type", "table", "NAME", "state", "county"]

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand Down Expand Up @@ -73,7 +74,7 @@ def fetch_table(year, table, for_clause, in_clause):
df["year"] = year
df["table"] = table
return df
except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
print(f" SKIP {year} / {table} / {for_clause}: {e}")
return None

Expand Down Expand Up @@ -133,7 +134,7 @@ def run_acs5_scrape(years: range = YEARS, geos: list = GEOS, append: bool = Fals
tidy_year["table"] = table
tidy_frames.append(tidy_year)

except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
Comment thread
marobinette marked this conversation as resolved.
print(f" SKIP tidy {year} / {table}: {e}")

if tidy_frames:
Expand All @@ -150,11 +151,11 @@ def run_acs5_scrape(years: range = YEARS, geos: list = GEOS, append: bool = Fals
def merge_tidy_tables():
"""Merge the per-table tidy parquets into one combined file."""
tidy_frames = []
for table, label in TABLES.items():
for label in TABLES.values():
path = f"{STORAGE_LOCATION}/vt_acs5_{label}_data_tidy.parquet"
try:
tidy_frames.append(pd.read_parquet(path))
except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
print(f" SKIP {path}: {e}")

if tidy_frames:
Expand Down
15 changes: 10 additions & 5 deletions backend/data_collection/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import requests

from data_collection.census import split_name_col
from query.clock import EASTERN_STD_TIME

# Define API key through the .env file
API_KEY = os.environ.get("CENSUS_API_KEY")
Expand All @@ -52,7 +53,7 @@
GEOS = [(k, *v) for k, v in ALL_GEOS.items()]


MAX_YEAR = datetime.now().year - 2
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 2

# ---------------------------------------------------------------------------
# Data structures
Expand Down Expand Up @@ -101,7 +102,7 @@ def fetch(
if c[0] == "B":
df[c] = pd.to_numeric(df[c], errors="coerce")
return df
except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
print(f" SKIP {year} / {for_clause}: {e}")
return None

Expand All @@ -114,9 +115,13 @@ def fetch(
def pct(val: float, total: float) -> float | None:
try:
if total and total > 0:
return round(val / total * 100, 1)
except Exception:
pass
return round((val / total) * 100, 1)
except OverflowError:
print(f"OverflowError computing pct({val}, {total})")
except FloatingPointError:
print(f"FloatingPointError computing pct({val}, {total})")
except ValueError:
print(f"ValueError computing pct({val}, {total})")
return None


Expand Down
5 changes: 3 additions & 2 deletions backend/data_collection/cdc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
Fetches Vermont CDC data from the CDC SODA API (In "Open Data Format")
"""

import pandas as pd
from io import BytesIO

import geopandas as gpd
import pandas as pd
import requests
from io import BytesIO

# ---------------------------------------------------------------------------
# API endpoints
Expand Down
3 changes: 2 additions & 1 deletion backend/data_collection/demographics.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import pandas as pd

from data_collection.base import ALL_GEOS, VarGroup, run_acs_b_scrape
from query.clock import EASTERN_STD_TIME

# ---------------------------------------------------------------------------
# Age band definitions: (label, male_suffix_range, female_suffix_range)
Expand All @@ -29,7 +30,7 @@
("75 Plus", range(23, 26), range(47, 50)),
]

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand Down
3 changes: 2 additions & 1 deletion backend/data_collection/economic.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import pandas as pd

from data_collection.base import ALL_GEOS, VarGroup, run_acs_b_scrape
from query.clock import EASTERN_STD_TIME

SL = "Labor Force"
SI = "Income"
Expand Down Expand Up @@ -86,7 +87,7 @@
"B19301": ["B19301_001E"],
}

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand Down
3 changes: 2 additions & 1 deletion backend/data_collection/education.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pandas as pd

from data_collection.base import ALL_GEOS, VarGroup, run_acs_b_scrape
from query.clock import EASTERN_STD_TIME

TOTAL = "B15003_001E"
S = "Educational Attainment"
Expand All @@ -41,7 +42,7 @@
"B15003": [TOTAL] + [f"B15003_{str(i).zfill(3)}E" for i in range(2, 26)],
}

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand Down
3 changes: 2 additions & 1 deletion backend/data_collection/housing.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import pandas as pd

from data_collection.base import ALL_GEOS, VarGroup, run_acs_b_scrape
from query.clock import EASTERN_STD_TIME

S = "Housing"

Expand All @@ -45,7 +46,7 @@
"B25077": ["B25077_001E"],
}

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand Down
6 changes: 4 additions & 2 deletions backend/data_collection/qcew.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import pandas as pd
import requests

from query.clock import EASTERN_STD_TIME

# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -89,7 +91,7 @@
BASE_URL = "https://data.bls.gov/cew/data/api/{year}/{q}/area/{fips}.csv"
QUARTERS = [1, 2, 3, 4]

MAX_YEAR = datetime.now().year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1

YEARS = range(2009, MAX_YEAR)

Expand All @@ -107,7 +109,7 @@ def fetch_quarter(year: int, quarter: int, area_fips: str) -> pd.DataFrame | Non
df = pd.read_csv(StringIO(r.text), dtype=str)
df.columns = df.columns.str.strip()
return df
except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
print(f" SKIP {year}Q{quarter} / {area_fips}: {e}")
return None

Expand Down
2 changes: 1 addition & 1 deletion backend/query/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}
_NAME_TO_MODULE = {n: m for m, names in _EXPORTS.items() for n in names}

__all__ = sorted(_NAME_TO_MODULE)
__all__ = sorted(_NAME_TO_MODULE) # noqa: PLE0605


def __getattr__(name: str):
Expand Down
5 changes: 5 additions & 0 deletions backend/query/clock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from datetime import timedelta, timezone

# Fixed UTC-5 (EST, no DST): MAX_YEAR only needs the year, and the year
# boundary always falls in winter.
EASTERN_STD_TIME = timezone(timedelta(hours=-5))
3 changes: 2 additions & 1 deletion backend/query/comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from api.models import FilterSource
from query.cdc import build_cmap, to_rgba
from query.clock import EASTERN_STD_TIME
from query.production_db import get_db
from query.sql_render import sql_filter_block

Expand All @@ -35,7 +36,7 @@
ACS_SENTINEL = -666666666
# Vintages this recent aren't final yet (ACS5/CDC Places both lag ~2 years),
# so the newest year at or before this is the one used per table.
MAX_YEAR = datetime.now().year - 2
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 2


class NoDataError(ValueError):
Expand Down
8 changes: 6 additions & 2 deletions backend/query/core_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,19 @@ def filter_tree(
tree_labels: list[str],
table: str,
db=DB,
rangemap: dict = {},
badgemap: dict = {},
rangemap: dict | None = None,
badgemap: dict | None = None,
) -> FilterResponse:
"""
Info for cascading filter UI.
TODO: Right now, we pass in separate db.
When we consolidate all SQL to one source/place, we'll update this to be just one.
TODO: update to not pass in tree_labels but just use from schema
"""
if rangemap is None:
rangemap = {}
if badgemap is None:
badgemap = {}
cols = [colmap.get(label) for label in tree_labels]
select = ", ".join(f'"{col}"' for col in cols)
order = ", ".join(str(i + 1) for i in range(len(cols)))
Expand Down
2 changes: 1 addition & 1 deletion backend/run_data_cleaning.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def run_master_clean(script_name: str | None = None):
cleaner.main(con)
print(f"Completed {name}")

except Exception as e:
except Exception as e: # noqa: BLE001 -- isolate any cleaner failure so the rest still run
failed.append(name)
print(f"FAILED {name}: {e}")

Expand Down
6 changes: 3 additions & 3 deletions backend/run_data_collection.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import argparse
from datetime import datetime, timedelta, timezone
from datetime import datetime

from data_collection import (
acs5,
Expand All @@ -20,6 +20,7 @@
zoning,
)
from lake_build import get_connection, insert_year, replace_table
from query.clock import EASTERN_STD_TIME

YEARLY_SCRAPERS = [
acs5,
Expand All @@ -43,8 +44,7 @@
zoning,
]

eastern_std_time = timezone(timedelta(hours=5))
MAX_YEAR = datetime.now(eastern_std_time).year - 1
MAX_YEAR = datetime.now(EASTERN_STD_TIME).year - 1


def run_scraper(
Expand Down
1 change: 0 additions & 1 deletion backend/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import pandas as pd
import pytest

from data_collection_OLD.base import VarGroup, compute_tidy_generic, pct

# ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/test_lake.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def inspect_schema(schema: str) -> None:

print(f"Years: {years[0]} → {years[1]} ({years[2]} distinct)")

except Exception as e:
except Exception as e: # noqa: BLE001 -- skip and keep the run going
print(f"Could not inspect years: {e}")


Expand Down
Loading
Loading