Skip to content
This repository was archived by the owner on Jan 8, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ venv/
.venv/
.tox
.ruff_cache/
docs/Overpass API_Overpass QL - OpenStreetMap Wiki.pdf
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ you can pass in another instance:
api = overpass.API(endpoint="https://overpass.myserver/interpreter")
```

You can also provide multiple endpoints and opt into fallback or rotation:

```python
api = overpass.API(
endpoints=[
"https://overpass-api.de/api/interpreter",
"https://maps.mail.ru/osm/tools/overpass/api/interpreter",
"https://overpass.private.coffee/api/interpreter",
"https://overpass.osm.jp/api/interpreter",
],
fallback=True, # try next endpoint on transient failures
)
```

If `fallback=True` is set without explicit `endpoints`, the library will use the public instances above.

#### `timeout`

The default timeout is 25 seconds, but you can set it to whatever you
Expand All @@ -60,6 +76,23 @@ api = overpass.API(timeout=600)

Setting this to `True` will get you debug output.

#### `retries`

You can opt into retries for transient failures (429/504/timeouts). Retries wait at least 10 seconds:

```python
api = overpass.API(max_retries=1, min_retry_delay=10)
```

#### `bbox guard`

When building queries, large bounding boxes can overload public instances. By default, bboxes over
1000 km² are rejected. Override with:

```python
api = overpass.API(allow_large_bbox=True)
```

### Getting data from Overpass: `get()`

Most users will only ever need to use the `get()` method. There are some convenience query methods for common queries as well, see below.
Expand All @@ -68,6 +101,14 @@ Most users will only ever need to use the `get()` method. There are some conveni
response = api.get('node["name"="Salt Lake City"]')
```

You can opt into Pydantic models using `model=True`:

```python
model = api.get('node["name"="Salt Lake City"]', model=True)
print(model.to_geojson())
geo_interface = model.__geo_interface__
```

`response` will be a dictionary representing the
JSON output you would get [from the Overpass API
directly](https://overpass-api.de/output_formats.html#json).
Expand Down Expand Up @@ -136,6 +177,22 @@ We will construct a valid Overpass QL query from the parameters you set by defau
You can query the data as it was on a given date. You can give either a standard ISO date alone (YYYY-MM-DD) or a full overpass date and time (YYYY-MM-DDTHH:MM:SSZ, i.e. 2020-04-28T00:00:00Z).
You can also directly pass a `date` or `datetime` object from the `datetime` library.

### Async usage

```python
import asyncio
import overpass


async def main():
async with overpass.AsyncAPI() as api:
data = await api.get('node["name"="Salt Lake City"]', model=True)
print(data.to_geojson())


asyncio.run(main())
```

### Pre-cooked Queries: `MapQuery`, `WayQuery`

In addition to just sending your query and parse the result, `overpass`
Expand Down
39 changes: 39 additions & 0 deletions docs/modernization-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 0.8 Modernization Plan

## Goals
- Keep sync `overpass.API` stable while adding a parallel async client.
- Introduce opt-in Pydantic models (v2) for responses and helpers for GeoJSON output.
- Improve test coverage to avoid regressions across all response formats and errors.

## Non-goals (for 0.8 alpha)
- Breaking changes to default return types.
- Full rewrite of the API surface.

## Design overview
- Split transport from parsing to make sync/async share code.
- Add a typed response layer:
- Pydantic models for Overpass JSON and GeoJSON.
- Dataclasses for configuration and small internal structures.
- Provide helpers on models (`to_geojson()`, `__geo_interface__`) while keeping
existing dict return behavior by default.

## Implemented (current branch)
- Shared transport abstraction for sync/async HTTP.
- `AsyncAPI` alongside `API` (httpx-based).
- Opt-in Pydantic models for Overpass JSON + GeoJSON, plus CSV/XML wrappers.
- `to_geojson()` and `__geo_interface__` on GeoJSON models (Shapely round-trip test).
- Extended tests for response formats, error mapping, and async parity.
- Hardened JSON parsing with clearer errors when content is invalid.
- `Utils.to_overpass_id` now requires a source type (`way` or `relation`).

## Testing strategy
- Unit tests for:
- Query construction (`MapQuery`, `WayQuery`, `build`, `verbosity`, `date`).
- Response parsing for CSV/XML/JSON/GeoJSON.
- Error mapping for HTTP status codes (400/429/504/other).
- Overpass status endpoint parsing.
- Async parity tests for the same responses using mocked HTTP.
- Integration tests remain opt-in (`RUN_NETWORK_TESTS=1`).

## Open questions
- GeoJSON hardening for relations/multipolygons/routes/boundaries (#181).
13 changes: 13 additions & 0 deletions docs/modernization-tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 0.8 Modernization Tasks

## Plan
- [x] Add transport abstraction shared by sync/async clients
- [x] Introduce `AsyncAPI` with httpx
- [x] Add Pydantic response models (opt-in)
- [x] Add GeoJSON helpers on models (`to_geojson`, `__geo_interface__`)
- [x] Expand test coverage for all response formats and error handling
- [x] Update docs for async usage and model opt-in

## Tracking
- [ ] Close #181 GeoJSON hardening (relations/multipolygons/routes/boundaries)
- [ ] Address open bugs: #172, #176
2 changes: 2 additions & 0 deletions overpass/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
__license__ = "Apache 2.0"

from .api import API
from .async_api import AsyncAPI
from .models import GeoJSONFeatureCollection, OverpassResponse, CsvResponse, XmlResponse
from .queries import MapQuery, WayQuery
from .errors import (
OverpassError,
Expand Down
Loading
Loading