vessel-api-python 1.0.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.
Files changed (29) hide show
  1. vessel_api_python-1.0.0/.github/workflows/ci.yml +46 -0
  2. vessel_api_python-1.0.0/.github/workflows/publish.yml +24 -0
  3. vessel_api_python-1.0.0/.gitignore +10 -0
  4. vessel_api_python-1.0.0/LICENSE +21 -0
  5. vessel_api_python-1.0.0/Makefile +21 -0
  6. vessel_api_python-1.0.0/PKG-INFO +168 -0
  7. vessel_api_python-1.0.0/README.md +134 -0
  8. vessel_api_python-1.0.0/SECURITY.md +11 -0
  9. vessel_api_python-1.0.0/examples/async_basic.py +49 -0
  10. vessel_api_python-1.0.0/examples/basic.py +67 -0
  11. vessel_api_python-1.0.0/openapi/swagger.json +5779 -0
  12. vessel_api_python-1.0.0/pyproject.toml +70 -0
  13. vessel_api_python-1.0.0/src/vessel_api_python/__init__.py +183 -0
  14. vessel_api_python-1.0.0/src/vessel_api_python/_client.py +163 -0
  15. vessel_api_python-1.0.0/src/vessel_api_python/_constants.py +8 -0
  16. vessel_api_python-1.0.0/src/vessel_api_python/_errors.py +137 -0
  17. vessel_api_python-1.0.0/src/vessel_api_python/_iterator.py +120 -0
  18. vessel_api_python-1.0.0/src/vessel_api_python/_models.py +887 -0
  19. vessel_api_python-1.0.0/src/vessel_api_python/_services.py +1180 -0
  20. vessel_api_python-1.0.0/src/vessel_api_python/_transport.py +185 -0
  21. vessel_api_python-1.0.0/src/vessel_api_python/py.typed +0 -0
  22. vessel_api_python-1.0.0/tests/__init__.py +0 -0
  23. vessel_api_python-1.0.0/tests/conftest.py +34 -0
  24. vessel_api_python-1.0.0/tests/test_client.py +102 -0
  25. vessel_api_python-1.0.0/tests/test_errors.py +136 -0
  26. vessel_api_python-1.0.0/tests/test_iterator.py +136 -0
  27. vessel_api_python-1.0.0/tests/test_services.py +125 -0
  28. vessel_api_python-1.0.0/tests/test_smoke.py +574 -0
  29. vessel_api_python-1.0.0/tests/test_transport.py +215 -0
