Skip to content
Draft
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ gha-creds-*.json
## vscode settings
/.vscode
*.db.init.lock

# Hypothesis example database
.hypothesis/
1 change: 1 addition & 0 deletions changelog.d/remove-v2-household-list.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed `GET /v2/households`, which listed stored households without a credential. Creating a household and reading one by ID are unchanged.
3 changes: 1 addition & 2 deletions docs/engineering/migration-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Generated from `policyengine_api/migration_registry.py` and `tests/contract/regi
| --- | ---: |
| route group count | 9 |
| workflow count | 16 |
| request count | 89 |
| request count | 88 |
| db entity count | 6 |
| sim flow count | 3 |

Expand Down Expand Up @@ -98,7 +98,6 @@ Generated from `policyengine_api/migration_registry.py` and `tests/contract/regi
| --- | --- | ---: | --- | --- | --- |
| `POST` | `/v2/households?country_id=us` | 201 | `household` | none | `status`, `message`, `result.item.id`, `result.item.country_id`, `result.item.default_year`, `result.item.household_data`, `result.item.created_at`, `result.item.updated_at` |
| `GET` | `/v2/households/{household_id}?country_id=us` | 200 | `household` | none | `status`, `message`, `result.item.id`, `result.item.country_id`, `result.item.default_year`, `result.item.household_data`, `result.item.created_at`, `result.item.updated_at` |
| `GET` | `/v2/households?country_id=us` | 200 | `household` | none | `status`, `message`, `result.items`, `result.offset`, `result.limit`, `result.has_more` |

### `user_household_associations_v2`

