1
1
import requests
2
2
import json
3
+ import csv
3
4
import geojson
4
5
import logging
5
-
6
+ from io import StringIO
6
7
from .errors import (OverpassSyntaxError , TimeoutError , MultipleRequestsError ,
7
8
ServerLoadError , UnknownOverpassError , ServerRuntimeError )
8
9
9
10
10
11
class API (object ):
11
12
"""A simple Python wrapper for the OpenStreetMap Overpass API."""
12
13
13
- SUPPORTED_FORMATS = ["geojson" , "json" , "xml" ]
14
+ SUPPORTED_FORMATS = ["geojson" , "json" , "xml" , "csv" ]
14
15
15
16
# defaults for the API class
16
17
_timeout = 25 # second
@@ -43,30 +44,40 @@ def __init__(self, *args, **kwargs):
43
44
requests_log .setLevel (logging .DEBUG )
44
45
requests_log .propagate = True
45
46
46
- def Get (self ,
47
+ def get (self ,
47
48
query ,
48
49
responseformat = "geojson" ,
49
50
verbosity = "body" ,
50
51
build = True ):
51
52
"""Pass in an Overpass query in Overpass QL."""
52
53
# Construct full Overpass query
53
54
if build :
54
- full_query = self ._ConstructQLQuery (query ,
55
- responseformat = responseformat ,
56
- verbosity = verbosity )
55
+ full_query = self ._construct_ql_query (
56
+ query ,
57
+ responseformat = responseformat ,
58
+ verbosity = verbosity )
57
59
else :
58
60
full_query = query
59
61
60
62
if self .debug :
61
63
logging .getLogger ().info (query )
62
64
63
65
# Get the response from Overpass
64
- raw_response = self ._GetFromOverpass (full_query )
66
+ r = self ._get_from_overpass (full_query )
67
+ content_type = r .headers .get ('content-type' )
65
68
66
- if responseformat == "xml" or responseformat .startswith ("csv" ):
67
- return raw_response
69
+ if self .debug :
70
+ print (content_type )
71
+ if content_type == "text/csv" :
72
+ result = []
73
+ reader = csv .reader (StringIO (r .text ), delimiter = '\t ' )
74
+ for row in reader :
75
+ result .append (row )
76
+ return result
77
+ elif content_type == "text/xml" or content_type == "application/xml" :
78
+ return r .text
68
79
69
- response = json .loads (raw_response )
80
+ response = json .loads (r )
70
81
71
82
# Check for valid answer from Overpass.
72
83
# A valid answer contains an 'elements' key at the root level.
@@ -83,13 +94,17 @@ def Get(self,
83
94
return response
84
95
85
96
# construct geojson
86
- return self ._asGeoJSON (response ["elements" ])
97
+ return self ._as_geojson (response ["elements" ])
87
98
88
- def Search (self , feature_type , regex = False ):
99
+ def search (self , feature_type , regex = False ):
89
100
"""Search for something."""
90
101
raise NotImplementedError ()
91
102
92
- def _ConstructQLQuery (self , userquery , responseformat , verbosity ):
103
+ # deprecation of upper case functions
104
+ Get = get
105
+ Search = search
106
+
107
+ def _construct_ql_query (self , userquery , responseformat , verbosity ):
93
108
raw_query = str (userquery )
94
109
if not raw_query .endswith (";" ):
95
110
raw_query += ";"
@@ -110,10 +125,7 @@ def _ConstructQLQuery(self, userquery, responseformat, verbosity):
110
125
print (complete_query )
111
126
return complete_query
112
127
113
- def _GetFromOverpass (self , query ):
114
- """This sends the API request to the Overpass instance and
115
- returns the raw result, or an error."""
116
-
128
+ def _get_from_overpass (self , query ):
117
129
payload = {"data" : query }
118
130
119
131
try :
@@ -141,20 +153,22 @@ def _GetFromOverpass(self, query):
141
153
code = self ._status ))
142
154
else :
143
155
r .encoding = 'utf-8'
144
- return r . text
156
+ return r
145
157
146
- def _asGeoJSON (self , elements ):
158
+ def _as_geojson (self , elements ):
147
159
148
160
features = []
149
161
for elem in elements :
150
- elem_type = elem [ "type" ]
151
- if elem_type == "node" :
152
- geometry = geojson .Point ((elem [ "lon" ] , elem [ "lat" ] ))
153
- elif elem_type == "way" :
162
+ elem_type = elem . get ( "type" )
163
+ if elem_type and elem_type == "node" :
164
+ geometry = geojson .Point ((elem . get ( "lon" ) , elem . get ( "lat" ) ))
165
+ elif elem_type and elem_type == "way" :
154
166
points = []
155
- for coords in elem ["geometry" ]:
156
- points .append ((coords ["lon" ], coords ["lat" ]))
157
- geometry = geojson .LineString (points )
167
+ geom = elem .get ("geometry" )
168
+ if geom :
169
+ for coords in elem .get ("geometry" ):
170
+ points .append ((coords ["lon" ], coords ["lat" ]))
171
+ geometry = geojson .LineString (points )
158
172
else :
159
173
continue
160
174
0 commit comments