Skip to content

Commit f010935

Browse files
committed
emails
1 parent 2dbf7cb commit f010935

6 files changed

Lines changed: 32 additions & 16 deletions

File tree

examples/local_service_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def upsert_sandbox_listener(
9797
updated = client.update_listener(
9898
current.id,
9999
webhook_url=public_webhook_url,
100-
email=current.email,
100+
emails=current.emails,
101101
filters=current.filters,
102102
name=current.name or preferred_listener_name,
103103
active=True,

notamify_sdk/client.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def list_listeners(self) -> list[Listener]:
164164
def create_listener(
165165
self,
166166
webhook_url: str | None = None,
167-
email: str = "",
167+
emails: list[str] | None = None,
168168
filters: ListenerFilters | Mapping[str, Any] | None = None,
169169
name: str = "",
170170
active: bool | None = None,
@@ -175,7 +175,7 @@ def create_listener(
175175
body = self._prepare_body(
176176
self._build_listener_request_body(
177177
webhook_url=webhook_url,
178-
email=email,
178+
emails=emails,
179179
filters=filters,
180180
name=name,
181181
active=active,
@@ -192,7 +192,7 @@ def update_listener(
192192
self,
193193
listener_id: str,
194194
webhook_url: str | None = None,
195-
email: str = "",
195+
emails: list[str] | None = None,
196196
filters: ListenerFilters | Mapping[str, Any] | None = None,
197197
name: str = "",
198198
active: bool | None = None,
@@ -203,7 +203,7 @@ def update_listener(
203203
body = self._prepare_body(
204204
self._build_listener_request_body(
205205
webhook_url=webhook_url,
206-
email=email,
206+
emails=emails,
207207
filters=filters,
208208
name=name,
209209
active=active,
@@ -428,7 +428,7 @@ def _iterate_notam_pages(
428428
def _build_listener_request_body(
429429
self,
430430
webhook_url: str | None,
431-
email: str,
431+
emails: list[str] | None,
432432
filters: ListenerFilters | Mapping[str, Any] | None,
433433
name: str,
434434
active: bool | None,
@@ -438,7 +438,7 @@ def _build_listener_request_body(
438438
) -> dict[str, Any]:
439439
return {
440440
"webhook_url": self._normalize_listener_text(webhook_url),
441-
"email": self._normalize_listener_text(email),
441+
"emails": emails,
442442
"filters": filters or {},
443443
"name": self._normalize_listener_text(name),
444444
"active": active,

notamify_sdk/models.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def normalize_types(cls, value: Any) -> Any:
129129
class ListenerRequest(NotamifyModel):
130130
name: str | None = None
131131
webhook_url: str | None = None
132-
email: str | None = None
132+
emails: list[str] | None = None
133133
filters: ListenerFilters = Field(default_factory=ListenerFilters)
134134
lifecycle: ListenerLifecycleRequest | None = None
135135
active: bool | None = None
@@ -155,7 +155,7 @@ class Listener(NotamifyModel):
155155
id: str = ""
156156
name: str = ""
157157
webhook_url: str = ""
158-
email: str = ""
158+
emails: list[str] = Field(default_factory=list)
159159
filters: ListenerFilters = Field(default_factory=ListenerFilters)
160160
lifecycle: ListenerLifecycle = Field(default_factory=ListenerLifecycle)
161161
metadata: ListenerMetadata = Field(default_factory=ListenerMetadata)

notamify_watcher_sdk/client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def base_url(self, value: str) -> None:
3434
def create_listener(
3535
self,
3636
webhook_url: str,
37-
email: str = "",
37+
emails: list[str] | None = None,
3838
filters: Mapping[str, Any] | None = None,
3939
name: str = "",
4040
active: bool | None = None,
@@ -44,7 +44,7 @@ def create_listener(
4444
) -> Listener:
4545
return super().create_listener(
4646
webhook_url=webhook_url,
47-
email=email,
47+
emails=emails,
4848
filters=filters,
4949
name=name,
5050
active=active,
@@ -57,7 +57,7 @@ def update_listener(
5757
self,
5858
listener_id: str,
5959
webhook_url: str,
60-
email: str = "",
60+
emails: list[str] | None = None,
6161
filters: Mapping[str, Any] | None = None,
6262
name: str = "",
6363
active: bool | None = None,
@@ -68,7 +68,7 @@ def update_listener(
6868
return super().update_listener(
6969
listener_id=listener_id,
7070
webhook_url=webhook_url,
71-
email=email,
71+
emails=emails,
7272
filters=filters,
7373
name=name,
7474
active=active,

tests/test_client.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def do_GET(self):
5757
"id": "l1",
5858
"name": "listener-1",
5959
"webhook_url": "https://x",
60+
"emails": ["ops@example.com"],
6061
"filters": {"notam_icao": ["KJFK"]},
6162
"lifecycle": {"enabled": False, "types": []},
6263
"metadata": {"notams_shipped": 7},
@@ -189,6 +190,7 @@ def do_POST(self):
189190
"id": "new",
190191
"name": body.get("name", ""),
191192
"webhook_url": "https://x",
193+
"emails": body.get("emails", []),
192194
"filters": body.get("filters", {}),
193195
"lifecycle": body.get("lifecycle", {"enabled": False, "types": []}),
194196
"metadata": {"notams_shipped": 0},
@@ -268,6 +270,7 @@ def do_PUT(self):
268270
"id": "l1",
269271
"name": body.get("name", ""),
270272
"webhook_url": "https://x2",
273+
"emails": body.get("emails", []),
271274
"filters": body.get("filters", {}),
272275
"lifecycle": body.get("lifecycle", {"enabled": False, "types": []}),
273276
"metadata": {"notams_shipped": 10},
@@ -335,9 +338,11 @@ def test_watcher_methods(self):
335338
self.assertFalse(listeners[0].lifecycle.enabled)
336339
self.assertFalse(listeners[0].lifecycle_enabled)
337340
self.assertEqual(listeners[0].team.owner, "teammate-1")
341+
self.assertEqual(listeners[0].emails, ["ops@example.com"])
338342

339343
created = client.create_listener(
340344
"https://x",
345+
emails=["created@example.com"],
341346
mode="sandbox",
342347
lifecycle={"enabled": True, "types": ["cancelled"]},
343348
)
@@ -347,6 +352,9 @@ def test_watcher_methods(self):
347352
self.assertEqual(created.lifecycle.types[0].value, "CANCELLED")
348353
self.assertTrue(created.lifecycle_enabled)
349354
self.assertEqual(created.webhook_secret, "nmf_wh_new_listener")
355+
self.assertEqual(created.emails, ["created@example.com"])
356+
self.assertEqual(_Handler.last_create_body.get("emails"), ["created@example.com"])
357+
self.assertNotIn("email", _Handler.last_create_body)
350358
self.assertEqual(_Handler.last_create_body.get("mode"), "sandbox")
351359
self.assertEqual(
352360
_Handler.last_create_body.get("lifecycle"),
@@ -375,10 +383,10 @@ def test_watcher_methods(self):
375383

376384
def test_update_listener_preserves_explicit_empty_fields(self):
377385
client = NotamifyClient(token="t", watcher_base_url=self.base_url, api_base_url=self.base_url)
378-
client.update_listener("l1", "https://x2", email="", name="")
379-
self.assertIn("email", _Handler.last_update_body)
386+
client.update_listener("l1", "https://x2", emails=[], name="")
387+
self.assertIn("emails", _Handler.last_update_body)
380388
self.assertIn("name", _Handler.last_update_body)
381-
self.assertEqual(_Handler.last_update_body["email"], "")
389+
self.assertEqual(_Handler.last_update_body["emails"], [])
382390
self.assertEqual(_Handler.last_update_body["name"], "")
383391

384392
def test_default_user_agent_tracks_sdk_version(self):

tests/test_models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,27 @@ def test_listener_request_accepts_nested_lifecycle_shape(self):
210210
model = ListenerRequest.model_validate(
211211
{
212212
"webhook_url": "https://example.com/hook",
213+
"emails": ["ops@example.com"],
213214
"filters": {},
214215
"lifecycle": {
215216
"enabled": True,
216217
"types": ["cancelled", "REPLACED"],
217218
},
218219
}
219220
)
221+
self.assertEqual(model.emails, ["ops@example.com"])
220222
self.assertTrue(model.lifecycle.enabled)
221223
self.assertEqual([item.value for item in model.lifecycle.types], ["CANCELLED", "REPLACED"])
222224

225+
def test_listener_request_rejects_scalar_emails(self):
226+
with self.assertRaises(ValidationError):
227+
ListenerRequest.model_validate({"webhook_url": "https://example.com/hook", "emails": "ops@example.com"})
228+
223229
def test_listener_model_maps_legacy_lifecycle_enabled_to_nested_shape(self):
224230
model = Listener.model_validate(
225231
{
226232
"id": "l1",
233+
"emails": ["ops@example.com"],
227234
"filters": {},
228235
"metadata": {"notams_shipped": 0},
229236
"active": True,
@@ -233,6 +240,7 @@ def test_listener_model_maps_legacy_lifecycle_enabled_to_nested_shape(self):
233240
"updated_at": "2026-03-01T10:01:00Z",
234241
}
235242
)
243+
self.assertEqual(model.emails, ["ops@example.com"])
236244
self.assertTrue(model.lifecycle.enabled)
237245
self.assertTrue(model.lifecycle_enabled)
238246

0 commit comments

Comments
 (0)