visicom-api-client 0.1.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.
- visicom_api_client-0.1.0/.github/workflows/ci.yml +26 -0
- visicom_api_client-0.1.0/.gitignore +11 -0
- visicom_api_client-0.1.0/PKG-INFO +93 -0
- visicom_api_client-0.1.0/README.md +70 -0
- visicom_api_client-0.1.0/pyproject.toml +52 -0
- visicom_api_client-0.1.0/scripts/smoke_test.py +46 -0
- visicom_api_client-0.1.0/src/visicom_api/__init__.py +59 -0
- visicom_api_client-0.1.0/src/visicom_api/_base.py +56 -0
- visicom_api_client-0.1.0/src/visicom_api/_endpoints.py +166 -0
- visicom_api_client-0.1.0/src/visicom_api/async_client.py +197 -0
- visicom_api_client-0.1.0/src/visicom_api/client.py +195 -0
- visicom_api_client-0.1.0/src/visicom_api/exceptions.py +49 -0
- visicom_api_client-0.1.0/src/visicom_api/models.py +329 -0
- visicom_api_client-0.1.0/src/visicom_api/py.typed +0 -0
- visicom_api_client-0.1.0/tests/test_client.py +89 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Install package with dev dependencies
|
|
20
|
+
run: pip install -e ".[dev]"
|
|
21
|
+
- name: Lint
|
|
22
|
+
run: ruff check .
|
|
23
|
+
- name: Type check
|
|
24
|
+
run: mypy src
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: pytest
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: visicom-api-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial sync/async Python client for the Visicom Data API
|
|
5
|
+
Project-URL: Homepage, https://api.visicom.ua/uk/products/data-api/data-api-references
|
|
6
|
+
Author: Your Name
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: api-client,geocoding,gis,visicom
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Typing :: Typed
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Requires-Dist: httpx>=0.24
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
20
|
+
Requires-Dist: respx>=0.20; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# visicom-api-client
|
|
25
|
+
|
|
26
|
+
Неофіційний Python-клієнт для [Visicom Data API](https://api.visicom.ua/uk/products/data-api/data-api-references) (геокодування, маршрутизація, буфери, прив'язка до доріг).
|
|
27
|
+
|
|
28
|
+
## Встановлення
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install -e ".[dev]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Використання
|
|
35
|
+
|
|
36
|
+
Синхронно:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from visicom_api import VisicomClient
|
|
40
|
+
|
|
41
|
+
with VisicomClient(api_key="YOUR_API_KEY") as client:
|
|
42
|
+
result = client.geocode(text="Київ, Хрещатик, 26")
|
|
43
|
+
print(result)
|
|
44
|
+
|
|
45
|
+
route = client.distance((30.42612, 50.45111), (30.44946, 50.45682))
|
|
46
|
+
print(route["distance"])
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Асинхронно:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import asyncio
|
|
53
|
+
from visicom_api import AsyncVisicomClient
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def main() -> None:
|
|
57
|
+
async with AsyncVisicomClient(api_key="YOUR_API_KEY") as client:
|
|
58
|
+
result = await client.geocode(categories="poi_restaurant", near=(30.5113, 50.4550), radius=300)
|
|
59
|
+
print(result)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
asyncio.run(main())
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Точки (`origin`, `near`, `waypoints`, ...) можна передавати як:
|
|
66
|
+
- ідентифікатор об'єкта: `"POIA1KIGKN"`
|
|
67
|
+
- координати: `(lng, lat)` кортеж
|
|
68
|
+
- список точок для `waypoints`/`locks`/`origins`/`destinations`/`points`: `[(lng, lat), ...]` або список id
|
|
69
|
+
- заздалегідь відформатований рядок (наприклад, WKT-геометрія)
|
|
70
|
+
|
|
71
|
+
## Обробка помилок
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from visicom_api import VisicomAuthError, VisicomRateLimitError, VisicomAPIError
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
client.geocode(text="...")
|
|
78
|
+
except VisicomAuthError:
|
|
79
|
+
... # невірний або відсутній ключ
|
|
80
|
+
except VisicomRateLimitError:
|
|
81
|
+
... # перевищено ліміт запитів
|
|
82
|
+
except VisicomAPIError as e:
|
|
83
|
+
... # інша помилка API, e.status_code
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Розробка
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install -e ".[dev]"
|
|
90
|
+
ruff check .
|
|
91
|
+
mypy src
|
|
92
|
+
pytest
|
|
93
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# visicom-api-client
|
|
2
|
+
|
|
3
|
+
Неофіційний Python-клієнт для [Visicom Data API](https://api.visicom.ua/uk/products/data-api/data-api-references) (геокодування, маршрутизація, буфери, прив'язка до доріг).
|
|
4
|
+
|
|
5
|
+
## Встановлення
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install -e ".[dev]"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Використання
|
|
12
|
+
|
|
13
|
+
Синхронно:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from visicom_api import VisicomClient
|
|
17
|
+
|
|
18
|
+
with VisicomClient(api_key="YOUR_API_KEY") as client:
|
|
19
|
+
result = client.geocode(text="Київ, Хрещатик, 26")
|
|
20
|
+
print(result)
|
|
21
|
+
|
|
22
|
+
route = client.distance((30.42612, 50.45111), (30.44946, 50.45682))
|
|
23
|
+
print(route["distance"])
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Асинхронно:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import asyncio
|
|
30
|
+
from visicom_api import AsyncVisicomClient
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def main() -> None:
|
|
34
|
+
async with AsyncVisicomClient(api_key="YOUR_API_KEY") as client:
|
|
35
|
+
result = await client.geocode(categories="poi_restaurant", near=(30.5113, 50.4550), radius=300)
|
|
36
|
+
print(result)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
asyncio.run(main())
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Точки (`origin`, `near`, `waypoints`, ...) можна передавати як:
|
|
43
|
+
- ідентифікатор об'єкта: `"POIA1KIGKN"`
|
|
44
|
+
- координати: `(lng, lat)` кортеж
|
|
45
|
+
- список точок для `waypoints`/`locks`/`origins`/`destinations`/`points`: `[(lng, lat), ...]` або список id
|
|
46
|
+
- заздалегідь відформатований рядок (наприклад, WKT-геометрія)
|
|
47
|
+
|
|
48
|
+
## Обробка помилок
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from visicom_api import VisicomAuthError, VisicomRateLimitError, VisicomAPIError
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
client.geocode(text="...")
|
|
55
|
+
except VisicomAuthError:
|
|
56
|
+
... # невірний або відсутній ключ
|
|
57
|
+
except VisicomRateLimitError:
|
|
58
|
+
... # перевищено ліміт запитів
|
|
59
|
+
except VisicomAPIError as e:
|
|
60
|
+
... # інша помилка API, e.status_code
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Розробка
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install -e ".[dev]"
|
|
67
|
+
ruff check .
|
|
68
|
+
mypy src
|
|
69
|
+
pytest
|
|
70
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "visicom-api-client"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Unofficial sync/async Python client for the Visicom Data API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Your Name" }]
|
|
13
|
+
keywords = ["visicom", "geocoding", "gis", "api-client"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Typing :: Typed",
|
|
20
|
+
]
|
|
21
|
+
dependencies = ["httpx>=0.24"]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
dev = [
|
|
25
|
+
"pytest>=7.0",
|
|
26
|
+
"pytest-asyncio>=0.21",
|
|
27
|
+
"respx>=0.20",
|
|
28
|
+
"ruff>=0.4",
|
|
29
|
+
"mypy>=1.8",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://api.visicom.ua/uk/products/data-api/data-api-references"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.build.targets.wheel]
|
|
36
|
+
packages = ["src/visicom_api"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
asyncio_mode = "auto"
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
|
|
42
|
+
[tool.ruff]
|
|
43
|
+
line-length = 100
|
|
44
|
+
target-version = "py39"
|
|
45
|
+
|
|
46
|
+
[tool.ruff.lint]
|
|
47
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
48
|
+
|
|
49
|
+
[tool.mypy]
|
|
50
|
+
python_version = "3.9"
|
|
51
|
+
strict = true
|
|
52
|
+
packages = ["visicom_api"]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Manual smoke test against the real Visicom Data API.
|
|
2
|
+
|
|
3
|
+
Not part of the pytest suite (network + real API key required). Run with:
|
|
4
|
+
VISICOM_API_KEY=... python scripts/smoke_test.py
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
|
|
14
|
+
|
|
15
|
+
from visicom_api import VisicomClient # noqa: E402
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main() -> None:
|
|
19
|
+
api_key = os.environ.get("VISICOM_API_KEY")
|
|
20
|
+
if not api_key:
|
|
21
|
+
raise SystemExit("Set VISICOM_API_KEY environment variable first")
|
|
22
|
+
|
|
23
|
+
with VisicomClient(api_key=api_key) as client:
|
|
24
|
+
print("=== geocode (single expected result, limit=1) ===")
|
|
25
|
+
geocode_result = client.geocode(text="Київ, Хрещатик, 26", limit=1)
|
|
26
|
+
print("type:", type(geocode_result).__name__)
|
|
27
|
+
print("top-level keys:", list(geocode_result.keys()))
|
|
28
|
+
print(json.dumps(geocode_result, ensure_ascii=False, indent=2)[:1500])
|
|
29
|
+
|
|
30
|
+
print("\n=== geocode (multiple results, no limit) ===")
|
|
31
|
+
many_result = client.geocode(
|
|
32
|
+
categories="poi_restaurant", near=(30.5113, 50.4550), radius=300
|
|
33
|
+
)
|
|
34
|
+
print("type:", type(many_result).__name__)
|
|
35
|
+
print("top-level keys:", list(many_result.keys()))
|
|
36
|
+
|
|
37
|
+
print("\n=== distancematrix (check for 'status' field) ===")
|
|
38
|
+
matrix = client.distancematrix(
|
|
39
|
+
origins=[(30.36277, 50.51605), (30.49667, 50.49508)],
|
|
40
|
+
destinations=[(30.36277, 50.51605), (30.49667, 50.49508)],
|
|
41
|
+
)
|
|
42
|
+
print(json.dumps(matrix, ensure_ascii=False, indent=2))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
main()
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Unofficial Python client for the Visicom Data API."""
|
|
2
|
+
|
|
3
|
+
from .async_client import AsyncVisicomClient
|
|
4
|
+
from .client import VisicomClient
|
|
5
|
+
from .exceptions import (
|
|
6
|
+
VisicomAPIError,
|
|
7
|
+
VisicomAuthError,
|
|
8
|
+
VisicomError,
|
|
9
|
+
VisicomRateLimitError,
|
|
10
|
+
)
|
|
11
|
+
from .models import (
|
|
12
|
+
AdmCountryProperties,
|
|
13
|
+
AdmDistrictProperties,
|
|
14
|
+
AdmLevel1Properties,
|
|
15
|
+
AdmLevel2Properties,
|
|
16
|
+
AdmLevel3Properties,
|
|
17
|
+
AdmSettlementProperties,
|
|
18
|
+
AdrAddressProperties,
|
|
19
|
+
AdrStreetProperties,
|
|
20
|
+
BufferResponse,
|
|
21
|
+
DistanceMatrixResponse,
|
|
22
|
+
DistanceResult,
|
|
23
|
+
FeatureCollection,
|
|
24
|
+
GeocodeResult,
|
|
25
|
+
GeoFeature,
|
|
26
|
+
LocationResponse,
|
|
27
|
+
PoiProperties,
|
|
28
|
+
SnapToRoadResult,
|
|
29
|
+
TspResponse,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"VisicomClient",
|
|
34
|
+
"AsyncVisicomClient",
|
|
35
|
+
"VisicomError",
|
|
36
|
+
"VisicomAPIError",
|
|
37
|
+
"VisicomAuthError",
|
|
38
|
+
"VisicomRateLimitError",
|
|
39
|
+
"GeoFeature",
|
|
40
|
+
"FeatureCollection",
|
|
41
|
+
"GeocodeResult",
|
|
42
|
+
"AdmCountryProperties",
|
|
43
|
+
"AdmDistrictProperties",
|
|
44
|
+
"AdmLevel1Properties",
|
|
45
|
+
"AdmLevel2Properties",
|
|
46
|
+
"AdmLevel3Properties",
|
|
47
|
+
"AdmSettlementProperties",
|
|
48
|
+
"AdrAddressProperties",
|
|
49
|
+
"AdrStreetProperties",
|
|
50
|
+
"PoiProperties",
|
|
51
|
+
"DistanceResult",
|
|
52
|
+
"DistanceMatrixResponse",
|
|
53
|
+
"TspResponse",
|
|
54
|
+
"SnapToRoadResult",
|
|
55
|
+
"BufferResponse",
|
|
56
|
+
"LocationResponse",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Shared helpers for query-parameter formatting.
|
|
2
|
+
|
|
3
|
+
Not part of the public API; import from `visicom_api` instead.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections.abc import Iterable
|
|
9
|
+
from typing import Any, Union
|
|
10
|
+
|
|
11
|
+
BASE_URL = "https://api.visicom.ua/data-api/5.0"
|
|
12
|
+
|
|
13
|
+
# A point is either an object id (or WKT geometry) string, or an (lng, lat) tuple.
|
|
14
|
+
Point = Union[str, tuple[float, float]]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _point_to_str(point: Point) -> str:
|
|
18
|
+
if isinstance(point, str):
|
|
19
|
+
return point
|
|
20
|
+
lng, lat = point
|
|
21
|
+
return f"{lng},{lat}"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _points_param(points: str | Iterable[Point]) -> str:
|
|
25
|
+
"""Format a list of points for a query parameter.
|
|
26
|
+
|
|
27
|
+
A pre-formatted string is passed through unchanged. Otherwise, the API
|
|
28
|
+
uses '|' to separate coordinate pairs and ',' to separate object ids, so
|
|
29
|
+
an iterable must be all-coordinates or all-ids; mixed lists must be
|
|
30
|
+
formatted by the caller and passed in as a raw string.
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(points, str):
|
|
33
|
+
return points
|
|
34
|
+
items = list(points)
|
|
35
|
+
if not items:
|
|
36
|
+
raise ValueError("points must not be empty")
|
|
37
|
+
if all(isinstance(p, str) for p in items):
|
|
38
|
+
return ",".join(items) # type: ignore[arg-type]
|
|
39
|
+
if all(not isinstance(p, str) for p in items):
|
|
40
|
+
return "|".join(_point_to_str(p) for p in items)
|
|
41
|
+
raise ValueError(
|
|
42
|
+
"cannot mix object ids and (lng, lat) tuples in one list; "
|
|
43
|
+
"pass a pre-formatted string instead"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _clean_params(params: dict[str, Any]) -> dict[str, Any]:
|
|
48
|
+
"""Drop None values and render booleans the way the API expects."""
|
|
49
|
+
cleaned: dict[str, Any] = {}
|
|
50
|
+
for key, value in params.items():
|
|
51
|
+
if value is None:
|
|
52
|
+
continue
|
|
53
|
+
if isinstance(value, bool):
|
|
54
|
+
value = "true" if value else "false"
|
|
55
|
+
cleaned[key] = value
|
|
56
|
+
return cleaned
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Query-parameter builders for every Visicom Data API endpoint.
|
|
2
|
+
|
|
3
|
+
This mixin is shared by the sync and async clients so the endpoint naming,
|
|
4
|
+
point formatting, and None-stripping logic lives in exactly one place.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterable
|
|
10
|
+
from typing import Any, Literal
|
|
11
|
+
|
|
12
|
+
from ._base import Point, _clean_params, _point_to_str, _points_param
|
|
13
|
+
|
|
14
|
+
Format = Literal["json", "csv"]
|
|
15
|
+
Lang = Literal["uk", "ru", "en"]
|
|
16
|
+
Mode = Literal["driving", "driving-shortest", "direct"]
|
|
17
|
+
SnapMode = Literal["driving", "walking"]
|
|
18
|
+
Order = Literal["relevance", "distance"]
|
|
19
|
+
|
|
20
|
+
PathParams = tuple[str, dict[str, Any]]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _Endpoints:
|
|
24
|
+
default_lang: Lang
|
|
25
|
+
|
|
26
|
+
def _geocode_path_params(
|
|
27
|
+
self,
|
|
28
|
+
*,
|
|
29
|
+
lang: Lang | None,
|
|
30
|
+
format: Format,
|
|
31
|
+
text: str | None,
|
|
32
|
+
word_text: str | None,
|
|
33
|
+
categories: str | None,
|
|
34
|
+
categories_exclude: str | None,
|
|
35
|
+
near: Point | None,
|
|
36
|
+
radius: float | None,
|
|
37
|
+
intersect: Point | None,
|
|
38
|
+
contains: Point | None,
|
|
39
|
+
order: Order | None,
|
|
40
|
+
zoom: int | None,
|
|
41
|
+
limit: int | None,
|
|
42
|
+
country: str | None,
|
|
43
|
+
boost_country: str | None,
|
|
44
|
+
) -> PathParams:
|
|
45
|
+
path = f"{lang or self.default_lang}/geocode.{format}"
|
|
46
|
+
params = _clean_params(
|
|
47
|
+
{
|
|
48
|
+
"text": text,
|
|
49
|
+
"word_text": word_text,
|
|
50
|
+
"categories": categories,
|
|
51
|
+
"categories_exclude": categories_exclude,
|
|
52
|
+
"near": _point_to_str(near) if near is not None else None,
|
|
53
|
+
"radius": radius,
|
|
54
|
+
"intersect": _point_to_str(intersect) if intersect is not None else None,
|
|
55
|
+
"contains": _point_to_str(contains) if contains is not None else None,
|
|
56
|
+
"order": order,
|
|
57
|
+
"zoom": zoom,
|
|
58
|
+
"limit": limit,
|
|
59
|
+
"country": country,
|
|
60
|
+
"boost_country": boost_country,
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
return path, params
|
|
64
|
+
|
|
65
|
+
def _feature_path_params(
|
|
66
|
+
self,
|
|
67
|
+
*,
|
|
68
|
+
ids: str | Iterable[str],
|
|
69
|
+
lang: Lang | None,
|
|
70
|
+
format: Format,
|
|
71
|
+
geometry: bool,
|
|
72
|
+
) -> PathParams:
|
|
73
|
+
id_param = ids if isinstance(ids, str) else ",".join(ids)
|
|
74
|
+
path = f"{lang or self.default_lang}/feature/{id_param}.{format}"
|
|
75
|
+
params = _clean_params({"geometry": None if geometry else "no"})
|
|
76
|
+
return path, params
|
|
77
|
+
|
|
78
|
+
def _distance_path_params(
|
|
79
|
+
self,
|
|
80
|
+
*,
|
|
81
|
+
origin: Point,
|
|
82
|
+
destination: Point,
|
|
83
|
+
waypoints: str | Iterable[Point] | None,
|
|
84
|
+
locks: str | Iterable[Point] | None,
|
|
85
|
+
mode: Mode,
|
|
86
|
+
geometry: Literal["no", "path"],
|
|
87
|
+
accuracy: float | None,
|
|
88
|
+
) -> PathParams:
|
|
89
|
+
params = _clean_params(
|
|
90
|
+
{
|
|
91
|
+
"origin": _point_to_str(origin),
|
|
92
|
+
"destination": _point_to_str(destination),
|
|
93
|
+
"waypoints": _points_param(waypoints) if waypoints is not None else None,
|
|
94
|
+
"locks": _points_param(locks) if locks is not None else None,
|
|
95
|
+
"mode": mode,
|
|
96
|
+
"geometry": geometry,
|
|
97
|
+
"accuracy": accuracy,
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
return "core/distance.json", params
|
|
101
|
+
|
|
102
|
+
def _distancematrix_path_params(
|
|
103
|
+
self,
|
|
104
|
+
*,
|
|
105
|
+
origins: str | Iterable[Point],
|
|
106
|
+
destinations: str | Iterable[Point],
|
|
107
|
+
locks: str | Iterable[Point] | None,
|
|
108
|
+
mode: Mode,
|
|
109
|
+
) -> PathParams:
|
|
110
|
+
params = _clean_params(
|
|
111
|
+
{
|
|
112
|
+
"origins": _points_param(origins),
|
|
113
|
+
"destinations": _points_param(destinations),
|
|
114
|
+
"locks": _points_param(locks) if locks is not None else None,
|
|
115
|
+
"mode": mode,
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
return "core/distancematrix.json", params
|
|
119
|
+
|
|
120
|
+
def _tsp_path_params(
|
|
121
|
+
self,
|
|
122
|
+
*,
|
|
123
|
+
waypoints: str | Iterable[Point],
|
|
124
|
+
round_trip: bool,
|
|
125
|
+
locks: str | Iterable[Point] | None,
|
|
126
|
+
mode: Mode,
|
|
127
|
+
) -> PathParams:
|
|
128
|
+
params = _clean_params(
|
|
129
|
+
{
|
|
130
|
+
"waypoints": _points_param(waypoints),
|
|
131
|
+
"round_trip": round_trip,
|
|
132
|
+
"locks": _points_param(locks) if locks is not None else None,
|
|
133
|
+
"mode": mode,
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
return "core/tsp.json", params
|
|
137
|
+
|
|
138
|
+
def _snaptoroad_path_params(
|
|
139
|
+
self,
|
|
140
|
+
*,
|
|
141
|
+
points: str | Iterable[Point],
|
|
142
|
+
interpolate: bool,
|
|
143
|
+
mode: SnapMode,
|
|
144
|
+
separate: bool,
|
|
145
|
+
) -> PathParams:
|
|
146
|
+
params = _clean_params(
|
|
147
|
+
{
|
|
148
|
+
"points": _points_param(points),
|
|
149
|
+
"interpolate": interpolate,
|
|
150
|
+
"mode": mode,
|
|
151
|
+
"separate": separate,
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
return "core/snaptoroad.json", params
|
|
155
|
+
|
|
156
|
+
def _location_path_params(
|
|
157
|
+
self, *, start: Point, azimut: float, distance: float, format: Format
|
|
158
|
+
) -> PathParams:
|
|
159
|
+
params = _clean_params(
|
|
160
|
+
{"start": _point_to_str(start), "azimut": azimut, "distance": distance}
|
|
161
|
+
)
|
|
162
|
+
return f"core/location.{format}", params
|
|
163
|
+
|
|
164
|
+
def _buffer_path_params(self, *, near: Point, radius: float, format: Format) -> PathParams:
|
|
165
|
+
params = _clean_params({"near": _point_to_str(near), "radius": radius})
|
|
166
|
+
return f"core/buffer.{format}", params
|