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
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.4
rev: v0.15.13
hooks:
- id: ruff-format
name: ruff-format
entry: make format
language_version: python3.11
language_version: python3.14
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ubuntu:24.04 AS builder

ENV PYTHON_VERSION=3.11.10
ENV UV_VERSION=0.5.5
ENV PYTHON_VERSION=3.14.2
ENV UV_VERSION=0.9.16
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_INSTALL_DIR="/usr/local/bin"
Expand Down Expand Up @@ -68,7 +68,7 @@ COPY pyproject.toml /app/TRE-server/pyproject.toml
COPY uv.lock /app/TRE-server/uv.lock
RUN cd /app/TRE-server \
&& uv venv $UV_PROJECT_ENVIRONMENT \
&& uv sync --frozen --no-dev --no-install-project \
&& UV_MALWARE_CHECK=1 uv sync --frozen --no-dev --no-install-project \
&& rm -f /app/TRE-server/pyproject.toml \
&& rm -f /app/TRE-server/uv.lock

Expand Down Expand Up @@ -116,4 +116,4 @@ COPY run.sh healthcheck.sh /app/

EXPOSE 5000
CMD ["/app/run.sh"]
HEALTHCHECK --interval=10s CMD ["/app/healthcheck.sh"]
HEALTHCHECK --interval=10s CMD ["/app/healthcheck.sh"]
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: install update format lint doc test run

install:
uv sync --frozen --no-install-project
UV_MALWARE_CHECK=1 uv sync --frozen --no-install-project
uv run pre-commit install

update:
Expand Down
4 changes: 2 additions & 2 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def convert_errors(
async def validation_exception_handler(request: Request, exc: RequestValidationError):
meta = {"code": 1, "title": "RequestValidationError"}
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
content=jsonable_encoder({"meta": meta, "detail": convert_errors(exc)}),
)

Expand All @@ -126,7 +126,7 @@ async def validation_exception_handler(request: Request, exc: RequestValidationE
async def query_validation_exception_handler(request: Request, exc: ValidationError):
meta = {"code": 1, "title": "RequestValidationError"}
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
content=jsonable_encoder({"meta": meta, "detail": convert_errors(exc)}),
)

Expand Down
39 changes: 2 additions & 37 deletions app/utils/fastapi_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,8 @@
SPDX-License-Identifier: Apache-2.0
"""

import decimal
from typing import Any

import orjson
from fastapi.responses import ORJSONResponse

from app.exceptions import Integer64bitLimitExceededError
from config import RESPONSE_VALIDATION_MODE


def decimal_default(obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
raise TypeError


class CustomORJSONResponse(ORJSONResponse):
media_type = "application/json"

def render(self, content: Any) -> bytes:
try:
result = orjson.dumps(
content,
option=orjson.OPT_NON_STR_KEYS | orjson.OPT_SERIALIZE_NUMPY,
default=decimal_default,
)
return result
except TypeError as e:
if e.args[0] == "Integer exceeds 64-bit range":
raise Integer64bitLimitExceededError(
"Response data includes integer which exceeds 64-bit range"
) from None
raise


def json_response(content: dict | list):
if RESPONSE_VALIDATION_MODE:
return content
else:
return CustomORJSONResponse(content=content)
def json_response(content: dict[str, Any] | list[Any]):
return content
25 changes: 13 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,33 @@ authors = [
]
license = {text = ""}
readme = "README.md"
requires-python = "==3.11.10"
requires-python = "==3.14.2"
dependencies = [
"py_ecc~=7.0.0",
"pycryptodome~=3.20",
"coincurve~=19.0.1",
"pydantic~=2.10.3",
"fastapi~=0.115.0",
"gunicorn~=23.0.0",
"orjson~=3.10.3",
"uvicorn-worker~=0.2.0",
"pydantic~=2.13.4",
"fastapi~=0.136.1",
"gunicorn~=26.0.0",
"uvicorn-worker~=0.4.0",
]

[tool.uv]
dev-dependencies = [
[dependency-groups]
dev = [
"pytest<9.0.0,>=8.3.2",
"pytest-cov<6.0.0,>=5.0.0",
"pytest-asyncio==0.23.8",
"pytest-aiohttp<2.0.0,>=1.0.5",
"pre-commit<4.0.0,>=3.6.0",
"ruff<1.0.0,>=0.5.4",
"ruff<1.0.0,>=0.15.13",
"ruamel-yaml<1.0.0,>=0.18.6",
"typer==0.12.3",
"httpx<1.0.0,>=0.27.0",
"httpx2<3.0.0,>=2.4.0",
]

[tool.ruff]
line-length = 88
indent-width = 4
target-version = "py311"
target-version = "py314"
exclude = [".venv/*"]

[tool.ruff.format]
Expand Down Expand Up @@ -79,3 +77,6 @@ include = [
"app/model/**/*",
"app/utils/**/*",
]

[tool.uv]
exclude-newer = "7 days"
8 changes: 4 additions & 4 deletions tests/Dockerfile_unittest
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ubuntu:24.04 AS builder

ENV PYTHON_VERSION=3.11.10
ENV UV_VERSION=0.5.5
ENV PYTHON_VERSION=3.14.2
ENV UV_VERSION=0.9.16
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy
ENV UV_INSTALL_DIR="/usr/local/bin"
Expand Down Expand Up @@ -68,7 +68,7 @@ COPY pyproject.toml /app/TRE-server/pyproject.toml
COPY uv.lock /app/TRE-server/uv.lock
RUN cd /app/TRE-server \
&& uv venv $UV_PROJECT_ENVIRONMENT \
&& uv sync --frozen --no-install-project \
&& UV_MALWARE_CHECK=1 uv sync --frozen --no-install-project \
&& rm -f /app/TRE-server/pyproject.toml \
&& rm -f /app/TRE-server/uv.lock

Expand Down Expand Up @@ -120,4 +120,4 @@ ENV UV_PROJECT_ENVIRONMENT="/home/apl/.venv"
ENV PYTHONUNBUFFERED=1
ENV PYTHONPATH=/app/TRE-server

CMD ["/app/TRE-server/tests/qa.sh"]
CMD ["/app/TRE-server/tests/qa.sh"]
7 changes: 5 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@
import pytest
import pytest_asyncio
from fastapi.testclient import TestClient
from httpx import AsyncClient
from httpx2 import ASGITransport, AsyncClient

from app.main import app


@pytest_asyncio.fixture(scope="session")
async def async_client() -> AsyncClient:
async_client = AsyncClient(app=app, base_url="http://localhost")
async_client = AsyncClient(
transport=ASGITransport(app=app),
base_url="http://localhost",
)
async with async_client as s:
yield s

Expand Down
Loading
Loading