From 79bb7c4fd0b8fbd9d7356e014e11c4a6d872040a Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Fri, 24 Jul 2026 15:22:26 +0300 Subject: [PATCH 1/2] Fix default .env discovery in oracles --- .../cvat/exchange-oracle/src/core/config.py | 16 +++++++++++++++- .../cvat/recording-oracle/src/core/config.py | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/examples/cvat/exchange-oracle/src/core/config.py b/packages/examples/cvat/exchange-oracle/src/core/config.py index 87a024ca00..453019939d 100644 --- a/packages/examples/cvat/exchange-oracle/src/core/config.py +++ b/packages/examples/cvat/exchange-oracle/src/core/config.py @@ -5,6 +5,7 @@ import os from collections.abc import Iterable from os import getenv +from pathlib import Path from typing import ClassVar, Optional from attrs.converters import to_bool @@ -17,13 +18,26 @@ from src.utils.logging import parse_log_level from src.utils.net import is_ipv4 + +def find_default_dotenv() -> Path | None: + # Check the default location in the project + dotenv_path = Path(__file__).parents[1] / ".env" + if dotenv_path.is_file(): + return str(dotenv_path) + else: + return None + + dotenv_path = getenv("DOTENV_PATH", None) + +if dotenv_path is None: + dotenv_path = find_default_dotenv() + if dotenv_path and not os.path.exists(dotenv_path): # noqa: PTH110 raise FileNotFoundError(dotenv_path) load_dotenv(dotenv_path) - # TODO: add some logic to report unused/deprecated env vars on startup diff --git a/packages/examples/cvat/recording-oracle/src/core/config.py b/packages/examples/cvat/recording-oracle/src/core/config.py index 477046d0bf..9cf334f9c6 100644 --- a/packages/examples/cvat/recording-oracle/src/core/config.py +++ b/packages/examples/cvat/recording-oracle/src/core/config.py @@ -5,6 +5,7 @@ import os from collections.abc import Iterable from os import getenv +from pathlib import Path from typing import ClassVar from attrs.converters import to_bool @@ -16,7 +17,21 @@ from src.utils.logging import parse_log_level from src.utils.net import is_ipv4 + +def find_default_dotenv() -> Path | None: + # Check the default location in the project + dotenv_path = Path(__file__).parents[1] / ".env" + if dotenv_path.is_file(): + return str(dotenv_path) + else: + return None + + dotenv_path = getenv("DOTENV_PATH", None) + +if dotenv_path is None: + dotenv_path = find_default_dotenv() + if dotenv_path and not os.path.exists(dotenv_path): # noqa: PTH110 raise FileNotFoundError(dotenv_path) From 0ffe53476ffa9efd260f741d7d086048dd329aa6 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Fri, 24 Jul 2026 15:23:52 +0300 Subject: [PATCH 2/2] Align RO app layout with EO --- .../cvat/recording-oracle/src/__init__.py | 37 ------------------- .../recording-oracle/src/apps/__init__.py | 0 .../src/apps/recording_oracle.py | 37 +++++++++++++++++++ .../recording-oracle/src/entrypoints/debug.py | 2 +- .../recording-oracle/src/entrypoints/run.py | 2 +- .../cvat/recording-oracle/tests/conftest.py | 2 +- 6 files changed, 40 insertions(+), 40 deletions(-) create mode 100644 packages/examples/cvat/recording-oracle/src/apps/__init__.py create mode 100644 packages/examples/cvat/recording-oracle/src/apps/recording_oracle.py diff --git a/packages/examples/cvat/recording-oracle/src/__init__.py b/packages/examples/cvat/recording-oracle/src/__init__.py index 1ecfdddd86..e69de29bb2 100644 --- a/packages/examples/cvat/recording-oracle/src/__init__.py +++ b/packages/examples/cvat/recording-oracle/src/__init__.py @@ -1,37 +0,0 @@ -import logging - -from fastapi import FastAPI - -from src.core.config import Config -from src.crons import setup_cron_jobs -from src.endpoints import init_api -from src.endpoints.error_handlers import setup_error_handlers -from src.log import setup_logging - -setup_logging() - -app = FastAPI( - title="Human Recording Oracle", - description=""" - Recording Oracle is a HUMAN oracle which main goal is to: - 1. Receive webhooks from an Exchange Oracle - 2. Process them and evaluate answers collected from CVAT - 3. Store evaluated answers in a s3 bucket - 4. Notify reputation oracle that final annotations are ready - """, - version="0.1.0", -) - -init_api(app) -setup_error_handlers(app) - - -@app.on_event("startup") -async def startup_event(): - logger = logging.getLogger("app") - logger.info("Recording Oracle is up and running!") - - -is_test = Config.environment == "test" -if not is_test: - setup_cron_jobs(app) diff --git a/packages/examples/cvat/recording-oracle/src/apps/__init__.py b/packages/examples/cvat/recording-oracle/src/apps/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/examples/cvat/recording-oracle/src/apps/recording_oracle.py b/packages/examples/cvat/recording-oracle/src/apps/recording_oracle.py new file mode 100644 index 0000000000..1ecfdddd86 --- /dev/null +++ b/packages/examples/cvat/recording-oracle/src/apps/recording_oracle.py @@ -0,0 +1,37 @@ +import logging + +from fastapi import FastAPI + +from src.core.config import Config +from src.crons import setup_cron_jobs +from src.endpoints import init_api +from src.endpoints.error_handlers import setup_error_handlers +from src.log import setup_logging + +setup_logging() + +app = FastAPI( + title="Human Recording Oracle", + description=""" + Recording Oracle is a HUMAN oracle which main goal is to: + 1. Receive webhooks from an Exchange Oracle + 2. Process them and evaluate answers collected from CVAT + 3. Store evaluated answers in a s3 bucket + 4. Notify reputation oracle that final annotations are ready + """, + version="0.1.0", +) + +init_api(app) +setup_error_handlers(app) + + +@app.on_event("startup") +async def startup_event(): + logger = logging.getLogger("app") + logger.info("Recording Oracle is up and running!") + + +is_test = Config.environment == "test" +if not is_test: + setup_cron_jobs(app) diff --git a/packages/examples/cvat/recording-oracle/src/entrypoints/debug.py b/packages/examples/cvat/recording-oracle/src/entrypoints/debug.py index 4549807de9..5afe74580c 100644 --- a/packages/examples/cvat/recording-oracle/src/entrypoints/debug.py +++ b/packages/examples/cvat/recording-oracle/src/entrypoints/debug.py @@ -196,7 +196,7 @@ def apply_local_development_patches() -> Generator[None, None, None]: register_in_kvstore() uvicorn.run( - app="src:app", + app="src.apps.recording_oracle:app", host="0.0.0.0", # noqa: S104 port=int(Config.port), workers=Config.workers_amount, diff --git a/packages/examples/cvat/recording-oracle/src/entrypoints/run.py b/packages/examples/cvat/recording-oracle/src/entrypoints/run.py index 2f09b1a09f..54adeba6ae 100644 --- a/packages/examples/cvat/recording-oracle/src/entrypoints/run.py +++ b/packages/examples/cvat/recording-oracle/src/entrypoints/run.py @@ -10,7 +10,7 @@ register_in_kvstore() uvicorn.run( - app="src:app", + app="src.apps.recording_oracle:app", host="0.0.0.0", # noqa: S104 port=int(Config.port), workers=Config.workers_amount, diff --git a/packages/examples/cvat/recording-oracle/tests/conftest.py b/packages/examples/cvat/recording-oracle/tests/conftest.py index 32972c10f8..2f8e634cda 100644 --- a/packages/examples/cvat/recording-oracle/tests/conftest.py +++ b/packages/examples/cvat/recording-oracle/tests/conftest.py @@ -5,7 +5,7 @@ from sqlalchemy import inspect, text from sqlalchemy.orm import Session -from src import app +from src.apps.recording_oracle import app from src.db import Base, SessionLocal, engine