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
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ cd src/typescript && npm run build
# Python
cd src/python && poetry build

# Python - after any dependency change, regenerate requirements.txt for Cloud Run Buildpack:
cd src/python && poetry export --without-hashes --without dev -f requirements.txt -o requirements.txt

# Go
cd src/go && make build

Expand Down
12 changes: 12 additions & 0 deletions src/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,18 @@ gcloud run deploy lamp-control-api \
--allow-unauthenticated
```

### Managing `requirements.txt`

Cloud Run uses the Google Cloud Buildpack, which relies on `requirements.txt` for dependency installation. This file must be kept in sync with `pyproject.toml` and `poetry.lock`.

**Regenerate after any dependency change:**

```bash
poetry export --without-hashes --without dev -f requirements.txt -o requirements.txt
```

> **Important:** Always commit the updated `requirements.txt` alongside any changes to `pyproject.toml` or `poetry.lock`. Failing to do so will cause Cloud Run deployments to use stale dependencies.

## Tests

### Running Unit Tests
Expand Down
14 changes: 7 additions & 7 deletions src/python/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ opentelemetry-instrumentation-sqlalchemy = "^0.50b0"
opentelemetry-instrumentation-httpx = "^0.50b0"
opentelemetry-instrumentation-logging = "^0.50b0"
python-json-logger = "^2.0"
httpx = "^0.27.2"

[tool.poetry.group.dev.dependencies]
pytest = "^8.3.5"
pytest-asyncio = "^0.26.0"
pytest-cov = "^6.1.1"
httpx = "^0.27.2"
black = "^26.3.1"
ruff = "^0.15.6"
mypy = "^1.15.0"
Expand Down
49 changes: 49 additions & 0 deletions src/python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
alembic==1.18.0 ; python_version >= "3.14" and python_version < "4.0"
annotated-types==0.7.0 ; python_version >= "3.14" and python_version < "4.0"
anyio==4.9.0 ; python_version >= "3.14" and python_version < "4.0"
asgiref==3.11.1 ; python_version >= "3.14" and python_version < "4.0"
asyncpg==0.30.0 ; python_version >= "3.14" and python_version < "4.0"
certifi==2025.4.26 ; python_version >= "3.14" and python_version < "4.0"
click==8.1.8 ; python_version >= "3.14" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.14" and python_version < "4.0" and platform_system == "Windows"
deprecated==1.3.1 ; python_version >= "3.14" and python_version < "4.0"
fastapi==0.115.12 ; python_version >= "3.14" and python_version < "4.0"
googleapis-common-protos==1.73.0 ; python_version >= "3.14" and python_version < "4.0"
greenlet==3.3.1 ; python_version >= "3.14" and python_version < "4.0" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32")
grpcio==1.78.0 ; python_version >= "3.14" and python_version < "4.0"
h11==0.16.0 ; python_version >= "3.14" and python_version < "4.0"
httpcore==1.0.9 ; python_version >= "3.14" and python_version < "4.0"
httptools==0.7.1 ; python_version >= "3.14" and python_version < "4.0"
httpx==0.27.2 ; python_version >= "3.14" and python_version < "4.0"
idna==3.10 ; python_version >= "3.14" and python_version < "4.0"
importlib-metadata==8.5.0 ; python_version >= "3.14" and python_version < "4.0"
mako==1.3.10 ; python_version >= "3.14" and python_version < "4.0"
markupsafe==3.0.2 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-api==1.29.0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-exporter-otlp-proto-common==1.29.0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-exporter-otlp-proto-grpc==1.29.0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation-asgi==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation-fastapi==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation-httpx==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation-logging==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation-sqlalchemy==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-instrumentation==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-proto==1.29.0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-sdk==1.29.0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-semantic-conventions==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
opentelemetry-util-http==0.50b0 ; python_version >= "3.14" and python_version < "4.0"
packaging==25.0 ; python_version >= "3.14" and python_version < "4.0"
protobuf==5.29.6 ; python_version >= "3.14" and python_version < "4.0"
pydantic-core==2.41.5 ; python_version >= "3.14" and python_version < "4.0"
pydantic-settings==2.12.0 ; python_version >= "3.14" and python_version < "4.0"
pydantic==2.12.5 ; python_version >= "3.14" and python_version < "4.0"
python-dotenv==1.1.0 ; python_version >= "3.14" and python_version < "4.0"
python-json-logger==2.0.7 ; python_version >= "3.14" and python_version < "4.0"
sniffio==1.3.1 ; python_version >= "3.14" and python_version < "4.0"
sqlalchemy==2.0.45 ; python_version >= "3.14" and python_version < "4.0"
starlette==0.46.2 ; python_version >= "3.14" and python_version < "4.0"
typing-extensions==4.15.0 ; python_version >= "3.14" and python_version < "4.0"
typing-inspection==0.4.2 ; python_version >= "3.14" and python_version < "4.0"
uvicorn==0.27.1 ; python_version >= "3.14" and python_version < "4.0"
wrapt==1.17.3 ; python_version >= "3.14" and python_version < "4.0"
zipp==3.23.0 ; python_version >= "3.14" and python_version < "4.0"
6 changes: 4 additions & 2 deletions src/python/src/openapi_server/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ async def lifespan(app: FastAPI):
and properly closes it on shutdown.
"""
# Startup
if configure_telemetry():
FastAPIInstrumentor.instrument_app(app)
initialize_database()
yield
# Shutdown
Expand All @@ -47,6 +45,10 @@ async def lifespan(app: FastAPI):
lifespan=lifespan,
)

# Middleware must be added before the app starts — cannot be done inside lifespan
if configure_telemetry():
FastAPIInstrumentor.instrument_app(app)


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
Expand Down
Loading