From 8a2fac03a68bfeb3d2468e88480366da27d8e272 Mon Sep 17 00:00:00 2001 From: gahusb Date: Sat, 16 May 2026 03:35:36 +0900 Subject: [PATCH] =?UTF-8?q?feat(signal=5Fv2):=20foundation=20=E2=80=94=20c?= =?UTF-8?q?onfig=20+=20state=20+=20requirements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - signal_v2/config.py: Settings dataclass loading web-ai/.env explicitly - signal_v2/state.py: PollState dataclass + module-level singleton - requirements.txt: httpx / fastapi / uvicorn / pytest-asyncio / respx - .gitignore: signal_v2/data/*.db (WAL/SHM) - empty tests/ marker Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 4 ++++ requirements.txt | 8 ++++++++ signal_v2/__init__.py | 0 signal_v2/config.py | 28 ++++++++++++++++++++++++++++ signal_v2/data/.gitkeep | 0 signal_v2/state.py | 15 +++++++++++++++ signal_v2/tests/__init__.py | 0 7 files changed, 55 insertions(+) create mode 100644 requirements.txt create mode 100644 signal_v2/__init__.py create mode 100644 signal_v2/config.py create mode 100644 signal_v2/data/.gitkeep create mode 100644 signal_v2/state.py create mode 100644 signal_v2/tests/__init__.py diff --git a/.gitignore b/.gitignore index b93af2c..c92758d 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,7 @@ Desktop.ini KIS_SETUP.md # Claude Code subagent state .claude/ + +# Signal V2 runtime data +signal_v2/data/*.db +signal_v2/data/*.db-* diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1af5998 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +# Signal V2 dependencies (added 2026-05-16, Phase 2) +httpx>=0.27 +fastapi>=0.110 +uvicorn>=0.27 +python-dotenv>=1.0 +pytest>=8.0 +pytest-asyncio>=0.23 +respx>=0.21 diff --git a/signal_v2/__init__.py b/signal_v2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/signal_v2/config.py b/signal_v2/config.py new file mode 100644 index 0000000..617b46a --- /dev/null +++ b/signal_v2/config.py @@ -0,0 +1,28 @@ +"""Signal V2 환경변수 로딩.""" +import os +from dataclasses import dataclass, field +from pathlib import Path + +from dotenv import load_dotenv + +# web-ai/.env 명시 로드 (signal_v2/config.py 의 parent.parent = web-ai/) +load_dotenv(Path(__file__).parent.parent / ".env") + + +@dataclass(frozen=True) +class Settings: + stock_api_url: str = field( + default_factory=lambda: os.getenv("STOCK_API_URL", "").rstrip("/") + ) + webai_api_key: str = field( + default_factory=lambda: os.getenv("WEBAI_API_KEY", "").strip() + ) + port: int = field(default_factory=lambda: int(os.getenv("SIGNAL_V2_PORT", "8001"))) + db_path: Path = field( + default_factory=lambda: Path(__file__).parent / "data" / "signal_v2.db" + ) + + +def get_settings() -> Settings: + """매 호출 시 신선한 Settings (테스트 monkeypatch 호환).""" + return Settings() diff --git a/signal_v2/data/.gitkeep b/signal_v2/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/signal_v2/state.py b/signal_v2/state.py new file mode 100644 index 0000000..d290b96 --- /dev/null +++ b/signal_v2/state.py @@ -0,0 +1,15 @@ +"""PollState — process-wide singleton.""" +from dataclasses import dataclass, field + + +@dataclass +class PollState: + portfolio: dict | None = None + news_sentiment: dict | None = None + screener_preview: dict | None = None + last_updated: dict[str, str] = field(default_factory=dict) + fetch_errors: dict[str, int] = field(default_factory=dict) + + +# Process-wide singleton. Phase 3 imports: from signal_v2.state import state +state = PollState() diff --git a/signal_v2/tests/__init__.py b/signal_v2/tests/__init__.py new file mode 100644 index 0000000..e69de29