Skip to content

Commit 8e87e70

Browse files
authored
Merge pull request #49 from QuantStrategyLab/remove-googlevoice-legacy-aliases
Remove legacy strategy plugin email aliases
2 parents dd63d8d + 13cc087 commit 8e87e70

5 files changed

Lines changed: 12 additions & 124 deletions

File tree

docs/strategy_plugin_runtime_contract.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ SMTP should use
113113
The publisher builds the shared subject/body, prefixes platform context, returns
114114
structured sent/skipped/failed diagnostics, and can use
115115
`StrategyPluginGoogleVoiceAlertMarkerStore` to skip alert keys that were already
116-
sent. The older `strategy_plugin_email` module remains as a compatibility alias
117-
for deployed platforms.
116+
sent. Platforms should expose this as Google Voice notification config, not as a
117+
generic email alert surface.
118118
This keeps the Crisis Response plugin behavior consistent across IBKR, Schwab,
119119
LongBridge, Firstrade, and future platform runtimes.

src/quant_platform_kit/notifications/__init__.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@
22

33
from .email import parse_email_recipients, send_smtp_email
44
from .events import NotificationPublisher, RenderedNotification, publish_rendered_notification
5-
from .strategy_plugin_email import (
6-
StrategyPluginEmailAlertDelivery,
7-
StrategyPluginEmailAlertMarkerStore,
8-
StrategyPluginEmailAlertPublishResult,
9-
StrategyPluginEmailSettings,
10-
publish_strategy_plugin_email_alerts,
11-
)
125
from .strategy_plugin_google_voice import (
136
StrategyPluginGoogleVoiceAlertDelivery,
147
StrategyPluginGoogleVoiceAlertMarkerStore,
@@ -21,18 +14,13 @@
2114
__all__ = [
2215
"NotificationPublisher",
2316
"RenderedNotification",
24-
"StrategyPluginEmailAlertDelivery",
25-
"StrategyPluginEmailAlertMarkerStore",
26-
"StrategyPluginEmailAlertPublishResult",
27-
"StrategyPluginEmailSettings",
2817
"StrategyPluginGoogleVoiceAlertDelivery",
2918
"StrategyPluginGoogleVoiceAlertMarkerStore",
3019
"StrategyPluginGoogleVoiceAlertPublishResult",
3120
"StrategyPluginGoogleVoiceSettings",
3221
"build_strategy_plugin_alert_context_label",
3322
"parse_email_recipients",
3423
"publish_rendered_notification",
35-
"publish_strategy_plugin_email_alerts",
3624
"publish_strategy_plugin_google_voice_alerts",
3725
"send_smtp_email",
3826
]

src/quant_platform_kit/notifications/strategy_plugin_email.py

Lines changed: 0 additions & 53 deletions
This file was deleted.

src/quant_platform_kit/notifications/strategy_plugin_google_voice.py

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,8 @@ def from_object(cls, value: object) -> "StrategyPluginGoogleVoiceSettings":
3737
return cls(
3838
smtp_host=_get_value(value, "crisis_alert_smtp_host"),
3939
smtp_port=int(_get_value(value, "crisis_alert_smtp_port", 587) or 587),
40-
sender=_first_non_empty(
41-
_get_value(value, "crisis_alert_smtp_from"),
42-
_get_value(value, "crisis_alert_google_voice_from"),
43-
_get_value(value, "crisis_alert_email_from"),
44-
),
45-
recipients=_merge_recipients(
46-
_get_value(value, "crisis_alert_google_voice_to", ()),
47-
_get_value(value, "crisis_alert_email_to", ()),
48-
),
40+
sender=_first_non_empty(_get_value(value, "crisis_alert_smtp_from")),
41+
recipients=tuple(parse_email_recipients(_get_value(value, "crisis_alert_google_voice_to", ()))),
4942
username=_get_value(value, "crisis_alert_smtp_username"),
5043
password=_get_value(value, "crisis_alert_smtp_password"),
5144
use_starttls=_coerce_bool(_get_value(value, "crisis_alert_smtp_starttls", True), default=True),
@@ -57,9 +50,9 @@ def missing_fields(self) -> tuple[str, ...]:
5750
if not str(self.smtp_host or "").strip():
5851
missing.append("CRISIS_ALERT_SMTP_HOST")
5952
if not str(self.sender or "").strip():
60-
missing.append("CRISIS_ALERT_SMTP_FROM/CRISIS_ALERT_EMAIL_FROM")
53+
missing.append("CRISIS_ALERT_SMTP_FROM")
6154
if not parse_email_recipients(self.recipients):
62-
missing.append("CRISIS_ALERT_GOOGLE_VOICE_TO/CRISIS_ALERT_EMAIL_TO")
55+
missing.append("CRISIS_ALERT_GOOGLE_VOICE_TO")
6356
return tuple(missing)
6457

6558
@property
@@ -124,16 +117,13 @@ class StrategyPluginGoogleVoiceAlertMarkerStore:
124117
gcs_prefix_uri: str | None = None
125118
gcp_project_id: str | None = None
126119
namespace: str = "strategy_plugin_google_voice_alerts"
127-
legacy_namespaces: tuple[str, ...] = ("strategy_plugin_email_alerts",)
128120
client_factory: Any = None
129121

130122
def has_alert(self, alert_key: str) -> bool:
131-
for candidate_key in _alert_key_candidates(alert_key):
132-
for namespace in (self.namespace, *self.legacy_namespaces):
133-
if self.gcs_prefix_uri and self._gcs_blob(candidate_key, namespace=namespace).exists():
134-
return True
135-
if self.local_dir and self._local_path(candidate_key, namespace=namespace).exists():
136-
return True
123+
if self.gcs_prefix_uri and self._gcs_blob(alert_key, namespace=self.namespace).exists():
124+
return True
125+
if self.local_dir and self._local_path(alert_key, namespace=self.namespace).exists():
126+
return True
137127
return False
138128

139129
def record_alert(
@@ -377,18 +367,6 @@ def _first_non_empty(*values: Any) -> str | None:
377367
return None
378368

379369

380-
def _merge_recipients(*values: Any) -> tuple[str, ...]:
381-
recipients: list[str] = []
382-
seen = set()
383-
for value in values:
384-
for recipient in parse_email_recipients(value):
385-
if recipient in seen:
386-
continue
387-
recipients.append(recipient)
388-
seen.add(recipient)
389-
return tuple(recipients)
390-
391-
392370
def _coerce_bool(value: Any, *, default: bool) -> bool:
393371
if value is None:
394372
return default
@@ -404,18 +382,6 @@ def _fallback_alert_key(message: StrategyPluginAlertMessage) -> str:
404382
return "strategy_plugin_google_voice_alert/" + _clean_relative_key(message.subject or "unknown")
405383

406384

407-
def _alert_key_candidates(alert_key: str) -> tuple[str, ...]:
408-
key = str(alert_key or "")
409-
legacy_key = key.replace(
410-
"strategy_plugin_google_voice_alert/",
411-
"strategy_plugin_email_alert/",
412-
1,
413-
)
414-
if legacy_key != key:
415-
return (key, legacy_key)
416-
return (key,)
417-
418-
419385
def _clean_relative_key(value: str) -> str:
420386
parts = []
421387
for raw_part in str(value or "").replace("\\", "/").split("/"):
Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,29 +148,16 @@ def test_publish_strategy_plugin_google_voice_alerts_skips_duplicate_marker(tmp_
148148
assert second.deliveries[0].reason == "duplicate_alert"
149149

150150

151-
def test_google_voice_marker_store_reads_legacy_email_namespace(tmp_path):
152-
store = StrategyPluginGoogleVoiceAlertMarkerStore(local_dir=tmp_path)
153-
legacy_store = StrategyPluginGoogleVoiceAlertMarkerStore(
154-
local_dir=tmp_path,
155-
namespace="strategy_plugin_email_alerts",
156-
legacy_namespaces=(),
157-
)
158-
legacy_store.record_alert("strategy_plugin_email_alert/example")
159-
160-
assert store.has_alert("strategy_plugin_google_voice_alert/example")
161-
162-
163-
def test_google_voice_settings_read_new_names_and_legacy_email_recipients():
151+
def test_google_voice_settings_read_google_voice_names_only():
164152
settings = StrategyPluginGoogleVoiceSettings.from_object(
165153
SimpleNamespace(
166154
crisis_alert_smtp_host="smtp.gmail.com",
167155
crisis_alert_smtp_from="sender@gmail.com",
168156
crisis_alert_google_voice_to="gateway@txt.voice.google.com",
169-
crisis_alert_email_to="ops@example.com,gateway@txt.voice.google.com",
170157
crisis_alert_smtp_username="sender@gmail.com",
171158
)
172159
)
173160

174161
assert settings.sender == "sender@gmail.com"
175-
assert settings.recipients == ("gateway@txt.voice.google.com", "ops@example.com")
162+
assert settings.recipients == ("gateway@txt.voice.google.com",)
176163
assert settings.missing_fields() == ()

0 commit comments

Comments
 (0)