Skip to content

Commit 98b6f63

Browse files
committed
response format flexibility
1 parent 37c3b15 commit 98b6f63

File tree

5 files changed

+32
-42
lines changed

5 files changed

+32
-42
lines changed

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ file.
4848
Options:
4949
--timeout INTEGER Timeout in seconds
5050
--endpoint TEXT URL of your prefered API
51-
--format TEXT Format to save the data. Options are 'geojson' and 'osm'. Default format is geojson.
51+
--format TEXT Format to save the data. Options are 'geojson', 'json', 'xml'. Default format is geojson.
5252
--help Show this message and exit.
5353

5454
For example:
@@ -63,7 +63,7 @@ Or to get the result as an OSM XML file:
6363

6464
.. code:: bash
6565
66-
overpass --timeout 50 --format osm 'node(area:3602758138)[amenity=cafe]' brasilia-cafe.osm
66+
overpass --timeout 50 --format xml 'node(area:3602758138)[amenity=cafe]' brasilia-cafe.osm
6767
6868
Python Library
6969
-------------
@@ -87,13 +87,13 @@ could do this for example:
8787
>>> print [(feature['tags']['name'], feature['id']) for feature in response['elements']]
8888
[(u'Salt Lake City', 150935219), (u'Salt Lake City', 585370637), (u'Salt Lake City', 1615721573)]
8989
90-
If you want to get the data on the OSM XML format, pass the option 'asGeoJSON=False':
90+
You can specify the format of the response. By default, you will get GeoJSON using the `responseformat` parameter. Alternatives are plain JSON (`json`) and OSM XML (`xml`), as ouput directly by the Overpass API.
9191

9292
.. code:: python
9393
9494
>>> import overpass
9595
>>> api = overpass.API()
96-
>>> response = api.Get('node["name"="Salt Lake City"]', asGeoJSON=False)
96+
>>> response = api.Get('node["name"="Salt Lake City"]', responseformat="xml")
9797
9898
Parameters
9999
~~~~~~~~~~

overpass/api.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
class API(object):
99
"""A simple Python wrapper for the OpenStreetMap Overpass API"""
1010

11+
SUPPORTED_FORMATS = ["geojson", "json", "xml"]
12+
1113
# defaults for the API class
1214
_timeout = 25 # seconds
1315
_endpoint = "http://overpass-api.de/api/interpreter"
1416
_debug = False
1517

16-
_XML_QUERY_TEMPLATE = "[out:xml]{query}out body;"
17-
_JSON_QUERY_TEMPLATE = "[out:json]{query}out body;"
18+
_QUERY_TEMPLATE = "[out:{out}];{query}out body;"
1819
_GEOJSON_QUERY_TEMPLATE = "[out:json];{query}out body geom;"
1920

2021
def __init__(self, *args, **kwargs):
@@ -34,19 +35,18 @@ def __init__(self, *args, **kwargs):
3435
requests_log.setLevel(logging.DEBUG)
3536
requests_log.propagate = True
3637

37-
def Get(self, query, asGeoJSON=False):
38+
def Get(self, query, responseformat="geojson"):
3839
"""Pass in an Overpass query in Overpass QL"""
3940

4041
# Construct full Overpass query
41-
full_query = self._ConstructQLQuery(query, asGeoJSON=asGeoJSON)
42+
full_query = self._ConstructQLQuery(query, responseformat=responseformat)
4243

43-
print("full query: ", full_query)
44-
4544
# Get the response from Overpass
4645
raw_response = self._GetFromOverpass(full_query)
4746

48-
print("raw response: ", raw_response)
49-
47+
if responseformat == "xml":
48+
return raw_response
49+
5050
response = json.loads(raw_response)
5151

5252
# Check for valid answer from Overpass. A valid answer contains an 'elements' key at the root level.
@@ -58,30 +58,27 @@ def Get(self, query, asGeoJSON=False):
5858
if overpass_remark and overpass_remark.startswith('runtime error'):
5959
raise ServerRuntimeError(overpass_remark)
6060

