From fcd49d67e5fe6c1695b7fd31b6f3f6c180da75d3 Mon Sep 17 00:00:00 2001 From: Tim Bolender Date: Wed, 10 Dec 2014 00:49:58 +0100 Subject: [PATCH] Implemented an exceptions class for every kind of error. --- overpass/__init__.py | 3 +++ overpass/api.py | 54 ++++++++++++-------------------------------- overpass/errors.py | 37 ++++++++++++++++++++++++++++++ overpass/queries.py | 3 +-- 4 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 overpass/errors.py diff --git a/overpass/__init__.py b/overpass/__init__.py index abaf7e0664f..267865a7b4d 100644 --- a/overpass/__init__.py +++ b/overpass/__init__.py @@ -8,3 +8,6 @@ from .api import API from .queries import MapQuery, WayQuery +from .errors import ( + OverpassError, OverpassSyntaxError, TimeoutError, MultipleRequestsError, ServerLoadError, UnknownOverpassError +) diff --git a/overpass/api.py b/overpass/api.py index 72e422f29cd..0764f85d681 100644 --- a/overpass/api.py +++ b/overpass/api.py @@ -1,8 +1,9 @@ -import sys import requests import json import geojson +from .errors import OverpassSyntaxError, TimeoutError, MultipleRequestsError, ServerLoadError, UnknownOverpassError + class API(object): """A simple Python wrapper for the OpenStreetMap Overpass API""" @@ -40,20 +41,12 @@ def __init__(self, *args, **kwargs): def Get(self, query, asGeoJSON=False): """Pass in an Overpass query in Overpass QL""" - response = "" + full_query = self._ConstructQLQuery(query, asGeoJSON=asGeoJSON) + raw_response = self._GetFromOverpass(full_query) + response = json.loads(raw_response) - try: - response = json.loads(self._GetFromOverpass( - self._ConstructQLQuery(query, asGeoJSON=asGeoJSON))) - except OverpassException as oe: - print(oe) - sys.exit(1) - - if "elements" not in response or len(response["elements"]) == 0: - raise OverpassException( - 204, - 'No OSM features satisfied your query' - ) + if "elements" not in response: + raise UnknownOverpassError("Received an invalid answer from Overpass.") if not asGeoJSON: return response @@ -63,7 +56,7 @@ def Get(self, query, asGeoJSON=False): def Search(self, feature_type, regex=False): """Search for something.""" - pass + raise NotImplementedError() def _ConstructQLQuery(self, userquery, asGeoJSON=False): raw_query = str(userquery) @@ -96,23 +89,18 @@ def _GetFromOverpass(self, query): timeout=self.timeout ) except requests.exceptions.Timeout: - raise OverpassException( - 408, - 'Query timed out. API instance is set to time out in {timeout}' - ' seconds. Try passing in a higher value when instantiating' - ' this API: api = Overpass.API(timeout=60)'.format( - timeout=self.timeout - ) - ) + raise TimeoutError(self._timeout) self._status = r.status_code if self._status != 200: if self._status == 400: - message = 'Query syntax error' - else: - message = 'Error from Overpass API' - raise OverpassException(self._status, message) + raise OverpassSyntaxError(query) + elif self._status == 429: + raise MultipleRequestsError() + elif self._status == 504: + raise ServerLoadError(self._timeout) + raise UnknownOverpassError("The request returned status code {code}".format(code = self._status)) else: return r.text @@ -139,15 +127,3 @@ def _asGeoJSON(self, elements): features.append(feature) return geojson.FeatureCollection(features) - - -class OverpassException(Exception): - def __init__(self, status_code, message): - self.status_code = status_code - self.message = message - - def __str__(self): - return json.dumps({ - 'status': self.status_code, - 'message': self.message - }) diff --git a/overpass/errors.py b/overpass/errors.py new file mode 100644 index 00000000000..b0249f7908c --- /dev/null +++ b/overpass/errors.py @@ -0,0 +1,37 @@ +class OverpassError(Exception): + """An error during your request occurred. Super class for all Overpass api errors.""" + pass + + +class OverpassSyntaxError(OverpassError, ValueError): + """The request contains a syntax error.""" + + def __init__(self, request): + self.request = request + + +class TimeoutError(OverpassError): + """A request timeout occurred.""" + + def __init__(self, timeout): + self.timeout = timeout + + +class MultipleRequestsError(OverpassError): + """You are trying to run multiple requests at the same time.""" + pass + + +class ServerLoadError(OverpassError): + """The Overpass server is currently under load and declined the request. Try again later or retry with reduced + timeout value.""" + + def __init__(self, timeout): + self.timeout = timeout + + +class UnknownOverpassError(OverpassError): + """An unknown kind of error happened during the request.""" + + def __init__(self, message): + self.message = message \ No newline at end of file diff --git a/overpass/queries.py b/overpass/queries.py index 2d98ddb10c0..f673950d2a3 100644 --- a/overpass/queries.py +++ b/overpass/queries.py @@ -29,8 +29,7 @@ def __str__(self): class WayQuery(object): - """Query to retrieve a set of ways and their dependent nodes satisfying - the input parameters""" + """Query to retrieve a set of ways and their dependent nodes satisfying the input parameters""" _QUERY_TEMPLATE = "(way{query_parameters});(._;>;);"