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.
- vessel_api_python/__init__.py +9 -64
- vessel_api_python/_client.py +0 -4
- vessel_api_python/_constants.py +1 -1
- vessel_api_python/_errors.py +49 -1
- vessel_api_python/_models.py +50 -396
- vessel_api_python/_services.py +2145 -351
- vessel_api_python/_transport.py +5 -2
- {vessel_api_python-1.3.0.dist-info → vessel_api_python-2.0.0.dist-info}/METADATA +80 -16
- vessel_api_python-2.0.0.dist-info/RECORD +13 -0
- {vessel_api_python-1.3.0.dist-info → vessel_api_python-2.0.0.dist-info}/WHEEL +1 -1
- vessel_api_python-1.3.0.dist-info/RECORD +0 -13
- {vessel_api_python-1.3.0.dist-info → vessel_api_python-2.0.0.dist-info}/licenses/LICENSE +0 -0
vessel_api_python/_services.py
CHANGED
|
@@ -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.
|
|
5
|
-
|
|
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(
|
|
86
|
-
""
|
|
87
|
-
|
|
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(
|
|
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(
|
|
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
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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(
|
|
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
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
214
|
-
|
|
215
|
-
|
|
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(
|
|
220
|
-
|
|
221
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
238
|
-
|
|
239
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
326
|
-
|
|
327
|
-
|
|
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(
|
|
332
|
-
|
|
333
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
666
|
-
""
|
|
667
|
-
|
|
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(
|
|
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(
|
|
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
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
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(
|
|
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
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
794
|
-
|
|
795
|
-
|
|
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(
|
|
800
|
-
|
|
801
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
818
|
-
|
|
819
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
906
|
-
|
|
907
|
-
|
|
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(
|
|
912
|
-
|
|
913
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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)
|