61-
if not asGeoJSON:
61+
if responseformat is not "geojson":
6262
return response
6363

6464
# construct geojson
6565
return self._asGeoJSON(response["elements"])
6666

67-
# construct geojson
68-
return self._asGeoJSON(response["elements"])
69-
7067
def Search(self, feature_type, regex=False):
7168
"""Search for something."""
7269
raise NotImplementedError()
7370

74-
def _ConstructQLQuery(self, userquery, asGeoJSON=False):
71+
def _ConstructQLQuery(self, userquery, responseformat):
7572
raw_query = str(userquery)
7673
if not raw_query.endswith(";"):
7774
raw_query += ";"
7875

79-
if asGeoJSON:
76+
if responseformat == "geojson":
8077
template = self._GEOJSON_QUERY_TEMPLATE
78+
complete_query = template.format(query=raw_query)
8179
else:
82-
template = self._JSON_QUERY_TEMPLATE
83-
84-
complete_query = template.format(query=raw_query)
80+
template = self._QUERY_TEMPLATE
81+
complete_query = template.format(query=raw_query, out=responseformat)
8582

8683
if self.debug:
8784
print(complete_query)
@@ -91,8 +88,6 @@ def _GetFromOverpass(self, query):
9188
"""This sends the API request to the Overpass instance and
9289
returns the raw result, or an error."""
9390

94-
print("query: ", query)
95-
9691
payload = {"data": query}
9792

9893
try:
@@ -125,7 +120,6 @@ def _GetFromOverpass(self, query):
125120
return r.text
126121

127122
def _asGeoJSON(self, elements):
128-
#print 'DEB _asGeoJson elements:', elements
129123

130124
features = []
131125
for elem in elements:

overpass/cli.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ def cli(timeout, endpoint, format, query, output_file):
1818
"""Run query and save the result in output_file"""
1919

2020
api = overpass.API(timeout=timeout, endpoint=endpoint)
21-
if format == 'geojson':
22-
result = api.Get(query, asGeoJSON=True)
23-
with open(output_file, 'w') as f:
21+
22+
if format not in api.SUPPORTED_FORMATS:
23+
print("format {} not supported. Supported formats: {}".format(
24+
format,
25+
api.SUPPORTED_FORMATS.join(", ")))
26+
result = api.Get(query, responseformat=format)
27+
with open(output_file, 'w') as f:
28+
if responseformat=="geojson":
2429
geojson.dump(result, f, indent=2, sort_keys=True)
25-
print('File saved at %s.' % output_file)
26-
elif format == 'osm':
27-
result = api.Get(query, asGeoJSON=False)
28-
with open(output_file, 'wb') as f:
30+
else:
2931
f.write(result.encode('utf-8'))
30-
f.close()
31-
print('File saved at %s.' % output_file)
32-
else:
33-
print('The format you typed is not supported.')
32+
f.close()
33+
print('File saved at %s.' % output_file)

tests/test_api.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@ def test_geojson():
1111
api = overpass.API()
1212

1313
osm_geo = api.Get(
14-
overpass.MapQuery(37.86517, -122.31851, 37.86687, -122.31635),
15-
asGeoJSON=True
16-
)
14+
overpass.MapQuery(37.86517, -122.31851, 37.86687, -122.31635))
1715
assert len(osm_geo['features']) > 1
1816

19-
osm_geo = api.Get('node(area:3602758138)[amenity=cafe]',
20-
asGeoJSON=True
21-
)
17+
osm_geo = api.Get('node(area:3602758138)[amenity=cafe]')
2218
assert len(osm_geo['features']) > 1

tests/test_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_cli_xml():
2323
with runner.isolated_filesystem():
2424
result = runner.invoke(cli, [
2525
'--timeout', 40,
26-
'--endpoint', 'http://overpass.osm.rambler.ru/cgi/interpreter',
26+
'--endpoint', 'http://overpass-api.de/api/interpreter',
2727
'--format', 'osm',
2828
'node(area:3600362504)[amenity=cafe]', 'out.osm'
2929
])

0 commit comments

Comments
 (0)