vessel-api-python 1.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 +183 -0
- vessel_api_python/_client.py +163 -0
- vessel_api_python/_constants.py +8 -0
- vessel_api_python/_errors.py +137 -0
- vessel_api_python/_iterator.py +120 -0
- vessel_api_python/_models.py +887 -0
- vessel_api_python/_services.py +1180 -0
- vessel_api_python/_transport.py +185 -0
- vessel_api_python/py.typed +0 -0
- vessel_api_python-1.0.0.dist-info/METADATA +168 -0
- vessel_api_python-1.0.0.dist-info/RECORD +13 -0
- vessel_api_python-1.0.0.dist-info/WHEEL +4 -0
- vessel_api_python-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,1180 @@
|
|
|
1
|
+
"""Service classes wrapping Vessel API endpoints.
|
|
2
|
+
|
|
3
|
+
Each service groups related API endpoints and provides typed methods with
|
|
4
|
+
sensible defaults. All endpoints that require ``filter_id_type`` default
|
|
5
|
+
to ``"imo"`` to match the Go SDK behaviour.
|
|
6
|
+
|
|
7
|
+
Services come in sync and async variants. The async variants have the same
|
|
8
|
+
method signatures but use ``await`` for HTTP calls.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
14
|
+
|
|
15
|
+
from ._errors import error_from_response
|
|
16
|
+
from ._iterator import AsyncIterator, SyncIterator
|
|
17
|
+
from ._models import (
|
|
18
|
+
ClassificationResponse,
|
|
19
|
+
DGPSStationsWithinLocationResponse,
|
|
20
|
+
FindDGPSStationsResponse,
|
|
21
|
+
FindLightAidsResponse,
|
|
22
|
+
FindMODUsResponse,
|
|
23
|
+
FindPortsResponse,
|
|
24
|
+
FindRadioBeaconsResponse,
|
|
25
|
+
FindVesselsResponse,
|
|
26
|
+
LightAidsWithinLocationResponse,
|
|
27
|
+
MarineCasualtiesResponse,
|
|
28
|
+
MODUsWithinLocationResponse,
|
|
29
|
+
NavtexMessagesResponse,
|
|
30
|
+
PortEventResponse,
|
|
31
|
+
PortEventsResponse,
|
|
32
|
+
PortResponse,
|
|
33
|
+
PortsWithinLocationResponse,
|
|
34
|
+
RadioBeaconsWithinLocationResponse,
|
|
35
|
+
TypesInspectionDetailResponse,
|
|
36
|
+
TypesInspectionsResponse,
|
|
37
|
+
TypesOwnershipResponse,
|
|
38
|
+
VesselEmissionsResponse,
|
|
39
|
+
VesselETAResponse,
|
|
40
|
+
VesselPositionResponse,
|
|
41
|
+
VesselPositionsResponse,
|
|
42
|
+
VesselResponse,
|
|
43
|
+
VesselsWithinLocationResponse,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if TYPE_CHECKING:
|
|
47
|
+
import httpx
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _strip_none(params: dict[str, Any]) -> dict[str, Any]:
|
|
51
|
+
"""Remove keys with None values from a dict of query params."""
|
|
52
|
+
return {k: v for k, v in params.items() if v is not None}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ===================================================================
|
|
56
|
+
# Sync services
|
|
57
|
+
# ===================================================================
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class VesselsService:
|
|
61
|
+
"""Vessel-related API endpoints (sync)."""
|
|
62
|
+
|
|
63
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
64
|
+
self._client = client
|
|
65
|
+
|
|
66
|
+
def get(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselResponse:
|
|
67
|
+
"""Retrieve vessel details by ID (IMO or MMSI)."""
|
|
68
|
+
r = self._client.get(f"/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type}))
|
|
69
|
+
error_from_response(r.status_code, r.content)
|
|
70
|
+
return VesselResponse.model_validate(r.json())
|
|
71
|
+
|
|
72
|
+
def position(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselPositionResponse:
|
|
73
|
+
"""Retrieve the latest position for a vessel."""
|
|
74
|
+
r = self._client.get(f"/vessel/{vessel_id}/position", params=_strip_none({"filter.idType": filter_id_type}))
|
|
75
|
+
error_from_response(r.status_code, r.content)
|
|
76
|
+
return VesselPositionResponse.model_validate(r.json())
|
|
77
|
+
|
|
78
|
+
def casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MarineCasualtiesResponse:
|
|
79
|
+
"""Retrieve marine casualty records for a vessel."""
|
|
80
|
+
r = self._client.get(f"/vessel/{vessel_id}/casualties", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
81
|
+
error_from_response(r.status_code, r.content)
|
|
82
|
+
return MarineCasualtiesResponse.model_validate(r.json())
|
|
83
|
+
|
|
84
|
+
def classification(self, vessel_id: str, *, filter_id_type: str = "imo") -> ClassificationResponse:
|
|
85
|
+
"""Retrieve classification data for a vessel."""
|
|
86
|
+
r = self._client.get(f"/vessel/{vessel_id}/classification", params=_strip_none({"filter.idType": filter_id_type}))
|
|
87
|
+
error_from_response(r.status_code, r.content)
|
|
88
|
+
return ClassificationResponse.model_validate(r.json())
|
|
89
|
+
|
|
90
|
+
def emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
|
|
91
|
+
"""Retrieve emissions data for a vessel."""
|
|
92
|
+
r = self._client.get(f"/vessel/{vessel_id}/emissions", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
93
|
+
error_from_response(r.status_code, r.content)
|
|
94
|
+
return VesselEmissionsResponse.model_validate(r.json())
|
|
95
|
+
|
|
96
|
+
def eta(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselETAResponse:
|
|
97
|
+
"""Retrieve the estimated time of arrival for a vessel."""
|
|
98
|
+
r = self._client.get(f"/vessel/{vessel_id}/eta", params=_strip_none({"filter.idType": filter_id_type}))
|
|
99
|
+
error_from_response(r.status_code, r.content)
|
|
100
|
+
return VesselETAResponse.model_validate(r.json())
|
|
101
|
+
|
|
102
|
+
def inspections(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> TypesInspectionsResponse:
|
|
103
|
+
"""Retrieve inspection records for a vessel."""
|
|
104
|
+
r = self._client.get(f"/vessel/{vessel_id}/inspections", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
105
|
+
error_from_response(r.status_code, r.content)
|
|
106
|
+
return TypesInspectionsResponse.model_validate(r.json())
|
|
107
|
+
|
|
108
|
+
def inspection_detail(self, vessel_id: str, detail_id: str, *, filter_id_type: str = "imo") -> TypesInspectionDetailResponse:
|
|
109
|
+
"""Retrieve detailed inspection data."""
|
|
110
|
+
r = self._client.get(f"/vessel/{vessel_id}/inspections/{detail_id}", params=_strip_none({"filter.idType": filter_id_type}))
|
|
111
|
+
error_from_response(r.status_code, r.content)
|
|
112
|
+
return TypesInspectionDetailResponse.model_validate(r.json())
|
|
113
|
+
|
|
114
|
+
def ownership(self, vessel_id: str, *, filter_id_type: str = "imo") -> TypesOwnershipResponse:
|
|
115
|
+
"""Retrieve ownership data for a vessel."""
|
|
116
|
+
r = self._client.get(f"/vessel/{vessel_id}/ownership", params=_strip_none({"filter.idType": filter_id_type}))
|
|
117
|
+
error_from_response(r.status_code, r.content)
|
|
118
|
+
return TypesOwnershipResponse.model_validate(r.json())
|
|
119
|
+
|
|
120
|
+
def positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselPositionsResponse:
|
|
121
|
+
"""Retrieve positions for multiple vessels."""
|
|
122
|
+
r = self._client.get("/vessels/positions", params=_strip_none({"filter.idType": filter_id_type, "filter.ids": filter_ids, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
123
|
+
error_from_response(r.status_code, r.content)
|
|
124
|
+
return VesselPositionsResponse.model_validate(r.json())
|
|
125
|
+
|
|
126
|
+
# --- Iterators ---
|
|
127
|
+
|
|
128
|
+
def all_casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> SyncIterator[Any]:
|
|
129
|
+
"""Iterate over all casualties for a vessel across pages."""
|
|
130
|
+
token: str | None = None
|
|
131
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
132
|
+
nonlocal token
|
|
133
|
+
resp = self.casualties(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
134
|
+
token = resp.next_token
|
|
135
|
+
return resp.casualties or [], token
|
|
136
|
+
return SyncIterator(fetch)
|
|
137
|
+
|
|
138
|
+
def all_emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> SyncIterator[Any]:
|
|
139
|
+
"""Iterate over all emissions for a vessel across pages."""
|
|
140
|
+
token: str | None = None
|
|
141
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
142
|
+
nonlocal token
|
|
143
|
+
resp = self.emissions(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
144
|
+
token = resp.next_token
|
|
145
|
+
return resp.emissions or [], token
|
|
146
|
+
return SyncIterator(fetch)
|
|
147
|
+
|
|
148
|
+
def all_positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None) -> SyncIterator[Any]:
|
|
149
|
+
"""Iterate over all positions for multiple vessels across pages."""
|
|
150
|
+
token: str | None = None
|
|
151
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
152
|
+
nonlocal token
|
|
153
|
+
resp = self.positions(filter_id_type=filter_id_type, filter_ids=filter_ids, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
154
|
+
token = resp.next_token
|
|
155
|
+
return resp.vessel_positions or [], token
|
|
156
|
+
return SyncIterator(fetch)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class PortsService:
|
|
160
|
+
"""Port lookup endpoints (sync)."""
|
|
161
|
+
|
|
162
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
163
|
+
self._client = client
|
|
164
|
+
|
|
165
|
+
def get(self, unlocode: str) -> PortResponse:
|
|
166
|
+
"""Retrieve a port by its UN/LOCODE."""
|
|
167
|
+
r = self._client.get(f"/port/{unlocode}")
|
|
168
|
+
error_from_response(r.status_code, r.content)
|
|
169
|
+
return PortResponse.model_validate(r.json())
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class PortEventsService:
|
|
173
|
+
"""Port event endpoints (sync)."""
|
|
174
|
+
|
|
175
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
176
|
+
self._client = client
|
|
177
|
+
|
|
178
|
+
def list(self, *, time_from: str | None = None, time_to: str | None = None, filter_country: str | None = None, filter_unlocode: str | None = None, filter_event_type: str | None = None, filter_vessel_name: str | None = None, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
179
|
+
"""Retrieve port events with optional filtering."""
|
|
180
|
+
r = self._client.get("/portevents", params=_strip_none({"time.from": time_from, "time.to": time_to, "filter.country": filter_country, "filter.unlocode": filter_unlocode, "filter.eventType": filter_event_type, "filter.vesselName": filter_vessel_name, "filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
181
|
+
error_from_response(r.status_code, r.content)
|
|
182
|
+
return PortEventsResponse.model_validate(r.json())
|
|
183
|
+
|
|
184
|
+
def by_port(self, unlocode: str, *, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
185
|
+
"""Retrieve port events for a specific port by UNLOCODE."""
|
|
186
|
+
r = self._client.get(f"/portevents/port/{unlocode}", params=_strip_none({"pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
187
|
+
error_from_response(r.status_code, r.content)
|
|
188
|
+
return PortEventsResponse.model_validate(r.json())
|
|
189
|
+
|
|
190
|
+
def by_ports(self, *, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
191
|
+
"""Retrieve port events by port name search."""
|
|
192
|
+
r = self._client.get("/portevents/ports", params=_strip_none({"filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
193
|
+
error_from_response(r.status_code, r.content)
|
|
194
|
+
return PortEventsResponse.model_validate(r.json())
|
|
195
|
+
|
|
196
|
+
def by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo", filter_event_type: str | None = None, filter_sort_order: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
197
|
+
"""Retrieve port events for a specific vessel."""
|
|
198
|
+
r = self._client.get(f"/portevents/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type, "filter.eventType": filter_event_type, "filter.sortOrder": filter_sort_order, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
199
|
+
error_from_response(r.status_code, r.content)
|
|
200
|
+
return PortEventsResponse.model_validate(r.json())
|
|
201
|
+
|
|
202
|
+
def last_by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo") -> PortEventResponse:
|
|
203
|
+
"""Retrieve the last port event for a vessel."""
|
|
204
|
+
r = self._client.get(f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type}))
|
|
205
|
+
error_from_response(r.status_code, r.content)
|
|
206
|
+
return PortEventResponse.model_validate(r.json())
|
|
207
|
+
|
|
208
|
+
def by_vessels(self, *, filter_vessel_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
209
|
+
"""Retrieve port events by vessel name search."""
|
|
210
|
+
r = self._client.get("/portevents/vessels", params=_strip_none({"filter.vesselName": filter_vessel_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
211
|
+
error_from_response(r.status_code, r.content)
|
|
212
|
+
return PortEventsResponse.model_validate(r.json())
|
|
213
|
+
|
|
214
|
+
# --- Iterators ---
|
|
215
|
+
|
|
216
|
+
def list_all(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
217
|
+
"""Iterate over all port events across pages."""
|
|
218
|
+
token: str | None = None
|
|
219
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
220
|
+
nonlocal token
|
|
221
|
+
resp = self.list(**kwargs, pagination_next_token=token)
|
|
222
|
+
token = resp.next_token
|
|
223
|
+
return resp.port_events or [], token
|
|
224
|
+
return SyncIterator(fetch)
|
|
225
|
+
|
|
226
|
+
def all_by_port(self, unlocode: str, **kwargs: Any) -> SyncIterator[Any]:
|
|
227
|
+
"""Iterate over all port events for a specific port."""
|
|
228
|
+
token: str | None = None
|
|
229
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
230
|
+
nonlocal token
|
|
231
|
+
resp = self.by_port(unlocode, **kwargs, pagination_next_token=token)
|
|
232
|
+
token = resp.next_token
|
|
233
|
+
return resp.port_events or [], token
|
|
234
|
+
return SyncIterator(fetch)
|
|
235
|
+
|
|
236
|
+
def all_by_ports(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
237
|
+
"""Iterate over all port events by port name search."""
|
|
238
|
+
token: str | None = None
|
|
239
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
240
|
+
nonlocal token
|
|
241
|
+
resp = self.by_ports(**kwargs, pagination_next_token=token)
|
|
242
|
+
token = resp.next_token
|
|
243
|
+
return resp.port_events or [], token
|
|
244
|
+
return SyncIterator(fetch)
|
|
245
|
+
|
|
246
|
+
def all_by_vessel(self, vessel_id: str, **kwargs: Any) -> SyncIterator[Any]:
|
|
247
|
+
"""Iterate over all port events for a vessel."""
|
|
248
|
+
token: str | None = None
|
|
249
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
250
|
+
nonlocal token
|
|
251
|
+
resp = self.by_vessel(vessel_id, **kwargs, pagination_next_token=token)
|
|
252
|
+
token = resp.next_token
|
|
253
|
+
return resp.port_events or [], token
|
|
254
|
+
return SyncIterator(fetch)
|
|
255
|
+
|
|
256
|
+
def all_by_vessels(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
257
|
+
"""Iterate over all port events by vessel name search."""
|
|
258
|
+
token: str | None = None
|
|
259
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
260
|
+
nonlocal token
|
|
261
|
+
resp = self.by_vessels(**kwargs, pagination_next_token=token)
|
|
262
|
+
token = resp.next_token
|
|
263
|
+
return resp.port_events or [], token
|
|
264
|
+
return SyncIterator(fetch)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class EmissionsService:
|
|
268
|
+
"""Emissions endpoints (sync)."""
|
|
269
|
+
|
|
270
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
271
|
+
self._client = client
|
|
272
|
+
|
|
273
|
+
def list(self, *, filter_period: int | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
|
|
274
|
+
"""Retrieve vessel emissions data."""
|
|
275
|
+
r = self._client.get("/emissions", params=_strip_none({"filter.period": filter_period, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
276
|
+
error_from_response(r.status_code, r.content)
|
|
277
|
+
return VesselEmissionsResponse.model_validate(r.json())
|
|
278
|
+
|
|
279
|
+
def list_all(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
280
|
+
"""Iterate over all emissions across pages."""
|
|
281
|
+
token: str | None = None
|
|
282
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
283
|
+
nonlocal token
|
|
284
|
+
resp = self.list(**kwargs, pagination_next_token=token)
|
|
285
|
+
token = resp.next_token
|
|
286
|
+
return resp.emissions or [], token
|
|
287
|
+
return SyncIterator(fetch)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class SearchService:
|
|
291
|
+
"""Search endpoints (sync)."""
|
|
292
|
+
|
|
293
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
294
|
+
self._client = client
|
|
295
|
+
|
|
296
|
+
def vessels(self, *, filter_name: str | None = None, filter_imo: str | None = None, filter_mmsi: str | None = None, filter_flag: str | None = None, filter_vessel_type: str | None = None, filter_callsign: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindVesselsResponse:
|
|
297
|
+
"""Search for vessels by name, callsign, flag, type, and other filters."""
|
|
298
|
+
r = self._client.get("/search/vessels", params=_strip_none({"filter.name": filter_name, "filter.imo": filter_imo, "filter.mmsi": filter_mmsi, "filter.flag": filter_flag, "filter.vesselType": filter_vessel_type, "filter.callsign": filter_callsign, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
299
|
+
error_from_response(r.status_code, r.content)
|
|
300
|
+
return FindVesselsResponse.model_validate(r.json())
|
|
301
|
+
|
|
302
|
+
def ports(self, *, filter_name: str | None = None, filter_country: str | None = None, filter_port_type: str | None = None, filter_region: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindPortsResponse:
|
|
303
|
+
"""Search for ports by name, country, type, region, and other filters."""
|
|
304
|
+
r = self._client.get("/search/ports", params=_strip_none({"filter.name": filter_name, "filter.country": filter_country, "filter.type": filter_port_type, "filter.region": filter_region, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
305
|
+
error_from_response(r.status_code, r.content)
|
|
306
|
+
return FindPortsResponse.model_validate(r.json())
|
|
307
|
+
|
|
308
|
+
def dgps(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindDGPSStationsResponse:
|
|
309
|
+
"""Search for DGPS stations by name."""
|
|
310
|
+
r = self._client.get("/search/dgps", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
311
|
+
error_from_response(r.status_code, r.content)
|
|
312
|
+
return FindDGPSStationsResponse.model_validate(r.json())
|
|
313
|
+
|
|
314
|
+
def light_aids(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindLightAidsResponse:
|
|
315
|
+
"""Search for light aids by name."""
|
|
316
|
+
r = self._client.get("/search/lightaids", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
317
|
+
error_from_response(r.status_code, r.content)
|
|
318
|
+
return FindLightAidsResponse.model_validate(r.json())
|
|
319
|
+
|
|
320
|
+
def modus(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindMODUsResponse:
|
|
321
|
+
"""Search for MODUs (Mobile Offshore Drilling Units) by name."""
|
|
322
|
+
r = self._client.get("/search/modus", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
323
|
+
error_from_response(r.status_code, r.content)
|
|
324
|
+
return FindMODUsResponse.model_validate(r.json())
|
|
325
|
+
|
|
326
|
+
def radio_beacons(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindRadioBeaconsResponse:
|
|
327
|
+
"""Search for radio beacons by name."""
|
|
328
|
+
r = self._client.get("/search/radiobeacons", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
329
|
+
error_from_response(r.status_code, r.content)
|
|
330
|
+
return FindRadioBeaconsResponse.model_validate(r.json())
|
|
331
|
+
|
|
332
|
+
# --- Iterators ---
|
|
333
|
+
|
|
334
|
+
def all_vessels(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
335
|
+
"""Iterate over all vessel search results across pages."""
|
|
336
|
+
token: str | None = None
|
|
337
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
338
|
+
nonlocal token
|
|
339
|
+
resp = self.vessels(**kwargs, pagination_next_token=token)
|
|
340
|
+
token = resp.next_token
|
|
341
|
+
return resp.vessels or [], token
|
|
342
|
+
return SyncIterator(fetch)
|
|
343
|
+
|
|
344
|
+
def all_ports(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
345
|
+
"""Iterate over all port search results across pages."""
|
|
346
|
+
token: str | None = None
|
|
347
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
348
|
+
nonlocal token
|
|
349
|
+
resp = self.ports(**kwargs, pagination_next_token=token)
|
|
350
|
+
token = resp.next_token
|
|
351
|
+
return resp.ports or [], token
|
|
352
|
+
return SyncIterator(fetch)
|
|
353
|
+
|
|
354
|
+
def all_dgps(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
355
|
+
"""Iterate over all DGPS station search results."""
|
|
356
|
+
token: str | None = None
|
|
357
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
358
|
+
nonlocal token
|
|
359
|
+
resp = self.dgps(**kwargs, pagination_next_token=token)
|
|
360
|
+
token = resp.next_token
|
|
361
|
+
return resp.dgps_stations or [], token
|
|
362
|
+
return SyncIterator(fetch)
|
|
363
|
+
|
|
364
|
+
def all_light_aids(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
365
|
+
"""Iterate over all light aid search results."""
|
|
366
|
+
token: str | None = None
|
|
367
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
368
|
+
nonlocal token
|
|
369
|
+
resp = self.light_aids(**kwargs, pagination_next_token=token)
|
|
370
|
+
token = resp.next_token
|
|
371
|
+
return resp.light_aids or [], token
|
|
372
|
+
return SyncIterator(fetch)
|
|
373
|
+
|
|
374
|
+
def all_modus(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
375
|
+
"""Iterate over all MODU search results."""
|
|
376
|
+
token: str | None = None
|
|
377
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
378
|
+
nonlocal token
|
|
379
|
+
resp = self.modus(**kwargs, pagination_next_token=token)
|
|
380
|
+
token = resp.next_token
|
|
381
|
+
return resp.modus or [], token
|
|
382
|
+
return SyncIterator(fetch)
|
|
383
|
+
|
|
384
|
+
def all_radio_beacons(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
385
|
+
"""Iterate over all radio beacon search results."""
|
|
386
|
+
token: str | None = None
|
|
387
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
388
|
+
nonlocal token
|
|
389
|
+
resp = self.radio_beacons(**kwargs, pagination_next_token=token)
|
|
390
|
+
token = resp.next_token
|
|
391
|
+
return resp.radio_beacons or [], token
|
|
392
|
+
return SyncIterator(fetch)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class LocationService:
|
|
396
|
+
"""Location-based query endpoints (sync)."""
|
|
397
|
+
|
|
398
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
399
|
+
self._client = client
|
|
400
|
+
|
|
401
|
+
def vessels_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
|
|
402
|
+
"""Retrieve vessel positions within a bounding box."""
|
|
403
|
+
r = self._client.get("/location/vessels/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
404
|
+
error_from_response(r.status_code, r.content)
|
|
405
|
+
return VesselsWithinLocationResponse.model_validate(r.json())
|
|
406
|
+
|
|
407
|
+
def vessels_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
|
|
408
|
+
"""Retrieve vessel positions within a radius."""
|
|
409
|
+
r = self._client.get("/location/vessels/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
410
|
+
error_from_response(r.status_code, r.content)
|
|
411
|
+
return VesselsWithinLocationResponse.model_validate(r.json())
|
|
412
|
+
|
|
413
|
+
def ports_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
|
|
414
|
+
"""Retrieve ports within a bounding box."""
|
|
415
|
+
r = self._client.get("/location/ports/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
416
|
+
error_from_response(r.status_code, r.content)
|
|
417
|
+
return PortsWithinLocationResponse.model_validate(r.json())
|
|
418
|
+
|
|
419
|
+
def ports_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
|
|
420
|
+
"""Retrieve ports within a radius."""
|
|
421
|
+
r = self._client.get("/location/ports/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
422
|
+
error_from_response(r.status_code, r.content)
|
|
423
|
+
return PortsWithinLocationResponse.model_validate(r.json())
|
|
424
|
+
|
|
425
|
+
def dgps_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
|
|
426
|
+
"""Retrieve DGPS stations within a bounding box."""
|
|
427
|
+
r = self._client.get("/location/dgps/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
428
|
+
error_from_response(r.status_code, r.content)
|
|
429
|
+
return DGPSStationsWithinLocationResponse.model_validate(r.json())
|
|
430
|
+
|
|
431
|
+
def dgps_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
|
|
432
|
+
"""Retrieve DGPS stations within a radius."""
|
|
433
|
+
r = self._client.get("/location/dgps/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
434
|
+
error_from_response(r.status_code, r.content)
|
|
435
|
+
return DGPSStationsWithinLocationResponse.model_validate(r.json())
|
|
436
|
+
|
|
437
|
+
def light_aids_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
|
|
438
|
+
"""Retrieve light aids within a bounding box."""
|
|
439
|
+
r = self._client.get("/location/lightaids/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
440
|
+
error_from_response(r.status_code, r.content)
|
|
441
|
+
return LightAidsWithinLocationResponse.model_validate(r.json())
|
|
442
|
+
|
|
443
|
+
def light_aids_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
|
|
444
|
+
"""Retrieve light aids within a radius."""
|
|
445
|
+
r = self._client.get("/location/lightaids/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
446
|
+
error_from_response(r.status_code, r.content)
|
|
447
|
+
return LightAidsWithinLocationResponse.model_validate(r.json())
|
|
448
|
+
|
|
449
|
+
def modus_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
|
|
450
|
+
"""Retrieve MODUs within a bounding box."""
|
|
451
|
+
r = self._client.get("/location/modu/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
452
|
+
error_from_response(r.status_code, r.content)
|
|
453
|
+
return MODUsWithinLocationResponse.model_validate(r.json())
|
|
454
|
+
|
|
455
|
+
def modus_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
|
|
456
|
+
"""Retrieve MODUs within a radius."""
|
|
457
|
+
r = self._client.get("/location/modu/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
458
|
+
error_from_response(r.status_code, r.content)
|
|
459
|
+
return MODUsWithinLocationResponse.model_validate(r.json())
|
|
460
|
+
|
|
461
|
+
def radio_beacons_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
|
|
462
|
+
"""Retrieve radio beacons within a bounding box."""
|
|
463
|
+
r = self._client.get("/location/radiobeacons/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
464
|
+
error_from_response(r.status_code, r.content)
|
|
465
|
+
return RadioBeaconsWithinLocationResponse.model_validate(r.json())
|
|
466
|
+
|
|
467
|
+
def radio_beacons_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
|
|
468
|
+
"""Retrieve radio beacons within a radius."""
|
|
469
|
+
r = self._client.get("/location/radiobeacons/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
470
|
+
error_from_response(r.status_code, r.content)
|
|
471
|
+
return RadioBeaconsWithinLocationResponse.model_validate(r.json())
|
|
472
|
+
|
|
473
|
+
# --- Iterators ---
|
|
474
|
+
|
|
475
|
+
def all_vessels_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
476
|
+
"""Iterate over all vessel positions in a bounding box."""
|
|
477
|
+
token: str | None = None
|
|
478
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
479
|
+
nonlocal token
|
|
480
|
+
resp = self.vessels_bounding_box(**kwargs, pagination_next_token=token)
|
|
481
|
+
token = resp.next_token
|
|
482
|
+
return resp.vessels or [], token
|
|
483
|
+
return SyncIterator(fetch)
|
|
484
|
+
|
|
485
|
+
def all_vessels_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
486
|
+
"""Iterate over all vessel positions within a radius."""
|
|
487
|
+
token: str | None = None
|
|
488
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
489
|
+
nonlocal token
|
|
490
|
+
resp = self.vessels_radius(**kwargs, pagination_next_token=token)
|
|
491
|
+
token = resp.next_token
|
|
492
|
+
return resp.vessels or [], token
|
|
493
|
+
return SyncIterator(fetch)
|
|
494
|
+
|
|
495
|
+
def all_ports_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
496
|
+
"""Iterate over all ports in a bounding box."""
|
|
497
|
+
token: str | None = None
|
|
498
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
499
|
+
nonlocal token
|
|
500
|
+
resp = self.ports_bounding_box(**kwargs, pagination_next_token=token)
|
|
501
|
+
token = resp.next_token
|
|
502
|
+
return resp.ports or [], token
|
|
503
|
+
return SyncIterator(fetch)
|
|
504
|
+
|
|
505
|
+
def all_ports_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
506
|
+
"""Iterate over all ports within a radius."""
|
|
507
|
+
token: str | None = None
|
|
508
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
509
|
+
nonlocal token
|
|
510
|
+
resp = self.ports_radius(**kwargs, pagination_next_token=token)
|
|
511
|
+
token = resp.next_token
|
|
512
|
+
return resp.ports or [], token
|
|
513
|
+
return SyncIterator(fetch)
|
|
514
|
+
|
|
515
|
+
def all_dgps_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
516
|
+
"""Iterate over all DGPS stations in a bounding box."""
|
|
517
|
+
token: str | None = None
|
|
518
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
519
|
+
nonlocal token
|
|
520
|
+
resp = self.dgps_bounding_box(**kwargs, pagination_next_token=token)
|
|
521
|
+
token = resp.next_token
|
|
522
|
+
return resp.dgps_stations or [], token
|
|
523
|
+
return SyncIterator(fetch)
|
|
524
|
+
|
|
525
|
+
def all_dgps_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
526
|
+
"""Iterate over all DGPS stations within a radius."""
|
|
527
|
+
token: str | None = None
|
|
528
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
529
|
+
nonlocal token
|
|
530
|
+
resp = self.dgps_radius(**kwargs, pagination_next_token=token)
|
|
531
|
+
token = resp.next_token
|
|
532
|
+
return resp.dgps_stations or [], token
|
|
533
|
+
return SyncIterator(fetch)
|
|
534
|
+
|
|
535
|
+
def all_light_aids_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
536
|
+
"""Iterate over all light aids in a bounding box."""
|
|
537
|
+
token: str | None = None
|
|
538
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
539
|
+
nonlocal token
|
|
540
|
+
resp = self.light_aids_bounding_box(**kwargs, pagination_next_token=token)
|
|
541
|
+
token = resp.next_token
|
|
542
|
+
return resp.light_aids or [], token
|
|
543
|
+
return SyncIterator(fetch)
|
|
544
|
+
|
|
545
|
+
def all_light_aids_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
546
|
+
"""Iterate over all light aids within a radius."""
|
|
547
|
+
token: str | None = None
|
|
548
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
549
|
+
nonlocal token
|
|
550
|
+
resp = self.light_aids_radius(**kwargs, pagination_next_token=token)
|
|
551
|
+
token = resp.next_token
|
|
552
|
+
return resp.light_aids or [], token
|
|
553
|
+
return SyncIterator(fetch)
|
|
554
|
+
|
|
555
|
+
def all_modus_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
556
|
+
"""Iterate over all MODUs in a bounding box."""
|
|
557
|
+
token: str | None = None
|
|
558
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
559
|
+
nonlocal token
|
|
560
|
+
resp = self.modus_bounding_box(**kwargs, pagination_next_token=token)
|
|
561
|
+
token = resp.next_token
|
|
562
|
+
return resp.modus or [], token
|
|
563
|
+
return SyncIterator(fetch)
|
|
564
|
+
|
|
565
|
+
def all_modus_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
566
|
+
"""Iterate over all MODUs within a radius."""
|
|
567
|
+
token: str | None = None
|
|
568
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
569
|
+
nonlocal token
|
|
570
|
+
resp = self.modus_radius(**kwargs, pagination_next_token=token)
|
|
571
|
+
token = resp.next_token
|
|
572
|
+
return resp.modus or [], token
|
|
573
|
+
return SyncIterator(fetch)
|
|
574
|
+
|
|
575
|
+
def all_radio_beacons_bounding_box(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
576
|
+
"""Iterate over all radio beacons in a bounding box."""
|
|
577
|
+
token: str | None = None
|
|
578
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
579
|
+
nonlocal token
|
|
580
|
+
resp = self.radio_beacons_bounding_box(**kwargs, pagination_next_token=token)
|
|
581
|
+
token = resp.next_token
|
|
582
|
+
return resp.radio_beacons or [], token
|
|
583
|
+
return SyncIterator(fetch)
|
|
584
|
+
|
|
585
|
+
def all_radio_beacons_radius(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
586
|
+
"""Iterate over all radio beacons within a radius."""
|
|
587
|
+
token: str | None = None
|
|
588
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
589
|
+
nonlocal token
|
|
590
|
+
resp = self.radio_beacons_radius(**kwargs, pagination_next_token=token)
|
|
591
|
+
token = resp.next_token
|
|
592
|
+
return resp.radio_beacons or [], token
|
|
593
|
+
return SyncIterator(fetch)
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
class NavtexService:
|
|
597
|
+
"""NAVTEX message endpoints (sync)."""
|
|
598
|
+
|
|
599
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
600
|
+
self._client = client
|
|
601
|
+
|
|
602
|
+
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:
|
|
603
|
+
"""Retrieve NAVTEX maritime safety messages."""
|
|
604
|
+
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}))
|
|
605
|
+
error_from_response(r.status_code, r.content)
|
|
606
|
+
return NavtexMessagesResponse.model_validate(r.json())
|
|
607
|
+
|
|
608
|
+
def list_all(self, **kwargs: Any) -> SyncIterator[Any]:
|
|
609
|
+
"""Iterate over all NAVTEX messages across pages."""
|
|
610
|
+
token: str | None = None
|
|
611
|
+
def fetch() -> tuple[list[Any], str | None]:
|
|
612
|
+
nonlocal token
|
|
613
|
+
resp = self.list(**kwargs, pagination_next_token=token)
|
|
614
|
+
token = resp.next_token
|
|
615
|
+
return resp.navtex_messages or [], token
|
|
616
|
+
return SyncIterator(fetch)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
# ===================================================================
|
|
620
|
+
# Async services
|
|
621
|
+
# ===================================================================
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
class AsyncVesselsService:
|
|
625
|
+
"""Vessel-related API endpoints (async)."""
|
|
626
|
+
|
|
627
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
628
|
+
self._client = client
|
|
629
|
+
|
|
630
|
+
async def get(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselResponse:
|
|
631
|
+
"""Retrieve vessel details by ID (IMO or MMSI)."""
|
|
632
|
+
r = await self._client.get(f"/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type}))
|
|
633
|
+
error_from_response(r.status_code, r.content)
|
|
634
|
+
return VesselResponse.model_validate(r.json())
|
|
635
|
+
|
|
636
|
+
async def position(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselPositionResponse:
|
|
637
|
+
"""Retrieve the latest position for a vessel."""
|
|
638
|
+
r = await self._client.get(f"/vessel/{vessel_id}/position", params=_strip_none({"filter.idType": filter_id_type}))
|
|
639
|
+
error_from_response(r.status_code, r.content)
|
|
640
|
+
return VesselPositionResponse.model_validate(r.json())
|
|
641
|
+
|
|
642
|
+
async def casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MarineCasualtiesResponse:
|
|
643
|
+
"""Retrieve marine casualty records for a vessel."""
|
|
644
|
+
r = await self._client.get(f"/vessel/{vessel_id}/casualties", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
645
|
+
error_from_response(r.status_code, r.content)
|
|
646
|
+
return MarineCasualtiesResponse.model_validate(r.json())
|
|
647
|
+
|
|
648
|
+
async def classification(self, vessel_id: str, *, filter_id_type: str = "imo") -> ClassificationResponse:
|
|
649
|
+
"""Retrieve classification data for a vessel."""
|
|
650
|
+
r = await self._client.get(f"/vessel/{vessel_id}/classification", params=_strip_none({"filter.idType": filter_id_type}))
|
|
651
|
+
error_from_response(r.status_code, r.content)
|
|
652
|
+
return ClassificationResponse.model_validate(r.json())
|
|
653
|
+
|
|
654
|
+
async def emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
|
|
655
|
+
"""Retrieve emissions data for a vessel."""
|
|
656
|
+
r = await self._client.get(f"/vessel/{vessel_id}/emissions", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
657
|
+
error_from_response(r.status_code, r.content)
|
|
658
|
+
return VesselEmissionsResponse.model_validate(r.json())
|
|
659
|
+
|
|
660
|
+
async def eta(self, vessel_id: str, *, filter_id_type: str = "imo") -> VesselETAResponse:
|
|
661
|
+
"""Retrieve the estimated time of arrival for a vessel."""
|
|
662
|
+
r = await self._client.get(f"/vessel/{vessel_id}/eta", params=_strip_none({"filter.idType": filter_id_type}))
|
|
663
|
+
error_from_response(r.status_code, r.content)
|
|
664
|
+
return VesselETAResponse.model_validate(r.json())
|
|
665
|
+
|
|
666
|
+
async def inspections(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None, pagination_next_token: str | None = None) -> TypesInspectionsResponse:
|
|
667
|
+
"""Retrieve inspection records for a vessel."""
|
|
668
|
+
r = await self._client.get(f"/vessel/{vessel_id}/inspections", params=_strip_none({"filter.idType": filter_id_type, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
669
|
+
error_from_response(r.status_code, r.content)
|
|
670
|
+
return TypesInspectionsResponse.model_validate(r.json())
|
|
671
|
+
|
|
672
|
+
async def inspection_detail(self, vessel_id: str, detail_id: str, *, filter_id_type: str = "imo") -> TypesInspectionDetailResponse:
|
|
673
|
+
"""Retrieve detailed inspection data."""
|
|
674
|
+
r = await self._client.get(f"/vessel/{vessel_id}/inspections/{detail_id}", params=_strip_none({"filter.idType": filter_id_type}))
|
|
675
|
+
error_from_response(r.status_code, r.content)
|
|
676
|
+
return TypesInspectionDetailResponse.model_validate(r.json())
|
|
677
|
+
|
|
678
|
+
async def ownership(self, vessel_id: str, *, filter_id_type: str = "imo") -> TypesOwnershipResponse:
|
|
679
|
+
"""Retrieve ownership data for a vessel."""
|
|
680
|
+
r = await self._client.get(f"/vessel/{vessel_id}/ownership", params=_strip_none({"filter.idType": filter_id_type}))
|
|
681
|
+
error_from_response(r.status_code, r.content)
|
|
682
|
+
return TypesOwnershipResponse.model_validate(r.json())
|
|
683
|
+
|
|
684
|
+
async def positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselPositionsResponse:
|
|
685
|
+
"""Retrieve positions for multiple vessels."""
|
|
686
|
+
r = await self._client.get("/vessels/positions", params=_strip_none({"filter.idType": filter_id_type, "filter.ids": filter_ids, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
687
|
+
error_from_response(r.status_code, r.content)
|
|
688
|
+
return VesselPositionsResponse.model_validate(r.json())
|
|
689
|
+
|
|
690
|
+
# --- Iterators ---
|
|
691
|
+
|
|
692
|
+
def all_casualties(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> AsyncIterator[Any]:
|
|
693
|
+
"""Iterate over all casualties for a vessel across pages."""
|
|
694
|
+
token: str | None = None
|
|
695
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
696
|
+
nonlocal token
|
|
697
|
+
resp = await self.casualties(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
698
|
+
token = resp.next_token
|
|
699
|
+
return resp.casualties or [], token
|
|
700
|
+
return AsyncIterator(fetch)
|
|
701
|
+
|
|
702
|
+
def all_emissions(self, vessel_id: str, *, filter_id_type: str = "imo", pagination_limit: int | None = None) -> AsyncIterator[Any]:
|
|
703
|
+
"""Iterate over all emissions for a vessel across pages."""
|
|
704
|
+
token: str | None = None
|
|
705
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
706
|
+
nonlocal token
|
|
707
|
+
resp = await self.emissions(vessel_id, filter_id_type=filter_id_type, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
708
|
+
token = resp.next_token
|
|
709
|
+
return resp.emissions or [], token
|
|
710
|
+
return AsyncIterator(fetch)
|
|
711
|
+
|
|
712
|
+
def all_positions(self, *, filter_id_type: str = "imo", filter_ids: str | None = None, pagination_limit: int | None = None) -> AsyncIterator[Any]:
|
|
713
|
+
"""Iterate over all positions for multiple vessels across pages."""
|
|
714
|
+
token: str | None = None
|
|
715
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
716
|
+
nonlocal token
|
|
717
|
+
resp = await self.positions(filter_id_type=filter_id_type, filter_ids=filter_ids, pagination_limit=pagination_limit, pagination_next_token=token)
|
|
718
|
+
token = resp.next_token
|
|
719
|
+
return resp.vessel_positions or [], token
|
|
720
|
+
return AsyncIterator(fetch)
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
class AsyncPortsService:
|
|
724
|
+
"""Port lookup endpoints (async)."""
|
|
725
|
+
|
|
726
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
727
|
+
self._client = client
|
|
728
|
+
|
|
729
|
+
async def get(self, unlocode: str) -> PortResponse:
|
|
730
|
+
"""Retrieve a port by its UN/LOCODE."""
|
|
731
|
+
r = await self._client.get(f"/port/{unlocode}")
|
|
732
|
+
error_from_response(r.status_code, r.content)
|
|
733
|
+
return PortResponse.model_validate(r.json())
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
class AsyncPortEventsService:
|
|
737
|
+
"""Port event endpoints (async)."""
|
|
738
|
+
|
|
739
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
740
|
+
self._client = client
|
|
741
|
+
|
|
742
|
+
async def list(self, *, time_from: str | None = None, time_to: str | None = None, filter_country: str | None = None, filter_unlocode: str | None = None, filter_event_type: str | None = None, filter_vessel_name: str | None = None, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
743
|
+
"""Retrieve port events with optional filtering."""
|
|
744
|
+
r = await self._client.get("/portevents", params=_strip_none({"time.from": time_from, "time.to": time_to, "filter.country": filter_country, "filter.unlocode": filter_unlocode, "filter.eventType": filter_event_type, "filter.vesselName": filter_vessel_name, "filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
745
|
+
error_from_response(r.status_code, r.content)
|
|
746
|
+
return PortEventsResponse.model_validate(r.json())
|
|
747
|
+
|
|
748
|
+
async def by_port(self, unlocode: str, *, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
749
|
+
"""Retrieve port events for a specific port by UNLOCODE."""
|
|
750
|
+
r = await self._client.get(f"/portevents/port/{unlocode}", params=_strip_none({"pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
751
|
+
error_from_response(r.status_code, r.content)
|
|
752
|
+
return PortEventsResponse.model_validate(r.json())
|
|
753
|
+
|
|
754
|
+
async def by_ports(self, *, filter_port_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
755
|
+
"""Retrieve port events by port name search."""
|
|
756
|
+
r = await self._client.get("/portevents/ports", params=_strip_none({"filter.portName": filter_port_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
757
|
+
error_from_response(r.status_code, r.content)
|
|
758
|
+
return PortEventsResponse.model_validate(r.json())
|
|
759
|
+
|
|
760
|
+
async def by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo", filter_event_type: str | None = None, filter_sort_order: str | None = None, time_from: str | None = None, time_to: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
761
|
+
"""Retrieve port events for a specific vessel."""
|
|
762
|
+
r = await self._client.get(f"/portevents/vessel/{vessel_id}", params=_strip_none({"filter.idType": filter_id_type, "filter.eventType": filter_event_type, "filter.sortOrder": filter_sort_order, "time.from": time_from, "time.to": time_to, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
763
|
+
error_from_response(r.status_code, r.content)
|
|
764
|
+
return PortEventsResponse.model_validate(r.json())
|
|
765
|
+
|
|
766
|
+
async def last_by_vessel(self, vessel_id: str, *, filter_id_type: str = "imo") -> PortEventResponse:
|
|
767
|
+
"""Retrieve the last port event for a vessel."""
|
|
768
|
+
r = await self._client.get(f"/portevents/vessel/{vessel_id}/last", params=_strip_none({"filter.idType": filter_id_type}))
|
|
769
|
+
error_from_response(r.status_code, r.content)
|
|
770
|
+
return PortEventResponse.model_validate(r.json())
|
|
771
|
+
|
|
772
|
+
async def by_vessels(self, *, filter_vessel_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortEventsResponse:
|
|
773
|
+
"""Retrieve port events by vessel name search."""
|
|
774
|
+
r = await self._client.get("/portevents/vessels", params=_strip_none({"filter.vesselName": filter_vessel_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
775
|
+
error_from_response(r.status_code, r.content)
|
|
776
|
+
return PortEventsResponse.model_validate(r.json())
|
|
777
|
+
|
|
778
|
+
# --- Iterators ---
|
|
779
|
+
|
|
780
|
+
def list_all(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
781
|
+
"""Iterate over all port events across pages."""
|
|
782
|
+
token: str | None = None
|
|
783
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
784
|
+
nonlocal token
|
|
785
|
+
resp = await self.list(**kwargs, pagination_next_token=token)
|
|
786
|
+
token = resp.next_token
|
|
787
|
+
return resp.port_events or [], token
|
|
788
|
+
return AsyncIterator(fetch)
|
|
789
|
+
|
|
790
|
+
def all_by_port(self, unlocode: str, **kwargs: Any) -> AsyncIterator[Any]:
|
|
791
|
+
"""Iterate over all port events for a specific port."""
|
|
792
|
+
token: str | None = None
|
|
793
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
794
|
+
nonlocal token
|
|
795
|
+
resp = await self.by_port(unlocode, **kwargs, pagination_next_token=token)
|
|
796
|
+
token = resp.next_token
|
|
797
|
+
return resp.port_events or [], token
|
|
798
|
+
return AsyncIterator(fetch)
|
|
799
|
+
|
|
800
|
+
def all_by_ports(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
801
|
+
"""Iterate over all port events by port name search."""
|
|
802
|
+
token: str | None = None
|
|
803
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
804
|
+
nonlocal token
|
|
805
|
+
resp = await self.by_ports(**kwargs, pagination_next_token=token)
|
|
806
|
+
token = resp.next_token
|
|
807
|
+
return resp.port_events or [], token
|
|
808
|
+
return AsyncIterator(fetch)
|
|
809
|
+
|
|
810
|
+
def all_by_vessel(self, vessel_id: str, **kwargs: Any) -> AsyncIterator[Any]:
|
|
811
|
+
"""Iterate over all port events for a vessel."""
|
|
812
|
+
token: str | None = None
|
|
813
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
814
|
+
nonlocal token
|
|
815
|
+
resp = await self.by_vessel(vessel_id, **kwargs, pagination_next_token=token)
|
|
816
|
+
token = resp.next_token
|
|
817
|
+
return resp.port_events or [], token
|
|
818
|
+
return AsyncIterator(fetch)
|
|
819
|
+
|
|
820
|
+
def all_by_vessels(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
821
|
+
"""Iterate over all port events by vessel name search."""
|
|
822
|
+
token: str | None = None
|
|
823
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
824
|
+
nonlocal token
|
|
825
|
+
resp = await self.by_vessels(**kwargs, pagination_next_token=token)
|
|
826
|
+
token = resp.next_token
|
|
827
|
+
return resp.port_events or [], token
|
|
828
|
+
return AsyncIterator(fetch)
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
class AsyncEmissionsService:
|
|
832
|
+
"""Emissions endpoints (async)."""
|
|
833
|
+
|
|
834
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
835
|
+
self._client = client
|
|
836
|
+
|
|
837
|
+
async def list(self, *, filter_period: int | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselEmissionsResponse:
|
|
838
|
+
"""Retrieve vessel emissions data."""
|
|
839
|
+
r = await self._client.get("/emissions", params=_strip_none({"filter.period": filter_period, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
840
|
+
error_from_response(r.status_code, r.content)
|
|
841
|
+
return VesselEmissionsResponse.model_validate(r.json())
|
|
842
|
+
|
|
843
|
+
def list_all(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
844
|
+
"""Iterate over all emissions across pages."""
|
|
845
|
+
token: str | None = None
|
|
846
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
847
|
+
nonlocal token
|
|
848
|
+
resp = await self.list(**kwargs, pagination_next_token=token)
|
|
849
|
+
token = resp.next_token
|
|
850
|
+
return resp.emissions or [], token
|
|
851
|
+
return AsyncIterator(fetch)
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
class AsyncSearchService:
|
|
855
|
+
"""Search endpoints (async)."""
|
|
856
|
+
|
|
857
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
858
|
+
self._client = client
|
|
859
|
+
|
|
860
|
+
async def vessels(self, *, filter_name: str | None = None, filter_imo: str | None = None, filter_mmsi: str | None = None, filter_flag: str | None = None, filter_vessel_type: str | None = None, filter_callsign: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindVesselsResponse:
|
|
861
|
+
"""Search for vessels."""
|
|
862
|
+
r = await self._client.get("/search/vessels", params=_strip_none({"filter.name": filter_name, "filter.imo": filter_imo, "filter.mmsi": filter_mmsi, "filter.flag": filter_flag, "filter.vesselType": filter_vessel_type, "filter.callsign": filter_callsign, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
863
|
+
error_from_response(r.status_code, r.content)
|
|
864
|
+
return FindVesselsResponse.model_validate(r.json())
|
|
865
|
+
|
|
866
|
+
async def ports(self, *, filter_name: str | None = None, filter_country: str | None = None, filter_port_type: str | None = None, filter_region: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindPortsResponse:
|
|
867
|
+
"""Search for ports."""
|
|
868
|
+
r = await self._client.get("/search/ports", params=_strip_none({"filter.name": filter_name, "filter.country": filter_country, "filter.type": filter_port_type, "filter.region": filter_region, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
869
|
+
error_from_response(r.status_code, r.content)
|
|
870
|
+
return FindPortsResponse.model_validate(r.json())
|
|
871
|
+
|
|
872
|
+
async def dgps(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindDGPSStationsResponse:
|
|
873
|
+
"""Search for DGPS stations."""
|
|
874
|
+
r = await self._client.get("/search/dgps", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
875
|
+
error_from_response(r.status_code, r.content)
|
|
876
|
+
return FindDGPSStationsResponse.model_validate(r.json())
|
|
877
|
+
|
|
878
|
+
async def light_aids(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindLightAidsResponse:
|
|
879
|
+
"""Search for light aids."""
|
|
880
|
+
r = await self._client.get("/search/lightaids", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
881
|
+
error_from_response(r.status_code, r.content)
|
|
882
|
+
return FindLightAidsResponse.model_validate(r.json())
|
|
883
|
+
|
|
884
|
+
async def modus(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindMODUsResponse:
|
|
885
|
+
"""Search for MODUs."""
|
|
886
|
+
r = await self._client.get("/search/modus", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
887
|
+
error_from_response(r.status_code, r.content)
|
|
888
|
+
return FindMODUsResponse.model_validate(r.json())
|
|
889
|
+
|
|
890
|
+
async def radio_beacons(self, *, filter_name: str | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> FindRadioBeaconsResponse:
|
|
891
|
+
"""Search for radio beacons."""
|
|
892
|
+
r = await self._client.get("/search/radiobeacons", params=_strip_none({"filter.name": filter_name, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
893
|
+
error_from_response(r.status_code, r.content)
|
|
894
|
+
return FindRadioBeaconsResponse.model_validate(r.json())
|
|
895
|
+
|
|
896
|
+
# --- Iterators ---
|
|
897
|
+
|
|
898
|
+
def all_vessels(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
899
|
+
"""Iterate over all vessel search results."""
|
|
900
|
+
token: str | None = None
|
|
901
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
902
|
+
nonlocal token
|
|
903
|
+
resp = await self.vessels(**kwargs, pagination_next_token=token)
|
|
904
|
+
token = resp.next_token
|
|
905
|
+
return resp.vessels or [], token
|
|
906
|
+
return AsyncIterator(fetch)
|
|
907
|
+
|
|
908
|
+
def all_ports(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
909
|
+
"""Iterate over all port search results."""
|
|
910
|
+
token: str | None = None
|
|
911
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
912
|
+
nonlocal token
|
|
913
|
+
resp = await self.ports(**kwargs, pagination_next_token=token)
|
|
914
|
+
token = resp.next_token
|
|
915
|
+
return resp.ports or [], token
|
|
916
|
+
return AsyncIterator(fetch)
|
|
917
|
+
|
|
918
|
+
def all_dgps(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
919
|
+
"""Iterate over all DGPS station search results."""
|
|
920
|
+
token: str | None = None
|
|
921
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
922
|
+
nonlocal token
|
|
923
|
+
resp = await self.dgps(**kwargs, pagination_next_token=token)
|
|
924
|
+
token = resp.next_token
|
|
925
|
+
return resp.dgps_stations or [], token
|
|
926
|
+
return AsyncIterator(fetch)
|
|
927
|
+
|
|
928
|
+
def all_light_aids(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
929
|
+
"""Iterate over all light aid search results."""
|
|
930
|
+
token: str | None = None
|
|
931
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
932
|
+
nonlocal token
|
|
933
|
+
resp = await self.light_aids(**kwargs, pagination_next_token=token)
|
|
934
|
+
token = resp.next_token
|
|
935
|
+
return resp.light_aids or [], token
|
|
936
|
+
return AsyncIterator(fetch)
|
|
937
|
+
|
|
938
|
+
def all_modus(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
939
|
+
"""Iterate over all MODU search results."""
|
|
940
|
+
token: str | None = None
|
|
941
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
942
|
+
nonlocal token
|
|
943
|
+
resp = await self.modus(**kwargs, pagination_next_token=token)
|
|
944
|
+
token = resp.next_token
|
|
945
|
+
return resp.modus or [], token
|
|
946
|
+
return AsyncIterator(fetch)
|
|
947
|
+
|
|
948
|
+
def all_radio_beacons(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
949
|
+
"""Iterate over all radio beacon search results."""
|
|
950
|
+
token: str | None = None
|
|
951
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
952
|
+
nonlocal token
|
|
953
|
+
resp = await self.radio_beacons(**kwargs, pagination_next_token=token)
|
|
954
|
+
token = resp.next_token
|
|
955
|
+
return resp.radio_beacons or [], token
|
|
956
|
+
return AsyncIterator(fetch)
|
|
957
|
+
|
|
958
|
+
|
|
959
|
+
class AsyncLocationService:
|
|
960
|
+
"""Location-based query endpoints (async)."""
|
|
961
|
+
|
|
962
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
963
|
+
self._client = client
|
|
964
|
+
|
|
965
|
+
async def vessels_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
|
|
966
|
+
"""Retrieve vessel positions within a bounding box."""
|
|
967
|
+
r = await self._client.get("/location/vessels/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
968
|
+
error_from_response(r.status_code, r.content)
|
|
969
|
+
return VesselsWithinLocationResponse.model_validate(r.json())
|
|
970
|
+
|
|
971
|
+
async def vessels_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> VesselsWithinLocationResponse:
|
|
972
|
+
"""Retrieve vessel positions within a radius."""
|
|
973
|
+
r = await self._client.get("/location/vessels/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
974
|
+
error_from_response(r.status_code, r.content)
|
|
975
|
+
return VesselsWithinLocationResponse.model_validate(r.json())
|
|
976
|
+
|
|
977
|
+
async def ports_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
|
|
978
|
+
"""Retrieve ports within a bounding box."""
|
|
979
|
+
r = await self._client.get("/location/ports/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
980
|
+
error_from_response(r.status_code, r.content)
|
|
981
|
+
return PortsWithinLocationResponse.model_validate(r.json())
|
|
982
|
+
|
|
983
|
+
async def ports_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> PortsWithinLocationResponse:
|
|
984
|
+
"""Retrieve ports within a radius."""
|
|
985
|
+
r = await self._client.get("/location/ports/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
986
|
+
error_from_response(r.status_code, r.content)
|
|
987
|
+
return PortsWithinLocationResponse.model_validate(r.json())
|
|
988
|
+
|
|
989
|
+
async def dgps_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
|
|
990
|
+
"""Retrieve DGPS stations within a bounding box."""
|
|
991
|
+
r = await self._client.get("/location/dgps/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
992
|
+
error_from_response(r.status_code, r.content)
|
|
993
|
+
return DGPSStationsWithinLocationResponse.model_validate(r.json())
|
|
994
|
+
|
|
995
|
+
async def dgps_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> DGPSStationsWithinLocationResponse:
|
|
996
|
+
"""Retrieve DGPS stations within a radius."""
|
|
997
|
+
r = await self._client.get("/location/dgps/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
998
|
+
error_from_response(r.status_code, r.content)
|
|
999
|
+
return DGPSStationsWithinLocationResponse.model_validate(r.json())
|
|
1000
|
+
|
|
1001
|
+
async def light_aids_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
|
|
1002
|
+
"""Retrieve light aids within a bounding box."""
|
|
1003
|
+
r = await self._client.get("/location/lightaids/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1004
|
+
error_from_response(r.status_code, r.content)
|
|
1005
|
+
return LightAidsWithinLocationResponse.model_validate(r.json())
|
|
1006
|
+
|
|
1007
|
+
async def light_aids_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> LightAidsWithinLocationResponse:
|
|
1008
|
+
"""Retrieve light aids within a radius."""
|
|
1009
|
+
r = await self._client.get("/location/lightaids/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1010
|
+
error_from_response(r.status_code, r.content)
|
|
1011
|
+
return LightAidsWithinLocationResponse.model_validate(r.json())
|
|
1012
|
+
|
|
1013
|
+
async def modus_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
|
|
1014
|
+
"""Retrieve MODUs within a bounding box."""
|
|
1015
|
+
r = await self._client.get("/location/modu/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1016
|
+
error_from_response(r.status_code, r.content)
|
|
1017
|
+
return MODUsWithinLocationResponse.model_validate(r.json())
|
|
1018
|
+
|
|
1019
|
+
async def modus_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> MODUsWithinLocationResponse:
|
|
1020
|
+
"""Retrieve MODUs within a radius."""
|
|
1021
|
+
r = await self._client.get("/location/modu/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1022
|
+
error_from_response(r.status_code, r.content)
|
|
1023
|
+
return MODUsWithinLocationResponse.model_validate(r.json())
|
|
1024
|
+
|
|
1025
|
+
async def radio_beacons_bounding_box(self, *, lat_min: float | None = None, lat_max: float | None = None, lon_min: float | None = None, lon_max: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
|
|
1026
|
+
"""Retrieve radio beacons within a bounding box."""
|
|
1027
|
+
r = await self._client.get("/location/radiobeacons/bounding-box", params=_strip_none({"filter.latBottom": lat_min, "filter.latTop": lat_max, "filter.lonLeft": lon_min, "filter.lonRight": lon_max, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1028
|
+
error_from_response(r.status_code, r.content)
|
|
1029
|
+
return RadioBeaconsWithinLocationResponse.model_validate(r.json())
|
|
1030
|
+
|
|
1031
|
+
async def radio_beacons_radius(self, *, latitude: float | None = None, longitude: float | None = None, radius: float | None = None, pagination_limit: int | None = None, pagination_next_token: str | None = None) -> RadioBeaconsWithinLocationResponse:
|
|
1032
|
+
"""Retrieve radio beacons within a radius."""
|
|
1033
|
+
r = await self._client.get("/location/radiobeacons/radius", params=_strip_none({"filter.latitude": latitude, "filter.longitude": longitude, "filter.radius": radius, "pagination.limit": pagination_limit, "pagination.nextToken": pagination_next_token}))
|
|
1034
|
+
error_from_response(r.status_code, r.content)
|
|
1035
|
+
return RadioBeaconsWithinLocationResponse.model_validate(r.json())
|
|
1036
|
+
|
|
1037
|
+
# --- Iterators ---
|
|
1038
|
+
|
|
1039
|
+
def all_vessels_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1040
|
+
"""Iterate over all vessel positions in a bounding box."""
|
|
1041
|
+
token: str | None = None
|
|
1042
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1043
|
+
nonlocal token
|
|
1044
|
+
resp = await self.vessels_bounding_box(**kwargs, pagination_next_token=token)
|
|
1045
|
+
token = resp.next_token
|
|
1046
|
+
return resp.vessels or [], token
|
|
1047
|
+
return AsyncIterator(fetch)
|
|
1048
|
+
|
|
1049
|
+
def all_vessels_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1050
|
+
"""Iterate over all vessel positions within a radius."""
|
|
1051
|
+
token: str | None = None
|
|
1052
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1053
|
+
nonlocal token
|
|
1054
|
+
resp = await self.vessels_radius(**kwargs, pagination_next_token=token)
|
|
1055
|
+
token = resp.next_token
|
|
1056
|
+
return resp.vessels or [], token
|
|
1057
|
+
return AsyncIterator(fetch)
|
|
1058
|
+
|
|
1059
|
+
def all_ports_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1060
|
+
"""Iterate over all ports in a bounding box."""
|
|
1061
|
+
token: str | None = None
|
|
1062
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1063
|
+
nonlocal token
|
|
1064
|
+
resp = await self.ports_bounding_box(**kwargs, pagination_next_token=token)
|
|
1065
|
+
token = resp.next_token
|
|
1066
|
+
return resp.ports or [], token
|
|
1067
|
+
return AsyncIterator(fetch)
|
|
1068
|
+
|
|
1069
|
+
def all_ports_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1070
|
+
"""Iterate over all ports within a radius."""
|
|
1071
|
+
token: str | None = None
|
|
1072
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1073
|
+
nonlocal token
|
|
1074
|
+
resp = await self.ports_radius(**kwargs, pagination_next_token=token)
|
|
1075
|
+
token = resp.next_token
|
|
1076
|
+
return resp.ports or [], token
|
|
1077
|
+
return AsyncIterator(fetch)
|
|
1078
|
+
|
|
1079
|
+
def all_dgps_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1080
|
+
"""Iterate over all DGPS stations in a bounding box."""
|
|
1081
|
+
token: str | None = None
|
|
1082
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1083
|
+
nonlocal token
|
|
1084
|
+
resp = await self.dgps_bounding_box(**kwargs, pagination_next_token=token)
|
|
1085
|
+
token = resp.next_token
|
|
1086
|
+
return resp.dgps_stations or [], token
|
|
1087
|
+
return AsyncIterator(fetch)
|
|
1088
|
+
|
|
1089
|
+
def all_dgps_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1090
|
+
"""Iterate over all DGPS stations within a radius."""
|
|
1091
|
+
token: str | None = None
|
|
1092
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1093
|
+
nonlocal token
|
|
1094
|
+
resp = await self.dgps_radius(**kwargs, pagination_next_token=token)
|
|
1095
|
+
token = resp.next_token
|
|
1096
|
+
return resp.dgps_stations or [], token
|
|
1097
|
+
return AsyncIterator(fetch)
|
|
1098
|
+
|
|
1099
|
+
def all_light_aids_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1100
|
+
"""Iterate over all light aids in a bounding box."""
|
|
1101
|
+
token: str | None = None
|
|
1102
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1103
|
+
nonlocal token
|
|
1104
|
+
resp = await self.light_aids_bounding_box(**kwargs, pagination_next_token=token)
|
|
1105
|
+
token = resp.next_token
|
|
1106
|
+
return resp.light_aids or [], token
|
|
1107
|
+
return AsyncIterator(fetch)
|
|
1108
|
+
|
|
1109
|
+
def all_light_aids_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1110
|
+
"""Iterate over all light aids within a radius."""
|
|
1111
|
+
token: str | None = None
|
|
1112
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1113
|
+
nonlocal token
|
|
1114
|
+
resp = await self.light_aids_radius(**kwargs, pagination_next_token=token)
|
|
1115
|
+
token = resp.next_token
|
|
1116
|
+
return resp.light_aids or [], token
|
|
1117
|
+
return AsyncIterator(fetch)
|
|
1118
|
+
|
|
1119
|
+
def all_modus_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1120
|
+
"""Iterate over all MODUs in a bounding box."""
|
|
1121
|
+
token: str | None = None
|
|
1122
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1123
|
+
nonlocal token
|
|
1124
|
+
resp = await self.modus_bounding_box(**kwargs, pagination_next_token=token)
|
|
1125
|
+
token = resp.next_token
|
|
1126
|
+
return resp.modus or [], token
|
|
1127
|
+
return AsyncIterator(fetch)
|
|
1128
|
+
|
|
1129
|
+
def all_modus_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1130
|
+
"""Iterate over all MODUs within a radius."""
|
|
1131
|
+
token: str | None = None
|
|
1132
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1133
|
+
nonlocal token
|
|
1134
|
+
resp = await self.modus_radius(**kwargs, pagination_next_token=token)
|
|
1135
|
+
token = resp.next_token
|
|
1136
|
+
return resp.modus or [], token
|
|
1137
|
+
return AsyncIterator(fetch)
|
|
1138
|
+
|
|
1139
|
+
def all_radio_beacons_bounding_box(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1140
|
+
"""Iterate over all radio beacons in a bounding box."""
|
|
1141
|
+
token: str | None = None
|
|
1142
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1143
|
+
nonlocal token
|
|
1144
|
+
resp = await self.radio_beacons_bounding_box(**kwargs, pagination_next_token=token)
|
|
1145
|
+
token = resp.next_token
|
|
1146
|
+
return resp.radio_beacons or [], token
|
|
1147
|
+
return AsyncIterator(fetch)
|
|
1148
|
+
|
|
1149
|
+
def all_radio_beacons_radius(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1150
|
+
"""Iterate over all radio beacons within a radius."""
|
|
1151
|
+
token: str | None = None
|
|
1152
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1153
|
+
nonlocal token
|
|
1154
|
+
resp = await self.radio_beacons_radius(**kwargs, pagination_next_token=token)
|
|
1155
|
+
token = resp.next_token
|
|
1156
|
+
return resp.radio_beacons or [], token
|
|
1157
|
+
return AsyncIterator(fetch)
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
class AsyncNavtexService:
|
|
1161
|
+
"""NAVTEX message endpoints (async)."""
|
|
1162
|
+
|
|
1163
|
+
def __init__(self, client: httpx.AsyncClient) -> None:
|
|
1164
|
+
self._client = client
|
|
1165
|
+
|
|
1166
|
+
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:
|
|
1167
|
+
"""Retrieve NAVTEX maritime safety messages."""
|
|
1168
|
+
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}))
|
|
1169
|
+
error_from_response(r.status_code, r.content)
|
|
1170
|
+
return NavtexMessagesResponse.model_validate(r.json())
|
|
1171
|
+
|
|
1172
|
+
def list_all(self, **kwargs: Any) -> AsyncIterator[Any]:
|
|
1173
|
+
"""Iterate over all NAVTEX messages across pages."""
|
|
1174
|
+
token: str | None = None
|
|
1175
|
+
async def fetch() -> tuple[list[Any], str | None]:
|
|
1176
|
+
nonlocal token
|
|
1177
|
+
resp = await self.list(**kwargs, pagination_next_token=token)
|
|
1178
|
+
token = resp.next_token
|
|
1179
|
+
return resp.navtex_messages or [], token
|
|
1180
|
+
return AsyncIterator(fetch)
|