Skip to content
Open
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
27 changes: 27 additions & 0 deletions alembic/versions/0493ebb8237d_enable_pg_trgm_extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""enable pg_trgm extension

Revision ID: 0493ebb8237d
Revises: t6u7v8w9x0y1
Create Date: 2026-05-01 11:17:44.571959

"""

from typing import Sequence, Union

from sqlalchemy import text

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "0493ebb8237d"
down_revision: Union[str, Sequence[str], None] = "t6u7v8w9x0y1"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.execute(text("CREATE EXTENSION IF NOT EXISTS pg_trgm"))


def downgrade() -> None:
op.execute(text("DROP EXTENSION IF EXISTS pg_trgm"))
16 changes: 15 additions & 1 deletion api/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import logging
import time

from fastapi import APIRouter, Depends, UploadFile, File
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File
from fastapi_pagination.ext.sqlalchemy import paginate
from sqlalchemy import select
from sqlalchemy.exc import ProgrammingError
Expand Down Expand Up @@ -173,6 +173,20 @@ async def add_asset(
assoc = AssetThingAssociation()
audit_add(user, assoc)
thing = session.get(Thing, thing_id)

if not thing:
raise HTTPException(
status_code=409,
detail=[
{
"loc": ["body", "thing_id"],
"msg": f"Thing with ID {thing_id} not found.",
"type": "value_error",
"input": {"thing_id": thing_id},
}
],
)

assoc.thing = thing
assoc.asset = asset
session.add(assoc)
Expand Down
31 changes: 13 additions & 18 deletions api/thing.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# limitations under the License.
# ===============================================================================
from typing import Annotated, Optional

from fastapi import APIRouter, Query, Request
from fastapi_pagination.ext.sqlalchemy import paginate
from sqlalchemy import select
Expand All @@ -29,47 +30,47 @@
from api.pagination import CustomPage
from core.app import public_route
from core.dependencies import (
session_dependency,
admin_dependency,
editor_dependency,
session_dependency,
viewer_dependency,
)
from db.deployment import Deployment
from db.thing import Thing, ThingIdLink, WellScreen
from schemas.deployment import DeploymentResponse
from schemas.thing import (
CreateSpring,
CreateThingIdLink,
CreateWell,
CreateWellScreen,
ThingResponse,
WellResponse,
WellScreenResponse,
UpdateSpring,
UpdateWell,
SpringResponse,
CreateSpring,
ThingIdLinkResponse,
ThingResponse,
UpdateSpring,
UpdateThingIdLink,
UpdateWell,
UpdateWellScreen,
WellResponse,
WellScreenResponse,
)
from schemas.well_details import WellDetailsResponse
from schemas.well_export import WellExportResponse
from services.crud_helper import model_patcher, model_adder, model_deleter
from services.crud_helper import model_adder, model_deleter, model_patcher
from services.exceptions_helper import PydanticStyleException
from services.lexicon_helper import get_terms_by_category
from services.query_helper import (
simple_get_by_id,
paginated_all_getter,
order_sort_filter,
paginated_all_getter,
simple_get_by_id,
)
from services.thing_helper import (
WELL_DESCRIPTOR_MODEL_MAP,
add_thing,
patch_thing,
add_well_screen,
get_db_things,
get_thing_of_a_thing_type_by_id,
modify_well_descriptor_tables,
WELL_DESCRIPTOR_MODEL_MAP,
patch_thing,
)
from services.well_details_helper import (
get_well_details_payload,
Expand Down Expand Up @@ -154,7 +155,6 @@ def get_water_wells(
filter_params: Annotated[list[str] | None, Query(alias="filter")] = None,
query: Optional[str] = None,
name: Optional[str] = None,
name_contains: Optional[str] = None,
include_contacts: bool = False,
) -> CustomPage[WellResponse]:
"""
Expand All @@ -171,7 +171,6 @@ def get_water_wells(
thing_type=thing_type,
include_contacts=include_contacts,
filters=filter_params,
name_contains=name_contains,
)


Expand Down Expand Up @@ -298,7 +297,6 @@ def get_springs(
order: str = None,
filter_params: Annotated[list[str] | None, Query(alias="filter")] = None,
query: str = None,
name_contains: Optional[str] = None,
) -> CustomPage[SpringResponse]:
"""
Retrieve all springs from the database.
Expand All @@ -312,7 +310,6 @@ def get_springs(
sort,
thing_type=thing_type,
filters=filter_params,
name_contains=name_contains,
)


Expand Down Expand Up @@ -373,7 +370,6 @@ def get_things(
order: Optional[str] = None,
include_contacts: bool = False,
filter_params: Annotated[list[str] | None, Query(alias="filter")] = None,
name_contains: Optional[str] = None,
) -> CustomPage[ThingResponse]:
"""
Retrieve all things or filter by type.
Expand All @@ -388,7 +384,6 @@ def get_things(
within=within,
include_contacts=include_contacts,
filters=filter_params,
name_contains=name_contains,
)


Expand Down
8 changes: 4 additions & 4 deletions db/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def getconn():

conn = connector.connect(
instance_name, # The Cloud SQL instance name
"pg8000",
"psycopg",
**connect_kwargs,
)
return conn
Expand All @@ -190,7 +190,7 @@ def getconn():
pool_timeout = int(os.environ.get("DB_POOL_TIMEOUT", "30"))

engine = create_engine(
"postgresql+pg8000://",
"postgresql+psycopg://",
creator=getconn,
echo=False,
pool_size=pool_size,
Expand Down Expand Up @@ -220,7 +220,7 @@ def getconn():

auth = f"{user}:{password}@" if user and password else ""
port_part = f":{port}" if port else ""
url = f"postgresql+pg8000://{auth}{host}{port_part}/{name}"
url = f"postgresql+psycopg://{auth}{host}{port_part}/{name}"
# else:
# url = "sqlite:///./development.db"

Expand All @@ -243,7 +243,7 @@ def getconn():
_install_pool_logging(engine)

async_engine = create_async_engine(
url.replace("postgresql+pg8000", "postgresql+asyncpg"),
url.replace("postgresql+psycopg", "postgresql+asyncpg"),
plugins=["geoalchemy2"],
)
# if "postgresql" not in url:
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ dependencies = [
"utm==0.8.1",
"uvicorn==0.42.0",
"yarl==1.23.0",
"psycopg[binary]>=3.3.3",
]

[tool.uv]
Expand Down
Loading
Loading