Skip to content

Commit d833dd3

Browse files
committed
support CSV
This adds CSV support and prepares for deprecation of upper case method names.
1 parent 9c1a469 commit d833dd3

File tree

4 files changed

+75
-37
lines changed

4 files changed

+75
-37
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ docs/_build/
5757

5858
# PyBuilder
5959
target/
60+
61+
Pipfile.lock
62+
63+
.vscode/

Pipfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[[source]]
2+
3+
url = "https://pypi.python.org/simple"
4+
verify_ssl = true
5+
name = "pypi"
6+
7+
8+
[packages]
9+
10+
geojson = "==1.3.1"
11+
requests = "==2.8.1"
12+
nose = "==1.3.7"
13+
14+
15+
[dev-packages]
16+
17+
18+
19+
[requires]
20+
21+
python_version = "3.6"

overpass/api.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import requests
22
import json
3+
import csv
34
import geojson
45
import logging
5-
6+
from io import StringIO
67
from .errors import (OverpassSyntaxError, TimeoutError, MultipleRequestsError,
78
ServerLoadError, UnknownOverpassError, ServerRuntimeError)
89

910

1011
class API(object):
1112
"""A simple Python wrapper for the OpenStreetMap Overpass API."""
1213

13-
SUPPORTED_FORMATS = ["geojson", "json", "xml"]
14+
SUPPORTED_FORMATS = ["geojson", "json", "xml", "csv"]
1415

1516
# defaults for the API class
1617
_timeout = 25 # second
@@ -43,30 +44,40 @@ def __init__(self, *args, **kwargs):
4344
requests_log.setLevel(logging.DEBUG)
4445
requests_log.propagate = True
4546

46-
def Get(self,
47+
def get(self,
4748
query,
4849
responseformat="geojson",
4950
verbosity="body",
5051
build=True):
5152
"""Pass in an Overpass query in Overpass QL."""
5253
# Construct full Overpass query
5354
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)
5759
else:
5860
full_query = query
5961

6062
if self.debug:
6163
logging.getLogger().info(query)
6264

6365
# 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')
6568

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
6879

69-
response = json.loads(raw_response)
80+
response = json.loads(r)
7081

7182
# Check for valid answer from Overpass.
7283
# A valid answer contains an 'elements' key at the root level.
@@ -83,13 +94,17 @@ def Get(self,
8394
return response
8495

8596
# construct geojson
86-
return self._asGeoJSON(response["elements"])
97+
return self._as_geojson(response["elements"])
8798

88-
def Search(self, feature_type, regex=False):
99+
def search(self, feature_type, regex=False):
89100
"""Search for something."""
90101
raise NotImplementedError()
91102

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):
93108
raw_query = str(userquery)
94109
if not raw_query.endswith(";"):
95110
raw_query += ";"
@@ -110,10 +125,7 @@ def _ConstructQLQuery(self, userquery, responseformat, verbosity):
110125
print(complete_query)
111126
return complete_query
112127

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):
117129
payload = {"data": query}
118130

119131
try:
@@ -141,20 +153,22 @@ def _GetFromOverpass(self, query):
141153
code=self._status))
142154
else:
143155
r.encoding = 'utf-8'
144-
return r.text
156+
return r
145157

146-
def _asGeoJSON(self, elements):
158+
def _as_geojson(self, elements):
147159

148160
features = []
149161
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":
154166
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)
158172
else:
159173
continue
160174

setup.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
from codecs import open as codecs_open
2-
from setuptools import setup, find_packages
1+
from setuptools import setup
32

43
setup(
54
name='overpass',
65
packages=['overpass'],
7-
version='0.5.6',
6+
version='0.5.7',
87
description='Python wrapper for the OpenStreetMap Overpass API',
98
long_description='See README.md',
109
author='Martijn van Exel',
@@ -13,14 +12,14 @@
1312
license='Apache',
1413
keywords=['openstreetmap', 'overpass', 'wrapper'],
1514
classifiers=[
16-
'License :: OSI Approved :: Apache Software License',
17-
'Programming Language :: Python :: 2.6',
18-
'Programming Language :: Python :: 2.7',
19-
'Programming Language :: Python :: 3.3',
20-
'Programming Language :: Python :: 3.4',
21-
'Programming Language :: Python :: 3.5',
22-
'Topic :: Scientific/Engineering :: GIS',
23-
'Topic :: Utilities',
15+
'License :: OSI Approved :: Apache Software License',
16+
'Programming Language :: Python :: 2.6',
17+
'Programming Language :: Python :: 2.7',
18+
'Programming Language :: Python :: 3.3',
19+
'Programming Language :: Python :: 3.4',
20+
'Programming Language :: Python :: 3.5',
21+
'Topic :: Scientific/Engineering :: GIS',
22+
'Topic :: Utilities',
2423
],
2524
install_requires=['requests>=2.3.0', 'geojson>=1.0.9'],
2625
extras_require={

0 commit comments

Comments
 (0)