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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -164,8 +164,11 @@ def _calc_backoff(attempt: int, response: httpx.Response) -> float:
164
164
  pass
165
165
  # Try HTTP-date format (RFC 7231 section 7.1.3).
166
166
  try:
167
- dt = parsedate_to_datetime(retry_after)
168
- delta = (dt - _utcnow()).total_seconds()
167
+ # Annotated because typeshed types parsedate_to_datetime as Any on
168
+ # Python 3.9, which propagates through the subtraction and makes the
169
+ # return Any. Without this, mypy passes on 3.12 and fails on 3.9.
170
+ dt: datetime.datetime = parsedate_to_datetime(retry_after)
171
+ delta: float = (dt - _utcnow()).total_seconds()
169
172
  return max(0.0, min(delta, MAX_BACKOFF))
170
173
  except (ValueError, TypeError):
171
174
  pass
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: vessel-api-python
3
- Version: 1.3.0
4
- Summary: Python client for the Vessel Tracking API — maritime vessel tracking, port events, emissions, and navigation data.
3
+ Version: 2.0.0
4
+ Summary: Python client for the Vessel Tracking API: maritime vessel tracking, port events, emissions, and nautical infrastructure.
5
5
  Project-URL: Documentation, https://vesselapi.com/docs
6
6
  Project-URL: Repository, https://github.com/vessel-api/vesselapi-python
7
7
  Project-URL: Issues, https://github.com/vessel-api/vesselapi-python/issues
