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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ As an example, below we update the backend on a development machine:

```bash
# Edit docker-compose-prod-build.yaml image version:
# image: ghcr.io/nismod/gri-backend:1.5.0
# image: ghcr.io/nismod/gri-backend:1.6.2

# Build
docker compose -f docker-compose-prod-build.yaml build backend
Expand All @@ -173,17 +173,17 @@ docker compose -f docker-compose-prod-build.yaml build backend
# see: https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry

# Push
docker push ghcr.io/nismod/gri-backend:1.5.0
docker push ghcr.io/nismod/gri-backend:1.6.2
```

On the production remote, pull the image and restart the service:

```bash
# Pull image
docker pull ghcr.io/nismod/gri-backend:1.5.0
docker pull ghcr.io/nismod/gri-backend:1.6.2

# Edit docker-compose-prod-deploy.yaml image version (or sync up):
# image: ghcr.io/nismod/gri-backend:1.5.0
# image: ghcr.io/nismod/gri-backend:1.6.2

# Restart service
docker compose up -d backend
Expand Down
2 changes: 1 addition & 1 deletion containers/backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10
FROM python:3.12
LABEL maintainer="frederick.thomas@ouce.ox.ac.uk"

WORKDIR /code
Expand Down
2 changes: 1 addition & 1 deletion containers/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ source venv/bin/activate
pip install -e .[dev]

# run the application
uvicorn app.main:app --port 8888 --reload
uvicorn backend.app.main:app --port 8888 --reload
```

## Configuration
Expand Down
2 changes: 1 addition & 1 deletion containers/backend/backend/app/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from db.database import SessionLocal
from backend.db.database import SessionLocal


def get_db():
Expand Down
8 changes: 4 additions & 4 deletions containers/backend/backend/app/internal/attribute_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from pydantic import Json, ValidationError


from app import schemas
from db import models
from backend.app import schemas
from backend.db import models


