vessel-api-python 1.0.0__tar.gz → 1.2.0__tar.gz
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-1.0.0 → vessel_api_python-1.2.0}/Makefile +1 -1
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/PKG-INFO +24 -7
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/README.md +22 -5
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/examples/async_basic.py +19 -1
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/examples/basic.py +20 -1
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/pyproject.toml +2 -2
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/__init__.py +4 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_constants.py +1 -1
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_models.py +28 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_services.py +157 -112
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_services.py +52 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_smoke.py +28 -1
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/.github/workflows/ci.yml +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/.github/workflows/publish.yml +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/.gitignore +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/LICENSE +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/SECURITY.md +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/openapi/swagger.json +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_client.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_errors.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_iterator.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/_transport.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/src/vessel_api_python/py.typed +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/__init__.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/conftest.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_client.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_errors.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_iterator.py +0 -0
- {vessel_api_python-1.0.0 → vessel_api_python-1.2.0}/tests/test_transport.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vessel-api-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Python client for the Vessel Tracking API — maritime vessel tracking, port events, emissions, and navigation data.
|
|
5
5
|
Project-URL: Documentation, https://vesselapi.com/docs
|
|
6
6
|
Project-URL: Repository, https://github.com/vessel-api/vesselapi-python
|
|
@@ -10,7 +10,7 @@ Author-email: Vessel API <support@vesselapi.com>
|
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Keywords: ais,maritime,sdk,tracking,vessel,vesselapi
|
|
13
|
-
Classifier: Development Status ::
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -34,7 +34,7 @@ Description-Content-Type: text/markdown
|
|
|
34
34
|
|
|
35
35
|
# vesselapi-python
|
|
36
36
|
|
|
37
|
-
[](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
|
|
37
|
+
[](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
|
|
38
38
|
[](https://pypi.org/project/vessel-api-python/)
|
|
39
39
|
[](https://pypi.org/project/vessel-api-python/)
|
|
40
40
|
[](LICENSE)
|
|
@@ -101,6 +101,23 @@ asyncio.run(main())
|
|
|
101
101
|
|
|
102
102
|
**37 methods total.**
|
|
103
103
|
|
|
104
|
+
## Vessel Lookup & Location
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Get vessel details by IMO number (defaults to IMO; pass filter_id_type="mmsi" for MMSI).
|
|
108
|
+
vessel = client.vessels.get("9811000")
|
|
109
|
+
print(f"{vessel.vessel.name} ({vessel.vessel.vessel_type})")
|
|
110
|
+
|
|
111
|
+
# Get the vessel's latest AIS position.
|
|
112
|
+
pos = client.vessels.position("9811000")
|
|
113
|
+
print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
|
|
114
|
+
|
|
115
|
+
# Find all vessels within 10 km of Rotterdam.
|
|
116
|
+
nearby = client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
|
|
117
|
+
for v in nearby.vessels or []:
|
|
118
|
+
print(f"{v.vessel_name} at {v.latitude}, {v.longitude}")
|
|
119
|
+
```
|
|
120
|
+
|
|
104
121
|
## Error Handling
|
|
105
122
|
|
|
106
123
|
All methods raise specific exception types on non-2xx responses:
|
|
@@ -126,15 +143,15 @@ Every list endpoint has an `all_*` / `list_all` variant returning an iterator:
|
|
|
126
143
|
|
|
127
144
|
```python
|
|
128
145
|
# Sync
|
|
129
|
-
for vessel in client.search.all_vessels(
|
|
146
|
+
for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
|
|
130
147
|
print(vessel.name)
|
|
131
148
|
|
|
132
149
|
# Async
|
|
133
|
-
async for vessel in client.search.all_vessels(
|
|
150
|
+
async for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
|
|
134
151
|
print(vessel.name)
|
|
135
152
|
|
|
136
|
-
# Collect
|
|
137
|
-
vessels = client.search.all_vessels(
|
|
153
|
+
# Collect a bounded set at once
|
|
154
|
+
vessels = client.search.all_vessels(filter_vessel_type="Tanker", pagination_limit=50).collect()
|
|
138
155
|
```
|
|
139
156
|
|
|
140
157
|
## Configuration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# vesselapi-python
|
|
2
2
|
|
|
3
|
-
[](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
|
|
3
|
+
[](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
|
|
4
4
|
[](https://pypi.org/project/vessel-api-python/)
|
|
5
5
|
[](https://pypi.org/project/vessel-api-python/)
|
|
6
6
|
[](LICENSE)
|
|
@@ -67,6 +67,23 @@ asyncio.run(main())
|
|
|
67
67
|
|
|
68
68
|
**37 methods total.**
|
|
69
69
|
|
|
70
|
+
## Vessel Lookup & Location
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
# Get vessel details by IMO number (defaults to IMO; pass filter_id_type="mmsi" for MMSI).
|
|
74
|
+
vessel = client.vessels.get("9811000")
|
|
75
|
+
print(f"{vessel.vessel.name} ({vessel.vessel.vessel_type})")
|
|
76
|
+
|
|
77
|
+
# Get the vessel's latest AIS position.
|
|
78
|
+
pos = client.vessels.position("9811000")
|
|
79
|
+
print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
|
|
80
|
+
|
|
81
|
+
# Find all vessels within 10 km of Rotterdam.
|
|
82
|
+
nearby = client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
|
|
83
|
+
for v in nearby.vessels or []:
|
|
84
|
+
print(f"{v.vessel_name} at {v.latitude}, {v.longitude}")
|
|
85
|
+
```
|
|
86
|
+
|
|
70
87
|
## Error Handling
|
|
71
88
|
|
|
72
89
|
All methods raise specific exception types on non-2xx responses:
|
|
@@ -92,15 +109,15 @@ Every list endpoint has an `all_*` / `list_all` variant returning an iterator:
|
|
|
92
109
|
|
|
93
110
|
```python
|
|
94
111
|
# Sync
|
|
95
|
-
for vessel in client.search.all_vessels(
|
|
112
|
+
for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
|
|
96
113
|
print(vessel.name)
|
|
97
114
|
|
|
98
115
|
# Async
|
|
99
|
-
async for vessel in client.search.all_vessels(
|
|
116
|
+
async for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
|
|
100
117
|
print(vessel.name)
|
|
101
118
|
|
|
102
|
-
# Collect
|
|
103
|
-
vessels = client.search.all_vessels(
|
|
119
|
+
# Collect a bounded set at once
|
|
120
|
+
vessels = client.search.all_vessels(filter_vessel_type="Tanker", pagination_limit=50).collect()
|
|
104
121
|
```
|
|
105
122
|
|
|
106
123
|
## Configuration
|
|
@@ -4,7 +4,7 @@ import asyncio
|
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from vessel_api_python import AsyncVesselClient, VesselAPIError
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
async def main() -> None:
|
|
@@ -26,6 +26,24 @@ async def main() -> None:
|
|
|
26
26
|
if port.port:
|
|
27
27
|
print(f"Port: {port.port.name} ({port.port.unlo_code})")
|
|
28
28
|
|
|
29
|
+
# Get vessel details by IMO number (defaults to IMO; pass filter_id_type="mmsi" for MMSI).
|
|
30
|
+
print("\n--- Vessel by IMO ---")
|
|
31
|
+
vessel = await client.vessels.get("9811000")
|
|
32
|
+
if vessel.vessel:
|
|
33
|
+
print(f"Vessel: {vessel.vessel.name} (Type: {vessel.vessel.vessel_type})")
|
|
34
|
+
|
|
35
|
+
# Get the vessel's latest AIS position.
|
|
36
|
+
print("\n--- Vessel Position ---")
|
|
37
|
+
pos = await client.vessels.position("9811000")
|
|
38
|
+
if pos.vessel_position:
|
|
39
|
+
print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
|
|
40
|
+
|
|
41
|
+
# Find vessels within 10 km of Rotterdam.
|
|
42
|
+
print("\n--- Vessels Near Rotterdam ---")
|
|
43
|
+
nearby = await client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
|
|
44
|
+
for v in nearby.vessels or []:
|
|
45
|
+
print(f"{v.vessel_name} (IMO: {v.imo}) at {v.latitude}, {v.longitude}")
|
|
46
|
+
|
|
29
47
|
# Error handling.
|
|
30
48
|
print("\n--- Error Handling ---")
|
|
31
49
|
try:
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
|
-
from
|
|
6
|
+
from vessel_api_python import VesselClient, VesselAPIError
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def main() -> None:
|
|
@@ -38,6 +38,25 @@ def main() -> None:
|
|
|
38
38
|
if port.port:
|
|
39
39
|
print(f"Port: {port.port.name} ({port.port.unlo_code})")
|
|
40
40
|
|
|
41
|
+
# Get vessel details by IMO number (defaults to IMO; pass filter_id_type="mmsi" for MMSI).
|
|
42
|
+
print("\n--- Vessel by IMO ---")
|
|
43
|
+
vessel = client.vessels.get("9811000")
|
|
44
|
+
if vessel.vessel:
|
|
45
|
+
print(f"Vessel: {vessel.vessel.name} (Type: {vessel.vessel.vessel_type})")
|
|
46
|
+
|
|
47
|
+
# Get the vessel's latest AIS position.
|
|
48
|
+
print("\n--- Vessel Position ---")
|
|
49
|
+
pos = client.vessels.position("9811000")
|
|
50
|
+
if pos.vessel_position:
|
|
51
|
+
print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
|
|
52
|
+
print(f"Speed: {pos.vessel_position.sog} knots, Heading: {pos.vessel_position.heading}")
|
|
53
|
+
|
|
54
|
+
# Find vessels within 10 km of Rotterdam.
|
|
55
|
+
print("\n--- Vessels Near Rotterdam ---")
|
|
56
|
+
nearby = client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
|
|
57
|
+
for v in nearby.vessels or []:
|
|
58
|
+
print(f"{v.vessel_name} (IMO: {v.imo}) at {v.latitude}, {v.longitude}")
|
|
59
|
+
|
|
41
60
|
# Handle a not-found port gracefully.
|
|
42
61
|
print("\n--- Not Found Handling ---")
|
|
43
62
|
try:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vessel-api-python"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "Python client for the Vessel Tracking API — maritime vessel tracking, port events, emissions, and navigation data."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -14,7 +14,7 @@ authors = [
|
|
|
14
14
|
]
|
|
15
15
|
keywords = ["vesselapi", "maritime", "vessel", "tracking", "ais", "sdk"]
|
|
16
16
|
classifiers = [
|
|
17
|
-
"Development Status ::
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
19
19
|
"License :: OSI Approved :: MIT License",
|
|
20
20
|
"Programming Language :: Python :: 3",
|
|
@@ -65,11 +65,13 @@ from ._models import (
|
|
|
65
65
|
PortEvent,
|
|
66
66
|
PortEventResponse,
|
|
67
67
|
PortEventsResponse,
|
|
68
|
+
PortInboundResponse,
|
|
68
69
|
PortReference,
|
|
69
70
|
PortResponse,
|
|
70
71
|
PortsWithinLocationResponse,
|
|
71
72
|
RadioBeacon,
|
|
72
73
|
RadioBeaconsWithinLocationResponse,
|
|
74
|
+
ResolutionMeta,
|
|
73
75
|
TypesInspectionDetailResponse,
|
|
74
76
|
TypesInspectionsResponse,
|
|
75
77
|
TypesOwnershipResponse,
|
|
@@ -111,6 +113,7 @@ __all__ = [
|
|
|
111
113
|
"VesselReference",
|
|
112
114
|
"VesselFormerName",
|
|
113
115
|
"BroadcastStation",
|
|
116
|
+
"ResolutionMeta",
|
|
114
117
|
# Models — Classification sub-models
|
|
115
118
|
"ClassificationCertificate",
|
|
116
119
|
"ClassificationCondition",
|
|
@@ -159,6 +162,7 @@ __all__ = [
|
|
|
159
162
|
"PortEvent",
|
|
160
163
|
"PortEventResponse",
|
|
161
164
|
"PortEventsResponse",
|
|
165
|
+
"PortInboundResponse",
|
|
162
166
|
# Models — Search
|
|
163
167
|
"FindVesselsResponse",
|
|
164
168
|
"FindPortsResponse",
|
|
@@ -224,6 +224,18 @@ class ClassificationYard(_Base):
|
|
|
224
224
|
keel_date: str | None = Field(default=None, alias="keelDate")
|
|
225
225
|
|
|
226
226
|
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
# Resolution metadata
|
|
229
|
+
# ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class ResolutionMeta(_Base):
|
|
233
|
+
"""Metadata about ID resolution fallback. Present when the API resolved using a different ID type."""
|
|
234
|
+
requested_id_type: str | None = Field(default=None, alias="requestedIdType")
|
|
235
|
+
resolved_id_type: str | None = Field(default=None, alias="resolvedIdType")
|
|
236
|
+
resolved_id: int | None = Field(default=None, alias="resolvedId")
|
|
237
|
+
|
|
238
|
+
|
|
227
239
|
# ---------------------------------------------------------------------------
|
|
228
240
|
# Vessel models
|
|
229
241
|
# ---------------------------------------------------------------------------
|
|
@@ -264,6 +276,7 @@ class VesselResponse(_Base):
|
|
|
264
276
|
"""Response for a single vessel lookup."""
|
|
265
277
|
|
|
266
278
|
vessel: Vessel | None = None
|
|
279
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
267
280
|
|
|
268
281
|
|
|
269
282
|
class VesselPosition(_Base):
|
|
@@ -290,6 +303,7 @@ class VesselPositionResponse(_Base):
|
|
|
290
303
|
vessel_position: VesselPosition | None = Field(
|
|
291
304
|
default=None, alias="vesselPosition"
|
|
292
305
|
)
|
|
306
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
293
307
|
|
|
294
308
|
|
|
295
309
|
class VesselPositionsResponse(_Base):
|
|
@@ -299,6 +313,7 @@ class VesselPositionsResponse(_Base):
|
|
|
299
313
|
default=None, alias="vesselPositions"
|
|
300
314
|
)
|
|
301
315
|
next_token: str | None = Field(default=None, alias="nextToken")
|
|
316
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
302
317
|
|
|
303
318
|
|
|
304
319
|
# ---------------------------------------------------------------------------
|
|
@@ -352,6 +367,7 @@ class MarineCasualtiesResponse(_Base):
|
|
|
352
367
|
|
|
353
368
|
casualties: list[MarineCasualty] | None = None
|
|
354
369
|
next_token: str | None = Field(default=None, alias="nextToken")
|
|
370
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
355
371
|
|
|
356
372
|
|
|
357
373
|
class ClassificationVessel(_Base):
|
|
@@ -379,6 +395,7 @@ class ClassificationResponse(_Base):
|
|
|
379
395
|
"""Response for vessel classification."""
|
|
380
396
|
|
|
381
397
|
classification: ClassificationVessel | None = None
|
|
398
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
382
399
|
|
|
383
400
|
|
|
384
401
|
class VesselEmission(_Base):
|
|
@@ -432,12 +449,14 @@ class VesselEmissionsResponse(_Base):
|
|
|
432
449
|
|
|
433
450
|
emissions: list[VesselEmission] | None = None
|
|
434
451
|
next_token: str | None = Field(default=None, alias="nextToken")
|
|
452
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
435
453
|
|
|
436
454
|
|
|
437
455
|
class VesselETA(_Base):
|
|
438
456
|
"""Vessel Estimated Time of Arrival information."""
|
|
439
457
|
|
|
440
458
|
destination: str | None = None
|
|
459
|
+
destination_port: str | None = None
|
|
441
460
|
draught: float | None = None
|
|
442
461
|
eta: str | None = None
|
|
443
462
|
imo: int | None = None
|
|
@@ -450,6 +469,13 @@ class VesselETAResponse(_Base):
|
|
|
450
469
|
"""Response for vessel ETA."""
|
|
451
470
|
|
|
452
471
|
vessel_eta: VesselETA | None = Field(default=None, alias="vesselEta")
|
|
472
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class PortInboundResponse(_Base):
|
|
476
|
+
"""Response containing vessels heading to a port."""
|
|
477
|
+
vessel_etas: list[VesselETA] | None = Field(default=None, alias="vesselETAs")
|
|
478
|
+
next_token: str | None = Field(default=None, alias="nextToken")
|
|
453
479
|
|
|
454
480
|
|
|
455
481
|
# ---------------------------------------------------------------------------
|
|
@@ -652,12 +678,14 @@ class PortEventsResponse(_Base):
|
|
|
652
678
|
default=None, alias="portEvents"
|
|
653
679
|
)
|
|
654
680
|
next_token: str | None = Field(default=None, alias="nextToken")
|
|
681
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
655
682
|
|
|
656
683
|
|
|
657
684
|
class PortEventResponse(_Base):
|
|
658
685
|
"""Response for a single port event (e.g. last by vessel)."""
|
|
659
686
|
|
|
660
687
|
port_event: PortEvent | None = Field(default=None, alias="portEvent")
|
|
688
|
+
meta: ResolutionMeta | None = Field(default=None, alias="_meta")
|
|
661
689
|
|
|
662
690
|
|
|
663
691
|
# ---------------------------------------------------------------------------
|