Expand Down
17 changes: 1 addition & 16 deletions docs/generated/migration_contracts.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"metadata": {
"db_entity_count": 6,
"request_count": 89,
"request_count": 88,
"route_group_count": 9,
"sim_flow_count": 3,
"workflow_count": 16
Expand Down Expand Up @@ -518,21 +518,6 @@
"result.item.created_at",
"result.item.updated_at"
]
},
{
"expected_status": 200,
"headers": [],
"method": "GET",
"path": "/v2/households?country_id=us",
"route_group": "household",
"stable_response_fields": [
"status",
"message",
"result.items",
"result.offset",
"result.limit",
"result.has_more"
]
}
]
},
Expand Down
12 changes: 0 additions & 12 deletions policyengine_api/fastapi_routes/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
LegacyReferenceChecker,
)
from policyengine_api.services.v2.households.types import (
HouseholdPage,
HouseholdRead,
NativeHouseholdCreation,
NativeHouseholdCreationInput,
Expand Down Expand Up @@ -371,17 +370,6 @@ def get_household(
"""
...

def list_households(
self,
*,
country_id: str,
default_year: int | None,
offset: int,
limit: int,
) -> HouseholdPage:
"""Return a page of the country's households, optionally of one default year."""
...


class V2UserPolicyResourceService(Protocol):
"""Route-independent user-policy operations for one request."""
Expand Down
28 changes: 0 additions & 28 deletions policyengine_api/fastapi_routes/v2/households/response_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

if TYPE_CHECKING:
from policyengine_api.services.v2.households.types import (
HouseholdPage,
HouseholdRead,
)

Expand Down Expand Up @@ -57,29 +56,6 @@ class HouseholdDetailResult(StrictHouseholdAPIModel):
item: HouseholdItem


class HouseholdPageResult(StrictHouseholdAPIModel):
"""One page of households, oldest first.

``offset`` and ``limit`` echo the request; when ``has_more`` is true, ask
for the next page with ``offset + limit``.
"""

items: list[HouseholdItem]
offset: int
limit: int
has_more: bool

@classmethod
def from_page(cls, page: HouseholdPage) -> HouseholdPageResult:
"""Build the response page from a service page, converting each item."""
return cls(
items=[HouseholdItem.from_read(item) for item in page.items],
offset=page.offset,
limit=page.limit,
has_more=page.has_more,
)


ResultT = TypeVar("ResultT")


Expand All @@ -95,10 +71,6 @@ class HouseholdDetailResponse(HouseholdSuccessResponse[HouseholdDetailResult]):
"""Success response holding one household."""


class HouseholdPageResponse(HouseholdSuccessResponse[HouseholdPageResult]):
"""Success response holding one page of households."""


HOUSEHOLD_ERROR_RESPONSES: dict[int | str, dict[str, Any]] = {
400: {
"model": V2ErrorResponse,
Expand Down
25 changes: 0 additions & 25 deletions policyengine_api/fastapi_routes/v2/households/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@
HouseholdDetailResponse,
HouseholdDetailResult,
HouseholdItem,
HouseholdPageResponse,
HouseholdPageResult,
)
from policyengine_api.query_parameters import (
HouseholdCollectionQuery,
HouseholdCreateQuery,
HouseholdDetailQuery,
)
Expand All @@ -59,9 +56,6 @@
HouseholdDetailQueryDependency = Annotated[
HouseholdDetailQuery, Depends(query_dependency(HouseholdDetailQuery))
]
HouseholdCollectionQueryDependency = Annotated[
HouseholdCollectionQuery, Depends(query_dependency(HouseholdCollectionQuery))
]


async def enforce_household_request_size(request: Request) -> None:
Expand Down Expand Up @@ -182,23 +176,4 @@ def read() -> HouseholdDetailResponse:

return _household_operation(read)

@router.get(
"/households",
response_model=HouseholdPageResponse,
summary="List immutable households",
)
def get_households(
query: HouseholdCollectionQueryDependency,
) -> HouseholdPageResponse | JSONResponse:
def read() -> HouseholdPageResponse:
page = service_factory().list_households(
country_id=query.country_id,
default_year=query.default_year,
offset=query.offset,
limit=query.limit,
)
return HouseholdPageResponse(result=HouseholdPageResult.from_page(page))

return _household_operation(read)

return router
6 changes: 0 additions & 6 deletions policyengine_api/query_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,6 @@ class HouseholdDetailQuery(CountryQuery):
"""Query contract for country-scoped household detail reads."""


class HouseholdCollectionQuery(CountryQuery, PaginationQuery):
"""Query contract for an exact-filtered household collection."""

default_year: DefaultYear | None = None


class UserHouseholdCreateQuery(CountryQuery):
"""Query contract for native user-household association creation."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from typing import TYPE_CHECKING

from sqlmodel import Session, col, select
from sqlmodel import Session, select

from policyengine_api.data.v2.models import Household, LegacyHouseholdMapping

Expand Down Expand Up @@ -36,30 +36,6 @@ def read_household_row(
).one_or_none()


def read_household_rows(
session: Session,
*,
country_id: str,
default_year: int | None,
offset: int,
limit: int,
) -> list[Household]:
"""Return up to ``limit + 1`` households in creation order, starting at ``offset``.

The extra row lets the caller report whether another page exists.
"""
statement = select(Household).where(Household.country_id == country_id)
if default_year is not None:
statement = statement.where(Household.default_year == default_year)
return list(
session.exec(
statement.order_by(col(Household.created_at), col(Household.id))
.offset(offset)
.limit(limit + 1)
).all()
)


def read_legacy_household_mapping(
session: Session,
*,
Expand Down
43 changes: 0 additions & 43 deletions policyengine_api/services/v2/households/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@
from policyengine_api.services.v2.households.database_connectors.reads import (
read_household_by_content_identity,
read_household_row,
read_household_rows,
read_legacy_household_mapping,
)
from policyengine_api.services.v2.households.transformations import (
LEGACY_HOUSEHOLD_FINGERPRINT_VERSION,
canonical_household_document,
canonicalize_household,
household_page,
household_read,
legacy_household_fingerprint,
stored_household_creation_input,
Expand All @@ -28,7 +26,6 @@
CanonicalHouseholdContent,
HouseholdCreationInput,
HouseholdCreationResult,
HouseholdPage,
HouseholdRead,
LegacyHouseholdPersistenceResult,
LegacyHouseholdSnapshot,
Expand Down Expand Up @@ -126,28 +123,6 @@ def read_complete_household(
return household_read(household)


def read_household_page(
session: Session,
*,
country_id: str,
default_year: int | None,
offset: int,
limit: int,
) -> HouseholdPage:
"""Return a page of households, optionally filtered by default year."""
return household_page(
read_household_rows(
session,
country_id=country_id,
default_year=default_year,
offset=offset,
limit=limit,
),
offset=offset,
limit=limit,
)


def mirror_legacy_household_in_session(
session: Session,
snapshot: LegacyHouseholdSnapshot,
Expand Down Expand Up @@ -256,24 +231,6 @@ def get_household(self, *, country_id: str, household_id: UUID) -> HouseholdRead
household_id=household_id,
)

def list_households(
self,
*,
country_id: str,
default_year: int | None,
offset: int,
limit: int,
) -> HouseholdPage:
"""Return a page of households, optionally filtered by default year."""
with self._database_session.read() as session:
return read_household_page(
session,
country_id=country_id,
default_year=default_year,
offset=offset,
limit=limit,
)

def mirror_legacy_household(
self, snapshot: LegacyHouseholdSnapshot
) -> LegacyHouseholdPersistenceResult:
Expand Down
15 changes: 0 additions & 15 deletions policyengine_api/services/v2/households/transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from policyengine_api.services.v2.households.types import (
CanonicalHouseholdContent,
HouseholdCreationInput,
HouseholdPage,
HouseholdRead,
LegacyHouseholdSnapshot,
)
Expand Down Expand Up @@ -136,20 +135,6 @@ def household_read(household: Household) -> HouseholdRead:
)


def household_page(rows: list[Household], *, offset: int, limit: int) -> HouseholdPage:
"""Build a page from up to ``limit + 1`` rows.

The extra row is not returned; it only sets ``has_more``.
"""
displayed = rows[:limit]
return HouseholdPage(
items=tuple(household_read(row) for row in displayed),
offset=offset,
limit=limit,
has_more=len(rows) > limit,
)


def _stable_ids(kind: str, source_names: list[str]) -> dict[str, str]:
return {
source_name: f"{kind}-{index + 1}"
Expand Down
10 changes: 0 additions & 10 deletions policyengine_api/services/v2/households/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,6 @@ class HouseholdRead:
updated_at: datetime


@dataclass(frozen=True)
class HouseholdPage:
"""One page of households in creation order; ``has_more`` says if more follow."""

items: tuple[HouseholdRead, ...]
offset: int
limit: int
has_more: bool


@dataclass(frozen=True)
class NativeHouseholdCreation:
"""A created-or-found household, with ``created`` choosing 201 or 200."""
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dependencies = [
dev = [
"build",
"coverage",
"hypothesis>=6.100",
"mypy>=1.15,<2",
"pytest",
"pytest-snapshot",
Expand Down
14 changes: 0 additions & 14 deletions tests/contract/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,20 +339,6 @@ class WorkflowContract:
),
route_group="household",
),
ContractRequest(
method="GET",
path="/v2/households?country_id=us",
expected_status=200,
stable_response_fields=(
"status",
"message",
"result.items",
"result.offset",
"result.limit",
"result.has_more",
),
route_group="household",
),
),
),
WorkflowContract(
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/routes/test_migration_context_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ def test_v2_household_resources_log_actual_supabase_read_and_write_sources(
ServedRequest(
request_id="request-read",
method="GET",
path="/v2/households",
path="/v2/households/00000000-0000-0000-0000-000000000010",
status_code=200,
started_at=None,
country_id="us",
Expand Down
Loading
Loading