def add_damages_expected_value_query(
Expand Down Expand Up @@ -55,7 +55,7 @@ def add_adaptation_value_query(
adaptation_protection_level=dimensions.adaptation_protection_level,
)

value: Column | ColumnOperators = None
value: Column | ColumnOperators | None = None

if field == "cost_benefit_ratio":
cost_benefit_params: schemas.AdaptationCostBenefitRatioParameters = field_params
Expand All @@ -78,7 +78,7 @@ class DataGroupConfig:
add_value_query: Callable[
[Query, schemas.DataDimensions, str, schemas.DataParameters | None], Query
]
field_parameters_schemas: Optional[dict[str, schemas.DataParameters]] = None
field_parameters_schemas: Optional[dict[str, schemas.DataParameters]] | None = None


DATA_GROUP_CONFIGS: dict[str, DataGroupConfig] = {
Expand Down
2 changes: 1 addition & 1 deletion containers/backend/backend/app/internal/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import logging
import traceback

from config import TILEDB_URI
from backend.config import TILEDB_URI


def build_driver_path(database: str, tiledb_uri: str = TILEDB_URI) -> str:
Expand Down
7 changes: 5 additions & 2 deletions containers/backend/backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from fastapi.routing import APIRoute
from fastapi.logger import logger

from .routers import attributes, features, tiles, colormap
from config import LOG_LEVEL
import backend.app.routers.attributes as attributes
import backend.app.routers.features as features
import backend.app.routers.tiles as tiles
import backend.app.routers.colormap as colormap
from backend.config import LOG_LEVEL

formatter = logging.Formatter(
"[%(asctime)s.%(msecs)03d] %(levelname)s %(filename)s - %(funcName)s - %(message)s",
Expand Down
8 changes: 4 additions & 4 deletions containers/backend/backend/app/routers/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
from fastapi import APIRouter, Body, Depends
from sqlalchemy.orm import Session

from app.dependencies import get_db
from app.internal.attribute_access import (
from backend.app.dependencies import get_db
from backend.app.internal.attribute_access import (
add_value_query,
parse_dimensions,
parse_parameters,
)

from db import models
from backend.db import models

from .. import schemas
from backend.app import schemas

router = APIRouter(tags=["attributes"])

Expand Down
21 changes: 15 additions & 6 deletions containers/backend/backend/app/routers/colormap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

import inspect
import json
from typing import Union

from fastapi import APIRouter, HTTPException
from fastapi.logger import logger

from app import schemas
from app.internal.helpers import handle_exception
from backend.app import schemas
from backend.app.internal.helpers import handle_exception


router = APIRouter(tags=["colormap"])
Expand All @@ -29,7 +28,7 @@ def _get_colormap(options: schemas.ColorMapOptions) -> schemas.ColorMap:
@router.get("", response_model=schemas.ColorMap)
async def get_colormap(
colormap: str,
stretch_range: Union[str, None],
stretch_range: str,
num_values: int = 255,
) -> schemas.ColorMap:
"""
Expand All @@ -43,18 +42,28 @@ async def get_colormap(

::kwarg num_values int Number of values to generate in the colormap
"""
try:
stretch_range_arg: list[int] = json.loads(stretch_range)
if len(stretch_range_arg) != 2:
raise ValueError
except ValueError:
raise HTTPException(
status_code=400,
detail="stretch_range should be a list of two values (min and max), like `stretch_range=[0,1]`",
)

logger.debug(
"performing %s, using %s, %s, %s",
inspect.stack()[0][3],
colormap,
json.loads(stretch_range),
stretch_range_arg,
num_values,
)
try:

options = schemas.ColorMapOptions(
colormap=colormap,
stretch_range=json.loads(stretch_range),
stretch_range=stretch_range_arg,
num_values=num_values,
)

Expand Down
15 changes: 10 additions & 5 deletions containers/backend/backend/app/routers/features.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException
from fastapi_pagination import Page, Params
from fastapi_pagination.ext.sqlalchemy import paginate
Expand All @@ -6,14 +8,14 @@
from sqlalchemy.orm import Session
from geoalchemy2 import functions

from app import schemas
from app.dependencies import get_db
from app.internal.attribute_access import (
from backend.app import schemas
from backend.app.dependencies import get_db
from backend.app.internal.attribute_access import (
add_value_query,
parse_dimensions,
parse_parameters,
)
from db import models
from backend.db import models


router = APIRouter(tags=["features"])
Expand All @@ -32,7 +34,10 @@ def read_feature(feature_id: int, db: Session = Depends(get_db)):


def get_layer_spec(
layer: str = None, sector: str = None, subsector: str = None, asset_type: str = None
layer: Optional[str] = None,
sector: Optional[str] = None,
subsector: Optional[str] = None,
asset_type: Optional[str] = None,
):
return schemas.LayerSpec(
layer_name=layer,
Expand Down
12 changes: 6 additions & 6 deletions containers/backend/backend/app/routers/tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
from terracotta import get_driver


from app import schemas
from app.dependencies import get_db
from db import models
from app.internal.helpers import build_driver_path, handle_exception
from app.exceptions import (
from backend.app import schemas
from backend.app.dependencies import get_db
from backend.db import models
from backend.app.internal.helpers import build_driver_path, handle_exception
from backend.app.exceptions import (
SourceDBDoesNotExistException,
MissingExplicitColourMapException,
)
from config import CATEGORICAL_COLOR_MAPS
from backend.config import CATEGORICAL_COLOR_MAPS


router = APIRouter(tags=["tiles"])
Expand Down
17 changes: 9 additions & 8 deletions containers/backend/backend/app/schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from enum import Enum
from typing import Generic, List, Optional, TypeVar, Union
from pydantic import BaseModel, ConfigDict, conint, validator
from typing import Generic, Optional, TypeVar, Union
from typing_extensions import Annotated
from pydantic import BaseModel, ConfigDict, Field, field_validator


class FeatureBase(BaseModel):
Expand Down Expand Up @@ -113,9 +114,9 @@ class AdaptationVariables(DataVariables):


class AdaptationCostBenefitRatioParameters(DataParameters):
eael_days: conint(ge=1, le=30)
eael_days: Annotated[int, Field(ge=1, le=30)]

@validator("eael_days")
@field_validator("eael_days")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're at it - was the reason for keeping this quirk fix since this was first released because it was too time consuming to recalculate the raw data?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - may revisit as @thomas-fred works on easier reproducibility of the risk calculations.

def fix_eael_days(cls, eael_days: int) -> float:
"""
The data for `AdaptationCostBenefit.avoided_eael_mean` is erroneous and
Expand Down Expand Up @@ -187,19 +188,19 @@ class TileSourceMeta(BaseModel):


class TileSourceDomains(BaseModel):
domains: List[dict[str, str]]
domains: list[dict[str, str]]


class ColorMapOptions(BaseModel):
stretch_range: List[int]
stretch_range: list[int]
colormap: str
num_values: Optional[int] = 255


class ColorMapEntry(BaseModel):
value: float
rgba: List[int]
rgba: list[int]


class ColorMap(BaseModel):
colormap: List[ColorMapEntry]
colormap: list[ColorMapEntry]
4 changes: 2 additions & 2 deletions containers/backend/backend/create_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
SQLAlchemy Schema Setup Main
"""

from db import models
from db.database import engine
from backend.db import models
from backend.db.database import engine

if __name__ == "__main__":
models.Base.metadata.drop_all(bind=engine)
Expand Down
16 changes: 9 additions & 7 deletions containers/backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ build-backend = "setuptools.build_meta"

[project]
name = "gri-backend"
version = "0.3.0"
version = "0.4.1"
description = "GRI API Backend"
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.12"
license = { text = "MIT" }
classifiers = ["Framework :: FastAPI", "Programming Language :: Python :: 3"]
dependencies = [
"fastapi==0.109.1",
"geoalchemy2==0.12.5",
"uvicorn==0.18.3",
"fastapi==0.115.5",
"fastapi-pagination==0.12.32",
"geoalchemy2==0.16.0",
"psycopg2-binary==2.9.10",
"fastapi-pagination==0.10.0",
"pydantic==2.9.2",
"sqlalchemy==2.0.36",
"setuptools==75.5.0",
"terracotta==0.8.3",
"sqlalchemy==1.4.41",
"uvicorn==0.32.0",
]

[project.optional-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions docker-compose-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ services:

backend:
build: ./containers/backend
image: ghcr.io/nismod/gri-backend:1.5.0
image: ghcr.io/nismod/gri-backend:1.6.2
volumes:
- ./etl/raster/cog/:/data/
- ./containers/backend/backend/:/code/backend/
Expand Down Expand Up @@ -118,7 +118,7 @@ services:
## WARNING - this will wipe the existing tables. TODO: Alembic
recreate-metadata-schema:
build: ./containers/backend
image: ghcr.io/nismod/gri-backend:1.5.0
image: ghcr.io/nismod/gri-backend:1.6.2
profiles: ["recreate-metadata-schema"]
volumes:
- ./containers/backend/backend/db/models.py:/code/backend/db/models.py
Expand Down
2 changes: 1 addition & 1 deletion docker-compose-prod-build.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
backend:
image: ghcr.io/nismod/gri-backend:1.5.0
image: ghcr.io/nismod/gri-backend:1.6.2
build: ./containers/backend

vector-tileserver:
Expand Down
2 changes: 1 addition & 1 deletion docker-compose-prod-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ services:
mem_limit: "250M"

backend:
image: ghcr.io/nismod/gri-backend:1.5.0
image: ghcr.io/nismod/gri-backend:1.6.2
restart: always
volumes:
- ./tileserver/raster/data:/data
Expand Down