refactor: centralize compact date formatting
This commit is contained in:
@@ -28,6 +28,8 @@ background scheduler
|
||||
|
||||
- `server.py` is the stable command/import facade. Runtime composition lives in
|
||||
`backend/application.py` and `backend/bootstrap/`.
|
||||
- `backend/bootstrap/` owns process configuration, dependency construction, startup, and
|
||||
shared input/display-format contracts. It does not own feature behavior.
|
||||
- `backend/http/` owns common authentication, request IDs, responses, static delivery, and
|
||||
error normalization. Feature-specific transport handlers live beside their feature.
|
||||
Exact POST endpoints that only delegate to one of those handlers use the explicit maps in
|
||||
|
||||
@@ -71,6 +71,10 @@ def normalize_date(value: str) -> str:
|
||||
return parsed.strftime("%Y%m%d")
|
||||
|
||||
|
||||
def display_compact_date(value: str) -> str:
|
||||
return f"{value[:4]}-{value[4:6]}-{value[6:8]}" if len(value) == 8 else value
|
||||
|
||||
|
||||
def validate_stock_code(value: str) -> str:
|
||||
code = value.strip()
|
||||
if not re.fullmatch(r"\d{6}", code):
|
||||
|
||||
@@ -11,6 +11,7 @@ from datetime import datetime, time as dt_time, timedelta
|
||||
from threading import Lock
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from backend.bootstrap.config import display_compact_date as _display_date
|
||||
from backend.data.numbers import finite_number as _number
|
||||
from backend.features.sentiment.engine import apply_sentiment_to_dashboard
|
||||
|
||||
@@ -2007,10 +2008,6 @@ def _display_time(value: Any) -> str:
|
||||
return f"{raw[:2]}:{raw[2:4]}:{raw[4:6]}"
|
||||
|
||||
|
||||
def _display_date(value: str) -> str:
|
||||
return f"{value[:4]}-{value[4:6]}-{value[6:8]}" if len(value) == 8 else value
|
||||
|
||||
|
||||
def _realtime_market_status(current_time: dt_time) -> str:
|
||||
if current_time < dt_time(9, 25):
|
||||
return "pre_open"
|
||||
|
||||
@@ -8,6 +8,7 @@ from collections import defaultdict
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any
|
||||
|
||||
from backend.bootstrap.config import display_compact_date as _display_date
|
||||
from backend.data.numbers import finite_number as _number
|
||||
from backend.data.providers.tushare_client import TushareClient, TushareError
|
||||
from backend.features.screener.strategies import ADVANCED_CURATED_STRATEGIES
|
||||
@@ -2200,7 +2201,3 @@ def _regime_reason(regime: str) -> str:
|
||||
"divergence": "指数或核心仍强,但广度、封板质量开始分化。",
|
||||
"retreat": "情绪指标继续走弱,应提高筛选门槛并接受无候选结果。",
|
||||
}.get(regime, "市场阶段待确认。")
|
||||
|
||||
|
||||
def _display_date(value: str) -> str:
|
||||
return f"{value[:4]}-{value[4:6]}-{value[6:8]}" if len(value) == 8 else value
|
||||
|
||||
@@ -230,6 +230,12 @@
|
||||
"path": "backend/data/numbers.py"
|
||||
}
|
||||
],
|
||||
"date_formatting": [
|
||||
{
|
||||
"function": "display_compact_date",
|
||||
"path": "backend/bootstrap/config.py"
|
||||
}
|
||||
],
|
||||
"llm_entrypoints": [
|
||||
{
|
||||
"function": "stream_with_mentor",
|
||||
@@ -289,13 +295,13 @@
|
||||
},
|
||||
{
|
||||
"path": "backend/features/screener/engine.py",
|
||||
"bytes": 108434,
|
||||
"lines": 2206
|
||||
"bytes": 108387,
|
||||
"lines": 2203
|
||||
},
|
||||
{
|
||||
"path": "backend/data/providers/tushare_client.py",
|
||||
"bytes": 94171,
|
||||
"lines": 2168
|
||||
"bytes": 94124,
|
||||
"lines": 2165
|
||||
},
|
||||
{
|
||||
"path": "frontend/app.js",
|
||||
|
||||
@@ -146,6 +146,7 @@ class MarketSliceSourceEquivalenceTests(unittest.TestCase):
|
||||
self.assertEqual(sha256(ORIGINAL_ROOT / original), sha256(APP_ROOT / migrated))
|
||||
original_tushare = top_level_definitions(ORIGINAL_ROOT / "tushare_client.py")
|
||||
original_tushare.pop("_number")
|
||||
original_tushare.pop("_display_date")
|
||||
self.assertEqual(
|
||||
original_tushare,
|
||||
top_level_definitions(APP_ROOT / "backend/data/providers/tushare_client.py"),
|
||||
@@ -155,6 +156,13 @@ class MarketSliceSourceEquivalenceTests(unittest.TestCase):
|
||||
function_contract(APP_ROOT / "backend/data/numbers.py", "finite_number"),
|
||||
)
|
||||
self.assertIs(canonical_tushare._number, finite_number)
|
||||
self.assertEqual(
|
||||
function_contract(ORIGINAL_ROOT / "tushare_client.py", "_display_date"),
|
||||
function_contract(
|
||||
APP_ROOT / "backend/bootstrap/config.py", "display_compact_date"
|
||||
),
|
||||
)
|
||||
self.assertIs(canonical_tushare._display_date, bootstrap_config.display_compact_date)
|
||||
original_charts = top_level_definitions(ORIGINAL_ROOT / "chart_data_provider.py")
|
||||
original_charts.pop("_stock_market_code")
|
||||
self.assertEqual(
|
||||
|
||||
@@ -9,6 +9,7 @@ import advanced_strategies
|
||||
import llm_strategy
|
||||
import screener
|
||||
import strategy_tracking
|
||||
from backend.bootstrap import config as bootstrap_config
|
||||
from backend.data.numbers import finite_number
|
||||
from backend.features.screener import compiler, engine, strategies, tracking
|
||||
from backend.features.screener import service as screener_service
|
||||
@@ -151,12 +152,12 @@ class ScreenerSliceSourceEquivalenceTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
module_contract(
|
||||
ORIGINAL_ROOT / "screener.py",
|
||||
excluded_definitions={"_number"},
|
||||
excluded_definitions={"_display_date", "_number"},
|
||||
exclude_imports=True,
|
||||
),
|
||||
module_contract(
|
||||
APP_ROOT / "backend" / "features" / "screener" / "engine.py",
|
||||
excluded_definitions={"_number"},
|
||||
excluded_definitions={"_display_date", "_number"},
|
||||
exclude_imports=True,
|
||||
),
|
||||
)
|
||||
@@ -165,6 +166,13 @@ class ScreenerSliceSourceEquivalenceTests(unittest.TestCase):
|
||||
function_contract(APP_ROOT / "backend/data/numbers.py", "finite_number"),
|
||||
)
|
||||
self.assertIs(engine._number, finite_number)
|
||||
self.assertEqual(
|
||||
function_contract(ORIGINAL_ROOT / "screener.py", "_display_date"),
|
||||
function_contract(
|
||||
APP_ROOT / "backend/bootstrap/config.py", "display_compact_date"
|
||||
),
|
||||
)
|
||||
self.assertIs(engine._display_date, bootstrap_config.display_compact_date)
|
||||
self.assertEqual(
|
||||
class_methods(
|
||||
ORIGINAL_ROOT / "backend" / "features" / "screener" / "tracking.py",
|
||||
|
||||
@@ -159,6 +159,9 @@ def build() -> dict[str, Any]:
|
||||
{"function": "finite_number", "path": "backend/data/numbers.py"},
|
||||
{"function": "non_nan_number", "path": "backend/data/numbers.py"},
|
||||
],
|
||||
"date_formatting": [
|
||||
{"function": "display_compact_date", "path": "backend/bootstrap/config.py"},
|
||||
],
|
||||
"llm_entrypoints": [
|
||||
{"function": "stream_with_mentor", "path": "backend/features/mentor/agent.py"},
|
||||
{"function": "interpret_heaven", "path": "backend/features/heaven/agent.py"},
|
||||
|
||||
Reference in New Issue
Block a user