vessel-api-python 1.3.0__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,13 @@
1
1
  """Service classes wrapping Vessel API endpoints.
2
2
 
3
3
  Each service groups related API endpoints and provides typed methods with
4
- sensible defaults. All endpoints that require ``filter_id_type`` default
5
- to ``"imo"`` to match the Go SDK behaviour.
4
+ sensible defaults.
5
+
6
+ Parameters the API declares as required are keyword-only with no default, so
7
+ omitting one raises ``TypeError`` at the call rather than an HTTP 400 from the
8
+ server. They are listed first in each signature. The one exception is
9
+ ``filter_id_type``: the API requires it, but the SDK always sends it and
10
+ defaults it to ``"imo"``.
6
11
 
7
12
  Services come in sync and async variants. The async variants have the same
8
13
  method signatures but use ``await`` for HTTP calls.
@@ -10,13 +15,12 @@ method signatures but use ``await`` for HTTP calls.
10
15
 
11
16
  from __future__ import annotations
12
17
 
13
- from typing import TYPE_CHECKING, Any
18
+ from typing import TYPE_CHECKING, Any, Union
14
19
 
15
20
  from ._errors import error_from_response
16
21
  from ._iterator import AsyncIterator, SyncIterator
17
22
  from ._models import (
18
23
  MODU,
19
- ClassificationResponse,
20
24
  DGPSStation,
21
25
  DGPSStationsWithinLocationResponse,
22
26
  FindDGPSStationsResponse,
@@ -30,8 +34,6 @@ from ._models import (
30
34
  MarineCasualtiesResponse,
31
35
  MarineCasualty,
32
36
  MODUsWithinLocationResponse,
33
- Navtex,
34
- NavtexMessagesResponse,
35
37
  Port,
36
38
  PortEvent,
37
39
  PortEventResponse,
@@ -41,9 +43,6 @@ from ._models import (
41
43
  PortsWithinLocationResponse,
42
44
  RadioBeacon,
43
45
  RadioBeaconsWithinLocationResponse,
44
- TypesInspectionDetailResponse,
45
- TypesInspectionsResponse,
46
- TypesOwnershipResponse,
47
46
  Vessel,
48
47
  VesselEmission,
49
48
  VesselEmissionsResponse,
@@ -60,8 +59,20 @@ if TYPE_CHECKING:
60
59
  import httpx
61
60
 
62
61
 
62
+ #: A filter the API accepts more than once.
63
+ #:
64
+ #: Pass a single string for one value, or a list of strings to match several.
65
+ #: A list is sent as a repeated query parameter (``?filter.flag=GB&filter.flag=NO``),
66
+ #: not a comma-joined string.
67
+ MultiFilter = Union[str, list[str]]
68
+
69
+
63
70
  def _strip_none(params: dict[str, Any]) -> dict[str, Any]:
64
- """Remove keys with None values from a dict of query params."""
71
+ """Remove keys with None values from a dict of query params.
72
+
73
+ List values pass through untouched: httpx serialises a list into a repeated
74
+ query parameter, which is what the API expects for its multi-value filters.
75
+ """
65
76
  return {k: v for k, v in params.items() if v is not None}
66
77
 
67
78
 
@@ -82,27 +93,61 @@ class VesselsService:
82
93
  error_from_response(r.status_code, r.content)
83
94
  return VesselResponse.model_validate(r.json())
84
95
 
85
- def position(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselPositionResponse:
86
- """Retrieve the latest position for a vessel."""
87
- r = self._client.get(f"/vessel/{vessel_id}/position", params=_strip_none({"filter.idType": filter_id_type}))
96
+ def position(
97
+ self, vessel_id: str, *, filter_id_type: str = "imo", filter_sat: bool | None = None
98
+ ) -> VesselPositionResponse:
99
+ """Retrieve the latest position for a vessel.
100
+
101
+ ``filter_sat`` enables satellite AIS fallback; the server defaults it to false.
102
+ """
103
+ r = self._client.get(
104
+ f"/vessel/{vessel_id}/position",
105
+ params=_strip_none({"filter.idType": filter_id_type, "filter.sat": filter_sat}),
106
+ )
88
107
  error_from_response(r.status_code, r.content)
89
108
  return VesselPositionResponse.model_validate(r.json())
90
109
 
91
- def casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MarineCasualtiesResponse:
110
+ def casualties(
111
+ self,
112
+ vessel_id: str,
113
+ *,
114
+ filter_id_type: str = "imo",
115
+ pagination_limit: int | None = None,
116
+ pagination_next_token: str | None = None,
117
+ ) -> MarineCasualtiesResponse:
92
118
  """Retrieve marine casualty records for a vessel."""
93
- r = self._client.get(f"/vessel/{vessel_id}/casualties", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
119
+ r = self._client.get(
120
+ f"/vessel/{vessel_id}/casualties",
121
+ params=_strip_none(
122
+ {
123
+ "filter.idType": filter_id_type,
124
+ "pagination.limit": pagination_limit,
125
+ "pagination.nextToken": pagination_next_token,
126
+ }
127
+ ),
128
+ )
94
129
  error_from_response(r.status_code, r.content)
95
130
  return MarineCasualtiesResponse.model_validate(r.json())
96
131
 
97
- def classification(self, vessel_id: str, *, filter_id_type: str = "imo") -> ClassificationResponse:
98
- """Retrieve classification data for a vessel."""
99
- r = self._client.get(f"/vessel/{vessel_id}/classification", params=_strip_none({"filter.idType": filter_id_type}))
100
- error_from_response(r.status_code, r.content)
101
- return ClassificationResponse.model_validate(r.json())
102
-
103
- def emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
132
+ def emissions(
133
+ self,
134
+ vessel_id: str,
135
+ *,
136
+ filter_id_type: str = "imo",
137
+ pagination_limit: int | None = None,
138
+ pagination_next_token: str | None = None,
139
+ ) -> VesselEmissionsResponse:
104
140
  """Retrieve emissions data for a vessel."""
105
- r = self._client.get(f"/vessel/{vessel_id}/emissions", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
141
+ r = self._client.get(
142
+ f"/vessel/{vessel_id}/emissions",
143
+ params=_strip_none(
144
+ {
145
+ "filter.idType": filter_id_type,
146
+ "pagination.limit": pagination_limit,
147
+ "pagination.nextToken": pagination_next_token,
148
+ }
149
+ ),
150
+ )
106
151
  error_from_response(r.status_code, r.content)
107
152
  return VesselEmissionsResponse.model_validate(r.json())
108
153
 
@@ -112,60 +157,96 @@ class VesselsService:
112
157
  error_from_response(r.status_code, r.content)
113
158
  return VesselETAResponse.model_validate(r.json())
114
159
 
115
- def inspections(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> TypesInspectionsResponse:
116
- """Retrieve inspection records for a vessel."""
117
- r = self._client.get(f"/vessel/{vessel_id}/inspections", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
118
- error_from_response(r.status_code, r.content)
119
- return TypesInspectionsResponse.model_validate(r.json())
120
-
121
- def inspection_detail(self, vessel_id: str, detail_id: str, *, filter_id_type: str = "imo") -> TypesInspectionDetailResponse:
122
- """Retrieve detailed inspection data."""
123
- r = self._client.get(f"/vessel/{vessel_id}/inspections/{detail_id}", params=_strip_none({"filter.idType": filter_id_type}))
124
- error_from_response(r.status_code, r.content)
125
- return TypesInspectionDetailResponse.model_validate(r.json())
126
-
127
- def ownership(self, vessel_id: str, *, filter_id_type: str = "imo") -> TypesOwnershipResponse:
128
- """Retrieve ownership data for a vessel."""
129
- r = self._client.get(f"/vessel/{vessel_id}/ownership", params=_strip_none({"filter.idType": filter_id_type}))
130
- error_from_response(r.status_code, r.content)
131
- return TypesOwnershipResponse.model_validate(r.json())
132
-
133
- def positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselPositionsResponse:
134
- """Retrieve positions for multiple vessels."""
135
- r = self._client.get("/vessels/positions", params=_strip_none({"filter.idType": filter_id_type, "filter.ids": filter_ids, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
160
+ def positions(
161
+ self,
162
+ *,
163
+ filter_ids: MultiFilter,
164
+ filter_id_type: str = "imo",
165
+ time_from: str | None = None,
166
+ time_to: str | None = None,
167
+ pagination_limit: int | None = None,
168
+ pagination_next_token: str | None = None,
169
+ ) -> VesselPositionsResponse:
170
+ """Retrieve positions for multiple vessels.
171
+
172
+ ``filter_ids`` takes a comma-separated string or a list of ids; a list is
173
+ sent as a repeated ``filter.ids`` parameter.
174
+ """
175
+ r = self._client.get(
176
+ "/vessels/positions",
177
+ params=_strip_none(
178
+ {
179
+ "filter.idType": filter_id_type,
180
+ "filter.ids": filter_ids,
181
+ "time.from": time_from,
182
+ "time.to": time_to,
183
+ "pagination.limit": pagination_limit,
184
+ "pagination.nextToken": pagination_next_token,
185
+ }
186
+ ),
187
+ )
136
188
  error_from_response(r.status_code, r.content)
137
189
  return VesselPositionsResponse.model_validate(r.json())
138
190
 
139
191
  # --- Iterators ---
140
192
 
141
- def all_casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> SyncIterator[MarineCasualty]:
193
+ def all_casualties(
194
+ self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None
195
+ ) -> SyncIterator[MarineCasualty]:
142
196
  """Iterate over all casualties for a vessel across pages."""
143
197
  token: str | None = None
198
+
144
199
  def fetch() -> tuple[list[MarineCasualty], str | None]:
145
200
  nonlocal token
146
- resp = self.casualties(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
201
+ resp = self.casualties(
202
+ vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token
203
+ )
147
204
  token = resp.next_token
148
205
  return resp.casualties or [], token
206
+
149
207
  return SyncIterator(fetch)
150
208
 
151
- def all_emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> SyncIterator[VesselEmission]:
209
+ def all_emissions(
210
+ self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None
211
+ ) -> SyncIterator[VesselEmission]:
152
212
  """Iterate over all emissions for a vessel across pages."""
153
213
  token: str | None = None
214
+
154
215
  def fetch() -> tuple[list[VesselEmission], str | None]:
155
216
  nonlocal token
156
- resp = self.emissions(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
217
+ resp = self.emissions(
218
+ vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token
219
+ )
157
220
  token = resp.next_token
158
221
  return resp.emissions or [], token
222
+
159
223
  return SyncIterator(fetch)
160
224
 
161
- def all_positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None) -> SyncIterator[VesselPosition]:
225
+ def all_positions(
226
+ self,
227
+ *,
228
+ filter_ids: MultiFilter,
229
+ filter_id_type: str = "imo",
230
+ time_from: str | None = None,
231
+ time_to: str | None = None,
232
+ pagination_limit: int | None = None,
233
+ ) -> SyncIterator[VesselPosition]:
162
234
  """Iterate over all positions for multiple vessels across pages."""
163
235
  token: str | None = None
236
+
164
237
  def fetch() -> tuple[list[VesselPosition], str | None]:
165
238
  nonlocal token
166
- resp = self.positions(filter_id_type=filter_id_type, filter_ids=filter_ids, pagination_limit=pagination_limit, pagination_next_token=token)
239
+ resp = self.positions(
240
+ filter_id_type=filter_id_type,
241
+ filter_ids=filter_ids,
242
+ time_from=time_from,
243
+ time_to=time_to,
244
+ pagination_limit=pagination_limit,
245
+ pagination_next_token=token,
246
+ )
167
247
  token = resp.next_token
168
248
  return resp.vessel_positions or [], token
249
+
169
250
  return SyncIterator(fetch)
170
251
 
171
252
 
@@ -181,20 +262,61 @@ class PortsService:
181
262
  error_from_response(r.status_code, r.content)
182
263
  return PortResponse.model_validate(r.json())
183
264
 
184
- def inbound(self, unlocode: str, *, eta_from: str, eta_to: str, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortInboundResponse:
265
+ def inbound(
266
+ self,
267
+ unlocode: str,
268
+ *,
269
+ eta_from: str | None = None,
270
+ eta_to: str | None = None,
271
+ time_from: str | None = None,
272
+ time_to: str | None = None,
273
+ pagination_limit: int | None = None,
274
+ pagination_next_token: str | None = None,
275
+ ) -> PortInboundResponse:
185
276
  """Retrieve vessels heading to a port."""
186
- r = self._client.get(f"/port/{unlocode}/inbound", params=_strip_none({"filter.etaFrom": eta_from, "filter.etaTo": eta_to, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
277
+ r = self._client.get(
278
+ f"/port/{unlocode}/inbound",
279
+ params=_strip_none(
280
+ {
281
+ "filter.etaFrom": eta_from,
282
+ "filter.etaTo": eta_to,
283
+ "time.from": time_from,
284
+ "time.to": time_to,
285
+ "pagination.limit": pagination_limit,
286
+ "pagination.nextToken": pagination_next_token,
287
+ }
288
+ ),
289
+ )
187
290
  error_from_response(r.status_code, r.content)
188
291
  return PortInboundResponse.model_validate(r.json())
189
292
 
190
- def inbound_all(self, unlocode: str, *, eta_from: str, eta_to: str, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None) -> SyncIterator[VesselETA]:
293
+ def inbound_all(
294
+ self,
295
+ unlocode: str,
296
+ *,
297
+ eta_from: str | None = None,
298
+ eta_to: str | None = None,
299
+ time_from: str | None = None,
300
+ time_to: str | None = None,
301
+ pagination_limit: int | None = None,
302
+ ) -> SyncIterator[VesselETA]:
191
303
  """Iterate over all inbound vessels for a port across pages."""
192
304
  token: str | None = None
305
+
193
306
  def fetch() -> tuple[list[VesselETA], str | None]:
194
307
  nonlocal token
195
- resp = self.inbound(unlocode, eta_from=eta_from, eta_to=eta_to, time_from=time_from, time_to=time_to, pagination_limit=pagination_limit, pagination_next_token=token)
308
+ resp = self.inbound(
309
+ unlocode,
310
+ eta_from=eta_from,
311
+ eta_to=eta_to,
312
+ time_from=time_from,
313
+ time_to=time_to,
314
+ pagination_limit=pagination_limit,
315
+ pagination_next_token=token,
316
+ )
196
317
  token = resp.next_token
197
318
  return resp.vessel_etas or [], token
319
+
198
320
  return SyncIterator(fetch)
199
321
 
200
322
 
@@ -204,92 +326,302 @@ class PortEventsService:
204
326
  def __init__(self, client: httpx.Client) -> None:
205
327
  self._client = client
206
328
 
207
- def list(self, *, time_from: str | None = None, time_to: str | None = None, filter_country: str | None = None, filter_unlocode: str | None = None, filter_event_type: str | None = None, filter_vessel_name: str | None = None, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
329
+ def list(
330
+ self,
331
+ *,
332
+ time_from: str | None = None,
333
+ time_to: str | None = None,
334
+ filter_country: str | None = None,
335
+ filter_unlocode: str | None = None,
336
+ filter_event_type: str | None = None,
337
+ filter_vessel_name: str | None = None,
338
+ filter_port_name: str | None = None,
339
+ pagination_limit: int | None = None,
340
+ pagination_next_token: str | None = None,
341
+ ) -> PortEventsResponse:
208
342
  """Retrieve port events with optional filtering."""
209
- r = self._client.get("/portevents", params=_strip_none({"time.from": time_from, "time.to": time_to, "filter.country": filter_country, "filter.unlocode": filter_unlocode, "filter.eventType": filter_event_type, "filter.vesselName": filter_vessel_name, "filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
343
+ r = self._client.get(
344
+ "/portevents",
345
+ params=_strip_none(
346
+ {
347
+ "time.from": time_from,
348
+ "time.to": time_to,
349
+ "filter.country": filter_country,
350
+ "filter.unlocode": filter_unlocode,
351
+ "filter.eventType": filter_event_type,
352
+ "filter.vesselName": filter_vessel_name,
353
+ "filter.portName": filter_port_name,
354
+ "pagination.limit": pagination_limit,
355
+ "pagination.nextToken": pagination_next_token,
356
+ }
357
+ ),
358
+ )
210
359
  error_from_response(r.status_code, r.content)
211
360
  return PortEventsResponse.model_validate(r.json())
212
361
 
213
- def by_port(self, unlocode: str, *, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
214
- """Retrieve port events for a specific port by UNLOCODE."""
215
- r = self._client.get(f"/portevents/port/{unlocode}", params=_strip_none({"pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
362
+ def by_port(
363
+ self,
364
+ unlocode: str,
365
+ *,
366
+ time_from: str | None = None,
367
+ time_to: str | None = None,
368
+ pagination_limit: int | None = None,
369
+ pagination_next_token: str | None = None,
370
+ ) -> PortEventsResponse:
371
+ """Retrieve port events for a specific port by UNLOCODE.
372
+
373
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
374
+ window to the last two hours.
375
+ """
376
+ r = self._client.get(
377
+ f"/portevents/port/{unlocode}",
378
+ params=_strip_none(
379
+ {
380
+ "time.from": time_from,
381
+ "time.to": time_to,
382
+ "pagination.limit": pagination_limit,
383
+ "pagination.nextToken": pagination_next_token,
384
+ }
385
+ ),
386
+ )
216
387
  error_from_response(r.status_code, r.content)
217
388
  return PortEventsResponse.model_validate(r.json())
218
389
 
219
- def by_ports(self, *, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
220
- """Retrieve port events by port name search."""
221
- r = self._client.get("/portevents/ports", params=_strip_none({"filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
390
+ def by_ports(
391
+ self,
392
+ *,
393
+ filter_port_name: str,
394
+ time_from: str | None = None,
395
+ time_to: str | None = None,
396
+ pagination_limit: int | None = None,
397
+ pagination_next_token: str | None = None,
398
+ ) -> PortEventsResponse:
399
+ """Retrieve port events by port name search.
400
+
401
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
402
+ window to the last two hours.
403
+ """
404
+ r = self._client.get(
405
+ "/portevents/ports",
406
+ params=_strip_none(
407
+ {
408
+ "filter.portName": filter_port_name,
409
+ "time.from": time_from,
410
+ "time.to": time_to,
411
+ "pagination.limit": pagination_limit,
412
+ "pagination.nextToken": pagination_next_token,
413
+ }
414
+ ),
415
+ )
222
416
  error_from_response(r.status_code, r.content)
223
417
  return PortEventsResponse.model_validate(r.json())
224
418
 
225
- def by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo", filter_event_type: str | None = None, filter_sort_order: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
419
+ def by_vessel(
420
+ self,
421
+ vessel_id: str,
422
+ *,
423
+ filter_id_type: str = "imo",
424
+ filter_event_type: str | None = None,
425
+ filter_sort_order: str | None = None,
426
+ time_from: str | None = None,
427
+ time_to: str | None = None,
428
+ pagination_limit: int | None = None,
429
+ pagination_next_token: str | None = None,
430
+ ) -> PortEventsResponse:
226
431
  """Retrieve port events for a specific vessel."""
227
- r = self._client.get(f"/portevents/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type, "filter.eventType": filter_event_type, "filter.sortOrder": filter_sort_order, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
432
+ r = self._client.get(
433
+ f"/portevents/vessel/{vessel_id}",
434
+ params=_strip_none(
435
+ {
436
+ "filter.idType": filter_id_type,
437
+ "filter.eventType": filter_event_type,
438
+ "filter.sortOrder": filter_sort_order,
439
+ "time.from": time_from,
440
+ "time.to": time_to,
441
+ "pagination.limit": pagination_limit,
442
+ "pagination.nextToken": pagination_next_token,
443
+ }
444
+ ),
445
+ )
228
446
  error_from_response(r.status_code, r.content)
229
447
  return PortEventsResponse.model_validate(r.json())
230
448
 
231
449
  def last_by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo") -> PortEventResponse:
232
450
  """Retrieve the last port event for a vessel."""
233
- r = self._client.get(f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type}))
451
+ r = self._client.get(
452
+ f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type})
453
+ )
234
454
  error_from_response(r.status_code, r.content)
235
455
  return PortEventResponse.model_validate(r.json())
236
456
 
237
- def by_vessels(self, *, filter_vessel_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
238
- """Retrieve port events by vessel name search."""
239
- r = self._client.get("/portevents/vessels", params=_strip_none({"filter.vesselName": filter_vessel_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
457
+ def by_vessels(
458
+ self,
459
+ *,
460
+ filter_vessel_name: str,
461
+ time_from: str | None = None,
462
+ time_to: str | None = None,
463
+ pagination_limit: int | None = None,
464
+ pagination_next_token: str | None = None,
465
+ ) -> PortEventsResponse:
466
+ """Retrieve port events by vessel name search.
467
+
468
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
469
+ window to the last two hours.
470
+ """
471
+ r = self._client.get(
472
+ "/portevents/vessels",
473
+ params=_strip_none(
474
+ {
475
+ "filter.vesselName": filter_vessel_name,
476
+ "time.from": time_from,
477
+ "time.to": time_to,
478
+ "pagination.limit": pagination_limit,
479
+ "pagination.nextToken": pagination_next_token,
480
+ }
481
+ ),
482
+ )
240
483
  error_from_response(r.status_code, r.content)
241
484
  return PortEventsResponse.model_validate(r.json())
242
485
 
243
486
  # --- Iterators ---
244
487
 
245
- def list_all(self, **kwargs: Any) -> SyncIterator[PortEvent]:
488
+ def list_all(
489
+ self,
490
+ *,
491
+ time_from: str | None = None,
492
+ time_to: str | None = None,
493
+ filter_country: str | None = None,
494
+ filter_unlocode: str | None = None,
495
+ filter_event_type: str | None = None,
496
+ filter_vessel_name: str | None = None,
497
+ filter_port_name: str | None = None,
498
+ pagination_limit: int | None = None,
499
+ ) -> SyncIterator[PortEvent]:
246
500
  """Iterate over all port events across pages."""
247
501
  token: str | None = None
502
+
248
503
  def fetch() -> tuple[list[PortEvent], str | None]:
249
504
  nonlocal token
250
- resp = self.list(**kwargs, pagination_next_token=token)
505
+ resp = self.list(
506
+ time_from=time_from,
507
+ time_to=time_to,
508
+ filter_country=filter_country,
509
+ filter_unlocode=filter_unlocode,
510
+ filter_event_type=filter_event_type,
511
+ filter_vessel_name=filter_vessel_name,
512
+ filter_port_name=filter_port_name,
513
+ pagination_limit=pagination_limit,
514
+ pagination_next_token=token,
515
+ )
251
516
  token = resp.next_token
252
517
  return resp.port_events or [], token
518
+
253
519
  return SyncIterator(fetch)
254
520
 
255
- def all_by_port(self, unlocode: str, **kwargs: Any) -> SyncIterator[PortEvent]:
521
+ def all_by_port(
522
+ self,
523
+ unlocode: str,
524
+ *,
525
+ time_from: str | None = None,
526
+ time_to: str | None = None,
527
+ pagination_limit: int | None = None,
528
+ ) -> SyncIterator[PortEvent]:
256
529
  """Iterate over all port events for a specific port."""
257
530
  token: str | None = None
531
+
258
532
  def fetch() -> tuple[list[PortEvent], str | None]:
259
533
  nonlocal token
260
- resp = self.by_port(unlocode, **kwargs, pagination_next_token=token)
534
+ resp = self.by_port(
535
+ unlocode,
536
+ time_from=time_from,
537
+ time_to=time_to,
538
+ pagination_limit=pagination_limit,
539
+ pagination_next_token=token,
540
+ )
261
541
  token = resp.next_token
262
542
  return resp.port_events or [], token
543
+
263
544
  return SyncIterator(fetch)
264
545
 
265
- def all_by_ports(self, **kwargs: Any) -> SyncIterator[PortEvent]:
546
+ def all_by_ports(
547
+ self,
548
+ *,
549
+ filter_port_name: str,
550
+ time_from: str | None = None,
551
+ time_to: str | None = None,
552
+ pagination_limit: int | None = None,
553
+ ) -> SyncIterator[PortEvent]:
266
554
  """Iterate over all port events by port name search."""
267
555
  token: str | None = None
556
+
268
557
  def fetch() -> tuple[list[PortEvent], str | None]:
269
558
  nonlocal token
270
- resp = self.by_ports(**kwargs, pagination_next_token=token)
559
+ resp = self.by_ports(
560
+ filter_port_name=filter_port_name,
561
+ time_from=time_from,
562
+ time_to=time_to,
563
+ pagination_limit=pagination_limit,
564
+ pagination_next_token=token,
565
+ )
271
566
  token = resp.next_token
272
567
  return resp.port_events or [], token
568
+
273
569
  return SyncIterator(fetch)
274
570
 
275
- def all_by_vessel(self, vessel_id: str, **kwargs: Any) -> SyncIterator[PortEvent]:
571
+ def all_by_vessel(
572
+ self,
573
+ vessel_id: str,
574
+ *,
575
+ filter_id_type: str = "imo",
576
+ filter_event_type: str | None = None,
577
+ filter_sort_order: str | None = None,
578
+ time_from: str | None = None,
579
+ time_to: str | None = None,
580
+ pagination_limit: int | None = None,
581
+ ) -> SyncIterator[PortEvent]:
276
582
  """Iterate over all port events for a vessel."""
277
583
  token: str | None = None
584
+
278
585
  def fetch() -> tuple[list[PortEvent], str | None]:
279
586
  nonlocal token
280
- resp = self.by_vessel(vessel_id, **kwargs, pagination_next_token=token)
587
+ resp = self.by_vessel(
588
+ vessel_id,
589
+ filter_id_type=filter_id_type,
590
+ filter_event_type=filter_event_type,
591
+ filter_sort_order=filter_sort_order,
592
+ time_from=time_from,
593
+ time_to=time_to,
594
+ pagination_limit=pagination_limit,
595
+ pagination_next_token=token,
596
+ )
281
597
  token = resp.next_token
282
598
  return resp.port_events or [], token
599
+
283
600
  return SyncIterator(fetch)
284
601
 
285
- def all_by_vessels(self, **kwargs: Any) -> SyncIterator[PortEvent]:
602
+ def all_by_vessels(
603
+ self,
604
+ *,
605
+ filter_vessel_name: str,
606
+ time_from: str | None = None,
607
+ time_to: str | None = None,
608
+ pagination_limit: int | None = None,
609
+ ) -> SyncIterator[PortEvent]:
286
610
  """Iterate over all port events by vessel name search."""
287
611
  token: str | None = None
612
+
288
613
  def fetch() -> tuple[list[PortEvent], str | None]:
289
614
  nonlocal token
290
- resp = self.by_vessels(**kwargs, pagination_next_token=token)
615
+ resp = self.by_vessels(
616
+ filter_vessel_name=filter_vessel_name,
617
+ time_from=time_from,
618
+ time_to=time_to,
619
+ pagination_limit=pagination_limit,
620
+ pagination_next_token=token,
621
+ )
291
622
  token = resp.next_token
292
623
  return resp.port_events or [], token
624
+
293
625
  return SyncIterator(fetch)
294
626
 
295
627
 
@@ -299,20 +631,41 @@ class EmissionsService:
299
631
  def __init__(self, client: httpx.Client) -> None:
300
632
  self._client = client
301
633
 
302
- def list(self, *, filter_period: int | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
634
+ def list(
635
+ self,
636
+ *,
637
+ filter_period: int | None = None,
638
+ pagination_limit: int | None = None,
639
+ pagination_next_token: str | None = None,
640
+ ) -> VesselEmissionsResponse:
303
641
  """Retrieve vessel emissions data."""
304
- r = self._client.get("/emissions", params=_strip_none({"filter.period": filter_period, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
642
+ r = self._client.get(
643
+ "/emissions",
644
+ params=_strip_none(
645
+ {
646
+ "filter.period": filter_period,
647
+ "pagination.limit": pagination_limit,
648
+ "pagination.nextToken": pagination_next_token,
649
+ }
650
+ ),
651
+ )
305
652
  error_from_response(r.status_code, r.content)
306
653
  return VesselEmissionsResponse.model_validate(r.json())
307
654
 
308
- def list_all(self, **kwargs: Any) -> SyncIterator[VesselEmission]:
655
+ def list_all(
656
+ self, *, filter_period: int | None = None, pagination_limit: int | None = None
657
+ ) -> SyncIterator[VesselEmission]:
309
658
  """Iterate over all emissions across pages."""
310
659
  token: str | None = None
660
+
311
661
  def fetch() -> tuple[list[VesselEmission], str | None]:
312
662
  nonlocal token
313
- resp = self.list(**kwargs, pagination_next_token=token)
663
+ resp = self.list(
664
+ filter_period=filter_period, pagination_limit=pagination_limit, pagination_next_token=token
665
+ )
314
666
  token = resp.next_token
315
667
  return resp.emissions or [], token
668
+
316
669
  return SyncIterator(fetch)
317
670
 
318
671
 
@@ -322,102 +675,282 @@ class SearchService:
322
675
  def __init__(self, client: httpx.Client) -> None:
323
676
  self._client = client
324
677
 
325
- def vessels(self, *, filter_name: str | None = None, filter_imo: str | None = None, filter_mmsi: str | None = None, filter_flag: str | None = None, filter_vessel_type: str | None = None, filter_callsign: str | None = None, filter_year_built_min: int | None = None, filter_year_built_max: int | None = None, filter_class_society: str | None = None, filter_owner: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindVesselsResponse:
326
- """Search for vessels by name, callsign, flag, type, and other filters."""
327
- r = self._client.get("/search/vessels", params=_strip_none({"filter.name": filter_name, "filter.imo": filter_imo, "filter.mmsi": filter_mmsi, "filter.flag": filter_flag, "filter.vesselType": filter_vessel_type, "filter.callsign": filter_callsign, "filter.yearBuiltMin": filter_year_built_min, "filter.yearBuiltMax": filter_year_built_max, "filter.classSociety": filter_class_society, "filter.owner": filter_owner, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
678
+ def vessels(
679
+ self,
680
+ *,
681
+ q: str | None = None,
682
+ filter_name: str | None = None,
683
+ filter_imo: str | None = None,
684
+ filter_mmsi: str | None = None,
685
+ filter_eni: str | None = None,
686
+ filter_flag: MultiFilter | None = None,
687
+ filter_vessel_type: MultiFilter | None = None,
688
+ filter_callsign: str | None = None,
689
+ filter_year_built_min: int | None = None,
690
+ filter_year_built_max: int | None = None,
691
+ pagination_limit: int | None = None,
692
+ pagination_next_token: str | None = None,
693
+ ) -> FindVesselsResponse:
694
+ """Search for vessels by name, callsign, flag, type, and other filters.
695
+
696
+ ``q`` is a unified search across IMO, MMSI, ENI, callsign and name; it
697
+ populates ``_meta`` on the response with the fields that matched.
698
+
699
+ ``filter_flag`` and ``filter_vessel_type`` accept a list to match several
700
+ values; each list is sent as a repeated query parameter.
701
+ """
702
+ r = self._client.get(
703
+ "/search/vessels",
704
+ params=_strip_none(
705
+ {
706
+ "q": q,
707
+ "filter.name": filter_name,
708
+ "filter.imo": filter_imo,
709
+ "filter.mmsi": filter_mmsi,
710
+ "filter.eni": filter_eni,
711
+ "filter.flag": filter_flag,
712
+ "filter.vesselType": filter_vessel_type,
713
+ "filter.callsign": filter_callsign,
714
+ "filter.yearBuiltMin": filter_year_built_min,
715
+ "filter.yearBuiltMax": filter_year_built_max,
716
+ "pagination.limit": pagination_limit,
717
+ "pagination.nextToken": pagination_next_token,
718
+ }
719
+ ),
720
+ )
328
721
  error_from_response(r.status_code, r.content)
329
722
  return FindVesselsResponse.model_validate(r.json())
330
723
 
331
- def ports(self, *, filter_name: str | None = None, filter_country: str | None = None, filter_port_type: str | None = None, filter_size: str | None = None, filter_region: str | None = None, filter_harbor_size: str | None = None, filter_harbor_use: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindPortsResponse:
332
- """Search for ports by name, country, type, region, and other filters."""
333
- r = self._client.get("/search/ports", params=_strip_none({"filter.name": filter_name, "filter.country": filter_country, "filter.type": filter_port_type, "filter.size": filter_size, "filter.region": filter_region, "filter.harborSize": filter_harbor_size, "filter.harborUse": filter_harbor_use, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
724
+ def ports(
725
+ self,
726
+ *,
727
+ filter_name: str | None = None,
728
+ filter_country: MultiFilter | None = None,
729
+ filter_port_type: MultiFilter | None = None,
730
+ filter_size: MultiFilter | None = None,
731
+ filter_region: str | None = None,
732
+ filter_harbor_size: MultiFilter | None = None,
733
+ filter_harbor_use: MultiFilter | None = None,
734
+ pagination_limit: int | None = None,
735
+ pagination_next_token: str | None = None,
736
+ ) -> FindPortsResponse:
737
+ """Search for ports by name, country, type, region, and other filters.
738
+
739
+ ``filter_country``, ``filter_port_type``, ``filter_size``,
740
+ ``filter_harbor_size`` and ``filter_harbor_use`` accept a list to match
741
+ several values; each list is sent as a repeated query parameter.
742
+ """
743
+ r = self._client.get(
744
+ "/search/ports",
745
+ params=_strip_none(
746
+ {
747
+ "filter.name": filter_name,
748
+ "filter.country": filter_country,
749
+ "filter.type": filter_port_type,
750
+ "filter.size": filter_size,
751
+ "filter.region": filter_region,
752
+ "filter.harborSize": filter_harbor_size,
753
+ "filter.harborUse": filter_harbor_use,
754
+ "pagination.limit": pagination_limit,
755
+ "pagination.nextToken": pagination_next_token,
756
+ }
757
+ ),
758
+ )
334
759
  error_from_response(r.status_code, r.content)
335
760
  return FindPortsResponse.model_validate(r.json())
336
761
 
337
- def dgps(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindDGPSStationsResponse:
762
+ def dgps(
763
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
764
+ ) -> FindDGPSStationsResponse:
338
765
  """Search for DGPS stations by name."""
339
- r = self._client.get("/search/dgps", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
766
+ r = self._client.get(
767
+ "/search/dgps",
768
+ params=_strip_none(
769
+ {
770
+ "filter.name": filter_name,
771
+ "pagination.limit": pagination_limit,
772
+ "pagination.nextToken": pagination_next_token,
773
+ }
774
+ ),
775
+ )
340
776
  error_from_response(r.status_code, r.content)
341
777
  return FindDGPSStationsResponse.model_validate(r.json())
342
778
 
343
- def light_aids(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindLightAidsResponse:
779
+ def light_aids(
780
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
781
+ ) -> FindLightAidsResponse:
344
782
  """Search for light aids by name."""
345
- r = self._client.get("/search/lightaids", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
783
+ r = self._client.get(
784
+ "/search/lightaids",
785
+ params=_strip_none(
786
+ {
787
+ "filter.name": filter_name,
788
+ "pagination.limit": pagination_limit,
789
+ "pagination.nextToken": pagination_next_token,
790
+ }
791
+ ),
792
+ )
346
793
  error_from_response(r.status_code, r.content)
347
794
  return FindLightAidsResponse.model_validate(r.json())
348
795
 
349
- def modus(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindMODUsResponse:
796
+ def modus(
797
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
798
+ ) -> FindMODUsResponse:
350
799
  """Search for MODUs (Mobile Offshore Drilling Units) by name."""
351
- r = self._client.get("/search/modus", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
800
+ r = self._client.get(
801
+ "/search/modus",
802
+ params=_strip_none(
803
+ {
804
+ "filter.name": filter_name,
805
+ "pagination.limit": pagination_limit,
806
+ "pagination.nextToken": pagination_next_token,
807
+ }
808
+ ),
809
+ )
352
810
  error_from_response(r.status_code, r.content)
353
811
  return FindMODUsResponse.model_validate(r.json())
354
812
 
355
- def radio_beacons(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindRadioBeaconsResponse:
813
+ def radio_beacons(
814
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
815
+ ) -> FindRadioBeaconsResponse:
356
816
  """Search for radio beacons by name."""
357
- r = self._client.get("/search/radiobeacons", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
817
+ r = self._client.get(
818
+ "/search/radiobeacons",
819
+ params=_strip_none(
820
+ {
821
+ "filter.name": filter_name,
822
+ "pagination.limit": pagination_limit,
823
+ "pagination.nextToken": pagination_next_token,
824
+ }
825
+ ),
826
+ )
358
827
  error_from_response(r.status_code, r.content)
359
828
  return FindRadioBeaconsResponse.model_validate(r.json())
360
829
 
361
830
  # --- Iterators ---
362
831
 
363
- def all_vessels(self, **kwargs: Any) -> SyncIterator[Vessel]:
832
+ def all_vessels(
833
+ self,
834
+ *,
835
+ q: str | None = None,
836
+ filter_name: str | None = None,
837
+ filter_imo: str | None = None,
838
+ filter_mmsi: str | None = None,
839
+ filter_eni: str | None = None,
840
+ filter_flag: MultiFilter | None = None,
841
+ filter_vessel_type: MultiFilter | None = None,
842
+ filter_callsign: str | None = None,
843
+ filter_year_built_min: int | None = None,
844
+ filter_year_built_max: int | None = None,
845
+ pagination_limit: int | None = None,
846
+ ) -> SyncIterator[Vessel]:
364
847
  """Iterate over all vessel search results across pages."""
365
848
  token: str | None = None
849
+
366
850
  def fetch() -> tuple[list[Vessel], str | None]:
367
851
  nonlocal token
368
- resp = self.vessels(**kwargs, pagination_next_token=token)
852
+ resp = self.vessels(
853
+ q=q,
854
+ filter_name=filter_name,
855
+ filter_imo=filter_imo,
856
+ filter_mmsi=filter_mmsi,
857
+ filter_eni=filter_eni,
858
+ filter_flag=filter_flag,
859
+ filter_vessel_type=filter_vessel_type,
860
+ filter_callsign=filter_callsign,
861
+ filter_year_built_min=filter_year_built_min,
862
+ filter_year_built_max=filter_year_built_max,
863
+ pagination_limit=pagination_limit,
864
+ pagination_next_token=token,
865
+ )
369
866
  token = resp.next_token
370
867
  return resp.vessels or [], token
868
+
371
869
  return SyncIterator(fetch)
372
870
 
373
- def all_ports(self, **kwargs: Any) -> SyncIterator[Port]:
871
+ def all_ports(
872
+ self,
873
+ *,
874
+ filter_name: str | None = None,
875
+ filter_country: MultiFilter | None = None,
876
+ filter_port_type: MultiFilter | None = None,
877
+ filter_size: MultiFilter | None = None,
878
+ filter_region: str | None = None,
879
+ filter_harbor_size: MultiFilter | None = None,
880
+ filter_harbor_use: MultiFilter | None = None,
881
+ pagination_limit: int | None = None,
882
+ ) -> SyncIterator[Port]:
374
883
  """Iterate over all port search results across pages."""
375
884
  token: str | None = None
885
+
376
886
  def fetch() -> tuple[list[Port], str | None]:
377
887
  nonlocal token
378
- resp = self.ports(**kwargs, pagination_next_token=token)
888
+ resp = self.ports(
889
+ filter_name=filter_name,
890
+ filter_country=filter_country,
891
+ filter_port_type=filter_port_type,
892
+ filter_size=filter_size,
893
+ filter_region=filter_region,
894
+ filter_harbor_size=filter_harbor_size,
895
+ filter_harbor_use=filter_harbor_use,
896
+ pagination_limit=pagination_limit,
897
+ pagination_next_token=token,
898
+ )
379
899
  token = resp.next_token
380
900
  return resp.ports or [], token
901
+
381
902
  return SyncIterator(fetch)
382
903
 
383
- def all_dgps(self, **kwargs: Any) -> SyncIterator[DGPSStation]:
904
+ def all_dgps(self, *, filter_name: str, pagination_limit: int | None = None) -> SyncIterator[DGPSStation]:
384
905
  """Iterate over all DGPS station search results."""
385
906
  token: str | None = None
907
+
386
908
  def fetch() -> tuple[list[DGPSStation], str | None]:
387
909
  nonlocal token
388
- resp = self.dgps(**kwargs, pagination_next_token=token)
910
+ resp = self.dgps(filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token)
389
911
  token = resp.next_token
390
912
  return resp.dgps_stations or [], token
913
+
391
914
  return SyncIterator(fetch)
392
915
 
393
- def all_light_aids(self, **kwargs: Any) -> SyncIterator[LightAid]:
916
+ def all_light_aids(self, *, filter_name: str, pagination_limit: int | None = None) -> SyncIterator[LightAid]:
394
917
  """Iterate over all light aid search results."""
395
918
  token: str | None = None
919
+
396
920
  def fetch() -> tuple[list[LightAid], str | None]:
397
921
  nonlocal token
398
- resp = self.light_aids(**kwargs, pagination_next_token=token)
922
+ resp = self.light_aids(
923
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
924
+ )
399
925
  token = resp.next_token
400
926
  return resp.light_aids or [], token
927
+
401
928
  return SyncIterator(fetch)
402
929
 
403
- def all_modus(self, **kwargs: Any) -> SyncIterator[MODU]:
930
+ def all_modus(self, *, filter_name: str, pagination_limit: int | None = None) -> SyncIterator[MODU]:
404
931
  """Iterate over all MODU search results."""
405
932
  token: str | None = None
933
+
406
934
  def fetch() -> tuple[list[MODU], str | None]:
407
935
  nonlocal token
408
- resp = self.modus(**kwargs, pagination_next_token=token)
936
+ resp = self.modus(filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token)
409
937
  token = resp.next_token
410
938
  return resp.modus or [], token
939
+
411
940
  return SyncIterator(fetch)
412
941
 
413
- def all_radio_beacons(self, **kwargs: Any) -> SyncIterator[RadioBeacon]:
942
+ def all_radio_beacons(self, *, filter_name: str, pagination_limit: int | None = None) -> SyncIterator[RadioBeacon]:
414
943
  """Iterate over all radio beacon search results."""
415
944
  token: str | None = None
945
+
416
946
  def fetch() -> tuple[list[RadioBeacon], str | None]:
417
947
  nonlocal token
418
- resp = self.radio_beacons(**kwargs, pagination_next_token=token)
948
+ resp = self.radio_beacons(
949
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
950
+ )
419
951
  token = resp.next_token
420
952
  return resp.radio_beacons or [], token
953
+
421
954
  return SyncIterator(fetch)
422
955
 
423
956
 
@@ -427,229 +960,594 @@ class LocationService:
427
960
  def __init__(self, client: httpx.Client) -> None:
428
961
  self._client = client
429
962
 
430
- def vessels_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
963
+ def vessels_bounding_box(
964
+ self,
965
+ *,
966
+ lat_min: float,
967
+ lat_max: float,
968
+ lon_min: float,
969
+ lon_max: float,
970
+ time_from: str | None = None,
971
+ time_to: str | None = None,
972
+ pagination_limit: int | None = None,
973
+ pagination_next_token: str | None = None,
974
+ ) -> VesselsWithinLocationResponse:
431
975
  """Retrieve vessel positions within a bounding box."""
432
- r = self._client.get("/location/vessels/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
976
+ r = self._client.get(
977
+ "/location/vessels/bounding-box",
978
+ params=_strip_none(
979
+ {
980
+ "filter.latBottom": lat_min,
981
+ "filter.latTop": lat_max,
982
+ "filter.lonLeft": lon_min,
983
+ "filter.lonRight": lon_max,
984
+ "time.from": time_from,
985
+ "time.to": time_to,
986
+ "pagination.limit": pagination_limit,
987
+ "pagination.nextToken": pagination_next_token,
988
+ }
989
+ ),
990
+ )
433
991
  error_from_response(r.status_code, r.content)
434
992
  return VesselsWithinLocationResponse.model_validate(r.json())
435
993
 
436
- def vessels_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
994
+ def vessels_radius(
995
+ self,
996
+ *,
997
+ latitude: float,
998
+ longitude: float,
999
+ radius: float,
1000
+ time_from: str | None = None,
1001
+ time_to: str | None = None,
1002
+ pagination_limit: int | None = None,
1003
+ pagination_next_token: str | None = None,
1004
+ ) -> VesselsWithinLocationResponse:
437
1005
  """Retrieve vessel positions within a radius."""
438
- r = self._client.get("/location/vessels/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1006
+ r = self._client.get(
1007
+ "/location/vessels/radius",
1008
+ params=_strip_none(
1009
+ {
1010
+ "filter.latitude": latitude,
1011
+ "filter.longitude": longitude,
1012
+ "filter.radius": radius,
1013
+ "time.from": time_from,
1014
+ "time.to": time_to,
1015
+ "pagination.limit": pagination_limit,
1016
+ "pagination.nextToken": pagination_next_token,
1017
+ }
1018
+ ),
1019
+ )
439
1020
  error_from_response(r.status_code, r.content)
440
1021
  return VesselsWithinLocationResponse.model_validate(r.json())
441
1022
 
442
- def ports_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
1023
+ def ports_bounding_box(
1024
+ self,
1025
+ *,
1026
+ lat_min: float,
1027
+ lat_max: float,
1028
+ lon_min: float,
1029
+ lon_max: float,
1030
+ pagination_limit: int | None = None,
1031
+ pagination_next_token: str | None = None,
1032
+ ) -> PortsWithinLocationResponse:
443
1033
  """Retrieve ports within a bounding box."""
444
- r = self._client.get("/location/ports/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1034
+ r = self._client.get(
1035
+ "/location/ports/bounding-box",
1036
+ params=_strip_none(
1037
+ {
1038
+ "filter.latBottom": lat_min,
1039
+ "filter.latTop": lat_max,
1040
+ "filter.lonLeft": lon_min,
1041
+ "filter.lonRight": lon_max,
1042
+ "pagination.limit": pagination_limit,
1043
+ "pagination.nextToken": pagination_next_token,
1044
+ }
1045
+ ),
1046
+ )
445
1047
  error_from_response(r.status_code, r.content)
446
1048
  return PortsWithinLocationResponse.model_validate(r.json())
447
1049
 
448
- def ports_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
1050
+ def ports_radius(
1051
+ self,
1052
+ *,
1053
+ latitude: float,
1054
+ longitude: float,
1055
+ radius: float,
1056
+ pagination_limit: int | None = None,
1057
+ pagination_next_token: str | None = None,
1058
+ ) -> PortsWithinLocationResponse:
449
1059
  """Retrieve ports within a radius."""
450
- r = self._client.get("/location/ports/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1060
+ r = self._client.get(
1061
+ "/location/ports/radius",
1062
+ params=_strip_none(
1063
+ {
1064
+ "filter.latitude": latitude,
1065
+ "filter.longitude": longitude,
1066
+ "filter.radius": radius,
1067
+ "pagination.limit": pagination_limit,
1068
+ "pagination.nextToken": pagination_next_token,
1069
+ }
1070
+ ),
1071
+ )
451
1072
  error_from_response(r.status_code, r.content)
452
1073
  return PortsWithinLocationResponse.model_validate(r.json())
453
1074
 
454
- def dgps_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
1075
+ def dgps_bounding_box(
1076
+ self,
1077
+ *,
1078
+ lat_min: float,
1079
+ lat_max: float,
1080
+ lon_min: float,
1081
+ lon_max: float,
1082
+ pagination_limit: int | None = None,
1083
+ pagination_next_token: str | None = None,
1084
+ ) -> DGPSStationsWithinLocationResponse:
455
1085
  """Retrieve DGPS stations within a bounding box."""
456
- r = self._client.get("/location/dgps/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1086
+ r = self._client.get(
1087
+ "/location/dgps/bounding-box",
1088
+ params=_strip_none(
1089
+ {
1090
+ "filter.latBottom": lat_min,
1091
+ "filter.latTop": lat_max,
1092
+ "filter.lonLeft": lon_min,
1093
+ "filter.lonRight": lon_max,
1094
+ "pagination.limit": pagination_limit,
1095
+ "pagination.nextToken": pagination_next_token,
1096
+ }
1097
+ ),
1098
+ )
457
1099
  error_from_response(r.status_code, r.content)
458
1100
  return DGPSStationsWithinLocationResponse.model_validate(r.json())
459
1101
 
460
- def dgps_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
1102
+ def dgps_radius(
1103
+ self,
1104
+ *,
1105
+ latitude: float,
1106
+ longitude: float,
1107
+ radius: float,
1108
+ pagination_limit: int | None = None,
1109
+ pagination_next_token: str | None = None,
1110
+ ) -> DGPSStationsWithinLocationResponse:
461
1111
  """Retrieve DGPS stations within a radius."""
462
- r = self._client.get("/location/dgps/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1112
+ r = self._client.get(
1113
+ "/location/dgps/radius",
1114
+ params=_strip_none(
1115
+ {
1116
+ "filter.latitude": latitude,
1117
+ "filter.longitude": longitude,
1118
+ "filter.radius": radius,
1119
+ "pagination.limit": pagination_limit,
1120
+ "pagination.nextToken": pagination_next_token,
1121
+ }
1122
+ ),
1123
+ )
463
1124
  error_from_response(r.status_code, r.content)
464
1125
  return DGPSStationsWithinLocationResponse.model_validate(r.json())
465
1126
 
466
- def light_aids_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
1127
+ def light_aids_bounding_box(
1128
+ self,
1129
+ *,
1130
+ lat_min: float,
1131
+ lat_max: float,
1132
+ lon_min: float,
1133
+ lon_max: float,
1134
+ pagination_limit: int | None = None,
1135
+ pagination_next_token: str | None = None,
1136
+ ) -> LightAidsWithinLocationResponse:
467
1137
  """Retrieve light aids within a bounding box."""
468
- r = self._client.get("/location/lightaids/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1138
+ r = self._client.get(
1139
+ "/location/lightaids/bounding-box",
1140
+ params=_strip_none(
1141
+ {
1142
+ "filter.latBottom": lat_min,
1143
+ "filter.latTop": lat_max,
1144
+ "filter.lonLeft": lon_min,
1145
+ "filter.lonRight": lon_max,
1146
+ "pagination.limit": pagination_limit,
1147
+ "pagination.nextToken": pagination_next_token,
1148
+ }
1149
+ ),
1150
+ )
469
1151
  error_from_response(r.status_code, r.content)
470
1152
  return LightAidsWithinLocationResponse.model_validate(r.json())
471
1153
 
472
- def light_aids_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
1154
+ def light_aids_radius(
1155
+ self,
1156
+ *,
1157
+ latitude: float,
1158
+ longitude: float,
1159
+ radius: float,
1160
+ pagination_limit: int | None = None,
1161
+ pagination_next_token: str | None = None,
1162
+ ) -> LightAidsWithinLocationResponse:
473
1163
  """Retrieve light aids within a radius."""
474
- r = self._client.get("/location/lightaids/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1164
+ r = self._client.get(
1165
+ "/location/lightaids/radius",
1166
+ params=_strip_none(
1167
+ {
1168
+ "filter.latitude": latitude,
1169
+ "filter.longitude": longitude,
1170
+ "filter.radius": radius,
1171
+ "pagination.limit": pagination_limit,
1172
+ "pagination.nextToken": pagination_next_token,
1173
+ }
1174
+ ),
1175
+ )
475
1176
  error_from_response(r.status_code, r.content)
476
1177
  return LightAidsWithinLocationResponse.model_validate(r.json())
477
1178
 
478
- def modus_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
1179
+ def modus_bounding_box(
1180
+ self,
1181
+ *,
1182
+ lat_min: float,
1183
+ lat_max: float,
1184
+ lon_min: float,
1185
+ lon_max: float,
1186
+ pagination_limit: int | None = None,
1187
+ pagination_next_token: str | None = None,
1188
+ ) -> MODUsWithinLocationResponse:
479
1189
  """Retrieve MODUs within a bounding box."""
480
- r = self._client.get("/location/modu/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1190
+ r = self._client.get(
1191
+ "/location/modu/bounding-box",
1192
+ params=_strip_none(
1193
+ {
1194
+ "filter.latBottom": lat_min,
1195
+ "filter.latTop": lat_max,
1196
+ "filter.lonLeft": lon_min,
1197
+ "filter.lonRight": lon_max,
1198
+ "pagination.limit": pagination_limit,
1199
+ "pagination.nextToken": pagination_next_token,
1200
+ }
1201
+ ),
1202
+ )
481
1203
  error_from_response(r.status_code, r.content)
482
1204
  return MODUsWithinLocationResponse.model_validate(r.json())
483
1205
 
484
- def modus_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
1206
+ def modus_radius(
1207
+ self,
1208
+ *,
1209
+ latitude: float,
1210
+ longitude: float,
1211
+ radius: float,
1212
+ pagination_limit: int | None = None,
1213
+ pagination_next_token: str | None = None,
1214
+ ) -> MODUsWithinLocationResponse:
485
1215
  """Retrieve MODUs within a radius."""
486
- r = self._client.get("/location/modu/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1216
+ r = self._client.get(
1217
+ "/location/modu/radius",
1218
+ params=_strip_none(
1219
+ {
1220
+ "filter.latitude": latitude,
1221
+ "filter.longitude": longitude,
1222
+ "filter.radius": radius,
1223
+ "pagination.limit": pagination_limit,
1224
+ "pagination.nextToken": pagination_next_token,
1225
+ }
1226
+ ),
1227
+ )
487
1228
  error_from_response(r.status_code, r.content)
488
1229
  return MODUsWithinLocationResponse.model_validate(r.json())
489
1230
 
490
- def radio_beacons_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
1231
+ def radio_beacons_bounding_box(
1232
+ self,
1233
+ *,
1234
+ lat_min: float,
1235
+ lat_max: float,
1236
+ lon_min: float,
1237
+ lon_max: float,
1238
+ pagination_limit: int | None = None,
1239
+ pagination_next_token: str | None = None,
1240
+ ) -> RadioBeaconsWithinLocationResponse:
491
1241
  """Retrieve radio beacons within a bounding box."""
492
- r = self._client.get("/location/radiobeacons/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1242
+ r = self._client.get(
1243
+ "/location/radiobeacons/bounding-box",
1244
+ params=_strip_none(
1245
+ {
1246
+ "filter.latBottom": lat_min,
1247
+ "filter.latTop": lat_max,
1248
+ "filter.lonLeft": lon_min,
1249
+ "filter.lonRight": lon_max,
1250
+ "pagination.limit": pagination_limit,
1251
+ "pagination.nextToken": pagination_next_token,
1252
+ }
1253
+ ),
1254
+ )
493
1255
  error_from_response(r.status_code, r.content)
494
1256
  return RadioBeaconsWithinLocationResponse.model_validate(r.json())
495
1257
 
496
- def radio_beacons_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
1258
+ def radio_beacons_radius(
1259
+ self,
1260
+ *,
1261
+ latitude: float,
1262
+ longitude: float,
1263
+ radius: float,
1264
+ pagination_limit: int | None = None,
1265
+ pagination_next_token: str | None = None,
1266
+ ) -> RadioBeaconsWithinLocationResponse:
497
1267
  """Retrieve radio beacons within a radius."""
498
- r = self._client.get("/location/radiobeacons/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1268
+ r = self._client.get(
1269
+ "/location/radiobeacons/radius",
1270
+ params=_strip_none(
1271
+ {
1272
+ "filter.latitude": latitude,
1273
+ "filter.longitude": longitude,
1274
+ "filter.radius": radius,
1275
+ "pagination.limit": pagination_limit,
1276
+ "pagination.nextToken": pagination_next_token,
1277
+ }
1278
+ ),
1279
+ )
499
1280
  error_from_response(r.status_code, r.content)
500
1281
  return RadioBeaconsWithinLocationResponse.model_validate(r.json())
501
1282
 
502
1283
  # --- Iterators ---
503
1284
 
504
- def all_vessels_bounding_box(self, **kwargs: Any) -> SyncIterator[VesselPosition]:
1285
+ def all_vessels_bounding_box(
1286
+ self,
1287
+ *,
1288
+ lat_min: float,
1289
+ lat_max: float,
1290
+ lon_min: float,
1291
+ lon_max: float,
1292
+ time_from: str | None = None,
1293
+ time_to: str | None = None,
1294
+ pagination_limit: int | None = None,
1295
+ ) -> SyncIterator[VesselPosition]:
505
1296
  """Iterate over all vessel positions in a bounding box."""
506
1297
  token: str | None = None
1298
+
507
1299
  def fetch() -> tuple[list[VesselPosition], str | None]:
508
1300
  nonlocal token
509
- resp = self.vessels_bounding_box(**kwargs, pagination_next_token=token)
1301
+ resp = self.vessels_bounding_box(
1302
+ lat_min=lat_min,
1303
+ lat_max=lat_max,
1304
+ lon_min=lon_min,
1305
+ lon_max=lon_max,
1306
+ time_from=time_from,
1307
+ time_to=time_to,
1308
+ pagination_limit=pagination_limit,
1309
+ pagination_next_token=token,
1310
+ )
510
1311
  token = resp.next_token
511
1312
  return resp.vessels or [], token
1313
+
512
1314
  return SyncIterator(fetch)
513
1315
 
514
- def all_vessels_radius(self, **kwargs: Any) -> SyncIterator[VesselPosition]:
1316
+ def all_vessels_radius(
1317
+ self,
1318
+ *,
1319
+ latitude: float,
1320
+ longitude: float,
1321
+ radius: float,
1322
+ time_from: str | None = None,
1323
+ time_to: str | None = None,
1324
+ pagination_limit: int | None = None,
1325
+ ) -> SyncIterator[VesselPosition]:
515
1326
  """Iterate over all vessel positions within a radius."""
516
1327
  token: str | None = None
1328
+
517
1329
  def fetch() -> tuple[list[VesselPosition], str | None]:
518
1330
  nonlocal token
519
- resp = self.vessels_radius(**kwargs, pagination_next_token=token)
1331
+ resp = self.vessels_radius(
1332
+ latitude=latitude,
1333
+ longitude=longitude,
1334
+ radius=radius,
1335
+ time_from=time_from,
1336
+ time_to=time_to,
1337
+ pagination_limit=pagination_limit,
1338
+ pagination_next_token=token,
1339
+ )
520
1340
  token = resp.next_token
521
1341
  return resp.vessels or [], token
1342
+
522
1343
  return SyncIterator(fetch)
523
1344
 
524
- def all_ports_bounding_box(self, **kwargs: Any) -> SyncIterator[Port]:
1345
+ def all_ports_bounding_box(
1346
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
1347
+ ) -> SyncIterator[Port]:
525
1348
  """Iterate over all ports in a bounding box."""
526
1349
  token: str | None = None
1350
+
527
1351
  def fetch() -> tuple[list[Port], str | None]:
528
1352
  nonlocal token
529
- resp = self.ports_bounding_box(**kwargs, pagination_next_token=token)
1353
+ resp = self.ports_bounding_box(
1354
+ lat_min=lat_min,
1355
+ lat_max=lat_max,
1356
+ lon_min=lon_min,
1357
+ lon_max=lon_max,
1358
+ pagination_limit=pagination_limit,
1359
+ pagination_next_token=token,
1360
+ )
530
1361
  token = resp.next_token
531
1362
  return resp.ports or [], token
1363
+
532
1364
  return SyncIterator(fetch)
533
1365
 
534
- def all_ports_radius(self, **kwargs: Any) -> SyncIterator[Port]:
1366
+ def all_ports_radius(
1367
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
1368
+ ) -> SyncIterator[Port]:
535
1369
  """Iterate over all ports within a radius."""
536
1370
  token: str | None = None
1371
+
537
1372
  def fetch() -> tuple[list[Port], str | None]:
538
1373
  nonlocal token
539
- resp = self.ports_radius(**kwargs, pagination_next_token=token)
1374
+ resp = self.ports_radius(
1375
+ latitude=latitude,
1376
+ longitude=longitude,
1377
+ radius=radius,
1378
+ pagination_limit=pagination_limit,
1379
+ pagination_next_token=token,
1380
+ )
540
1381
  token = resp.next_token
541
1382
  return resp.ports or [], token
1383
+
542
1384
  return SyncIterator(fetch)
543
1385
 
544
- def all_dgps_bounding_box(self, **kwargs: Any) -> SyncIterator[DGPSStation]:
1386
+ def all_dgps_bounding_box(
1387
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
1388
+ ) -> SyncIterator[DGPSStation]:
545
1389
  """Iterate over all DGPS stations in a bounding box."""
546
1390
  token: str | None = None
1391
+
547
1392
  def fetch() -> tuple[list[DGPSStation], str | None]:
548
1393
  nonlocal token
549
- resp = self.dgps_bounding_box(**kwargs, pagination_next_token=token)
1394
+ resp = self.dgps_bounding_box(
1395
+ lat_min=lat_min,
1396
+ lat_max=lat_max,
1397
+ lon_min=lon_min,
1398
+ lon_max=lon_max,
1399
+ pagination_limit=pagination_limit,
1400
+ pagination_next_token=token,
1401
+ )
550
1402
  token = resp.next_token
551
1403
  return resp.dgps_stations or [], token
1404
+
552
1405
  return SyncIterator(fetch)
553
1406
 
554
- def all_dgps_radius(self, **kwargs: Any) -> SyncIterator[DGPSStation]:
1407
+ def all_dgps_radius(
1408
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
1409
+ ) -> SyncIterator[DGPSStation]:
555
1410
  """Iterate over all DGPS stations within a radius."""
556
1411
  token: str | None = None
1412
+
557
1413
  def fetch() -> tuple[list[DGPSStation], str | None]:
558
1414
  nonlocal token
559
- resp = self.dgps_radius(**kwargs, pagination_next_token=token)
1415
+ resp = self.dgps_radius(
1416
+ latitude=latitude,
1417
+ longitude=longitude,
1418
+ radius=radius,
1419
+ pagination_limit=pagination_limit,
1420
+ pagination_next_token=token,
1421
+ )
560
1422
  token = resp.next_token
561
1423
  return resp.dgps_stations or [], token
1424
+
562
1425
  return SyncIterator(fetch)
563
1426
 
564
- def all_light_aids_bounding_box(self, **kwargs: Any) -> SyncIterator[LightAid]:
1427
+ def all_light_aids_bounding_box(
1428
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
1429
+ ) -> SyncIterator[LightAid]:
565
1430
  """Iterate over all light aids in a bounding box."""
566
1431
  token: str | None = None
1432
+
567
1433
  def fetch() -> tuple[list[LightAid], str | None]:
568
1434
  nonlocal token
569
- resp = self.light_aids_bounding_box(**kwargs, pagination_next_token=token)
1435
+ resp = self.light_aids_bounding_box(
1436
+ lat_min=lat_min,
1437
+ lat_max=lat_max,
1438
+ lon_min=lon_min,
1439
+ lon_max=lon_max,
1440
+ pagination_limit=pagination_limit,
1441
+ pagination_next_token=token,
1442
+ )
570
1443
  token = resp.next_token
571
1444
  return resp.light_aids or [], token
1445
+
572
1446
  return SyncIterator(fetch)
573
1447
 
574
- def all_light_aids_radius(self, **kwargs: Any) -> SyncIterator[LightAid]:
1448
+ def all_light_aids_radius(
1449
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
1450
+ ) -> SyncIterator[LightAid]:
575
1451
  """Iterate over all light aids within a radius."""
576
1452
  token: str | None = None
1453
+
577
1454
  def fetch() -> tuple[list[LightAid], str | None]:
578
1455
  nonlocal token
579
- resp = self.light_aids_radius(**kwargs, pagination_next_token=token)
1456
+ resp = self.light_aids_radius(
1457
+ latitude=latitude,
1458
+ longitude=longitude,
1459
+ radius=radius,
1460
+ pagination_limit=pagination_limit,
1461
+ pagination_next_token=token,
1462
+ )
580
1463
  token = resp.next_token
581
1464
  return resp.light_aids or [], token
1465
+
582
1466
  return SyncIterator(fetch)
583
1467
 
584
- def all_modus_bounding_box(self, **kwargs: Any) -> SyncIterator[MODU]:
1468
+ def all_modus_bounding_box(
1469
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
1470
+ ) -> SyncIterator[MODU]:
585
1471
  """Iterate over all MODUs in a bounding box."""
586
1472
  token: str | None = None
1473
+
587
1474
  def fetch() -> tuple[list[MODU], str | None]:
588
1475
  nonlocal token
589
- resp = self.modus_bounding_box(**kwargs, pagination_next_token=token)
1476
+ resp = self.modus_bounding_box(
1477
+ lat_min=lat_min,
1478
+ lat_max=lat_max,
1479
+ lon_min=lon_min,
1480
+ lon_max=lon_max,
1481
+ pagination_limit=pagination_limit,
1482
+ pagination_next_token=token,
1483
+ )
590
1484
  token = resp.next_token
591
1485
  return resp.modus or [], token
1486
+
592
1487
  return SyncIterator(fetch)
593
1488
 
594
- def all_modus_radius(self, **kwargs: Any) -> SyncIterator[MODU]:
1489
+ def all_modus_radius(
1490
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
1491
+ ) -> SyncIterator[MODU]:
595
1492
  """Iterate over all MODUs within a radius."""
596
1493
  token: str | None = None
1494
+
597
1495
  def fetch() -> tuple[list[MODU], str | None]:
598
1496
  nonlocal token
599
- resp = self.modus_radius(**kwargs, pagination_next_token=token)
1497
+ resp = self.modus_radius(
1498
+ latitude=latitude,
1499
+ longitude=longitude,
1500
+ radius=radius,
1501
+ pagination_limit=pagination_limit,
1502
+ pagination_next_token=token,
1503
+ )
600
1504
  token = resp.next_token
601
1505
  return resp.modus or [], token
1506
+
602
1507
  return SyncIterator(fetch)
603
1508
 
604
- def all_radio_beacons_bounding_box(self, **kwargs: Any) -> SyncIterator[RadioBeacon]:
1509
+ def all_radio_beacons_bounding_box(
1510
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
1511
+ ) -> SyncIterator[RadioBeacon]:
605
1512
  """Iterate over all radio beacons in a bounding box."""
606
1513
  token: str | None = None
1514
+
607
1515
  def fetch() -> tuple[list[RadioBeacon], str | None]:
608
1516
  nonlocal token
609
- resp = self.radio_beacons_bounding_box(**kwargs, pagination_next_token=token)
1517
+ resp = self.radio_beacons_bounding_box(
1518
+ lat_min=lat_min,
1519
+ lat_max=lat_max,
1520
+ lon_min=lon_min,
1521
+ lon_max=lon_max,
1522
+ pagination_limit=pagination_limit,
1523
+ pagination_next_token=token,
1524
+ )
610
1525
  token = resp.next_token
611
1526
  return resp.radio_beacons or [], token
1527
+
612
1528
  return SyncIterator(fetch)
613
1529
 
614
- def all_radio_beacons_radius(self, **kwargs: Any) -> SyncIterator[RadioBeacon]:
1530
+ def all_radio_beacons_radius(
1531
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
1532
+ ) -> SyncIterator[RadioBeacon]:
615
1533
  """Iterate over all radio beacons within a radius."""
616
1534
  token: str | None = None
1535
+
617
1536
  def fetch() -> tuple[list[RadioBeacon], str | None]:
618
1537
  nonlocal token
619
- resp = self.radio_beacons_radius(**kwargs, pagination_next_token=token)
1538
+ resp = self.radio_beacons_radius(
1539
+ latitude=latitude,
1540
+ longitude=longitude,
1541
+ radius=radius,
1542
+ pagination_limit=pagination_limit,
1543
+ pagination_next_token=token,
1544
+ )
620
1545
  token = resp.next_token
621
1546
  return resp.radio_beacons or [], token
622
- return SyncIterator(fetch)
623
-
624
1547
 
625
- class NavtexService:
626
- """NAVTEX message endpoints (sync)."""
627
-
628
- def __init__(self, client: httpx.Client) -> None:
629
- self._client = client
630
-
631
- def list(self, *, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> NavtexMessagesResponse:
632
- """Retrieve NAVTEX maritime safety messages."""
633
- r = self._client.get("/navtex", params=_strip_none({"time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
634
- error_from_response(r.status_code, r.content)
635
- return NavtexMessagesResponse.model_validate(r.json())
636
-
637
- def list_all(self, **kwargs: Any) -> SyncIterator[Navtex]:
638
- """Iterate over all NAVTEX messages across pages."""
639
- token: str | None = None
640
- def fetch() -> tuple[list[Navtex], str | None]:
641
- nonlocal token
642
- resp = self.list(**kwargs, pagination_next_token=token)
643
- token = resp.next_token
644
- return resp.navtex_messages or [], token
645
1548
  return SyncIterator(fetch)
646
1549
 
647
1550
 
648
- # ===================================================================
649
- # Async services
650
- # ===================================================================
651
-
652
-
653
1551
  class AsyncVesselsService:
654
1552
  """Vessel-related API endpoints (async)."""
655
1553
 
@@ -662,27 +1560,61 @@ class AsyncVesselsService:
662
1560
  error_from_response(r.status_code, r.content)
663
1561
  return VesselResponse.model_validate(r.json())
664
1562
 
665
- async def position(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselPositionResponse:
666
- """Retrieve the latest position for a vessel."""
667
- r = await self._client.get(f"/vessel/{vessel_id}/position", params=_strip_none({"filter.idType": filter_id_type}))
1563
+ async def position(
1564
+ self, vessel_id: str, *, filter_id_type: str = "imo", filter_sat: bool | None = None
1565
+ ) -> VesselPositionResponse:
1566
+ """Retrieve the latest position for a vessel.
1567
+
1568
+ ``filter_sat`` enables satellite AIS fallback; the server defaults it to false.
1569
+ """
1570
+ r = await self._client.get(
1571
+ f"/vessel/{vessel_id}/position",
1572
+ params=_strip_none({"filter.idType": filter_id_type, "filter.sat": filter_sat}),
1573
+ )
668
1574
  error_from_response(r.status_code, r.content)
669
1575
  return VesselPositionResponse.model_validate(r.json())
670
1576
 
671
- async def casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MarineCasualtiesResponse:
1577
+ async def casualties(
1578
+ self,
1579
+ vessel_id: str,
1580
+ *,
1581
+ filter_id_type: str = "imo",
1582
+ pagination_limit: int | None = None,
1583
+ pagination_next_token: str | None = None,
1584
+ ) -> MarineCasualtiesResponse:
672
1585
  """Retrieve marine casualty records for a vessel."""
673
- r = await self._client.get(f"/vessel/{vessel_id}/casualties", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1586
+ r = await self._client.get(
1587
+ f"/vessel/{vessel_id}/casualties",
1588
+ params=_strip_none(
1589
+ {
1590
+ "filter.idType": filter_id_type,
1591
+ "pagination.limit": pagination_limit,
1592
+ "pagination.nextToken": pagination_next_token,
1593
+ }
1594
+ ),
1595
+ )
674
1596
  error_from_response(r.status_code, r.content)
675
1597
  return MarineCasualtiesResponse.model_validate(r.json())
676
1598
 
677
- async def classification(self, vessel_id: str, *, filter_id_type: str = "imo") -> ClassificationResponse:
678
- """Retrieve classification data for a vessel."""
679
- r = await self._client.get(f"/vessel/{vessel_id}/classification", params=_strip_none({"filter.idType": filter_id_type}))
680
- error_from_response(r.status_code, r.content)
681
- return ClassificationResponse.model_validate(r.json())
682
-
683
- async def emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
1599
+ async def emissions(
1600
+ self,
1601
+ vessel_id: str,
1602
+ *,
1603
+ filter_id_type: str = "imo",
1604
+ pagination_limit: int | None = None,
1605
+ pagination_next_token: str | None = None,
1606
+ ) -> VesselEmissionsResponse:
684
1607
  """Retrieve emissions data for a vessel."""
685
- r = await self._client.get(f"/vessel/{vessel_id}/emissions", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1608
+ r = await self._client.get(
1609
+ f"/vessel/{vessel_id}/emissions",
1610
+ params=_strip_none(
1611
+ {
1612
+ "filter.idType": filter_id_type,
1613
+ "pagination.limit": pagination_limit,
1614
+ "pagination.nextToken": pagination_next_token,
1615
+ }
1616
+ ),
1617
+ )
686
1618
  error_from_response(r.status_code, r.content)
687
1619
  return VesselEmissionsResponse.model_validate(r.json())
688
1620
 
@@ -692,60 +1624,96 @@ class AsyncVesselsService:
692
1624
  error_from_response(r.status_code, r.content)
693
1625
  return VesselETAResponse.model_validate(r.json())
694
1626
 
695
- async def inspections(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> TypesInspectionsResponse:
696
- """Retrieve inspection records for a vessel."""
697
- r = await self._client.get(f"/vessel/{vessel_id}/inspections", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
698
- error_from_response(r.status_code, r.content)
699
- return TypesInspectionsResponse.model_validate(r.json())
700
-
701
- async def inspection_detail(self, vessel_id: str, detail_id: str, *, filter_id_type: str = "imo") -> TypesInspectionDetailResponse:
702
- """Retrieve detailed inspection data."""
703
- r = await self._client.get(f"/vessel/{vessel_id}/inspections/{detail_id}", params=_strip_none({"filter.idType": filter_id_type}))
704
- error_from_response(r.status_code, r.content)
705
- return TypesInspectionDetailResponse.model_validate(r.json())
706
-
707
- async def ownership(self, vessel_id: str, *, filter_id_type: str = "imo") -> TypesOwnershipResponse:
708
- """Retrieve ownership data for a vessel."""
709
- r = await self._client.get(f"/vessel/{vessel_id}/ownership", params=_strip_none({"filter.idType": filter_id_type}))
710
- error_from_response(r.status_code, r.content)
711
- return TypesOwnershipResponse.model_validate(r.json())
712
-
713
- async def positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselPositionsResponse:
714
- """Retrieve positions for multiple vessels."""
715
- r = await self._client.get("/vessels/positions", params=_strip_none({"filter.idType": filter_id_type, "filter.ids": filter_ids, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1627
+ async def positions(
1628
+ self,
1629
+ *,
1630
+ filter_ids: MultiFilter,
1631
+ filter_id_type: str = "imo",
1632
+ time_from: str | None = None,
1633
+ time_to: str | None = None,
1634
+ pagination_limit: int | None = None,
1635
+ pagination_next_token: str | None = None,
1636
+ ) -> VesselPositionsResponse:
1637
+ """Retrieve positions for multiple vessels.
1638
+
1639
+ ``filter_ids`` takes a comma-separated string or a list of ids; a list is
1640
+ sent as a repeated ``filter.ids`` parameter.
1641
+ """
1642
+ r = await self._client.get(
1643
+ "/vessels/positions",
1644
+ params=_strip_none(
1645
+ {
1646
+ "filter.idType": filter_id_type,
1647
+ "filter.ids": filter_ids,
1648
+ "time.from": time_from,
1649
+ "time.to": time_to,
1650
+ "pagination.limit": pagination_limit,
1651
+ "pagination.nextToken": pagination_next_token,
1652
+ }
1653
+ ),
1654
+ )
716
1655
  error_from_response(r.status_code, r.content)
717
1656
  return VesselPositionsResponse.model_validate(r.json())
718
1657
 
719
1658
  # --- Iterators ---
720
1659
 
721
- def all_casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> AsyncIterator[MarineCasualty]:
1660
+ def all_casualties(
1661
+ self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None
1662
+ ) -> AsyncIterator[MarineCasualty]:
722
1663
  """Iterate over all casualties for a vessel across pages."""
723
1664
  token: str | None = None
1665
+
724
1666
  async def fetch() -> tuple[list[MarineCasualty], str | None]:
725
1667
  nonlocal token
726
- resp = await self.casualties(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
1668
+ resp = await self.casualties(
1669
+ vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token
1670
+ )
727
1671
  token = resp.next_token
728
1672
  return resp.casualties or [], token
1673
+
729
1674
  return AsyncIterator(fetch)
730
1675
 
731
- def all_emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> AsyncIterator[VesselEmission]:
1676
+ def all_emissions(
1677
+ self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None
1678
+ ) -> AsyncIterator[VesselEmission]:
732
1679
  """Iterate over all emissions for a vessel across pages."""
733
1680
  token: str | None = None
1681
+
734
1682
  async def fetch() -> tuple[list[VesselEmission], str | None]:
735
1683
  nonlocal token
736
- resp = await self.emissions(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
1684
+ resp = await self.emissions(
1685
+ vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token
1686
+ )
737
1687
  token = resp.next_token
738
1688
  return resp.emissions or [], token
1689
+
739
1690
  return AsyncIterator(fetch)
740
1691
 
741
- def all_positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None) -> AsyncIterator[VesselPosition]:
1692
+ def all_positions(
1693
+ self,
1694
+ *,
1695
+ filter_ids: MultiFilter,
1696
+ filter_id_type: str = "imo",
1697
+ time_from: str | None = None,
1698
+ time_to: str | None = None,
1699
+ pagination_limit: int | None = None,
1700
+ ) -> AsyncIterator[VesselPosition]:
742
1701
  """Iterate over all positions for multiple vessels across pages."""
743
1702
  token: str | None = None
1703
+
744
1704
  async def fetch() -> tuple[list[VesselPosition], str | None]:
745
1705
  nonlocal token
746
- resp = await self.positions(filter_id_type=filter_id_type, filter_ids=filter_ids, pagination_limit=pagination_limit, pagination_next_token=token)
1706
+ resp = await self.positions(
1707
+ filter_id_type=filter_id_type,
1708
+ filter_ids=filter_ids,
1709
+ time_from=time_from,
1710
+ time_to=time_to,
1711
+ pagination_limit=pagination_limit,
1712
+ pagination_next_token=token,
1713
+ )
747
1714
  token = resp.next_token
748
1715
  return resp.vessel_positions or [], token
1716
+
749
1717
  return AsyncIterator(fetch)
750
1718
 
751
1719
 
@@ -761,20 +1729,61 @@ class AsyncPortsService:
761
1729
  error_from_response(r.status_code, r.content)
762
1730
  return PortResponse.model_validate(r.json())
763
1731
 
764
- async def inbound(self, unlocode: str, *, eta_from: str, eta_to: str, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortInboundResponse:
1732
+ async def inbound(
1733
+ self,
1734
+ unlocode: str,
1735
+ *,
1736
+ eta_from: str | None = None,
1737
+ eta_to: str | None = None,
1738
+ time_from: str | None = None,
1739
+ time_to: str | None = None,
1740
+ pagination_limit: int | None = None,
1741
+ pagination_next_token: str | None = None,
1742
+ ) -> PortInboundResponse:
765
1743
  """Retrieve vessels heading to a port."""
766
- r = await self._client.get(f"/port/{unlocode}/inbound", params=_strip_none({"filter.etaFrom": eta_from, "filter.etaTo": eta_to, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1744
+ r = await self._client.get(
1745
+ f"/port/{unlocode}/inbound",
1746
+ params=_strip_none(
1747
+ {
1748
+ "filter.etaFrom": eta_from,
1749
+ "filter.etaTo": eta_to,
1750
+ "time.from": time_from,
1751
+ "time.to": time_to,
1752
+ "pagination.limit": pagination_limit,
1753
+ "pagination.nextToken": pagination_next_token,
1754
+ }
1755
+ ),
1756
+ )
767
1757
  error_from_response(r.status_code, r.content)
768
1758
  return PortInboundResponse.model_validate(r.json())
769
1759
 
770
- def inbound_all(self, unlocode: str, *, eta_from: str, eta_to: str, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None) -> AsyncIterator[VesselETA]:
1760
+ def inbound_all(
1761
+ self,
1762
+ unlocode: str,
1763
+ *,
1764
+ eta_from: str | None = None,
1765
+ eta_to: str | None = None,
1766
+ time_from: str | None = None,
1767
+ time_to: str | None = None,
1768
+ pagination_limit: int | None = None,
1769
+ ) -> AsyncIterator[VesselETA]:
771
1770
  """Iterate over all inbound vessels for a port across pages."""
772
1771
  token: str | None = None
1772
+
773
1773
  async def fetch() -> tuple[list[VesselETA], str | None]:
774
1774
  nonlocal token
775
- resp = await self.inbound(unlocode, eta_from=eta_from, eta_to=eta_to, time_from=time_from, time_to=time_to, pagination_limit=pagination_limit, pagination_next_token=token)
1775
+ resp = await self.inbound(
1776
+ unlocode,
1777
+ eta_from=eta_from,
1778
+ eta_to=eta_to,
1779
+ time_from=time_from,
1780
+ time_to=time_to,
1781
+ pagination_limit=pagination_limit,
1782
+ pagination_next_token=token,
1783
+ )
776
1784
  token = resp.next_token
777
1785
  return resp.vessel_etas or [], token
1786
+
778
1787
  return AsyncIterator(fetch)
779
1788
 
780
1789
 
@@ -784,92 +1793,302 @@ class AsyncPortEventsService:
784
1793
  def __init__(self, client: httpx.AsyncClient) -> None:
785
1794
  self._client = client
786
1795
 
787
- async def list(self, *, time_from: str | None = None, time_to: str | None = None, filter_country: str | None = None, filter_unlocode: str | None = None, filter_event_type: str | None = None, filter_vessel_name: str | None = None, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
1796
+ async def list(
1797
+ self,
1798
+ *,
1799
+ time_from: str | None = None,
1800
+ time_to: str | None = None,
1801
+ filter_country: str | None = None,
1802
+ filter_unlocode: str | None = None,
1803
+ filter_event_type: str | None = None,
1804
+ filter_vessel_name: str | None = None,
1805
+ filter_port_name: str | None = None,
1806
+ pagination_limit: int | None = None,
1807
+ pagination_next_token: str | None = None,
1808
+ ) -> PortEventsResponse:
788
1809
  """Retrieve port events with optional filtering."""
789
- r = await self._client.get("/portevents", params=_strip_none({"time.from": time_from, "time.to": time_to, "filter.country": filter_country, "filter.unlocode": filter_unlocode, "filter.eventType": filter_event_type, "filter.vesselName": filter_vessel_name, "filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1810
+ r = await self._client.get(
1811
+ "/portevents",
1812
+ params=_strip_none(
1813
+ {
1814
+ "time.from": time_from,
1815
+ "time.to": time_to,
1816
+ "filter.country": filter_country,
1817
+ "filter.unlocode": filter_unlocode,
1818
+ "filter.eventType": filter_event_type,
1819
+ "filter.vesselName": filter_vessel_name,
1820
+ "filter.portName": filter_port_name,
1821
+ "pagination.limit": pagination_limit,
1822
+ "pagination.nextToken": pagination_next_token,
1823
+ }
1824
+ ),
1825
+ )
790
1826
  error_from_response(r.status_code, r.content)
791
1827
  return PortEventsResponse.model_validate(r.json())
792
1828
 
793
- async def by_port(self, unlocode: str, *, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
794
- """Retrieve port events for a specific port by UNLOCODE."""
795
- r = await self._client.get(f"/portevents/port/{unlocode}", params=_strip_none({"pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1829
+ async def by_port(
1830
+ self,
1831
+ unlocode: str,
1832
+ *,
1833
+ time_from: str | None = None,
1834
+ time_to: str | None = None,
1835
+ pagination_limit: int | None = None,
1836
+ pagination_next_token: str | None = None,
1837
+ ) -> PortEventsResponse:
1838
+ """Retrieve port events for a specific port by UNLOCODE.
1839
+
1840
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
1841
+ window to the last two hours.
1842
+ """
1843
+ r = await self._client.get(
1844
+ f"/portevents/port/{unlocode}",
1845
+ params=_strip_none(
1846
+ {
1847
+ "time.from": time_from,
1848
+ "time.to": time_to,
1849
+ "pagination.limit": pagination_limit,
1850
+ "pagination.nextToken": pagination_next_token,
1851
+ }
1852
+ ),
1853
+ )
796
1854
  error_from_response(r.status_code, r.content)
797
1855
  return PortEventsResponse.model_validate(r.json())
798
1856
 
799
- async def by_ports(self, *, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
800
- """Retrieve port events by port name search."""
801
- r = await self._client.get("/portevents/ports", params=_strip_none({"filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1857
+ async def by_ports(
1858
+ self,
1859
+ *,
1860
+ filter_port_name: str,
1861
+ time_from: str | None = None,
1862
+ time_to: str | None = None,
1863
+ pagination_limit: int | None = None,
1864
+ pagination_next_token: str | None = None,
1865
+ ) -> PortEventsResponse:
1866
+ """Retrieve port events by port name search.
1867
+
1868
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
1869
+ window to the last two hours.
1870
+ """
1871
+ r = await self._client.get(
1872
+ "/portevents/ports",
1873
+ params=_strip_none(
1874
+ {
1875
+ "filter.portName": filter_port_name,
1876
+ "time.from": time_from,
1877
+ "time.to": time_to,
1878
+ "pagination.limit": pagination_limit,
1879
+ "pagination.nextToken": pagination_next_token,
1880
+ }
1881
+ ),
1882
+ )
802
1883
  error_from_response(r.status_code, r.content)
803
1884
  return PortEventsResponse.model_validate(r.json())
804
1885
 
805
- async def by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo", filter_event_type: str | None = None, filter_sort_order: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
1886
+ async def by_vessel(
1887
+ self,
1888
+ vessel_id: str,
1889
+ *,
1890
+ filter_id_type: str = "imo",
1891
+ filter_event_type: str | None = None,
1892
+ filter_sort_order: str | None = None,
1893
+ time_from: str | None = None,
1894
+ time_to: str | None = None,
1895
+ pagination_limit: int | None = None,
1896
+ pagination_next_token: str | None = None,
1897
+ ) -> PortEventsResponse:
806
1898
  """Retrieve port events for a specific vessel."""
807
- r = await self._client.get(f"/portevents/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type, "filter.eventType": filter_event_type, "filter.sortOrder": filter_sort_order, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1899
+ r = await self._client.get(
1900
+ f"/portevents/vessel/{vessel_id}",
1901
+ params=_strip_none(
1902
+ {
1903
+ "filter.idType": filter_id_type,
1904
+ "filter.eventType": filter_event_type,
1905
+ "filter.sortOrder": filter_sort_order,
1906
+ "time.from": time_from,
1907
+ "time.to": time_to,
1908
+ "pagination.limit": pagination_limit,
1909
+ "pagination.nextToken": pagination_next_token,
1910
+ }
1911
+ ),
1912
+ )
808
1913
  error_from_response(r.status_code, r.content)
809
1914
  return PortEventsResponse.model_validate(r.json())
810
1915
 
811
1916
  async def last_by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo") -> PortEventResponse:
812
1917
  """Retrieve the last port event for a vessel."""
813
- r = await self._client.get(f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type}))
1918
+ r = await self._client.get(
1919
+ f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type})
1920
+ )
814
1921
  error_from_response(r.status_code, r.content)
815
1922
  return PortEventResponse.model_validate(r.json())
816
1923
 
817
- async def by_vessels(self, *, filter_vessel_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
818
- """Retrieve port events by vessel name search."""
819
- r = await self._client.get("/portevents/vessels", params=_strip_none({"filter.vesselName": filter_vessel_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1924
+ async def by_vessels(
1925
+ self,
1926
+ *,
1927
+ filter_vessel_name: str,
1928
+ time_from: str | None = None,
1929
+ time_to: str | None = None,
1930
+ pagination_limit: int | None = None,
1931
+ pagination_next_token: str | None = None,
1932
+ ) -> PortEventsResponse:
1933
+ """Retrieve port events by vessel name search.
1934
+
1935
+ ``time_from``/``time_to`` are RFC3339 timestamps; the server defaults the
1936
+ window to the last two hours.
1937
+ """
1938
+ r = await self._client.get(
1939
+ "/portevents/vessels",
1940
+ params=_strip_none(
1941
+ {
1942
+ "filter.vesselName": filter_vessel_name,
1943
+ "time.from": time_from,
1944
+ "time.to": time_to,
1945
+ "pagination.limit": pagination_limit,
1946
+ "pagination.nextToken": pagination_next_token,
1947
+ }
1948
+ ),
1949
+ )
820
1950
  error_from_response(r.status_code, r.content)
821
1951
  return PortEventsResponse.model_validate(r.json())
822
1952
 
823
1953
  # --- Iterators ---
824
1954
 
825
- def list_all(self, **kwargs: Any) -> AsyncIterator[PortEvent]:
1955
+ def list_all(
1956
+ self,
1957
+ *,
1958
+ time_from: str | None = None,
1959
+ time_to: str | None = None,
1960
+ filter_country: str | None = None,
1961
+ filter_unlocode: str | None = None,
1962
+ filter_event_type: str | None = None,
1963
+ filter_vessel_name: str | None = None,
1964
+ filter_port_name: str | None = None,
1965
+ pagination_limit: int | None = None,
1966
+ ) -> AsyncIterator[PortEvent]:
826
1967
  """Iterate over all port events across pages."""
827
1968
  token: str | None = None
1969
+
828
1970
  async def fetch() -> tuple[list[PortEvent], str | None]:
829
1971
  nonlocal token
830
- resp = await self.list(**kwargs, pagination_next_token=token)
1972
+ resp = await self.list(
1973
+ time_from=time_from,
1974
+ time_to=time_to,
1975
+ filter_country=filter_country,
1976
+ filter_unlocode=filter_unlocode,
1977
+ filter_event_type=filter_event_type,
1978
+ filter_vessel_name=filter_vessel_name,
1979
+ filter_port_name=filter_port_name,
1980
+ pagination_limit=pagination_limit,
1981
+ pagination_next_token=token,
1982
+ )
831
1983
  token = resp.next_token
832
1984
  return resp.port_events or [], token
1985
+
833
1986
  return AsyncIterator(fetch)
834
1987
 
835
- def all_by_port(self, unlocode: str, **kwargs: Any) -> AsyncIterator[PortEvent]:
1988
+ def all_by_port(
1989
+ self,
1990
+ unlocode: str,
1991
+ *,
1992
+ time_from: str | None = None,
1993
+ time_to: str | None = None,
1994
+ pagination_limit: int | None = None,
1995
+ ) -> AsyncIterator[PortEvent]:
836
1996
  """Iterate over all port events for a specific port."""
837
1997
  token: str | None = None
1998
+
838
1999
  async def fetch() -> tuple[list[PortEvent], str | None]:
839
2000
  nonlocal token
840
- resp = await self.by_port(unlocode, **kwargs, pagination_next_token=token)
2001
+ resp = await self.by_port(
2002
+ unlocode,
2003
+ time_from=time_from,
2004
+ time_to=time_to,
2005
+ pagination_limit=pagination_limit,
2006
+ pagination_next_token=token,
2007
+ )
841
2008
  token = resp.next_token
842
2009
  return resp.port_events or [], token
2010
+
843
2011
  return AsyncIterator(fetch)
844
2012
 
845
- def all_by_ports(self, **kwargs: Any) -> AsyncIterator[PortEvent]:
2013
+ def all_by_ports(
2014
+ self,
2015
+ *,
2016
+ filter_port_name: str,
2017
+ time_from: str | None = None,
2018
+ time_to: str | None = None,
2019
+ pagination_limit: int | None = None,
2020
+ ) -> AsyncIterator[PortEvent]:
846
2021
  """Iterate over all port events by port name search."""
847
2022
  token: str | None = None
2023
+
848
2024
  async def fetch() -> tuple[list[PortEvent], str | None]:
849
2025
  nonlocal token
850
- resp = await self.by_ports(**kwargs, pagination_next_token=token)
2026
+ resp = await self.by_ports(
2027
+ filter_port_name=filter_port_name,
2028
+ time_from=time_from,
2029
+ time_to=time_to,
2030
+ pagination_limit=pagination_limit,
2031
+ pagination_next_token=token,
2032
+ )
851
2033
  token = resp.next_token
852
2034
  return resp.port_events or [], token
2035
+
853
2036
  return AsyncIterator(fetch)
854
2037
 
855
- def all_by_vessel(self, vessel_id: str, **kwargs: Any) -> AsyncIterator[PortEvent]:
2038
+ def all_by_vessel(
2039
+ self,
2040
+ vessel_id: str,
2041
+ *,
2042
+ filter_id_type: str = "imo",
2043
+ filter_event_type: str | None = None,
2044
+ filter_sort_order: str | None = None,
2045
+ time_from: str | None = None,
2046
+ time_to: str | None = None,
2047
+ pagination_limit: int | None = None,
2048
+ ) -> AsyncIterator[PortEvent]:
856
2049
  """Iterate over all port events for a vessel."""
857
2050
  token: str | None = None
2051
+
858
2052
  async def fetch() -> tuple[list[PortEvent], str | None]:
859
2053
  nonlocal token
860
- resp = await self.by_vessel(vessel_id, **kwargs, pagination_next_token=token)
2054
+ resp = await self.by_vessel(
2055
+ vessel_id,
2056
+ filter_id_type=filter_id_type,
2057
+ filter_event_type=filter_event_type,
2058
+ filter_sort_order=filter_sort_order,
2059
+ time_from=time_from,
2060
+ time_to=time_to,
2061
+ pagination_limit=pagination_limit,
2062
+ pagination_next_token=token,
2063
+ )
861
2064
  token = resp.next_token
862
2065
  return resp.port_events or [], token
2066
+
863
2067
  return AsyncIterator(fetch)
864
2068
 
865
- def all_by_vessels(self, **kwargs: Any) -> AsyncIterator[PortEvent]:
2069
+ def all_by_vessels(
2070
+ self,
2071
+ *,
2072
+ filter_vessel_name: str,
2073
+ time_from: str | None = None,
2074
+ time_to: str | None = None,
2075
+ pagination_limit: int | None = None,
2076
+ ) -> AsyncIterator[PortEvent]:
866
2077
  """Iterate over all port events by vessel name search."""
867
2078
  token: str | None = None
2079
+
868
2080
  async def fetch() -> tuple[list[PortEvent], str | None]:
869
2081
  nonlocal token
870
- resp = await self.by_vessels(**kwargs, pagination_next_token=token)
2082
+ resp = await self.by_vessels(
2083
+ filter_vessel_name=filter_vessel_name,
2084
+ time_from=time_from,
2085
+ time_to=time_to,
2086
+ pagination_limit=pagination_limit,
2087
+ pagination_next_token=token,
2088
+ )
871
2089
  token = resp.next_token
872
2090
  return resp.port_events or [], token
2091
+
873
2092
  return AsyncIterator(fetch)
874
2093
 
875
2094
 
@@ -879,20 +2098,41 @@ class AsyncEmissionsService:
879
2098
  def __init__(self, client: httpx.AsyncClient) -> None:
880
2099
  self._client = client
881
2100
 
882
- async def list(self, *, filter_period: int | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
2101
+ async def list(
2102
+ self,
2103
+ *,
2104
+ filter_period: int | None = None,
2105
+ pagination_limit: int | None = None,
2106
+ pagination_next_token: str | None = None,
2107
+ ) -> VesselEmissionsResponse:
883
2108
  """Retrieve vessel emissions data."""
884
- r = await self._client.get("/emissions", params=_strip_none({"filter.period": filter_period, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2109
+ r = await self._client.get(
2110
+ "/emissions",
2111
+ params=_strip_none(
2112
+ {
2113
+ "filter.period": filter_period,
2114
+ "pagination.limit": pagination_limit,
2115
+ "pagination.nextToken": pagination_next_token,
2116
+ }
2117
+ ),
2118
+ )
885
2119
  error_from_response(r.status_code, r.content)
886
2120
  return VesselEmissionsResponse.model_validate(r.json())
887
2121
 
888
- def list_all(self, **kwargs: Any) -> AsyncIterator[VesselEmission]:
2122
+ def list_all(
2123
+ self, *, filter_period: int | None = None, pagination_limit: int | None = None
2124
+ ) -> AsyncIterator[VesselEmission]:
889
2125
  """Iterate over all emissions across pages."""
890
2126
  token: str | None = None
2127
+
891
2128
  async def fetch() -> tuple[list[VesselEmission], str | None]:
892
2129
  nonlocal token
893
- resp = await self.list(**kwargs, pagination_next_token=token)
2130
+ resp = await self.list(
2131
+ filter_period=filter_period, pagination_limit=pagination_limit, pagination_next_token=token
2132
+ )
894
2133
  token = resp.next_token
895
2134
  return resp.emissions or [], token
2135
+
896
2136
  return AsyncIterator(fetch)
897
2137
 
898
2138
 
@@ -902,102 +2142,286 @@ class AsyncSearchService:
902
2142
  def __init__(self, client: httpx.AsyncClient) -> None:
903
2143
  self._client = client
904
2144
 
905
- async def vessels(self, *, filter_name: str | None = None, filter_imo: str | None = None, filter_mmsi: str | None = None, filter_flag: str | None = None, filter_vessel_type: str | None = None, filter_callsign: str | None = None, filter_year_built_min: int | None = None, filter_year_built_max: int | None = None, filter_class_society: str | None = None, filter_owner: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindVesselsResponse:
906
- """Search for vessels."""
907
- r = await self._client.get("/search/vessels", params=_strip_none({"filter.name": filter_name, "filter.imo": filter_imo, "filter.mmsi": filter_mmsi, "filter.flag": filter_flag, "filter.vesselType": filter_vessel_type, "filter.callsign": filter_callsign, "filter.yearBuiltMin": filter_year_built_min, "filter.yearBuiltMax": filter_year_built_max, "filter.classSociety": filter_class_society, "filter.owner": filter_owner, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2145
+ async def vessels(
2146
+ self,
2147
+ *,
2148
+ q: str | None = None,
2149
+ filter_name: str | None = None,
2150
+ filter_imo: str | None = None,
2151
+ filter_mmsi: str | None = None,
2152
+ filter_eni: str | None = None,
2153
+ filter_flag: MultiFilter | None = None,
2154
+ filter_vessel_type: MultiFilter | None = None,
2155
+ filter_callsign: str | None = None,
2156
+ filter_year_built_min: int | None = None,
2157
+ filter_year_built_max: int | None = None,
2158
+ pagination_limit: int | None = None,
2159
+ pagination_next_token: str | None = None,
2160
+ ) -> FindVesselsResponse:
2161
+ """Search for vessels.
2162
+
2163
+ ``q`` is a unified search across IMO, MMSI, ENI, callsign and name; it
2164
+ populates ``_meta`` on the response with the fields that matched.
2165
+
2166
+ ``filter_flag`` and ``filter_vessel_type`` accept a list to match several
2167
+ values; each list is sent as a repeated query parameter.
2168
+ """
2169
+ r = await self._client.get(
2170
+ "/search/vessels",
2171
+ params=_strip_none(
2172
+ {
2173
+ "q": q,
2174
+ "filter.name": filter_name,
2175
+ "filter.imo": filter_imo,
2176
+ "filter.mmsi": filter_mmsi,
2177
+ "filter.eni": filter_eni,
2178
+ "filter.flag": filter_flag,
2179
+ "filter.vesselType": filter_vessel_type,
2180
+ "filter.callsign": filter_callsign,
2181
+ "filter.yearBuiltMin": filter_year_built_min,
2182
+ "filter.yearBuiltMax": filter_year_built_max,
2183
+ "pagination.limit": pagination_limit,
2184
+ "pagination.nextToken": pagination_next_token,
2185
+ }
2186
+ ),
2187
+ )
908
2188
  error_from_response(r.status_code, r.content)
909
2189
  return FindVesselsResponse.model_validate(r.json())
910
2190
 
911
- async def ports(self, *, filter_name: str | None = None, filter_country: str | None = None, filter_port_type: str | None = None, filter_size: str | None = None, filter_region: str | None = None, filter_harbor_size: str | None = None, filter_harbor_use: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindPortsResponse:
912
- """Search for ports."""
913
- r = await self._client.get("/search/ports", params=_strip_none({"filter.name": filter_name, "filter.country": filter_country, "filter.type": filter_port_type, "filter.size": filter_size, "filter.region": filter_region, "filter.harborSize": filter_harbor_size, "filter.harborUse": filter_harbor_use, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2191
+ async def ports(
2192
+ self,
2193
+ *,
2194
+ filter_name: str | None = None,
2195
+ filter_country: MultiFilter | None = None,
2196
+ filter_port_type: MultiFilter | None = None,
2197
+ filter_size: MultiFilter | None = None,
2198
+ filter_region: str | None = None,
2199
+ filter_harbor_size: MultiFilter | None = None,
2200
+ filter_harbor_use: MultiFilter | None = None,
2201
+ pagination_limit: int | None = None,
2202
+ pagination_next_token: str | None = None,
2203
+ ) -> FindPortsResponse:
2204
+ """Search for ports.
2205
+
2206
+ ``filter_country``, ``filter_port_type``, ``filter_size``,
2207
+ ``filter_harbor_size`` and ``filter_harbor_use`` accept a list to match
2208
+ several values; each list is sent as a repeated query parameter.
2209
+ """
2210
+ r = await self._client.get(
2211
+ "/search/ports",
2212
+ params=_strip_none(
2213
+ {
2214
+ "filter.name": filter_name,
2215
+ "filter.country": filter_country,
2216
+ "filter.type": filter_port_type,
2217
+ "filter.size": filter_size,
2218
+ "filter.region": filter_region,
2219
+ "filter.harborSize": filter_harbor_size,
2220
+ "filter.harborUse": filter_harbor_use,
2221
+ "pagination.limit": pagination_limit,
2222
+ "pagination.nextToken": pagination_next_token,
2223
+ }
2224
+ ),
2225
+ )
914
2226
  error_from_response(r.status_code, r.content)
915
2227
  return FindPortsResponse.model_validate(r.json())
916
2228
 
917
- async def dgps(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindDGPSStationsResponse:
2229
+ async def dgps(
2230
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
2231
+ ) -> FindDGPSStationsResponse:
918
2232
  """Search for DGPS stations."""
919
- r = await self._client.get("/search/dgps", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2233
+ r = await self._client.get(
2234
+ "/search/dgps",
2235
+ params=_strip_none(
2236
+ {
2237
+ "filter.name": filter_name,
2238
+ "pagination.limit": pagination_limit,
2239
+ "pagination.nextToken": pagination_next_token,
2240
+ }
2241
+ ),
2242
+ )
920
2243
  error_from_response(r.status_code, r.content)
921
2244
  return FindDGPSStationsResponse.model_validate(r.json())
922
2245
 
923
- async def light_aids(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindLightAidsResponse:
2246
+ async def light_aids(
2247
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
2248
+ ) -> FindLightAidsResponse:
924
2249
  """Search for light aids."""
925
- r = await self._client.get("/search/lightaids", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2250
+ r = await self._client.get(
2251
+ "/search/lightaids",
2252
+ params=_strip_none(
2253
+ {
2254
+ "filter.name": filter_name,
2255
+ "pagination.limit": pagination_limit,
2256
+ "pagination.nextToken": pagination_next_token,
2257
+ }
2258
+ ),
2259
+ )
926
2260
  error_from_response(r.status_code, r.content)
927
2261
  return FindLightAidsResponse.model_validate(r.json())
928
2262
 
929
- async def modus(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindMODUsResponse:
2263
+ async def modus(
2264
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
2265
+ ) -> FindMODUsResponse:
930
2266
  """Search for MODUs."""
931
- r = await self._client.get("/search/modus", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2267
+ r = await self._client.get(
2268
+ "/search/modus",
2269
+ params=_strip_none(
2270
+ {
2271
+ "filter.name": filter_name,
2272
+ "pagination.limit": pagination_limit,
2273
+ "pagination.nextToken": pagination_next_token,
2274
+ }
2275
+ ),
2276
+ )
932
2277
  error_from_response(r.status_code, r.content)
933
2278
  return FindMODUsResponse.model_validate(r.json())
934
2279
 
935
- async def radio_beacons(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindRadioBeaconsResponse:
2280
+ async def radio_beacons(
2281
+ self, *, filter_name: str, pagination_limit: int | None = None, pagination_next_token: str | None = None
2282
+ ) -> FindRadioBeaconsResponse:
936
2283
  """Search for radio beacons."""
937
- r = await self._client.get("/search/radiobeacons", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2284
+ r = await self._client.get(
2285
+ "/search/radiobeacons",
2286
+ params=_strip_none(
2287
+ {
2288
+ "filter.name": filter_name,
2289
+ "pagination.limit": pagination_limit,
2290
+ "pagination.nextToken": pagination_next_token,
2291
+ }
2292
+ ),
2293
+ )
938
2294
  error_from_response(r.status_code, r.content)
939
2295
  return FindRadioBeaconsResponse.model_validate(r.json())
940
2296
 
941
2297
  # --- Iterators ---
942
2298
 
943
- def all_vessels(self, **kwargs: Any) -> AsyncIterator[Vessel]:
2299
+ def all_vessels(
2300
+ self,
2301
+ *,
2302
+ q: str | None = None,
2303
+ filter_name: str | None = None,
2304
+ filter_imo: str | None = None,
2305
+ filter_mmsi: str | None = None,
2306
+ filter_eni: str | None = None,
2307
+ filter_flag: MultiFilter | None = None,
2308
+ filter_vessel_type: MultiFilter | None = None,
2309
+ filter_callsign: str | None = None,
2310
+ filter_year_built_min: int | None = None,
2311
+ filter_year_built_max: int | None = None,
2312
+ pagination_limit: int | None = None,
2313
+ ) -> AsyncIterator[Vessel]:
944
2314
  """Iterate over all vessel search results."""
945
2315
  token: str | None = None
2316
+
946
2317
  async def fetch() -> tuple[list[Vessel], str | None]:
947
2318
  nonlocal token
948
- resp = await self.vessels(**kwargs, pagination_next_token=token)
2319
+ resp = await self.vessels(
2320
+ q=q,
2321
+ filter_name=filter_name,
2322
+ filter_imo=filter_imo,
2323
+ filter_mmsi=filter_mmsi,
2324
+ filter_eni=filter_eni,
2325
+ filter_flag=filter_flag,
2326
+ filter_vessel_type=filter_vessel_type,
2327
+ filter_callsign=filter_callsign,
2328
+ filter_year_built_min=filter_year_built_min,
2329
+ filter_year_built_max=filter_year_built_max,
2330
+ pagination_limit=pagination_limit,
2331
+ pagination_next_token=token,
2332
+ )
949
2333
  token = resp.next_token
950
2334
  return resp.vessels or [], token
2335
+
951
2336
  return AsyncIterator(fetch)
952
2337
 
953
- def all_ports(self, **kwargs: Any) -> AsyncIterator[Port]:
2338
+ def all_ports(
2339
+ self,
2340
+ *,
2341
+ filter_name: str | None = None,
2342
+ filter_country: MultiFilter | None = None,
2343
+ filter_port_type: MultiFilter | None = None,
2344
+ filter_size: MultiFilter | None = None,
2345
+ filter_region: str | None = None,
2346
+ filter_harbor_size: MultiFilter | None = None,
2347
+ filter_harbor_use: MultiFilter | None = None,
2348
+ pagination_limit: int | None = None,
2349
+ ) -> AsyncIterator[Port]:
954
2350
  """Iterate over all port search results."""
955
2351
  token: str | None = None
2352
+
956
2353
  async def fetch() -> tuple[list[Port], str | None]:
957
2354
  nonlocal token
958
- resp = await self.ports(**kwargs, pagination_next_token=token)
2355
+ resp = await self.ports(
2356
+ filter_name=filter_name,
2357
+ filter_country=filter_country,
2358
+ filter_port_type=filter_port_type,
2359
+ filter_size=filter_size,
2360
+ filter_region=filter_region,
2361
+ filter_harbor_size=filter_harbor_size,
2362
+ filter_harbor_use=filter_harbor_use,
2363
+ pagination_limit=pagination_limit,
2364
+ pagination_next_token=token,
2365
+ )
959
2366
  token = resp.next_token
960
2367
  return resp.ports or [], token
2368
+
961
2369
  return AsyncIterator(fetch)
962
2370
 
963
- def all_dgps(self, **kwargs: Any) -> AsyncIterator[DGPSStation]:
2371
+ def all_dgps(self, *, filter_name: str, pagination_limit: int | None = None) -> AsyncIterator[DGPSStation]:
964
2372
  """Iterate over all DGPS station search results."""
965
2373
  token: str | None = None
2374
+
966
2375
  async def fetch() -> tuple[list[DGPSStation], str | None]:
967
2376
  nonlocal token
968
- resp = await self.dgps(**kwargs, pagination_next_token=token)
2377
+ resp = await self.dgps(
2378
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
2379
+ )
969
2380
  token = resp.next_token
970
2381
  return resp.dgps_stations or [], token
2382
+
971
2383
  return AsyncIterator(fetch)
972
2384
 
973
- def all_light_aids(self, **kwargs: Any) -> AsyncIterator[LightAid]:
2385
+ def all_light_aids(self, *, filter_name: str, pagination_limit: int | None = None) -> AsyncIterator[LightAid]:
974
2386
  """Iterate over all light aid search results."""
975
2387
  token: str | None = None
2388
+
976
2389
  async def fetch() -> tuple[list[LightAid], str | None]:
977
2390
  nonlocal token
978
- resp = await self.light_aids(**kwargs, pagination_next_token=token)
2391
+ resp = await self.light_aids(
2392
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
2393
+ )
979
2394
  token = resp.next_token
980
2395
  return resp.light_aids or [], token
2396
+
981
2397
  return AsyncIterator(fetch)
982
2398
 
983
- def all_modus(self, **kwargs: Any) -> AsyncIterator[MODU]:
2399
+ def all_modus(self, *, filter_name: str, pagination_limit: int | None = None) -> AsyncIterator[MODU]:
984
2400
  """Iterate over all MODU search results."""
985
2401
  token: str | None = None
2402
+
986
2403
  async def fetch() -> tuple[list[MODU], str | None]:
987
2404
  nonlocal token
988
- resp = await self.modus(**kwargs, pagination_next_token=token)
2405
+ resp = await self.modus(
2406
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
2407
+ )
989
2408
  token = resp.next_token
990
2409
  return resp.modus or [], token
2410
+
991
2411
  return AsyncIterator(fetch)
992
2412
 
993
- def all_radio_beacons(self, **kwargs: Any) -> AsyncIterator[RadioBeacon]:
2413
+ def all_radio_beacons(self, *, filter_name: str, pagination_limit: int | None = None) -> AsyncIterator[RadioBeacon]:
994
2414
  """Iterate over all radio beacon search results."""
995
2415
  token: str | None = None
2416
+
996
2417
  async def fetch() -> tuple[list[RadioBeacon], str | None]:
997
2418
  nonlocal token
998
- resp = await self.radio_beacons(**kwargs, pagination_next_token=token)
2419
+ resp = await self.radio_beacons(
2420
+ filter_name=filter_name, pagination_limit=pagination_limit, pagination_next_token=token
2421
+ )
999
2422
  token = resp.next_token
1000
2423
  return resp.radio_beacons or [], token
2424
+
1001
2425
  return AsyncIterator(fetch)
1002
2426
 
1003
2427
 
@@ -1007,219 +2431,589 @@ class AsyncLocationService:
1007
2431
  def __init__(self, client: httpx.AsyncClient) -> None:
1008
2432
  self._client = client
1009
2433
 
1010
- async def vessels_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
2434
+ async def vessels_bounding_box(
2435
+ self,
2436
+ *,
2437
+ lat_min: float,
2438
+ lat_max: float,
2439
+ lon_min: float,
2440
+ lon_max: float,
2441
+ time_from: str | None = None,
2442
+ time_to: str | None = None,
2443
+ pagination_limit: int | None = None,
2444
+ pagination_next_token: str | None = None,
2445
+ ) -> VesselsWithinLocationResponse:
1011
2446
  """Retrieve vessel positions within a bounding box."""
1012
- r = await self._client.get("/location/vessels/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2447
+ r = await self._client.get(
2448
+ "/location/vessels/bounding-box",
2449
+ params=_strip_none(
2450
+ {
2451
+ "filter.latBottom": lat_min,
2452
+ "filter.latTop": lat_max,
2453
+ "filter.lonLeft": lon_min,
2454
+ "filter.lonRight": lon_max,
2455
+ "time.from": time_from,
2456
+ "time.to": time_to,
2457
+ "pagination.limit": pagination_limit,
2458
+ "pagination.nextToken": pagination_next_token,
2459
+ }
2460
+ ),
2461
+ )
1013
2462
  error_from_response(r.status_code, r.content)
1014
2463
  return VesselsWithinLocationResponse.model_validate(r.json())
1015
2464
 
1016
- async def vessels_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
2465
+ async def vessels_radius(
2466
+ self,
2467
+ *,
2468
+ latitude: float,
2469
+ longitude: float,
2470
+ radius: float,
2471
+ time_from: str | None = None,
2472
+ time_to: str | None = None,
2473
+ pagination_limit: int | None = None,
2474
+ pagination_next_token: str | None = None,
2475
+ ) -> VesselsWithinLocationResponse:
1017
2476
  """Retrieve vessel positions within a radius."""
1018
- r = await self._client.get("/location/vessels/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2477
+ r = await self._client.get(
2478
+ "/location/vessels/radius",
2479
+ params=_strip_none(
2480
+ {
2481
+ "filter.latitude": latitude,
2482
+ "filter.longitude": longitude,
2483
+ "filter.radius": radius,
2484
+ "time.from": time_from,
2485
+ "time.to": time_to,
2486
+ "pagination.limit": pagination_limit,
2487
+ "pagination.nextToken": pagination_next_token,
2488
+ }
2489
+ ),
2490
+ )
1019
2491
  error_from_response(r.status_code, r.content)
1020
2492
  return VesselsWithinLocationResponse.model_validate(r.json())
1021
2493
 
1022
- async def ports_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
2494
+ async def ports_bounding_box(
2495
+ self,
2496
+ *,
2497
+ lat_min: float,
2498
+ lat_max: float,
2499
+ lon_min: float,
2500
+ lon_max: float,
2501
+ pagination_limit: int | None = None,
2502
+ pagination_next_token: str | None = None,
2503
+ ) -> PortsWithinLocationResponse:
1023
2504
  """Retrieve ports within a bounding box."""
1024
- r = await self._client.get("/location/ports/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2505
+ r = await self._client.get(
2506
+ "/location/ports/bounding-box",
2507
+ params=_strip_none(
2508
+ {
2509
+ "filter.latBottom": lat_min,
2510
+ "filter.latTop": lat_max,
2511
+ "filter.lonLeft": lon_min,
2512
+ "filter.lonRight": lon_max,
2513
+ "pagination.limit": pagination_limit,
2514
+ "pagination.nextToken": pagination_next_token,
2515
+ }
2516
+ ),
2517
+ )
1025
2518
  error_from_response(r.status_code, r.content)
1026
2519
  return PortsWithinLocationResponse.model_validate(r.json())
1027
2520
 
1028
- async def ports_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
2521
+ async def ports_radius(
2522
+ self,
2523
+ *,
2524
+ latitude: float,
2525
+ longitude: float,
2526
+ radius: float,
2527
+ pagination_limit: int | None = None,
2528
+ pagination_next_token: str | None = None,
2529
+ ) -> PortsWithinLocationResponse:
1029
2530
  """Retrieve ports within a radius."""
1030
- r = await self._client.get("/location/ports/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2531
+ r = await self._client.get(
2532
+ "/location/ports/radius",
2533
+ params=_strip_none(
2534
+ {
2535
+ "filter.latitude": latitude,
2536
+ "filter.longitude": longitude,
2537
+ "filter.radius": radius,
2538
+ "pagination.limit": pagination_limit,
2539
+ "pagination.nextToken": pagination_next_token,
2540
+ }
2541
+ ),
2542
+ )
1031
2543
  error_from_response(r.status_code, r.content)
1032
2544
  return PortsWithinLocationResponse.model_validate(r.json())
1033
2545
 
1034
- async def dgps_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
2546
+ async def dgps_bounding_box(
2547
+ self,
2548
+ *,
2549
+ lat_min: float,
2550
+ lat_max: float,
2551
+ lon_min: float,
2552
+ lon_max: float,
2553
+ pagination_limit: int | None = None,
2554
+ pagination_next_token: str | None = None,
2555
+ ) -> DGPSStationsWithinLocationResponse:
1035
2556
  """Retrieve DGPS stations within a bounding box."""
1036
- r = await self._client.get("/location/dgps/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2557
+ r = await self._client.get(
2558
+ "/location/dgps/bounding-box",
2559
+ params=_strip_none(
2560
+ {
2561
+ "filter.latBottom": lat_min,
2562
+ "filter.latTop": lat_max,
2563
+ "filter.lonLeft": lon_min,
2564
+ "filter.lonRight": lon_max,
2565
+ "pagination.limit": pagination_limit,
2566
+ "pagination.nextToken": pagination_next_token,
2567
+ }
2568
+ ),
2569
+ )
1037
2570
  error_from_response(r.status_code, r.content)
1038
2571
  return DGPSStationsWithinLocationResponse.model_validate(r.json())
1039
2572
 
1040
- async def dgps_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
2573
+ async def dgps_radius(
2574
+ self,
2575
+ *,
2576
+ latitude: float,
2577
+ longitude: float,
2578
+ radius: float,
2579
+ pagination_limit: int | None = None,
2580
+ pagination_next_token: str | None = None,
2581
+ ) -> DGPSStationsWithinLocationResponse:
1041
2582
  """Retrieve DGPS stations within a radius."""
1042
- r = await self._client.get("/location/dgps/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2583
+ r = await self._client.get(
2584
+ "/location/dgps/radius",
2585
+ params=_strip_none(
2586
+ {
2587
+ "filter.latitude": latitude,
2588
+ "filter.longitude": longitude,
2589
+ "filter.radius": radius,
2590
+ "pagination.limit": pagination_limit,
2591
+ "pagination.nextToken": pagination_next_token,
2592
+ }
2593
+ ),
2594
+ )
1043
2595
  error_from_response(r.status_code, r.content)
1044
2596
  return DGPSStationsWithinLocationResponse.model_validate(r.json())
1045
2597
 
1046
- async def light_aids_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
2598
+ async def light_aids_bounding_box(
2599
+ self,
2600
+ *,
2601
+ lat_min: float,
2602
+ lat_max: float,
2603
+ lon_min: float,
2604
+ lon_max: float,
2605
+ pagination_limit: int | None = None,
2606
+ pagination_next_token: str | None = None,
2607
+ ) -> LightAidsWithinLocationResponse:
1047
2608
  """Retrieve light aids within a bounding box."""
1048
- r = await self._client.get("/location/lightaids/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2609
+ r = await self._client.get(
2610
+ "/location/lightaids/bounding-box",
2611
+ params=_strip_none(
2612
+ {
2613
+ "filter.latBottom": lat_min,
2614
+ "filter.latTop": lat_max,
2615
+ "filter.lonLeft": lon_min,
2616
+ "filter.lonRight": lon_max,
2617
+ "pagination.limit": pagination_limit,
2618
+ "pagination.nextToken": pagination_next_token,
2619
+ }
2620
+ ),
2621
+ )
1049
2622
  error_from_response(r.status_code, r.content)
1050
2623
  return LightAidsWithinLocationResponse.model_validate(r.json())
1051
2624
 
1052
- async def light_aids_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
2625
+ async def light_aids_radius(
2626
+ self,
2627
+ *,
2628
+ latitude: float,
2629
+ longitude: float,
2630
+ radius: float,
2631
+ pagination_limit: int | None = None,
2632
+ pagination_next_token: str | None = None,
2633
+ ) -> LightAidsWithinLocationResponse:
1053
2634
  """Retrieve light aids within a radius."""
1054
- r = await self._client.get("/location/lightaids/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2635
+ r = await self._client.get(
2636
+ "/location/lightaids/radius",
2637
+ params=_strip_none(
2638
+ {
2639
+ "filter.latitude": latitude,
2640
+ "filter.longitude": longitude,
2641
+ "filter.radius": radius,
2642
+ "pagination.limit": pagination_limit,
2643
+ "pagination.nextToken": pagination_next_token,
2644
+ }
2645
+ ),
2646
+ )
1055
2647
  error_from_response(r.status_code, r.content)
1056
2648
  return LightAidsWithinLocationResponse.model_validate(r.json())
1057
2649
 
1058
- async def modus_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
2650
+ async def modus_bounding_box(
2651
+ self,
2652
+ *,
2653
+ lat_min: float,
2654
+ lat_max: float,
2655
+ lon_min: float,
2656
+ lon_max: float,
2657
+ pagination_limit: int | None = None,
2658
+ pagination_next_token: str | None = None,
2659
+ ) -> MODUsWithinLocationResponse:
1059
2660
  """Retrieve MODUs within a bounding box."""
1060
- r = await self._client.get("/location/modu/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2661
+ r = await self._client.get(
2662
+ "/location/modu/bounding-box",
2663
+ params=_strip_none(
2664
+ {
2665
+ "filter.latBottom": lat_min,
2666
+ "filter.latTop": lat_max,
2667
+ "filter.lonLeft": lon_min,
2668
+ "filter.lonRight": lon_max,
2669
+ "pagination.limit": pagination_limit,
2670
+ "pagination.nextToken": pagination_next_token,
2671
+ }
2672
+ ),
2673
+ )
1061
2674
  error_from_response(r.status_code, r.content)
1062
2675
  return MODUsWithinLocationResponse.model_validate(r.json())
1063
2676
 
1064
- async def modus_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
2677
+ async def modus_radius(
2678
+ self,
2679
+ *,
2680
+ latitude: float,
2681
+ longitude: float,
2682
+ radius: float,
2683
+ pagination_limit: int | None = None,
2684
+ pagination_next_token: str | None = None,
2685
+ ) -> MODUsWithinLocationResponse:
1065
2686
  """Retrieve MODUs within a radius."""
1066
- r = await self._client.get("/location/modu/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2687
+ r = await self._client.get(
2688
+ "/location/modu/radius",
2689
+ params=_strip_none(
2690
+ {
2691
+ "filter.latitude": latitude,
2692
+ "filter.longitude": longitude,
2693
+ "filter.radius": radius,
2694
+ "pagination.limit": pagination_limit,
2695
+ "pagination.nextToken": pagination_next_token,
2696
+ }
2697
+ ),
2698
+ )
1067
2699
  error_from_response(r.status_code, r.content)
1068
2700
  return MODUsWithinLocationResponse.model_validate(r.json())
1069
2701
 
1070
- async def radio_beacons_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
2702
+ async def radio_beacons_bounding_box(
2703
+ self,
2704
+ *,
2705
+ lat_min: float,
2706
+ lat_max: float,
2707
+ lon_min: float,
2708
+ lon_max: float,
2709
+ pagination_limit: int | None = None,
2710
+ pagination_next_token: str | None = None,
2711
+ ) -> RadioBeaconsWithinLocationResponse:
1071
2712
  """Retrieve radio beacons within a bounding box."""
1072
- r = await self._client.get("/location/radiobeacons/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2713
+ r = await self._client.get(
2714
+ "/location/radiobeacons/bounding-box",
2715
+ params=_strip_none(
2716
+ {
2717
+ "filter.latBottom": lat_min,
2718
+ "filter.latTop": lat_max,
2719
+ "filter.lonLeft": lon_min,
2720
+ "filter.lonRight": lon_max,
2721
+ "pagination.limit": pagination_limit,
2722
+ "pagination.nextToken": pagination_next_token,
2723
+ }
2724
+ ),
2725
+ )
1073
2726
  error_from_response(r.status_code, r.content)
1074
2727
  return RadioBeaconsWithinLocationResponse.model_validate(r.json())
1075
2728
 
1076
- async def radio_beacons_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
2729
+ async def radio_beacons_radius(
2730
+ self,
2731
+ *,
2732
+ latitude: float,
2733
+ longitude: float,
2734
+ radius: float,
2735
+ pagination_limit: int | None = None,
2736
+ pagination_next_token: str | None = None,
2737
+ ) -> RadioBeaconsWithinLocationResponse:
1077
2738
  """Retrieve radio beacons within a radius."""
1078
- r = await self._client.get("/location/radiobeacons/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
2739
+ r = await self._client.get(
2740
+ "/location/radiobeacons/radius",
2741
+ params=_strip_none(
2742
+ {
2743
+ "filter.latitude": latitude,
2744
+ "filter.longitude": longitude,
2745
+ "filter.radius": radius,
2746
+ "pagination.limit": pagination_limit,
2747
+ "pagination.nextToken": pagination_next_token,
2748
+ }
2749
+ ),
2750
+ )
1079
2751
  error_from_response(r.status_code, r.content)
1080
2752
  return RadioBeaconsWithinLocationResponse.model_validate(r.json())
1081
2753
 
1082
2754
  # --- Iterators ---
1083
2755
 
1084
- def all_vessels_bounding_box(self, **kwargs: Any) -> AsyncIterator[VesselPosition]:
2756
+ def all_vessels_bounding_box(
2757
+ self,
2758
+ *,
2759
+ lat_min: float,
2760
+ lat_max: float,
2761
+ lon_min: float,
2762
+ lon_max: float,
2763
+ time_from: str | None = None,
2764
+ time_to: str | None = None,
2765
+ pagination_limit: int | None = None,
2766
+ ) -> AsyncIterator[VesselPosition]:
1085
2767
  """Iterate over all vessel positions in a bounding box."""
1086
2768
  token: str | None = None
2769
+
1087
2770
  async def fetch() -> tuple[list[VesselPosition], str | None]:
1088
2771
  nonlocal token
1089
- resp = await self.vessels_bounding_box(**kwargs, pagination_next_token=token)
2772
+ resp = await self.vessels_bounding_box(
2773
+ lat_min=lat_min,
2774
+ lat_max=lat_max,
2775
+ lon_min=lon_min,
2776
+ lon_max=lon_max,
2777
+ time_from=time_from,
2778
+ time_to=time_to,
2779
+ pagination_limit=pagination_limit,
2780
+ pagination_next_token=token,
2781
+ )
1090
2782
  token = resp.next_token
1091
2783
  return resp.vessels or [], token
2784
+
1092
2785
  return AsyncIterator(fetch)
1093
2786
 
1094
- def all_vessels_radius(self, **kwargs: Any) -> AsyncIterator[VesselPosition]:
2787
+ def all_vessels_radius(
2788
+ self,
2789
+ *,
2790
+ latitude: float,
2791
+ longitude: float,
2792
+ radius: float,
2793
+ time_from: str | None = None,
2794
+ time_to: str | None = None,
2795
+ pagination_limit: int | None = None,
2796
+ ) -> AsyncIterator[VesselPosition]:
1095
2797
  """Iterate over all vessel positions within a radius."""
1096
2798
  token: str | None = None
2799
+
1097
2800
  async def fetch() -> tuple[list[VesselPosition], str | None]:
1098
2801
  nonlocal token
1099
- resp = await self.vessels_radius(**kwargs, pagination_next_token=token)
2802
+ resp = await self.vessels_radius(
2803
+ latitude=latitude,
2804
+ longitude=longitude,
2805
+ radius=radius,
2806
+ time_from=time_from,
2807
+ time_to=time_to,
2808
+ pagination_limit=pagination_limit,
2809
+ pagination_next_token=token,
2810
+ )
1100
2811
  token = resp.next_token
1101
2812
  return resp.vessels or [], token
2813
+
1102
2814
  return AsyncIterator(fetch)
1103
2815
 
1104
- def all_ports_bounding_box(self, **kwargs: Any) -> AsyncIterator[Port]:
2816
+ def all_ports_bounding_box(
2817
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
2818
+ ) -> AsyncIterator[Port]:
1105
2819
  """Iterate over all ports in a bounding box."""
1106
2820
  token: str | None = None
2821
+
1107
2822
  async def fetch() -> tuple[list[Port], str | None]:
1108
2823
  nonlocal token
1109
- resp = await self.ports_bounding_box(**kwargs, pagination_next_token=token)
2824
+ resp = await self.ports_bounding_box(
2825
+ lat_min=lat_min,
2826
+ lat_max=lat_max,
2827
+ lon_min=lon_min,
2828
+ lon_max=lon_max,
2829
+ pagination_limit=pagination_limit,
2830
+ pagination_next_token=token,
2831
+ )
1110
2832
  token = resp.next_token
1111
2833
  return resp.ports or [], token
2834
+
1112
2835
  return AsyncIterator(fetch)
1113
2836
 
1114
- def all_ports_radius(self, **kwargs: Any) -> AsyncIterator[Port]:
2837
+ def all_ports_radius(
2838
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
2839
+ ) -> AsyncIterator[Port]:
1115
2840
  """Iterate over all ports within a radius."""
1116
2841
  token: str | None = None
2842
+
1117
2843
  async def fetch() -> tuple[list[Port], str | None]:
1118
2844
  nonlocal token
1119
- resp = await self.ports_radius(**kwargs, pagination_next_token=token)
2845
+ resp = await self.ports_radius(
2846
+ latitude=latitude,
2847
+ longitude=longitude,
2848
+ radius=radius,
2849
+ pagination_limit=pagination_limit,
2850
+ pagination_next_token=token,
2851
+ )
1120
2852
  token = resp.next_token
1121
2853
  return resp.ports or [], token
2854
+
1122
2855
  return AsyncIterator(fetch)
1123
2856
 
1124
- def all_dgps_bounding_box(self, **kwargs: Any) -> AsyncIterator[DGPSStation]:
2857
+ def all_dgps_bounding_box(
2858
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
2859
+ ) -> AsyncIterator[DGPSStation]:
1125
2860
  """Iterate over all DGPS stations in a bounding box."""
1126
2861
  token: str | None = None
2862
+
1127
2863
  async def fetch() -> tuple[list[DGPSStation], str | None]:
1128
2864
  nonlocal token
1129
- resp = await self.dgps_bounding_box(**kwargs, pagination_next_token=token)
2865
+ resp = await self.dgps_bounding_box(
2866
+ lat_min=lat_min,
2867
+ lat_max=lat_max,
2868
+ lon_min=lon_min,
2869
+ lon_max=lon_max,
2870
+ pagination_limit=pagination_limit,
2871
+ pagination_next_token=token,
2872
+ )
1130
2873
  token = resp.next_token
1131
2874
  return resp.dgps_stations or [], token
2875
+
1132
2876
  return AsyncIterator(fetch)
1133
2877
 
1134
- def all_dgps_radius(self, **kwargs: Any) -> AsyncIterator[DGPSStation]:
2878
+ def all_dgps_radius(
2879
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
2880
+ ) -> AsyncIterator[DGPSStation]:
1135
2881
  """Iterate over all DGPS stations within a radius."""
1136
2882
  token: str | None = None
2883
+
1137
2884
  async def fetch() -> tuple[list[DGPSStation], str | None]:
1138
2885
  nonlocal token
1139
- resp = await self.dgps_radius(**kwargs, pagination_next_token=token)
2886
+ resp = await self.dgps_radius(
2887
+ latitude=latitude,
2888
+ longitude=longitude,
2889
+ radius=radius,
2890
+ pagination_limit=pagination_limit,
2891
+ pagination_next_token=token,
2892
+ )
1140
2893
  token = resp.next_token
1141
2894
  return resp.dgps_stations or [], token
2895
+
1142
2896
  return AsyncIterator(fetch)
1143
2897
 
1144
- def all_light_aids_bounding_box(self, **kwargs: Any) -> AsyncIterator[LightAid]:
2898
+ def all_light_aids_bounding_box(
2899
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
2900
+ ) -> AsyncIterator[LightAid]:
1145
2901
  """Iterate over all light aids in a bounding box."""
1146
2902
  token: str | None = None
2903
+
1147
2904
  async def fetch() -> tuple[list[LightAid], str | None]:
1148
2905
  nonlocal token
1149
- resp = await self.light_aids_bounding_box(**kwargs, pagination_next_token=token)
2906
+ resp = await self.light_aids_bounding_box(
2907
+ lat_min=lat_min,
2908
+ lat_max=lat_max,
2909
+ lon_min=lon_min,
2910
+ lon_max=lon_max,
2911
+ pagination_limit=pagination_limit,
2912
+ pagination_next_token=token,
2913
+ )
1150
2914
  token = resp.next_token
1151
2915
  return resp.light_aids or [], token
2916
+
1152
2917
  return AsyncIterator(fetch)
1153
2918
 
1154
- def all_light_aids_radius(self, **kwargs: Any) -> AsyncIterator[LightAid]:
2919
+ def all_light_aids_radius(
2920
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
2921
+ ) -> AsyncIterator[LightAid]:
1155
2922
  """Iterate over all light aids within a radius."""
1156
2923
  token: str | None = None
2924
+
1157
2925
  async def fetch() -> tuple[list[LightAid], str | None]:
1158
2926
  nonlocal token
1159
- resp = await self.light_aids_radius(**kwargs, pagination_next_token=token)
2927
+ resp = await self.light_aids_radius(
2928
+ latitude=latitude,
2929
+ longitude=longitude,
2930
+ radius=radius,
2931
+ pagination_limit=pagination_limit,
2932
+ pagination_next_token=token,
2933
+ )
1160
2934
  token = resp.next_token
1161
2935
  return resp.light_aids or [], token
2936
+
1162
2937
  return AsyncIterator(fetch)
1163
2938
 
1164
- def all_modus_bounding_box(self, **kwargs: Any) -> AsyncIterator[MODU]:
2939
+ def all_modus_bounding_box(
2940
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
2941
+ ) -> AsyncIterator[MODU]:
1165
2942
  """Iterate over all MODUs in a bounding box."""
1166
2943
  token: str | None = None
2944
+
1167
2945
  async def fetch() -> tuple[list[MODU], str | None]:
1168
2946
  nonlocal token
1169
- resp = await self.modus_bounding_box(**kwargs, pagination_next_token=token)
2947
+ resp = await self.modus_bounding_box(
2948
+ lat_min=lat_min,
2949
+ lat_max=lat_max,
2950
+ lon_min=lon_min,
2951
+ lon_max=lon_max,
2952
+ pagination_limit=pagination_limit,
2953
+ pagination_next_token=token,
2954
+ )
1170
2955
  token = resp.next_token
1171
2956
  return resp.modus or [], token
2957
+
1172
2958
  return AsyncIterator(fetch)
1173
2959
 
1174
- def all_modus_radius(self, **kwargs: Any) -> AsyncIterator[MODU]:
2960
+ def all_modus_radius(
2961
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
2962
+ ) -> AsyncIterator[MODU]:
1175
2963
  """Iterate over all MODUs within a radius."""
1176
2964
  token: str | None = None
2965
+
1177
2966
  async def fetch() -> tuple[list[MODU], str | None]:
1178
2967
  nonlocal token
1179
- resp = await self.modus_radius(**kwargs, pagination_next_token=token)
2968
+ resp = await self.modus_radius(
2969
+ latitude=latitude,
2970
+ longitude=longitude,
2971
+ radius=radius,
2972
+ pagination_limit=pagination_limit,
2973
+ pagination_next_token=token,
2974
+ )
1180
2975
  token = resp.next_token
1181
2976
  return resp.modus or [], token
2977
+
1182
2978
  return AsyncIterator(fetch)
1183
2979
 
1184
- def all_radio_beacons_bounding_box(self, **kwargs: Any) -> AsyncIterator[RadioBeacon]:
2980
+ def all_radio_beacons_bounding_box(
2981
+ self, *, lat_min: float, lat_max: float, lon_min: float, lon_max: float, pagination_limit: int | None = None
2982
+ ) -> AsyncIterator[RadioBeacon]:
1185
2983
  """Iterate over all radio beacons in a bounding box."""
1186
2984
  token: str | None = None
2985
+
1187
2986
  async def fetch() -> tuple[list[RadioBeacon], str | None]:
1188
2987
  nonlocal token
1189
- resp = await self.radio_beacons_bounding_box(**kwargs, pagination_next_token=token)
2988
+ resp = await self.radio_beacons_bounding_box(
2989
+ lat_min=lat_min,
2990
+ lat_max=lat_max,
2991
+ lon_min=lon_min,
2992
+ lon_max=lon_max,
2993
+ pagination_limit=pagination_limit,
2994
+ pagination_next_token=token,
2995
+ )
1190
2996
  token = resp.next_token
1191
2997
  return resp.radio_beacons or [], token
2998
+
1192
2999
  return AsyncIterator(fetch)
1193
3000
 
1194
- def all_radio_beacons_radius(self, **kwargs: Any) -> AsyncIterator[RadioBeacon]:
3001
+ def all_radio_beacons_radius(
3002
+ self, *, latitude: float, longitude: float, radius: float, pagination_limit: int | None = None
3003
+ ) -> AsyncIterator[RadioBeacon]:
1195
3004
  """Iterate over all radio beacons within a radius."""
1196
3005
  token: str | None = None
3006
+
1197
3007
  async def fetch() -> tuple[list[RadioBeacon], str | None]:
1198
3008
  nonlocal token
1199
- resp = await self.radio_beacons_radius(**kwargs, pagination_next_token=token)
3009
+ resp = await self.radio_beacons_radius(
3010
+ latitude=latitude,
3011
+ longitude=longitude,
3012
+ radius=radius,
3013
+ pagination_limit=pagination_limit,
3014
+ pagination_next_token=token,
3015
+ )
1200
3016
  token = resp.next_token
1201
3017
  return resp.radio_beacons or [], token
1202
- return AsyncIterator(fetch)
1203
-
1204
3018
 
1205
- class AsyncNavtexService:
1206
- """NAVTEX message endpoints (async)."""
1207
-
1208
- def __init__(self, client: httpx.AsyncClient) -> None:
1209
- self._client = client
1210
-
1211
- async def list(self, *, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> NavtexMessagesResponse:
1212
- """Retrieve NAVTEX maritime safety messages."""
1213
- r = await self._client.get("/navtex", params=_strip_none({"time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
1214
- error_from_response(r.status_code, r.content)
1215
- return NavtexMessagesResponse.model_validate(r.json())
1216
-
1217
- def list_all(self, **kwargs: Any) -> AsyncIterator[Navtex]:
1218
- """Iterate over all NAVTEX messages across pages."""
1219
- token: str | None = None
1220
- async def fetch() -> tuple[list[Navtex], str | None]:
1221
- nonlocal token
1222
- resp = await self.list(**kwargs, pagination_next_token=token)
1223
- token = resp.next_token
1224
- return resp.navtex_messages or [], token
1225
3019
  return AsyncIterator(fetch)