osmfeatures 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.
Files changed (44) hide show
  1. osmfeatures-0.1.0/.github/copilot-instructions.md +11 -0
  2. osmfeatures-0.1.0/.github/instructions/osmgeojson-python-conventions.instructions.md +15 -0
  3. osmfeatures-0.1.0/.gitignore +16 -0
  4. osmfeatures-0.1.0/LICENSE +21 -0
  5. osmfeatures-0.1.0/Makefile +15 -0
  6. osmfeatures-0.1.0/PKG-INFO +253 -0
  7. osmfeatures-0.1.0/README.md +213 -0
  8. osmfeatures-0.1.0/pyproject.toml +64 -0
  9. osmfeatures-0.1.0/src/osmfeatures/__init__.py +102 -0
  10. osmfeatures-0.1.0/src/osmfeatures/_http.py +136 -0
  11. osmfeatures-0.1.0/src/osmfeatures/_pagination.py +112 -0
  12. osmfeatures-0.1.0/src/osmfeatures/async_client.py +297 -0
  13. osmfeatures-0.1.0/src/osmfeatures/chunking.py +117 -0
  14. osmfeatures-0.1.0/src/osmfeatures/cli.py +310 -0
  15. osmfeatures-0.1.0/src/osmfeatures/client.py +374 -0
  16. osmfeatures-0.1.0/src/osmfeatures/convenience.py +424 -0
  17. osmfeatures-0.1.0/src/osmfeatures/models.py +197 -0
  18. osmfeatures-0.1.0/src/osmfeatures/output.py +124 -0
  19. osmfeatures-0.1.0/src/osmfeatures/py.typed +0 -0
  20. osmfeatures-0.1.0/src/osmfeatures/retry.py +144 -0
  21. osmfeatures-0.1.0/tests/.env.example +2 -0
  22. osmfeatures-0.1.0/tests/README.md +50 -0
  23. osmfeatures-0.1.0/tests/__init__.py +0 -0
  24. osmfeatures-0.1.0/tests/conftest.py +100 -0
  25. osmfeatures-0.1.0/tests/example_apps/__init__.py +0 -0
  26. osmfeatures-0.1.0/tests/example_apps/conftest.py +105 -0
  27. osmfeatures-0.1.0/tests/example_apps/graph_utils.py +75 -0
  28. osmfeatures-0.1.0/tests/example_apps/test_bike_path_dijkstra_liljeholmen_to_djurgarden.py +160 -0
  29. osmfeatures-0.1.0/tests/example_apps/test_city_cycling_infrastructure.py +81 -0
  30. osmfeatures-0.1.0/tests/example_apps/test_cycling_trails.py +58 -0
  31. osmfeatures-0.1.0/tests/example_apps/test_geometry_filters.py +116 -0
  32. osmfeatures-0.1.0/tests/example_apps/test_lakeside_ice_cream_hunt.py +155 -0
  33. osmfeatures-0.1.0/tests/example_apps/test_park_bench_finder.py +38 -0
  34. osmfeatures-0.1.0/tests/example_apps/test_park_explorer.py +64 -0
  35. osmfeatures-0.1.0/tests/example_apps/test_pedestrian_shortest_path.py +123 -0
  36. osmfeatures-0.1.0/tests/example_apps/test_pedestrian_wavefront_bfs.py +156 -0
  37. osmfeatures-0.1.0/tests/example_apps/test_restaurant_guide.py +55 -0
  38. osmfeatures-0.1.0/tests/test_async_client.py +440 -0
  39. osmfeatures-0.1.0/tests/test_chunking.py +86 -0
  40. osmfeatures-0.1.0/tests/test_cli.py +231 -0
  41. osmfeatures-0.1.0/tests/test_client.py +306 -0
  42. osmfeatures-0.1.0/tests/test_output.py +74 -0
  43. osmfeatures-0.1.0/tests/test_pagination.py +149 -0
  44. osmfeatures-0.1.0/tests/test_retry.py +105 -0