@@ -39,7 +39,7 @@ Description-Content-Type: text/markdown
39
39
  [![Python](https://img.shields.io/pypi/pyversions/vessel-api-python.svg)](https://pypi.org/project/vessel-api-python/)
40
40
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
41
41
 
42
- Python client for the [Vessel Tracking API](https://vesselapi.com) — maritime vessel tracking, port events, emissions, and navigation data.
42
+ Python client for the [Vessel Tracking API](https://vesselapi.com): maritime vessel tracking, port events, emissions, and nautical infrastructure.
43
43
 
44
44
  **Resources**: [Documentation](https://vesselapi.com/docs) | [API Explorer](https://vesselapi.com/api-reference) | [Dashboard](https://dashboard.vesselapi.com) | [Contact Support](mailto:support@vesselapi.com)
45
45
 
@@ -91,15 +91,33 @@ asyncio.run(main())
91
91
 
92
92
  | Service | Methods | Description |
93
93
  |---------|---------|-------------|
94
- | `vessels` | `get`, `position`, `casualties`, `classification`, `emissions`, `eta`, `inspections`, `inspection_detail`, `ownership`, `positions` | Vessel details, positions, and records |
95
- | `ports` | `get` | Port lookup by UN/LOCODE |
94
+ | `vessels` | `get`, `position`, `casualties`, `emissions`, `eta`, `positions` | Vessel details, positions, and records |
95
+ | `ports` | `get`, `inbound`, `inbound_all` | Port lookup by UN/LOCODE and inbound vessels |
96
96
  | `port_events` | `list`, `by_port`, `by_ports`, `by_vessel`, `last_by_vessel`, `by_vessels` | Vessel arrival/departure events |
97
97
  | `emissions` | `list` | EU MRV emissions data |
98
98
  | `search` | `vessels`, `ports`, `dgps`, `light_aids`, `modus`, `radio_beacons` | Full-text search across entity types |
99
99
  | `location` | `vessels_bounding_box`, `vessels_radius`, `ports_bounding_box`, `ports_radius`, `dgps_bounding_box`, `dgps_radius`, `light_aids_bounding_box`, `light_aids_radius`, `modus_bounding_box`, `modus_radius`, `radio_beacons_bounding_box`, `radio_beacons_radius` | Geo queries by bounding box or radius |
100
- | `navtex` | `list` | NAVTEX maritime safety messages |
101
100
 
102
- **37 methods total.**
101
+ **33 methods total**, one per API endpoint, plus 28 auto-pagination iterators.
102
+
103
+ ## Required Parameters
104
+
105
+ Parameters the API requires are keyword-only with no default, so leaving one out
106
+ raises `TypeError` at the call instead of returning HTTP 400 from the server:
107
+
108
+ ```python
109
+ client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
110
+ client.location.vessels_radius(latitude=51.9225) # TypeError: missing longitude, radius
111
+ ```
112
+
113
+ This covers the geo bounds on every `location` method (`lat_min`, `lat_max`,
114
+ `lon_min`, `lon_max` for bounding boxes; `latitude`, `longitude`, `radius` for
115
+ radius queries), `filter_name` on `search.dgps`, `search.light_aids`,
116
+ `search.modus` and `search.radio_beacons`, `filter_port_name` on
117
+ `port_events.by_ports`, `filter_vessel_name` on `port_events.by_vessels`, and
118
+ `filter_ids` on `vessels.positions`, along with the matching `all_*` iterators.
119
+ `filter_id_type` is required by the API but keeps its `"imo"` default, since the
120
+ SDK always sends it.
103
121
 
104
122
  ## Vessel Lookup & Location
105
123
 
@@ -108,16 +126,47 @@ asyncio.run(main())
108
126
  vessel = client.vessels.get("9811000")
109
127
  print(f"{vessel.vessel.name} ({vessel.vessel.vessel_type})")
110
128
 
111
- # Get the vessel's latest AIS position.
112
- pos = client.vessels.position("9811000")
129
+ # Get a vessel's latest stored AIS position. A vessel that exists may have no
130
+ # stored position, which raises VesselNotFoundError rather than returning empty.
131
+ pos = client.vessels.position("232003239", filter_id_type="mmsi")
113
132
  print(f"Position: {pos.vessel_position.latitude}, {pos.vessel_position.longitude}")
114
133
 
134
+ # filter_sat=True falls back to satellite AIS when nothing is stored.
135
+ # ⚠️ Satellite lookups draw on a prepaid balance and are charged per call.
136
+ # Omit it unless you need that fallback.
137
+
115
138
  # Find all vessels within 10 km of Rotterdam.
116
139
  nearby = client.location.vessels_radius(latitude=51.9225, longitude=4.47917, radius=10000)
117
140
  for v in nearby.vessels or []:
118
141
  print(f"{v.vessel_name} at {v.latitude}, {v.longitude}")
119
142
  ```
120
143
 
144
+ ## Search
145
+
146
+ `search.vessels` accepts `q`, a unified search across IMO, MMSI, ENI, callsign and
147
+ name. One value can return several vessels, and `_meta.matched_on` maps each result's
148
+ index to the fields it matched on.
149
+
150
+ ```python
151
+ res = client.search.vessels(q="4606770")
152
+ print(res.meta.matched_on) # {"0": ["eni"]}
153
+ ```
154
+
155
+ Filters the API declares as repeatable take either one value or a list. A list is
156
+ sent as a repeated query parameter, so the values are OR-ed:
157
+
158
+ ```python
159
+ # ?filter.flag=PA&filter.flag=LR&filter.vesselType=Container%20Ship
160
+ client.search.vessels(filter_flag=["PA", "LR"], filter_vessel_type="Container Ship")
161
+
162
+ client.search.ports(filter_country=["NL", "BE"], filter_size=["LARGE", "MEDIUM"])
163
+ ```
164
+
165
+ These are `filter_flag` and `filter_vessel_type` on `search.vessels`;
166
+ `filter_country`, `filter_port_type`, `filter_size`, `filter_harbor_size` and
167
+ `filter_harbor_use` on `search.ports`; and `filter_ids` on `vessels.positions`,
168
+ which also accepts the comma-separated single-string form.
169
+
121
170
  ## Error Handling
122
171
 
123
172
  All methods raise specific exception types on non-2xx responses:
@@ -131,7 +180,7 @@ except VesselAPIError as err:
131
180
  if err.is_not_found:
132
181
  print("Port not found")
133
182
  elif err.is_rate_limited:
134
- print("Rate limited — back off")
183
+ print("Rate limited, backing off")
135
184
  elif err.is_auth_error:
136
185
  print("Check API key")
137
186
  print(err.status_code, err.message)
@@ -150,8 +199,14 @@ for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
150
199
  async for vessel in client.search.all_vessels(filter_vessel_type="Tanker"):
151
200
  print(vessel.name)
152
201
 
153
- # Collect a bounded set at once
202
+ # Collect every match at once. pagination_limit is the page size, not a total:
203
+ # .collect() walks to the end, so this is one request per page until exhausted.
154
204
  vessels = client.search.all_vessels(filter_vessel_type="Tanker", pagination_limit=50).collect()
205
+
206
+ # To take a fixed number, stop the iterator yourself.
207
+ from itertools import islice
208
+
209
+ first_50 = list(islice(client.search.all_vessels(filter_vessel_type="Tanker"), 50))
155
210
  ```
156
211
 
157
212
  ## Configuration
@@ -170,15 +225,24 @@ Retries use exponential backoff with jitter on 429 and 5xx responses. The `Retry
170
225
 
171
226
  ## Documentation
172
227
 
173
- - [API Documentation](https://vesselapi.com/docs) — endpoint guides, request/response schemas, and usage examples
174
- - [API Explorer](https://vesselapi.com/api-reference) — interactive API reference
175
- - [Dashboard](https://dashboard.vesselapi.com) — manage API keys and monitor usage
228
+ - [API Documentation](https://vesselapi.com/docs): endpoint guides, request/response schemas, and usage examples
229
+ - [API Explorer](https://vesselapi.com/api-reference): interactive API reference
230
+ - [Dashboard](https://dashboard.vesselapi.com): manage API keys and monitor usage
176
231
 
177
232
  ## Contributing & Support
178
233
 
179
234
  Found a bug, have a feature request, or need help? You're welcome to [open an issue](https://github.com/vessel-api/vesselapi-python/issues). For API-level bugs and feature requests, please use the [main VesselAPI repository](https://github.com/vessel-api/VesselApi/issues).
180
235
 
181
- For security vulnerabilities, **do not** open a public issue — email security@vesselapi.com instead. See [SECURITY.md](SECURITY.md).
236
+ For security vulnerabilities, **do not** open a public issue. Email security@vesselapi.com instead. See [SECURITY.md](SECURITY.md).
237
+
238
+ ## Data Sources & Attribution
239
+
240
+ Emissions and casualty data: © European Union. Source: European Maritime Safety Agency
241
+ (EMSA): THETIS-MRV (EU MRV, Regulation (EU) 2015/757) and the European Marine Casualty
242
+ Information Platform (EMCIP). Reused under the European Commission reuse notice
243
+ (Commission Decision 2011/833/EU), which authorises reuse for commercial and
244
+ non-commercial purposes with acknowledgement of the source. Data may be transformed and
245
+ combined; EMSA does not endorse this service.
182
246
 
183
247
  ## License
184
248
 
@@ -0,0 +1,13 @@
1
+ vessel_api_python/__init__.py,sha256=-c0Rq1t5pDN4OY1w_9uNNeHjUI__kovOiyWvvU319jo,3114
2
+ vessel_api_python/_client.py,sha256=L7qkzUiATDpPlxWViEKicNpNx7D90gCohas56uCimgA,4919
3
+ vessel_api_python/_constants.py,sha256=Im6d9J9HSo5D-Rt4SVIQ35lqqGXIovSxhGsBhNqTVdU,244
4
+ vessel_api_python/_errors.py,sha256=DaiyCjYKJZTo6-6sOqAcJBdOeFaIYgWHE48nsHWGeGA,6414
5
+ vessel_api_python/_iterator.py,sha256=SkgsGSdxLrKtw-ad8fSUPaEDDJCamAKK0PrG_P8HX-4,3198
6
+ vessel_api_python/_models.py,sha256=rJnRaZZ9y-h3xYbn0e-7nRLm6Sr9bSkigLIC6jY_HW0,19739
7
+ vessel_api_python/_services.py,sha256=8f6yxKHvzDuIbrQCpN01wT_g4OsByWGHOIhKgDGeaQg,108285
8
+ vessel_api_python/_transport.py,sha256=pfRaJwkq_GYpA5Ev8wH7tBdlzN2ykgy29Ag1L3F5K4Y,6956
9
+ vessel_api_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ vessel_api_python-2.0.0.dist-info/METADATA,sha256=1HWjKevhtZDfUq9F1k4DNZoGZvtfaWnzsJw5dnPOVA0,10048
11
+ vessel_api_python-2.0.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
12
+ vessel_api_python-2.0.0.dist-info/licenses/LICENSE,sha256=zoj_abq99mj8cz-Bz71XCnwB-Qv3kU1VzVXeKEntuQU,1067
13
+ vessel_api_python-2.0.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.29.0
2
+ Generator: hatchling 1.32.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,13 +0,0 @@
1
- vessel_api_python/__init__.py,sha256=kmYpzbtVfaMHRXUBoom7JqZa5hCif3vGL8y-q5n4DrA,4599
2
- vessel_api_python/_client.py,sha256=39yKlQ4W2TnE85sTtK7KlBzFF385Pl52I5ghyq575EA,5067
3
- vessel_api_python/_constants.py,sha256=Cp_uNnK0RljiWlyPmkMrVFoQtF5GpXTggSCD1SPvcyk,244
4
- vessel_api_python/_errors.py,sha256=pxDm36mbrviOoDRmJ-ogtlUIsyu-dHpC0jcs5f34WDU,4310
5
- vessel_api_python/_iterator.py,sha256=SkgsGSdxLrKtw-ad8fSUPaEDDJCamAKK0PrG_P8HX-4,3198
6
- vessel_api_python/_models.py,sha256=eawnhctWmvGK505EJzDyszTqXpI5ctRg73-uR6AVOck,30575
7
- vessel_api_python/_services.py,sha256=PoRoHZP7PoqcUGGEaZNszm9_a1K_nTBQu_s5OaPCIqI,79094
8
- vessel_api_python/_transport.py,sha256=_4s-65JMRwD2S435u0iuoLGH_GyLNaX8cP_uSh_u80I,6692
9
- vessel_api_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- vessel_api_python-1.3.0.dist-info/METADATA,sha256=omcgGfIpL-dHECfAZqvoTmHqAUn6oKf14g0NoAULcHk,7019
11
- vessel_api_python-1.3.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
12
- vessel_api_python-1.3.0.dist-info/licenses/LICENSE,sha256=zoj_abq99mj8cz-Bz71XCnwB-Qv3kU1VzVXeKEntuQU,1067
13
- vessel_api_python-1.3.0.dist-info/RECORD,,