Skip to content

Commit afb77f2

Browse files
committed
Initial release: Datalastic Python SDK v0.1.0
0 parents  commit afb77f2

17 files changed

Lines changed: 3479 additions & 0 deletions

.github/workflows/publish.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
strategy:
12+
matrix:
13+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
14+
steps:
15+
- uses: actions/checkout@v4
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
- name: Install dependencies
21+
run: |
22+
python -m pip install --upgrade pip
23+
pip install -e ".[dev]"
24+
- name: Run tests
25+
run: pytest tests/ -v
26+
27+
publish:
28+
needs: test
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
- name: Set up Python
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: "3.11"
36+
- name: Install build tooling
37+
run: |
38+
python -m pip install --upgrade pip
39+
pip install build twine
40+
- name: Build distributions
41+
run: python -m build
42+
- name: Check distributions
43+
run: twine check dist/*
44+
- name: Publish to PyPI
45+
env:
46+
TWINE_USERNAME: __token__
47+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
48+
run: twine upload dist/*

.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# Distribution / packaging
7+
build/
8+
dist/
9+
*.egg-info/
10+
*.egg
11+
.eggs/
12+
wheels/
13+
14+
# Test / coverage
15+
.pytest_cache/
16+
.coverage
17+
.coverage.*
18+
htmlcov/
19+
.tox/
20+
.cache/
21+
22+
# Virtual environments
23+
.venv/
24+
venv/
25+
env/
26+
ENV/
27+
28+
# IDEs / editors
29+
.idea/
30+
.vscode/
31+
*.swp
32+
.DS_Store
33+
34+
# Secrets
35+
.env
36+
*.env
37+
38+
# Internal dev notes — keep off GitHub
39+
CLAUDE.md

AGENTS.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Agent guide
2+
3+
Guidance for AI assistants working in this repository.
4+
5+
## Setup
6+
7+
```bash
8+
pip install -e ".[dev]"
9+
pytest tests/ -v
10+
```
11+
12+
No network access is needed for tests; every HTTP call is mocked with `unittest.mock.patch` on `requests.Session.get` / `requests.Session.post`.
13+
14+
## Project structure
15+
16+
```
17+
datalastic/
18+
__init__.py public exports (Client, models, exceptions)
19+
client.py Client + _get/_post/_handle + base URLs + stat()
20+
vessels.py VesselsResource (8 methods)
21+
ports.py PortsResource (find, get)
22+
routes.py RoutesResource (calculate)
23+
intel.py IntelResource (8 maritime_reports endpoints)
24+
reports.py ReportsResource (submit, get, list_all)
25+
models.py dict-backed data classes, each with .raw and __repr__
26+
exceptions.py exception hierarchy
27+
tests/test_client.py
28+
```
29+
30+
## Key conventions
31+
32+
- **Auth is a query parameter.** `api-key` is appended to params in `_get()` and
33+
injected into the JSON body in `_post()`. Never a header.
34+
- **Three base URLs.** `BASE_V0` (default), `BASE_EXT` (sea routes, SAT-E),
35+
`BASE_MR` (all `intel` endpoints). Pass `base=` to `_get()`.
36+
- **Date params are renamed.** Python `from_date` / `to_date` are sent as the
37+
`from` / `to` query keys. `vessel_type` in `vessels.find()` is sent as `type`
38+
to avoid shadowing the builtin.
39+
- **None filtering.** Always strip `None` values before building the request
40+
(`{k: v for k, v in params.items() if v is not None}`).
41+
- **Validate before HTTP.** Required-parameter checks raise `ValueError`
42+
before any request is made.
43+
- **Bulk uses repeated params.** `vessels.bulk()` builds a list of
44+
`(key, value)` tuples so identifiers are sent as `mmsi=x&mmsi=y`.
45+
- **Response unwrapping.** `_get()` / `_post()` unwrap the envelope and return
46+
`body["data"]` directly; callers use the returned value as the model data.
47+
List endpoints map each element into a model.
48+
- **Models never raise on missing fields.** They use `.get()` and keep the
49+
raw payload in `.raw`.
50+
51+
## Exception hierarchy
52+
53+
```
54+
DatalasticError
55+
├── AuthenticationError 401
56+
├── InsufficientCreditsError 402
57+
├── NotFoundError 404
58+
├── RateLimitError 429
59+
└── APIError everything else; has .status_code
60+
```
61+
62+
Timeouts, connection errors, non-JSON bodies, and missing `data` keys all map
63+
to `APIError`.
64+
65+
## Testing conventions
66+
67+
- Build fake responses with the `make_response()` / `ok()` helpers in
68+
`tests/test_client.py`.
69+
- Every resource method has a happy-path test plus validation-error tests.
70+
- Assert the called URL prefix to confirm the correct base URL is used.
71+
- Assert query params / JSON body to confirm renaming and auth injection.
72+
- Keep tests offline — never hit the live API.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Datalastic
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 commit comments

Comments
 (0)