@@ -0,0 +1,11 @@
1
+ # Copilot Instructions for osmgeojson-python
2
+
3
+ Always-on baseline for this repository.
4
+
5
+ MapLark is a self-hosted GeoJSON API over OpenStreetMap data, backed by PostGIS and served via FastAPI.
6
+
7
+ - Keep changes minimal and backward compatible unless a task explicitly asks for breaking changes.
8
+ - Prefer strong typing and mypy-compatible changes.
9
+ - Keep sync and async client behavior aligned for equivalent features.
10
+ - Prefer deterministic tests with mocked HTTP over live network calls.
11
+ - Treat `.github/instructions/*.instructions.md` as the source of detailed, file-specific rules.
@@ -0,0 +1,15 @@
1
+ ---
2
+ description: "Use when editing Python code in osmgeojson (SDK, tests, or examples). Prefer strict typing, sync/async parity, and deterministic tests unless the task requires an exception."
3
+ name: "OSMGeoJSON Python Conventions"
4
+ applyTo: "**/*.py"
5
+ ---
6
+ # OSMGeoJSON Python Conventions
7
+
8
+ - Prefer complete type hints that remain compatible with strict mypy checks.
9
+ - Prefer preserving public API compatibility unless the task explicitly requests a breaking change.
10
+ - When adding or changing request parameters in the sync client, prefer mirroring the behavior in the async client unless there is a documented reason not to.
11
+ - Prefer routing HTTP retries and rate-limit handling through shared retry/http helpers instead of duplicating retry logic in client methods.
12
+ - For pagination or chunking changes, preserve deduplication-by-id behavior and existing guardrails against stale offsets.
13
+ - For tests that exercise HTTP flows, prefer mocked HTTP requests (for example with `responses`) and avoid live network calls.
14
+ - Add or update tests for behavioral changes, including both success and error paths when practical.
15
+ - Keep docstrings user-focused: include parameter semantics and API-specific constraints rather than generic restatements.
@@ -0,0 +1,16 @@
1
+ dist
2
+ .env
3
+ .env.deploy
4
+ __pycache__/
5
+ .pytest_cache/
6
+ *.pyc
7
+ *.pyo
8
+ *.pyd
9
+ .Python
10
+ env/
11
+ venv/
12
+ .venv/
13
+ ENV/
14
+ *.log
15
+ .DS_Store
16
+ cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MapLark
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,15 @@
1
+ SHELL := /bin/bash
2
+
3
+ VENV_DIR := $(CURDIR)/.venv
4
+ VENV_PY := $(VENV_DIR)/bin/python3
5
+ VENV_PIP := $(VENV_DIR)/bin/pip
6
+ setup:
7
+ python3 -m venv $(VENV_DIR)
8
+ source $(VENV_DIR)/bin/activate
9
+ $(VENV_PIP) install -e ".[all,test]"
10
+
11
+ test: setup
12
+ $(VENV_PY) -m pytest tests/ -v
13
+
14
+ clean:
15
+ rm -rf $(VENV_DIR)
@@ -0,0 +1,253 @@
1
+ Metadata-Version: 2.4
2
+ Name: osmfeatures
3
+ Version: 0.1.0
4
+ Summary: Official client for the MapLark OSM Features API (GeoJSON, FlatGeobuf, GeoParquet, CSV)
5
+ Project-URL: Homepage, https://maplark.com
6
+ Project-URL: Repository, https://github.com/MapLark/osmfeatures-python
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: flatgeobuf,geojson,geoparquet,geospatial,maplark,maps,openstreetmap,osm,overpass
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Scientific/Engineering :: GIS
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: click>=8.1
21
+ Requires-Dist: geojson>=3.0
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: requests>=2.28
24
+ Provides-Extra: all
25
+ Requires-Dist: geopandas>=0.14; extra == 'all'
26
+ Requires-Dist: pandas>=2.0; extra == 'all'
27
+ Requires-Dist: shapely>=2.0; extra == 'all'
28
+ Provides-Extra: geo
29
+ Requires-Dist: geopandas>=0.14; extra == 'geo'
30
+ Requires-Dist: pandas>=2.0; extra == 'geo'
31
+ Requires-Dist: shapely>=2.0; extra == 'geo'
32
+ Provides-Extra: test
33
+ Requires-Dist: haversine>=2.8; extra == 'test'
34
+ Requires-Dist: networkx>=3.0; extra == 'test'
35
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'test'
36
+ Requires-Dist: pytest>=7.0; extra == 'test'
37
+ Requires-Dist: python-dotenv>=1.0; extra == 'test'
38
+ Requires-Dist: responses>=0.25; extra == 'test'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # MapLark OSM Features API
42
+
43
+ Query OpenStreetMap features such as buildings, streets, and Points of Interest easily. Search for OSM features by bounding box, tags, and geometry shape and get GeoJSON back within less than 250ms (dependent on query size). No converting between formats manually. The API keeps OpenStreetMap semantics intact, like tags and ways, and returns GeoJSON Features you can feed straight into Leaflet, MapLibre, OpenLayers, or any geospatial toolchain. It is backed by postgis with tiered API keys and rate limiting to keep noisy neighbours out to give you predictable latency for real traffic. It also has self-host path for those willing to host complex infrastructure themselves.
44
+
45
+ The translation layer is very simple:
46
+
47
+ - `node` - GeoJSON Point
48
+ - `way` - LineString or Polygon
49
+ - `relation` - MultiPolygon or grouped geometries
50
+
51
+ You filter with the same tags mappers already use (`amenity=cafe`, `building=yes`, and so on). Knowledge from OSM, Overpass, and tagging docs transfers immediately.
52
+
53
+ To narrow down between "open ways" and "closed ways", use the `shape` parameter:
54
+
55
+ - `shape=line` - open ways (roads, paths, rivers) or line-shaped relations (routes, boundaries)
56
+ - `shape=polygon` - closed ways (buildings, parks) or multipolygon relations.
57
+ - `shape=all` - both shapes (default when shape is omitted).
58
+
59
+ For example, to get all buildings in an area:
60
+
61
+ `type=way & tags=building`
62
+
63
+ This is the equivalent of the Overpass query `way[building]`.
64
+
65
+ Read the full API reference here [https://maplark.com/developer](https://maplark.com/developer).
66
+
67
+ ## Python SDK
68
+
69
+ This client library comes with auto-pagination, bbox tiling (enables larger bbox queries), retry/backoff, pandas/geopandas output, async support, and convenience methods to get common OSM data such as buildings, amenities, bike roads, etc.
70
+
71
+ ```
72
+ pip install osmfeatures
73
+ pip install "osmfeatures[geo]" # pandas / geopandas / shapely support
74
+ ```
75
+
76
+ Official client for the MapLark OSM Features API (GeoJSON, FlatGeobuf, GeoParquet, CSV).
77
+ The SDK talks to `api.maplark.com` by default.
78
+
79
+ ## Quick start
80
+
81
+ ```python
82
+ from osmfeatures import OSMFeaturesClient
83
+
84
+ with OSMFeaturesClient(api_key="sk-...") as client:
85
+ fc = client.query(bbox="18.06,59.32,18.09,59.34", tags=["building"])
86
+ print(len(fc.features), "buildings found")
87
+ ```
88
+
89
+
90
+
91
+ ## Basic API usage
92
+
93
+
94
+
95
+ ### 1) Create a client
96
+
97
+ ```python
98
+ from osmfeatures import OSMFeaturesClient
99
+
100
+ client = OSMFeaturesClient(api_key="sk-...")
101
+ ```
102
+
103
+ You can use the client directly and close it when done, or use a context manager:
104
+
105
+ ```python
106
+ from osmfeatures import OSMFeaturesClient
107
+
108
+ with OSMFeaturesClient(api_key="sk-...") as client:
109
+ ...
110
+ ```
111
+
112
+
113
+
114
+ ### 2) Query OSM features
115
+
116
+ `query()` fetches a single page:
117
+
118
+ ```python
119
+ fc = client.query(
120
+ bbox="18.063,59.322,18.082,59.332",
121
+ type="way",
122
+ shape="line",
123
+ tags=["highway=cycleway"],
124
+ limit=500,
125
+ )
126
+
127
+ for feature in fc.features:
128
+ print(feature["id"], feature["geometry"]["type"], feature.tags)
129
+ ```
130
+
131
+ Common filters:
132
+
133
+ - `bbox="min_lon,min_lat,max_lon,max_lat"`
134
+ - `around="lon,lat,radius_m"`
135
+ - `tags=["amenity=restaurant"]` (AND)
136
+ - `or_tags=["bicycle=yes", "bicycle=designated"]` (OR)
137
+ - `not_tags=["access=private"]` (exclude)
138
+ - `type="node" | "way" | "relation"`
139
+ - `shape="polygon" | "line" | "all"` (omit = both shapes; `all` also means both)
140
+ - `cursor` (pagination; use SDK `meta.next_cursor` from previous page, sourced from `X-Next-Cursor`)
141
+
142
+
143
+
144
+ ### 3) Auto-pagination and bbox tiling
145
+
146
+ Use `query_all()` to fetch all pages and deduplicate by OSM feature id. By default it splits the bbox into 2 tiles (power of 2) so large areas use more requests; pass `bbox_tiles=1` to disable, or raise it (`4`, `8`, …) for bigger areas:
147
+
148
+ ```python
149
+ all_restaurants = client.query_all(
150
+ bbox="18.063,59.322,18.082,59.332",
151
+ tags="amenity=restaurant",
152
+ limit_per_page=1000, # page size per HTTP request
153
+ max_features=55_000, # total cap; pass None for no cap
154
+ bbox_tiles=2, # default
155
+ )
156
+
157
+ print(all_restaurants.meta.returned)
158
+ ```
159
+
160
+
161
+
162
+ ### 4) Async client
163
+
164
+ Async methods mirror the sync API (`query_async`, `query_all_async`):
165
+
166
+ ```python
167
+ import asyncio
168
+ from osmfeatures import AsyncOSMFeaturesClient
169
+
170
+
171
+ async def main() -> None:
172
+ async with AsyncOSMFeaturesClient(api_key="sk-...") as client:
173
+ fc = await client.query_async(
174
+ bbox="18.06,59.32,18.09,59.34",
175
+ tags=["building"],
176
+ )
177
+ print(len(fc.features))
178
+
179
+
180
+ asyncio.run(main())
181
+ ```
182
+
183
+
184
+
185
+ ### 5) Convenience helpers
186
+
187
+ For common datasets, use convenience methods built on top of `query_all()`:
188
+
189
+ ```python
190
+ from osmfeatures import OSMFeaturesClient, get_buildings, get_restaurants
191
+
192
+ with OSMFeaturesClient(api_key="sk-...") as client:
193
+ buildings = get_buildings(client, bbox="18.063,59.322,18.082,59.332")
194
+ restaurants = get_restaurants(client, bbox="18.063,59.322,18.082,59.332")
195
+ print(len(buildings.features), len(restaurants.features))
196
+ ```
197
+
198
+
199
+
200
+ ### 6) Cost and usage
201
+
202
+ ```python
203
+ estimate = client.estimate_cost(
204
+ bbox="18.063,59.322,18.082,59.332",
205
+ tags=["building"],
206
+ )
207
+ print("estimated credits:", estimate.estimated_credits)
208
+
209
+ usage = client.usage()
210
+ print("Usage:", usage)
211
+ ```
212
+
213
+
214
+
215
+ ### 7) CLI usage
216
+
217
+ If the package is installed, the CLI is available as `osmfeatures`:
218
+
219
+ ```bash
220
+ export MAPLARK_API_KEY="sk-..."
221
+ osmfeatures query --bbox "18.063,59.322,18.082,59.332" --tags building --type way
222
+ osmfeatures query --bbox "18.063,59.322,18.082,59.332" --tags building --all-pages --bbox-tiles 4
223
+ ```
224
+
225
+
226
+
227
+ ## Example apps
228
+
229
+ The repository includes runnable example-app tests in `tests/example_apps/` showing end-to-end usage patterns against real OSM data.
230
+
231
+ - `test_restaurant_guide.py`: restaurant discovery list with names/cuisines and map coordinates.
232
+ - `test_park_bench_finder.py`: bench finder for park maps (`amenity=bench`).
233
+ - `test_park_explorer.py`: park browser with polygon boundaries, centroids, and area estimates.
234
+ - `test_cycling_trails.py`: unpaved cycling trail layer for MTB/gravel planning.
235
+ - `test_city_cycling_infrastructure.py`: city cycling overlay combining cycleways and bike lanes.
236
+ - `test_lakeside_ice_cream_hunt.py`: nearest ice cream shops to waterfront edges.
237
+ - `test_pedestrian_shortest_path.py`: shortest walking route via graph + Dijkstra.
238
+ - `test_pedestrian_wavefront_bfs.py`: hop-based accessibility rings via BFS.
239
+ - `test_bike_path_dijkstra_liljeholmen_to_djurgarden.py`: tiled corridor bike routing from Liljeholmen to Djurgarden.
240
+ - `test_geometry_filters.py`: zoom + area/length filters for large buildings and long roads.
241
+
242
+ Run all example apps:
243
+
244
+ ```bash
245
+ pytest tests/example_apps -v
246
+ ```
247
+
248
+ Run one example app:
249
+
250
+ ```bash
251
+ pytest tests/example_apps/test_restaurant_guide.py -v
252
+ ```
253
+
@@ -0,0 +1,213 @@
1
+ # MapLark OSM Features API
2
+
3
+ Query OpenStreetMap features such as buildings, streets, and Points of Interest easily. Search for OSM features by bounding box, tags, and geometry shape and get GeoJSON back within less than 250ms (dependent on query size). No converting between formats manually. The API keeps OpenStreetMap semantics intact, like tags and ways, and returns GeoJSON Features you can feed straight into Leaflet, MapLibre, OpenLayers, or any geospatial toolchain. It is backed by postgis with tiered API keys and rate limiting to keep noisy neighbours out to give you predictable latency for real traffic. It also has self-host path for those willing to host complex infrastructure themselves.
4
+
5
+ The translation layer is very simple:
6
+
7
+ - `node` - GeoJSON Point
8
+ - `way` - LineString or Polygon
9
+ - `relation` - MultiPolygon or grouped geometries
10
+
11
+ You filter with the same tags mappers already use (`amenity=cafe`, `building=yes`, and so on). Knowledge from OSM, Overpass, and tagging docs transfers immediately.
12
+
13
+ To narrow down between "open ways" and "closed ways", use the `shape` parameter:
14
+
15
+ - `shape=line` - open ways (roads, paths, rivers) or line-shaped relations (routes, boundaries)
16
+ - `shape=polygon` - closed ways (buildings, parks) or multipolygon relations.
17
+ - `shape=all` - both shapes (default when shape is omitted).
18
+
19
+ For example, to get all buildings in an area:
20
+
21
+ `type=way & tags=building`
22
+
23
+ This is the equivalent of the Overpass query `way[building]`.
24
+
25
+ Read the full API reference here [https://maplark.com/developer](https://maplark.com/developer).
26
+
27
+ ## Python SDK
28
+
29
+ This client library comes with auto-pagination, bbox tiling (enables larger bbox queries), retry/backoff, pandas/geopandas output, async support, and convenience methods to get common OSM data such as buildings, amenities, bike roads, etc.
30
+
31
+ ```
32
+ pip install osmfeatures
33
+ pip install "osmfeatures[geo]" # pandas / geopandas / shapely support
34
+ ```
35
+
36
+ Official client for the MapLark OSM Features API (GeoJSON, FlatGeobuf, GeoParquet, CSV).
37
+ The SDK talks to `api.maplark.com` by default.
38
+
39
+ ## Quick start
40
+
41
+ ```python
42
+ from osmfeatures import OSMFeaturesClient
43
+
44
+ with OSMFeaturesClient(api_key="sk-...") as client:
45
+ fc = client.query(bbox="18.06,59.32,18.09,59.34", tags=["building"])
46
+ print(len(fc.features), "buildings found")
47
+ ```
48
+
49
+
50
+
51
+ ## Basic API usage
52
+
53
+
54
+
55
+ ### 1) Create a client
56
+
57
+ ```python
58
+ from osmfeatures import OSMFeaturesClient
59
+
60
+ client = OSMFeaturesClient(api_key="sk-...")
61
+ ```
62
+
63
+ You can use the client directly and close it when done, or use a context manager:
64
+
65
+ ```python
66
+ from osmfeatures import OSMFeaturesClient
67
+
68
+ with OSMFeaturesClient(api_key="sk-...") as client:
69
+ ...
70
+ ```
71
+
72
+
73
+
74
+ ### 2) Query OSM features
75
+
76
+ `query()` fetches a single page:
77
+
78
+ ```python
79
+ fc = client.query(
80
+ bbox="18.063,59.322,18.082,59.332",
81
+ type="way",
82
+ shape="line",
83
+ tags=["highway=cycleway"],
84
+ limit=500,
85
+ )
86
+
87
+ for feature in fc.features:
88
+ print(feature["id"], feature["geometry"]["type"], feature.tags)
89
+ ```
90
+
91
+ Common filters:
92
+
93
+ - `bbox="min_lon,min_lat,max_lon,max_lat"`
94
+ - `around="lon,lat,radius_m"`
95
+ - `tags=["amenity=restaurant"]` (AND)
96
+ - `or_tags=["bicycle=yes", "bicycle=designated"]` (OR)
97
+ - `not_tags=["access=private"]` (exclude)
98
+ - `type="node" | "way" | "relation"`
99
+ - `shape="polygon" | "line" | "all"` (omit = both shapes; `all` also means both)
100
+ - `cursor` (pagination; use SDK `meta.next_cursor` from previous page, sourced from `X-Next-Cursor`)
101
+
102
+
103
+
104
+ ### 3) Auto-pagination and bbox tiling
105
+
106
+ Use `query_all()` to fetch all pages and deduplicate by OSM feature id. By default it splits the bbox into 2 tiles (power of 2) so large areas use more requests; pass `bbox_tiles=1` to disable, or raise it (`4`, `8`, …) for bigger areas:
107
+
108
+ ```python
109
+ all_restaurants = client.query_all(
110
+ bbox="18.063,59.322,18.082,59.332",
111
+ tags="amenity=restaurant",
112
+ limit_per_page=1000, # page size per HTTP request
113
+ max_features=55_000, # total cap; pass None for no cap
114
+ bbox_tiles=2, # default
115
+ )
116
+
117
+ print(all_restaurants.meta.returned)
118
+ ```
119
+
120
+
121
+
122
+ ### 4) Async client
123
+
124
+ Async methods mirror the sync API (`query_async`, `query_all_async`):
125
+
126
+ ```python
127
+ import asyncio
128
+ from osmfeatures import AsyncOSMFeaturesClient
129
+
130
+
131
+ async def main() -> None:
132
+ async with AsyncOSMFeaturesClient(api_key="sk-...") as client:
133
+ fc = await client.query_async(
134
+ bbox="18.06,59.32,18.09,59.34",
135
+ tags=["building"],
136
+ )
137
+ print(len(fc.features))
138
+
139
+
140
+ asyncio.run(main())
141
+ ```
142
+
143
+
144
+
145
+ ### 5) Convenience helpers
146
+
147
+ For common datasets, use convenience methods built on top of `query_all()`:
148
+
149
+ ```python
150
+ from osmfeatures import OSMFeaturesClient, get_buildings, get_restaurants
151
+
152
+ with OSMFeaturesClient(api_key="sk-...") as client:
153
+ buildings = get_buildings(client, bbox="18.063,59.322,18.082,59.332")
154
+ restaurants = get_restaurants(client, bbox="18.063,59.322,18.082,59.332")
155
+ print(len(buildings.features), len(restaurants.features))
156
+ ```
157
+
158
+
159
+
160
+ ### 6) Cost and usage
161
+
162
+ ```python
163
+ estimate = client.estimate_cost(
164
+ bbox="18.063,59.322,18.082,59.332",
165
+ tags=["building"],
166
+ )
167
+ print("estimated credits:", estimate.estimated_credits)
168
+
169
+ usage = client.usage()
170
+ print("Usage:", usage)
171
+ ```
172
+
173
+
174
+
175
+ ### 7) CLI usage
176
+
177
+ If the package is installed, the CLI is available as `osmfeatures`:
178
+
179
+ ```bash
180
+ export MAPLARK_API_KEY="sk-..."
181
+ osmfeatures query --bbox "18.063,59.322,18.082,59.332" --tags building --type way
182
+ osmfeatures query --bbox "18.063,59.322,18.082,59.332" --tags building --all-pages --bbox-tiles 4
183
+ ```
184
+
185
+
186
+
187
+ ## Example apps
188
+
189
+ The repository includes runnable example-app tests in `tests/example_apps/` showing end-to-end usage patterns against real OSM data.
190
+
191
+ - `test_restaurant_guide.py`: restaurant discovery list with names/cuisines and map coordinates.
192
+ - `test_park_bench_finder.py`: bench finder for park maps (`amenity=bench`).
193
+ - `test_park_explorer.py`: park browser with polygon boundaries, centroids, and area estimates.
194
+ - `test_cycling_trails.py`: unpaved cycling trail layer for MTB/gravel planning.
195
+ - `test_city_cycling_infrastructure.py`: city cycling overlay combining cycleways and bike lanes.
196
+ - `test_lakeside_ice_cream_hunt.py`: nearest ice cream shops to waterfront edges.
197
+ - `test_pedestrian_shortest_path.py`: shortest walking route via graph + Dijkstra.
198
+ - `test_pedestrian_wavefront_bfs.py`: hop-based accessibility rings via BFS.
199
+ - `test_bike_path_dijkstra_liljeholmen_to_djurgarden.py`: tiled corridor bike routing from Liljeholmen to Djurgarden.
200
+ - `test_geometry_filters.py`: zoom + area/length filters for large buildings and long roads.
201
+
202
+ Run all example apps:
203
+
204
+ ```bash
205
+ pytest tests/example_apps -v
206
+ ```
207
+
208
+ Run one example app:
209
+
210
+ ```bash
211
+ pytest tests/example_apps/test_restaurant_guide.py -v
212
+ ```
213
+
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "osmfeatures"
7
+ version = "0.1.0"
8
+ description = "Official client for the MapLark OSM Features API (GeoJSON, FlatGeobuf, GeoParquet, CSV)"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ keywords = ["openstreetmap", "osm", "geojson", "flatgeobuf", "geoparquet", "overpass", "maplark", "geospatial", "maps"]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Scientific/Engineering :: GIS",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = [
25
+ "requests>=2.28",
26
+ "httpx>=0.27",
27
+ "click>=8.1",
28
+ "geojson>=3.0",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ geo = [
33
+ "pandas>=2.0",
34
+ "geopandas>=0.14",
35
+ "shapely>=2.0",
36
+ ]
37
+ all = ["pandas>=2.0", "geopandas>=0.14", "shapely>=2.0"]
38
+ test = [
39
+ "pytest>=7.0",
40
+ "responses>=0.25",
41
+ "pytest-asyncio>=0.23",
42
+ "networkx>=3.0",
43
+ "haversine>=2.8",
44
+ "python-dotenv>=1.0",
45
+ ]
46
+
47
+ [project.scripts]
48
+ osmfeatures = "osmfeatures.cli:cli"
49
+
50
+ [project.urls]
51
+ Homepage = "https://maplark.com"
52
+ Repository = "https://github.com/MapLark/osmfeatures-python"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/osmfeatures"]
56
+ include = ["src/osmfeatures/py.typed"]
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
60
+ pythonpath = ["."]
61
+ asyncio_mode = "auto"
62
+
63
+ [tool.mypy]
64
+ strict = true