默认全部读取/影子开关关闭,网站继续走旧 Tushare 链路;开启单项时只替换该类原料并在失败时回旧,问天保持旧路径。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
40 lines
1.0 KiB
Python
40 lines
1.0 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
SECRET_HINTS = (
|
|
"token",
|
|
"password",
|
|
"secret",
|
|
"key",
|
|
"authorization",
|
|
"credential",
|
|
"cookie",
|
|
)
|
|
|
|
|
|
def redact_value(value: Any, key: str = "", secrets: tuple[str, ...] = ()) -> Any:
|
|
lowered = key.lower()
|
|
if any(part in lowered for part in SECRET_HINTS):
|
|
return "***"
|
|
if isinstance(value, dict):
|
|
return {
|
|
str(item_key): redact_value(item_value, str(item_key), secrets)
|
|
for item_key, item_value in value.items()
|
|
}
|
|
if isinstance(value, list):
|
|
return [redact_value(item, key, secrets) for item in value]
|
|
text = str(value) if value is not None and not isinstance(value, (int, float, bool)) else value
|
|
if isinstance(text, str):
|
|
return redact_text(text, secrets)
|
|
return value
|
|
|
|
|
|
def redact_text(text: str, secrets: tuple[str, ...] = ()) -> str:
|
|
redacted = text
|
|
for secret in secrets:
|
|
if secret:
|
|
redacted = redacted.replace(secret, "***")
|
|
return redacted
|