osmfinder 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.
@@ -0,0 +1,271 @@
1
+ Metadata-Version: 2.3
2
+ Name: osmfinder
3
+ Version: 1.0.0
4
+ Summary: Find and download OpenStreetMap *.osm.pbf extracts by name, id or geometry.
5
+ Keywords: openstreetmap,osm,pbf,extract,geofabrik,bbbike,gis,download
6
+ Author: Kamil Raczycki
7
+ Author-email: Kamil Raczycki <kraczycki@kraina.ai>
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Topic :: Scientific/Engineering :: GIS
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Operating System :: Unix
20
+ Classifier: Operating System :: MacOS
21
+ Classifier: Operating System :: Microsoft :: Windows
22
+ Requires-Dist: shapely>=2
23
+ Requires-Dist: pyproj>=3
24
+ Requires-Dist: pooch>=1.6.0
25
+ Requires-Dist: requests
26
+ Requires-Dist: beautifulsoup4
27
+ Requires-Dist: rich>=12.0.0
28
+ Requires-Dist: tqdm>=4.42.0
29
+ Requires-Dist: platformdirs>=2
30
+ Requires-Dist: anyascii>=0.3.3
31
+ Requires-Dist: python-dateutil>=2.8
32
+ Requires-Dist: arro3-core>=0.8.0
33
+ Requires-Dist: arro3-io>=0.8.0
34
+ Requires-Python: >=3.10
35
+ Project-URL: Homepage, https://github.com/RaczeQ/osmfinder
36
+ Project-URL: Repository, https://github.com/RaczeQ/osmfinder
37
+ Project-URL: Changelog, https://github.com/RaczeQ/osmfinder/blob/main/CHANGELOG.md
38
+ Description-Content-Type: text/markdown
39
+
40
+
41
+
42
+ # OSM Finder
43
+
44
+ Find and download publicly available OpenStreetMap `*.osm.pbf` extracts by **name**, **id** or
45
+ **geometry**.
46
+
47
+ `osmfinder` wraps several public extract providers behind a single API:
48
+ [Geofabrik](https://download.geofabrik.de/), [BBBike](https://download.bbbike.org/osm/bbbike/),
49
+ [OpenStreetMap.fr](https://download.openstreetmap.fr/), [Movisda](https://osm.download.movisda.io/)
50
+ and [GEO2day](https://geo2day.com/). It can look up an extract by a text query, or find the
51
+ smallest set of extracts covering an arbitrary geometry, and download the matching `*.osm.pbf`
52
+ files.
53
+
54
+ <p align="center">
55
+ <img width="300" src="https://raw.githubusercontent.com/raczeq/osmfinder/main/docs/assets/logos/osmfinder_logo.png"><br/>
56
+ </p>
57
+
58
+ <p align="center">
59
+ <img alt="GitHub" src="https://img.shields.io/github/license/raczeq/osmfinder?logo=mit&logoColor=%23fff">
60
+ <img src="https://img.shields.io/github/checks-status/raczeq/osmfinder/main?logo=GitHubActions&logoColor=%23fff" alt="Checks">
61
+ <a href="https://github.com/raczeq/osmfinder/actions/workflows/ci-prod.yml" target="_blank"><img alt="GitHub Workflow Status - PROD" src="https://img.shields.io/github/actions/workflow/status/raczeq/osmfinder/ci-prod.yml?label=build-prod&logo=GitHubActions&logoColor=%23fff"></a>
62
+ <a href="https://results.pre-commit.ci/latest/github/raczeq/osmfinder/main" target="_blank"><img src="https://results.pre-commit.ci/badge/github/raczeq/osmfinder/main.svg" alt="pre-commit.ci status"></a>
63
+ <a href="https://www.codefactor.io/repository/github/raczeq/osmfinder"><img alt="CodeFactor Grade" src="https://img.shields.io/codefactor/grade/github/raczeq/osmfinder?logo=codefactor&logoColor=%23fff"></a>
64
+ <a href="https://app.codecov.io/gh/raczeq/osmfinder/tree/main"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/raczeq/osmfinder?logo=codecov&token=PRS4E02ZX0&logoColor=%23fff"></a>
65
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img src="https://img.shields.io/pypi/v/osmfinder?color=%2334D058&label=pypi%20package&logo=pypi&logoColor=%23fff" alt="Package version"></a>
66
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img src="https://img.shields.io/pypi/pyversions/osmfinder.svg?color=%2334D058&logo=python&logoColor=%23fff" alt="Supported Python versions"></a>
67
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/osmfinder"></a>
68
+ </p>
69
+
70
+ > **Logo attribution:** The osmfinder logo uses icons from the [Lucide](https://lucide.dev/) icon set —
71
+ > specifically the **earth** and **square-dashed** icons.
72
+
73
+ ## Installation
74
+
75
+ ```bash
76
+ pip install osmfinder
77
+ ```
78
+
79
+ ## Usage
80
+
81
+ ```python
82
+ import osmfinder
83
+ from shapely.geometry import box
84
+
85
+ # --- by name / id ---
86
+ # Returns an OsmfinderQueryResult with .extracts list and .extract accessor.
87
+ result = osmfinder.find("Monaco")
88
+ print(result.extracts[0].id) # 'Movisda-admin_MC'
89
+ print(result.extracts[0].file_name) # 'movisda-admin_monaco'
90
+ print(result.extract.id) # convenience accessor for single-match queries
91
+
92
+ # Download by name - returns OsmfinderDownloadResult with .download_paths.
93
+ dl = osmfinder.download("Monaco", download_directory="files")
94
+ print(dl.download_paths) # [Path('files/movisda-admin_monaco.osm.pbf')]
95
+ print(dl.find_result.extract.id) # 'Movisda-admin_MC'
96
+
97
+ # --- by geometry ---
98
+ geometry = box(2.11, 48.77, 2.54, 48.98)
99
+ result = osmfinder.find(geometry)
100
+ print(result) # multi-line OsmfinderGeometryResult with extracts, coverage, steps
101
+ print(len(result.extracts)) # number of extracts covering the geometry
102
+ print(result.extracts[0].id) # 'BBBike_Paris'
103
+
104
+ # Download by geometry
105
+ dl = osmfinder.download(geometry, source="Geofabrik", download_directory="files")
106
+ print(len(dl.download_paths)) # number of downloaded files
107
+ print(dl.download_paths[0].name) # 'geofabrik_europe_monaco.osm.pbf'
108
+
109
+ # --- by point ---
110
+ extracts = osmfinder.find_extracts_covering_point((-0.1276, 51.5074), source="Geofabrik")
111
+ print(len(extracts)) # number of extracts covering central London
112
+ print(extracts[0].id) # 'Geofabrik_greater-london'
113
+
114
+ # --- force single extract ---
115
+ geometry = box(9.4, 47.2, 9.8, 47.6)
116
+ result = osmfinder.find_smallest_containing_extracts(
117
+ geometry, force_single_result=False # default behaviour
118
+ )
119
+ print(len(result.extracts)) # 4
120
+ print(result.extracts[0].id) # 'GEO2Day_europe_austria_vorarlberg'
121
+ print(result.extracts[1].id) # 'BBBike_Konstanz'
122
+ print(result.extracts[2].id) # 'GEO2Day_europe_switzerland_saint_gallen'
123
+ print(result.extracts[3].id) # 'Movisda-admin_LI'
124
+
125
+ result = osmfinder.find_smallest_containing_extracts(
126
+ geometry, force_single_result=True
127
+ )
128
+ print(len(result.extracts)) # 1
129
+ print(result.extracts[0].id) # 'Movisda-grid_N47W009'
130
+
131
+ # --- explore what's available ---
132
+ osmfinder.display_available_extracts(source="Geofabrik") # source is optional
133
+
134
+ # Get all extracts as a list for programmatic use
135
+ extracts = osmfinder.get_available_extracts(source="Geofabrik") # source is optional
136
+ for extract in extracts:
137
+ print(extract.id, extract.file_name)
138
+ ```
139
+
140
+ ### Sources
141
+
142
+ The `source` argument accepts a single value, an iterable, or a comma-separated string. Available
143
+ values: `any`, `Geofabrik`, `BBBike`, `osmfr`, `GEO2Day`, `Movisda-admin`, `Movisda-grid`.
144
+
145
+ ```python
146
+ osmfinder.get_extract_by_query("Berlin", ["Geofabrik", "BBBike"])
147
+ osmfinder.get_extract_by_query("Berlin", "geofabrik,bbbike")
148
+ ```
149
+
150
+ ## Result classes
151
+
152
+ All find and download operations return typed result objects instead of raw lists.
153
+
154
+ ### `OsmfinderQueryResult`
155
+
156
+ Returned by `get_extract_by_query()` and `find()` when called with a string query.
157
+
158
+ | Attribute | Type | Description |
159
+ |---|---|---|
160
+ | `extracts` | `list[OpenStreetMapExtract]` | All matched extracts |
161
+ | `extract` | `OpenStreetMapExtract` | Convenience accessor for the single matched extract |
162
+ | `matched_extracts` | `list[OpenStreetMapExtract]` | All extracts matched by the query before selection (may contain more than `extracts` when `select_first_match=True`) |
163
+ | `query` | `str` | The original query string |
164
+ | `sources_used` | `list[OsmExtractSource]` | Sources that were searched |
165
+
166
+ ### `OsmfinderGeometryResult`
167
+
168
+ Returned by `find_smallest_containing_extracts()` and `find()` when called with a geometry.
169
+
170
+ | Attribute | Type | Description |
171
+ |---|---|---|
172
+ | `extracts` | `list[OpenStreetMapExtract]` | Selected extracts covering the geometry |
173
+ | `input_geometry` | `BaseGeometry` | The original input geometry |
174
+ | `covered_geometry` | `BaseGeometry` | Union of extract geometries intersecting the input |
175
+ | `uncovered_geometry` | `BaseGeometry` | Parts of the input not covered by any extract |
176
+ | `steps` | `list[GeometryCoveringStep]` | Record of each extract considered during covering |
177
+ | `iou_threshold` | `float` | IoU threshold used for selection |
178
+ | `sources_used` | `list[OsmExtractSource]` | Sources that were searched |
179
+
180
+ ### `OsmfinderDownloadResult`
181
+
182
+ Returned by `download_extract_by_query()`, `find_and_download_extracts_pbf_files()`, and `download()`.
183
+
184
+ | Attribute | Type | Description |
185
+ |---|---|---|
186
+ | `find_result` | `OsmfinderQueryResult \| OsmfinderGeometryResult` | The underlying find result |
187
+ | `download_paths` | `list[Path]` | Paths to downloaded `.osm.pbf` files |
188
+ | `unavailable_extracts` | `list[OpenStreetMapExtract]` | Extracts that could not be downloaded |
189
+
190
+ ### `GeometryCoveringStep`
191
+
192
+ Record of a single extract considered during geometry covering.
193
+
194
+ | Attribute | Type | Description |
195
+ |---|---|---|
196
+ | `extract` | `OpenStreetMapExtract` | The extract considered |
197
+ | `iou` | `float` | Intersection over Union with the remaining geometry |
198
+ | `selected` | `bool` | Whether the extract was selected |
199
+ | `reason` | `str` | Selection reason (`"selected"` or `"low_iou"`) |
200
+ | `geometry_to_cover` | `BaseGeometry` | Remaining geometry before this step |
201
+ | `intersection_geometry` | `BaseGeometry` | Intersection of the extract with the remaining geometry |
202
+
203
+ ### Example `repr` output
204
+
205
+ All result objects use a verbose multi-line `repr` for easier debugging:
206
+
207
+ ```python
208
+ >>> result = osmfinder.find("Monaco")
209
+ >>> print(result)
210
+ OsmfinderQueryResult
211
+ query: Monaco
212
+ extract: Movisda-admin_MC — Monaco
213
+ matched extracts: Movisda-admin_MC, Geofabrik_monaco, BBBike_Monaco, OSM_fr_monaco, geofabrik_andorra, +3 more
214
+ sources used: Geofabrik, BBBike, OSM_fr, Movisda-admin, GEO2Day
215
+
216
+ >>> geometry = box(7.40, 43.71, 7.44, 43.75)
217
+ >>> result = osmfinder.find(geometry, source="Geofabrik")
218
+ >>> print(result)
219
+ OsmfinderGeometryResult
220
+ extracts:
221
+ Geofabrik_europe_monaco — Monaco
222
+ coverage: 100.0%
223
+ iou threshold: 0.01
224
+ steps:
225
+ Geofabrik_europe_monaco — Monaco
226
+ iou: 1.0000, selected, first_extract
227
+ sources used: Geofabrik
228
+
229
+ >>> dl = osmfinder.download("Monaco", download_directory="files")
230
+ >>> print(dl)
231
+ OsmfinderDownloadResult
232
+ downloaded:
233
+ files/movisda-admin_monaco.osm.pbf
234
+ unavailable:
235
+ none
236
+ find result:
237
+ OsmfinderQueryResult
238
+ query: Monaco
239
+ extract: Movisda-admin_MC — Monaco
240
+ matched extracts: Movisda-admin_MC, Geofabrik_monaco, BBBike_Monaco, OSM_fr_monaco, geofabrik_andorra, +3 more
241
+ sources used: Geofabrik, BBBike, OSM_fr, Movisda-admin, GEO2Day
242
+ ```
243
+
244
+ ## Public API
245
+
246
+ | Function | Search by | Returns |
247
+ |---|---|---|
248
+ | `get_extract_by_query` | name / id | `OsmfinderQueryResult` |
249
+ | `get_available_extracts` | — | `list[OpenStreetMapExtract]` |
250
+ | `download_extract_by_query` | name / id | `OsmfinderDownloadResult` |
251
+ | `find_smallest_containing_extracts` | geometry | `OsmfinderGeometryResult` |
252
+ | `find_and_download_extracts_pbf_files` | geometry | `OsmfinderDownloadResult` |
253
+ | `download_extracts_pbf_files` | list of extracts | `list[Path]` |
254
+ | `display_available_extracts` | — | prints a tree |
255
+ | `clear_osm_index_cache` | — | clears the local index cache |
256
+
257
+ > **Note:** `find()` and `download()` are dual-purpose helpers. When called with a **string query** they
258
+ > return an `OsmfinderQueryResult` / `OsmfinderDownloadResult`. When called with a **geometry** they
259
+ > return an `OsmfinderGeometryResult` / `OsmfinderDownloadResult`. Use the explicit
260
+ > `get_extract_by_query` / `download_extract_by_query` if you want a single object without the list wrapper.
261
+
262
+ ## Index cache
263
+
264
+ Provider indexes are cached locally (in the platform cache dir) as GeoParquet (`*.parquet`).
265
+ Precalculated indexes are downloaded from this repo's `precalculated_indexes/` folder on first use,
266
+ so most sources don't need to be rebuilt from scratch. Use `clear_osm_index_cache()` to force a
267
+ refresh.
268
+
269
+ ## License
270
+
271
+ MIT
@@ -0,0 +1,232 @@
1
+
2
+
3
+ # OSM Finder
4
+
5
+ Find and download publicly available OpenStreetMap `*.osm.pbf` extracts by **name**, **id** or
6
+ **geometry**.
7
+
8
+ `osmfinder` wraps several public extract providers behind a single API:
9
+ [Geofabrik](https://download.geofabrik.de/), [BBBike](https://download.bbbike.org/osm/bbbike/),
10
+ [OpenStreetMap.fr](https://download.openstreetmap.fr/), [Movisda](https://osm.download.movisda.io/)
11
+ and [GEO2day](https://geo2day.com/). It can look up an extract by a text query, or find the
12
+ smallest set of extracts covering an arbitrary geometry, and download the matching `*.osm.pbf`
13
+ files.
14
+
15
+ <p align="center">
16
+ <img width="300" src="https://raw.githubusercontent.com/raczeq/osmfinder/main/docs/assets/logos/osmfinder_logo.png"><br/>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <img alt="GitHub" src="https://img.shields.io/github/license/raczeq/osmfinder?logo=mit&logoColor=%23fff">
21
+ <img src="https://img.shields.io/github/checks-status/raczeq/osmfinder/main?logo=GitHubActions&logoColor=%23fff" alt="Checks">
22
+ <a href="https://github.com/raczeq/osmfinder/actions/workflows/ci-prod.yml" target="_blank"><img alt="GitHub Workflow Status - PROD" src="https://img.shields.io/github/actions/workflow/status/raczeq/osmfinder/ci-prod.yml?label=build-prod&logo=GitHubActions&logoColor=%23fff"></a>
23
+ <a href="https://results.pre-commit.ci/latest/github/raczeq/osmfinder/main" target="_blank"><img src="https://results.pre-commit.ci/badge/github/raczeq/osmfinder/main.svg" alt="pre-commit.ci status"></a>
24
+ <a href="https://www.codefactor.io/repository/github/raczeq/osmfinder"><img alt="CodeFactor Grade" src="https://img.shields.io/codefactor/grade/github/raczeq/osmfinder?logo=codefactor&logoColor=%23fff"></a>
25
+ <a href="https://app.codecov.io/gh/raczeq/osmfinder/tree/main"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/raczeq/osmfinder?logo=codecov&token=PRS4E02ZX0&logoColor=%23fff"></a>
26
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img src="https://img.shields.io/pypi/v/osmfinder?color=%2334D058&label=pypi%20package&logo=pypi&logoColor=%23fff" alt="Package version"></a>
27
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img src="https://img.shields.io/pypi/pyversions/osmfinder.svg?color=%2334D058&logo=python&logoColor=%23fff" alt="Supported Python versions"></a>
28
+ <a href="https://pypi.org/project/osmfinder" target="_blank"><img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/osmfinder"></a>
29
+ </p>
30
+
31
+ > **Logo attribution:** The osmfinder logo uses icons from the [Lucide](https://lucide.dev/) icon set —
32
+ > specifically the **earth** and **square-dashed** icons.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install osmfinder
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ```python
43
+ import osmfinder
44
+ from shapely.geometry import box
45
+
46
+ # --- by name / id ---
47
+ # Returns an OsmfinderQueryResult with .extracts list and .extract accessor.
48
+ result = osmfinder.find("Monaco")
49
+ print(result.extracts[0].id) # 'Movisda-admin_MC'
50
+ print(result.extracts[0].file_name) # 'movisda-admin_monaco'
51
+ print(result.extract.id) # convenience accessor for single-match queries
52
+
53
+ # Download by name - returns OsmfinderDownloadResult with .download_paths.
54
+ dl = osmfinder.download("Monaco", download_directory="files")
55
+ print(dl.download_paths) # [Path('files/movisda-admin_monaco.osm.pbf')]
56
+ print(dl.find_result.extract.id) # 'Movisda-admin_MC'
57
+
58
+ # --- by geometry ---
59
+ geometry = box(2.11, 48.77, 2.54, 48.98)
60
+ result = osmfinder.find(geometry)
61
+ print(result) # multi-line OsmfinderGeometryResult with extracts, coverage, steps
62
+ print(len(result.extracts)) # number of extracts covering the geometry
63
+ print(result.extracts[0].id) # 'BBBike_Paris'
64
+
65
+ # Download by geometry
66
+ dl = osmfinder.download(geometry, source="Geofabrik", download_directory="files")
67
+ print(len(dl.download_paths)) # number of downloaded files
68
+ print(dl.download_paths[0].name) # 'geofabrik_europe_monaco.osm.pbf'
69
+
70
+ # --- by point ---
71
+ extracts = osmfinder.find_extracts_covering_point((-0.1276, 51.5074), source="Geofabrik")
72
+ print(len(extracts)) # number of extracts covering central London
73
+ print(extracts[0].id) # 'Geofabrik_greater-london'
74
+
75
+ # --- force single extract ---
76
+ geometry = box(9.4, 47.2, 9.8, 47.6)
77
+ result = osmfinder.find_smallest_containing_extracts(
78
+ geometry, force_single_result=False # default behaviour
79
+ )
80
+ print(len(result.extracts)) # 4
81
+ print(result.extracts[0].id) # 'GEO2Day_europe_austria_vorarlberg'
82
+ print(result.extracts[1].id) # 'BBBike_Konstanz'
83
+ print(result.extracts[2].id) # 'GEO2Day_europe_switzerland_saint_gallen'
84
+ print(result.extracts[3].id) # 'Movisda-admin_LI'
85
+
86
+ result = osmfinder.find_smallest_containing_extracts(
87
+ geometry, force_single_result=True
88
+ )
89
+ print(len(result.extracts)) # 1
90
+ print(result.extracts[0].id) # 'Movisda-grid_N47W009'
91
+
92
+ # --- explore what's available ---
93
+ osmfinder.display_available_extracts(source="Geofabrik") # source is optional
94
+
95
+ # Get all extracts as a list for programmatic use
96
+ extracts = osmfinder.get_available_extracts(source="Geofabrik") # source is optional
97
+ for extract in extracts:
98
+ print(extract.id, extract.file_name)
99
+ ```
100
+
101
+ ### Sources
102
+
103
+ The `source` argument accepts a single value, an iterable, or a comma-separated string. Available
104
+ values: `any`, `Geofabrik`, `BBBike`, `osmfr`, `GEO2Day`, `Movisda-admin`, `Movisda-grid`.
105
+
106
+ ```python
107
+ osmfinder.get_extract_by_query("Berlin", ["Geofabrik", "BBBike"])
108
+ osmfinder.get_extract_by_query("Berlin", "geofabrik,bbbike")
109
+ ```
110
+
111
+ ## Result classes
112
+
113
+ All find and download operations return typed result objects instead of raw lists.
114
+
115
+ ### `OsmfinderQueryResult`
116
+
117
+ Returned by `get_extract_by_query()` and `find()` when called with a string query.
118
+
119
+ | Attribute | Type | Description |
120
+ |---|---|---|
121
+ | `extracts` | `list[OpenStreetMapExtract]` | All matched extracts |
122
+ | `extract` | `OpenStreetMapExtract` | Convenience accessor for the single matched extract |
123
+ | `matched_extracts` | `list[OpenStreetMapExtract]` | All extracts matched by the query before selection (may contain more than `extracts` when `select_first_match=True`) |
124
+ | `query` | `str` | The original query string |
125
+ | `sources_used` | `list[OsmExtractSource]` | Sources that were searched |
126
+
127
+ ### `OsmfinderGeometryResult`
128
+
129
+ Returned by `find_smallest_containing_extracts()` and `find()` when called with a geometry.
130
+
131
+ | Attribute | Type | Description |
132
+ |---|---|---|
133
+ | `extracts` | `list[OpenStreetMapExtract]` | Selected extracts covering the geometry |
134
+ | `input_geometry` | `BaseGeometry` | The original input geometry |
135
+ | `covered_geometry` | `BaseGeometry` | Union of extract geometries intersecting the input |
136
+ | `uncovered_geometry` | `BaseGeometry` | Parts of the input not covered by any extract |
137
+ | `steps` | `list[GeometryCoveringStep]` | Record of each extract considered during covering |
138
+ | `iou_threshold` | `float` | IoU threshold used for selection |
139
+ | `sources_used` | `list[OsmExtractSource]` | Sources that were searched |
140
+
141
+ ### `OsmfinderDownloadResult`
142
+
143
+ Returned by `download_extract_by_query()`, `find_and_download_extracts_pbf_files()`, and `download()`.
144
+
145
+ | Attribute | Type | Description |
146
+ |---|---|---|
147
+ | `find_result` | `OsmfinderQueryResult \| OsmfinderGeometryResult` | The underlying find result |
148
+ | `download_paths` | `list[Path]` | Paths to downloaded `.osm.pbf` files |
149
+ | `unavailable_extracts` | `list[OpenStreetMapExtract]` | Extracts that could not be downloaded |
150
+
151
+ ### `GeometryCoveringStep`
152
+
153
+ Record of a single extract considered during geometry covering.
154
+
155
+ | Attribute | Type | Description |
156
+ |---|---|---|
157
+ | `extract` | `OpenStreetMapExtract` | The extract considered |
158
+ | `iou` | `float` | Intersection over Union with the remaining geometry |
159
+ | `selected` | `bool` | Whether the extract was selected |
160
+ | `reason` | `str` | Selection reason (`"selected"` or `"low_iou"`) |
161
+ | `geometry_to_cover` | `BaseGeometry` | Remaining geometry before this step |
162
+ | `intersection_geometry` | `BaseGeometry` | Intersection of the extract with the remaining geometry |
163
+
164
+ ### Example `repr` output
165
+
166
+ All result objects use a verbose multi-line `repr` for easier debugging:
167
+
168
+ ```python
169
+ >>> result = osmfinder.find("Monaco")
170
+ >>> print(result)
171
+ OsmfinderQueryResult
172
+ query: Monaco
173
+ extract: Movisda-admin_MC — Monaco
174
+ matched extracts: Movisda-admin_MC, Geofabrik_monaco, BBBike_Monaco, OSM_fr_monaco, geofabrik_andorra, +3 more
175
+ sources used: Geofabrik, BBBike, OSM_fr, Movisda-admin, GEO2Day
176
+
177
+ >>> geometry = box(7.40, 43.71, 7.44, 43.75)
178
+ >>> result = osmfinder.find(geometry, source="Geofabrik")
179
+ >>> print(result)
180
+ OsmfinderGeometryResult
181
+ extracts:
182
+ Geofabrik_europe_monaco — Monaco
183
+ coverage: 100.0%
184
+ iou threshold: 0.01
185
+ steps:
186
+ Geofabrik_europe_monaco — Monaco
187
+ iou: 1.0000, selected, first_extract
188
+ sources used: Geofabrik
189
+
190
+ >>> dl = osmfinder.download("Monaco", download_directory="files")
191
+ >>> print(dl)
192
+ OsmfinderDownloadResult
193
+ downloaded:
194
+ files/movisda-admin_monaco.osm.pbf
195
+ unavailable:
196
+ none
197
+ find result:
198
+ OsmfinderQueryResult
199
+ query: Monaco
200
+ extract: Movisda-admin_MC — Monaco
201
+ matched extracts: Movisda-admin_MC, Geofabrik_monaco, BBBike_Monaco, OSM_fr_monaco, geofabrik_andorra, +3 more
202
+ sources used: Geofabrik, BBBike, OSM_fr, Movisda-admin, GEO2Day
203
+ ```
204
+
205
+ ## Public API
206
+
207
+ | Function | Search by | Returns |
208
+ |---|---|---|
209
+ | `get_extract_by_query` | name / id | `OsmfinderQueryResult` |
210
+ | `get_available_extracts` | — | `list[OpenStreetMapExtract]` |
211
+ | `download_extract_by_query` | name / id | `OsmfinderDownloadResult` |
212
+ | `find_smallest_containing_extracts` | geometry | `OsmfinderGeometryResult` |
213
+ | `find_and_download_extracts_pbf_files` | geometry | `OsmfinderDownloadResult` |
214
+ | `download_extracts_pbf_files` | list of extracts | `list[Path]` |
215
+ | `display_available_extracts` | — | prints a tree |
216
+ | `clear_osm_index_cache` | — | clears the local index cache |
217
+
218
+ > **Note:** `find()` and `download()` are dual-purpose helpers. When called with a **string query** they
219
+ > return an `OsmfinderQueryResult` / `OsmfinderDownloadResult`. When called with a **geometry** they
220
+ > return an `OsmfinderGeometryResult` / `OsmfinderDownloadResult`. Use the explicit
221
+ > `get_extract_by_query` / `download_extract_by_query` if you want a single object without the list wrapper.
222
+
223
+ ## Index cache
224
+
225
+ Provider indexes are cached locally (in the platform cache dir) as GeoParquet (`*.parquet`).
226
+ Precalculated indexes are downloaded from this repo's `precalculated_indexes/` folder on first use,
227
+ so most sources don't need to be rebuilt from scratch. Use `clear_osm_index_cache()` to force a
228
+ refresh.
229
+
230
+ ## License
231
+
232
+ MIT
@@ -0,0 +1,54 @@
1
+ """
2
+ osmfinder.
3
+
4
+ Find and download publicly available OpenStreetMap `*.osm.pbf` extracts by name, id or geometry.
5
+
6
+ The library wraps several public extract providers (Geofabrik, BBBike, OpenStreetMap.fr, Movisda,
7
+ GEO2day) behind a single API. It can look up an extract by a text query, or find the smallest set of
8
+ extracts covering an arbitrary geometry, and download the matching `*.osm.pbf` files.
9
+ """
10
+
11
+ from osmfinder._results import (
12
+ GeometryCoveringStep,
13
+ OsmfinderDownloadResult,
14
+ OsmfinderGeometryResult,
15
+ OsmfinderQueryResult,
16
+ )
17
+ from osmfinder._typing import OpenStreetMapExtract, OsmExtractSource
18
+ from osmfinder.extract import clear_osm_index_cache
19
+ from osmfinder.finder import (
20
+ OsmExtractSourceLike,
21
+ display_available_extracts,
22
+ download,
23
+ download_extract_by_query,
24
+ download_extracts_pbf_files,
25
+ find,
26
+ find_and_download_extracts_pbf_files,
27
+ find_extracts_covering_point,
28
+ find_smallest_containing_extracts,
29
+ get_available_extracts,
30
+ get_extract_by_query,
31
+ )
32
+
33
+ __version__ = "1.0.0"
34
+
35
+ __all__ = [
36
+ "GeometryCoveringStep",
37
+ "OpenStreetMapExtract",
38
+ "OsmExtractSource",
39
+ "OsmExtractSourceLike",
40
+ "OsmfinderDownloadResult",
41
+ "OsmfinderGeometryResult",
42
+ "OsmfinderQueryResult",
43
+ "clear_osm_index_cache",
44
+ "display_available_extracts",
45
+ "download",
46
+ "download_extract_by_query",
47
+ "download_extracts_pbf_files",
48
+ "find",
49
+ "find_and_download_extracts_pbf_files",
50
+ "find_extracts_covering_point",
51
+ "find_smallest_containing_extracts",
52
+ "get_available_extracts",
53
+ "get_extract_by_query",
54
+ ]
@@ -0,0 +1,15 @@
1
+ """
2
+ Small compatibility helpers.
3
+
4
+ These were previously imported from ``rq_geo_toolkit``. They are vendored here (a few lines each)
5
+ so that ``osmfinder`` stays lightweight and doesn't pull the whole toolkit as a dependency.
6
+ """
7
+
8
+ import os
9
+
10
+ # Force terminal-style (non-jupyter, non-interactive) rich output when set.
11
+ FORCE_TERMINAL = os.getenv("FORCE_TERMINAL_MODE", "false").lower() == "true"
12
+
13
+ __all__ = [
14
+ "FORCE_TERMINAL",
15
+ ]
@@ -0,0 +1,14 @@
1
+ """Constants used across osmfinder."""
2
+
3
+ WGS84_CRS = "EPSG:4326"
4
+
5
+ OSM_EXTRACTS_REQUEST_TIMEOUT_SECONDS = 30
6
+
7
+ # Sent as the User-Agent header on every request to the extract providers.
8
+ USER_AGENT = "osmfinder Python package (https://github.com/RaczeQ/osmfinder)"
9
+
10
+ __all__ = [
11
+ "OSM_EXTRACTS_REQUEST_TIMEOUT_SECONDS",
12
+ "USER_AGENT",
13
+ "WGS84_CRS",
14
+ ]