@@ -0,0 +1,46 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ unit-tests:
12
+ name: Unit Tests (Python ${{ matrix.python-version }})
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ python-version: ["3.9", "3.12", "3.13"]
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - run: pip install -e ".[dev]"
25
+ - run: ruff check src/ tests/
26
+ - run: mypy src/vessel_api_python/
27
+ - run: pytest -v tests/
28
+
29
+ smoke-tests:
30
+ name: Smoke Tests
31
+ runs-on: ubuntu-latest
32
+ if: >-
33
+ github.event_name == 'workflow_dispatch' ||
34
+ github.event_name == 'push' ||
35
+ github.event.pull_request.head.repo.full_name == github.repository
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: "3.12"
42
+
43
+ - run: pip install -e ".[dev]"
44
+ - run: pytest -v -m smoke tests/
45
+ env:
46
+ VESSELAPI_API_KEY: ${{ secrets.VESSELAPI_API_KEY }}
@@ -0,0 +1,24 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ id-token: write
9
+
10
+ jobs:
11
+ publish:
12
+ name: Build & Publish
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.12"
20
+
21
+ - run: pip install build
22
+ - run: python -m build
23
+
24
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .ruff_cache/
9
+ *.egg
10
+ .env
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Vessel API
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ .PHONY: all lint typecheck test fmt install smoke
2
+
3
+ all: fmt lint typecheck test
4
+
5
+ lint:
6
+ ruff check src/ tests/
7
+
8
+ typecheck:
9
+ mypy src/vesselapi/
10
+
11
+ test:
12
+ pytest -v tests/
13
+
14
+ fmt:
15
+ ruff format src/ tests/
16
+
17
+ install:
18
+ pip install -e ".[dev]"
19
+
20
+ smoke:
21
+ pytest -v -m smoke tests/
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.4
2
+ Name: vessel-api-python
3
+ Version: 1.0.0
4
+ Summary: Python client for the Vessel Tracking API — maritime vessel tracking, port events, emissions, and navigation data.
5
+ Project-URL: Documentation, https://vesselapi.com/docs
6
+ Project-URL: Repository, https://github.com/vessel-api/vesselapi-python
7
+ Project-URL: Issues, https://github.com/vessel-api/vesselapi-python/issues
8
+ Project-URL: Changelog, https://github.com/vessel-api/vesselapi-python/releases
9
+ Author-email: Vessel API <support@vesselapi.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ais,maritime,sdk,tracking,vessel,vesselapi
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: eval-type-backport>=0.2.0; python_version < '3.10'
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: pydantic>=2.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: mypy>=1.10; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Requires-Dist: respx>=0.21; extra == 'dev'
32
+ Requires-Dist: ruff>=0.4; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # vesselapi-python
36
+
37
+ [![CI](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml/badge.svg)](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
38
+ [![PyPI](https://img.shields.io/pypi/v/vessel-api-python.svg)](https://pypi.org/project/vessel-api-python/)
39
+ [![Python](https://img.shields.io/pypi/pyversions/vessel-api-python.svg)](https://pypi.org/project/vessel-api-python/)
40
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
41
+
42
+ Python client for the [Vessel Tracking API](https://vesselapi.com) — maritime vessel tracking, port events, emissions, and navigation data.
43
+
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
+
46
+ ## Install
47
+
48
+ ```bash
49
+ pip install vessel-api-python
50
+ ```
51
+
52
+ Requires Python 3.9+.
53
+
54
+ ## Quick Start
55
+
56
+ ```python
57
+ from vessel_api_python import VesselClient
58
+
59
+ client = VesselClient(api_key="your-api-key")
60
+
61
+ # Search for a vessel by name.
62
+ result = client.search.vessels(filter_name="Ever Given")
63
+ for v in result.vessels or []:
64
+ print(f"{v.name} (IMO {v.imo})")
65
+
66
+ # Get a port by UN/LOCODE.
67
+ port = client.ports.get("NLRTM")
68
+ print(port.port.name)
69
+
70
+ # Auto-paginate through port events.
71
+ for event in client.port_events.list_all(pagination_limit=10):
72
+ print(f"{event.event} at {event.timestamp}")
73
+ ```
74
+
75
+ ### Async
76
+
77
+ ```python
78
+ import asyncio
79
+ from vessel_api_python import AsyncVesselClient
80
+
81
+ async def main():
82
+ async with AsyncVesselClient(api_key="your-api-key") as client:
83
+ result = await client.search.vessels(filter_name="Ever Given")
84
+ async for event in client.port_events.list_all(pagination_limit=10):
85
+ print(f"{event.event} at {event.timestamp}")
86
+
87
+ asyncio.run(main())
88
+ ```
89
+
90
+ ## Available Services
91
+
92
+ | Service | Methods | Description |
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 |
96
+ | `port_events` | `list`, `by_port`, `by_ports`, `by_vessel`, `last_by_vessel`, `by_vessels` | Vessel arrival/departure events |
97
+ | `emissions` | `list` | EU MRV emissions data |
98
+ | `search` | `vessels`, `ports`, `dgps`, `light_aids`, `modus`, `radio_beacons` | Full-text search across entity types |
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
+
102
+ **37 methods total.**
103
+
104
+ ## Error Handling
105
+
106
+ All methods raise specific exception types on non-2xx responses:
107
+
108
+ ```python
109
+ from vessel_api_python import VesselAPIError
110
+
111
+ try:
112
+ client.ports.get("ZZZZZ")
113
+ except VesselAPIError as err:
114
+ if err.is_not_found:
115
+ print("Port not found")
116
+ elif err.is_rate_limited:
117
+ print("Rate limited — back off")
118
+ elif err.is_auth_error:
119
+ print("Check API key")
120
+ print(err.status_code, err.message)
121
+ ```
122
+
123
+ ## Auto-Pagination
124
+
125
+ Every list endpoint has an `all_*` / `list_all` variant returning an iterator:
126
+
127
+ ```python
128
+ # Sync
129
+ for vessel in client.search.all_vessels(filter_name="tanker"):
130
+ print(vessel.name)
131
+
132
+ # Async
133
+ async for vessel in client.search.all_vessels(filter_name="tanker"):
134
+ print(vessel.name)
135
+
136
+ # Collect all at once
137
+ vessels = client.search.all_vessels(filter_name="tanker").collect()
138
+ ```
139
+
140
+ ## Configuration
141
+
142
+ ```python
143
+ client = VesselClient(
144
+ api_key="your-api-key",
145
+ base_url="https://custom-endpoint.example.com/v1",
146
+ timeout=60.0,
147
+ max_retries=5, # default: 3
148
+ user_agent="my-app/1.0",
149
+ )
150
+ ```
151
+
152
+ Retries use exponential backoff with jitter on 429 and 5xx responses. The `Retry-After` header is respected.
153
+
154
+ ## Documentation
155
+
156
+ - [API Documentation](https://vesselapi.com/docs) — endpoint guides, request/response schemas, and usage examples
157
+ - [API Explorer](https://vesselapi.com/api-reference) — interactive API reference
158
+ - [Dashboard](https://dashboard.vesselapi.com) — manage API keys and monitor usage
159
+
160
+ ## Contributing & Support
161
+
162
+ 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).
163
+
164
+ For security vulnerabilities, **do not** open a public issue — email security@vesselapi.com instead. See [SECURITY.md](SECURITY.md).
165
+
166
+ ## License
167
+
168
+ [MIT](LICENSE)
@@ -0,0 +1,134 @@
1
+ # vesselapi-python
2
+
3
+ [![CI](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml/badge.svg)](https://github.com/vessel-api/vesselapi-python/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/vessel-api-python.svg)](https://pypi.org/project/vessel-api-python/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/vessel-api-python.svg)](https://pypi.org/project/vessel-api-python/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ Python client for the [Vessel Tracking API](https://vesselapi.com) — maritime vessel tracking, port events, emissions, and navigation data.
9
+
10
+ **Resources**: [Documentation](https://vesselapi.com/docs) | [API Explorer](https://vesselapi.com/api-reference) | [Dashboard](https://dashboard.vesselapi.com) | [Contact Support](mailto:support@vesselapi.com)
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install vessel-api-python
16
+ ```
17
+
18
+ Requires Python 3.9+.
19
+
20
+ ## Quick Start
21
+
22
+ ```python
23
+ from vessel_api_python import VesselClient
24
+
25
+ client = VesselClient(api_key="your-api-key")
26
+
27
+ # Search for a vessel by name.
28
+ result = client.search.vessels(filter_name="Ever Given")
29
+ for v in result.vessels or []:
30
+ print(f"{v.name} (IMO {v.imo})")
31
+
32
+ # Get a port by UN/LOCODE.
33
+ port = client.ports.get("NLRTM")
34
+ print(port.port.name)
35
+
36
+ # Auto-paginate through port events.
37
+ for event in client.port_events.list_all(pagination_limit=10):
38
+ print(f"{event.event} at {event.timestamp}")
39
+ ```
40
+
41
+ ### Async
42
+
43
+ ```python
44
+ import asyncio
45
+ from vessel_api_python import AsyncVesselClient
46
+
47
+ async def main():
48
+ async with AsyncVesselClient(api_key="your-api-key") as client:
49
+ result = await client.search.vessels(filter_name="Ever Given")
50
+ async for event in client.port_events.list_all(pagination_limit=10):
51
+ print(f"{event.event} at {event.timestamp}")
52
+
53
+ asyncio.run(main())
54
+ ```
55
+
56
+ ## Available Services
57
+
58
+ | Service | Methods | Description |
59
+ |---------|---------|-------------|
60
+ | `vessels` | `get`, `position`, `casualties`, `classification`, `emissions`, `eta`, `inspections`, `inspection_detail`, `ownership`, `positions` | Vessel details, positions, and records |
61
+ | `ports` | `get` | Port lookup by UN/LOCODE |
62
+ | `port_events` | `list`, `by_port`, `by_ports`, `by_vessel`, `last_by_vessel`, `by_vessels` | Vessel arrival/departure events |
63
+ | `emissions` | `list` | EU MRV emissions data |
64
+ | `search` | `vessels`, `ports`, `dgps`, `light_aids`, `modus`, `radio_beacons` | Full-text search across entity types |
65
+ | `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 |
66
+ | `navtex` | `list` | NAVTEX maritime safety messages |
67
+
68
+ **37 methods total.**
69
+
70
+ ## Error Handling
71
+
72
+ All methods raise specific exception types on non-2xx responses:
73
+
74
+ ```python
75
+ from vessel_api_python import VesselAPIError
76
+
77
+ try:
78
+ client.ports.get("ZZZZZ")
79
+ except VesselAPIError as err:
80
+ if err.is_not_found:
81
+ print("Port not found")
82
+ elif err.is_rate_limited:
83
+ print("Rate limited — back off")
84
+ elif err.is_auth_error:
85
+ print("Check API key")
86
+ print(err.status_code, err.message)
87
+ ```
88
+
89
+ ## Auto-Pagination
90
+
91
+ Every list endpoint has an `all_*` / `list_all` variant returning an iterator:
92
+
93
+ ```python
94
+ # Sync
95
+ for vessel in client.search.all_vessels(filter_name="tanker"):
96
+ print(vessel.name)
97
+
98
+ # Async
99
+ async for vessel in client.search.all_vessels(filter_name="tanker"):
100
+ print(vessel.name)
101
+
102
+ # Collect all at once
103
+ vessels = client.search.all_vessels(filter_name="tanker").collect()
104
+ ```
105
+
106
+ ## Configuration
107
+
108
+ ```python
109
+ client = VesselClient(
110
+ api_key="your-api-key",
111
+ base_url="https://custom-endpoint.example.com/v1",
112
+ timeout=60.0,
113
+ max_retries=5, # default: 3
114
+ user_agent="my-app/1.0",
115
+ )
116
+ ```
117
+
118
+ Retries use exponential backoff with jitter on 429 and 5xx responses. The `Retry-After` header is respected.
119
+
120
+ ## Documentation
121
+
122
+ - [API Documentation](https://vesselapi.com/docs) — endpoint guides, request/response schemas, and usage examples
123
+ - [API Explorer](https://vesselapi.com/api-reference) — interactive API reference
124
+ - [Dashboard](https://dashboard.vesselapi.com) — manage API keys and monitor usage
125
+
126
+ ## Contributing & Support
127
+
128
+ 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).
129
+
130
+ For security vulnerabilities, **do not** open a public issue — email security@vesselapi.com instead. See [SECURITY.md](SECURITY.md).
131
+
132
+ ## License
133
+
134
+ [MIT](LICENSE)
@@ -0,0 +1,11 @@
1
+ # Security Policy
2
+
3
+ This repository follows the security policy of the main VesselAPI project.
4
+
5
+ ## Reporting a Vulnerability
6
+
7
+ **DO NOT** open a public GitHub issue for security vulnerabilities.
8
+
9
+ **Email:** security@vesselapi.com
10
+
11
+ For full details on reporting process, severity levels, scope, and safe harbor policy, see the [VesselAPI Security Policy](https://github.com/vessel-api/VesselApi/blob/master/SECURITY.md).
@@ -0,0 +1,49 @@
1
+ """Basic asynchronous usage of the Vessel API Python SDK."""
2
+
3
+ import asyncio
4
+ import os
5
+ import sys
6
+
7
+ from vesselapi import AsyncVesselClient, VesselAPIError
8
+
9
+
10
+ async def main() -> None:
11
+ api_key = os.environ.get("VESSELAPI_API_KEY", "")
12
+ if not api_key:
13
+ print("VESSELAPI_API_KEY environment variable is required")
14
+ sys.exit(1)
15
+
16
+ async with AsyncVesselClient(api_key=api_key) as client:
17
+ # Search for vessels.
18
+ print("--- Search Vessels ---")
19
+ result = await client.search.vessels(filter_name="Ever Given")
20
+ for v in result.vessels or []:
21
+ print(f"Vessel: {v.name} (IMO: {v.imo})")
22
+
23
+ # Get a port.
24
+ print("\n--- Get Port ---")
25
+ port = await client.ports.get("NLRTM")
26
+ if port.port:
27
+ print(f"Port: {port.port.name} ({port.port.unlo_code})")
28
+
29
+ # Error handling.
30
+ print("\n--- Error Handling ---")
31
+ try:
32
+ await client.ports.get("ZZZZZ")
33
+ except VesselAPIError as err:
34
+ if err.is_not_found:
35
+ print(f"Port not found (status {err.status_code})")
36
+
37
+ # Auto-paginate (async).
38
+ print("\n--- Port Events (async paginated) ---")
39
+ count = 0
40
+ async for event in client.port_events.list_all(pagination_limit=10):
41
+ print(f"Event: {event.event} at {event.timestamp}")
42
+ count += 1
43
+ if count >= 25:
44
+ break
45
+ print(f"Total events shown: {count}")
46
+
47
+
48
+ if __name__ == "__main__":
49
+ asyncio.run(main())
@@ -0,0 +1,67 @@
1
+ """Basic synchronous usage of the Vessel API Python SDK."""
2
+
3
+ import os
4
+ import sys
5
+
6
+ from vesselapi import VesselClient, VesselAPIError
7
+
8
+
9
+ def main() -> None:
10
+ api_key = os.environ.get("VESSELAPI_API_KEY", "")
11
+ if not api_key:
12
+ print("VESSELAPI_API_KEY environment variable is required")
13
+ sys.exit(1)
14
+
15
+ client = VesselClient(api_key=api_key)
16
+
17
+ # Search for vessels by name.
18
+ print("--- Search Vessels ---")
19
+ result = client.search.vessels(filter_name="Ever Given")
20
+ for v in result.vessels or []:
21
+ print(f"Vessel: {v.name} (IMO: {v.imo})")
22
+
23
+ # Search for vessels by flag.
24
+ print("\n--- Search Vessels by Flag ---")
25
+ flag_result = client.search.vessels(filter_flag="PA", filter_vessel_type="Container Ship", pagination_limit=5)
26
+ for v in flag_result.vessels or []:
27
+ print(f"Vessel: {v.name} (IMO: {v.imo}, Country: {v.country})")
28
+
29
+ # Search for ports by country.
30
+ print("\n--- Search Ports by Country ---")
31
+ port_search = client.search.ports(filter_country="NL", pagination_limit=5)
32
+ for p in port_search.ports or []:
33
+ print(f"Port: {p.name} ({p.unlo_code})")
34
+
35
+ # Get a port by UNLOCODE.
36
+ print("\n--- Get Port ---")
37
+ port = client.ports.get("NLRTM")
38
+ if port.port:
39
+ print(f"Port: {port.port.name} ({port.port.unlo_code})")
40
+
41
+ # Handle a not-found port gracefully.
42
+ print("\n--- Not Found Handling ---")
43
+ try:
44
+ client.ports.get("ZZZZZ")
45
+ except VesselAPIError as err:
46
+ if err.is_not_found:
47
+ print(f"Port ZZZZZ not found (status {err.status_code})")
48
+ elif err.is_rate_limited:
49
+ print("Rate limited — try again later")
50
+ else:
51
+ print(f"API error: {err.message} (status {err.status_code})")
52
+
53
+ # Auto-paginate through port events.
54
+ print("\n--- Port Events (paginated) ---")
55
+ count = 0
56
+ for event in client.port_events.list_all(pagination_limit=10):
57
+ print(f"Event: {event.event} at {event.timestamp}")
58
+ count += 1
59
+ if count >= 25:
60
+ break
61
+ print(f"Total events shown: {count}")
62
+
63
+ client.close()
64
+
65
+
66
+ if __name__ == "__main__":
67
+ main()