diff --git a/overpy/__init__.py b/overpy/__init__.py
index 78072e9..13de583 100644
--- a/overpy/__init__.py
+++ b/overpy/__init__.py
@@ -84,6 +84,22 @@ def __init__(self, read_chunk_size=None, url=None, xml_parser=XML_PARSER_SAX, ma
self.xml_parser = xml_parser
+ def _handle_remark_msg(self, msg):
+ """
+ Try to parse the message provided with the remark tag or element.
+
+ :param str msg: The message
+ :raises overpy.exception.OverpassRuntimeError: If message starts with 'runtime error:'
+ :raises overpy.exception.OverpassRuntimeRemark: If message starts with 'runtime remark:'
+ :raises overpy.exception.OverpassUnknownError: If we are unable to identify the error
+ """
+ msg = msg.strip()
+ if msg.startswith("runtime error:"):
+ raise exception.OverpassRuntimeError(msg=msg)
+ elif msg.startswith("runtime remark:"):
+ raise exception.OverpassRuntimeRemark(msg=msg)
+ raise exception.OverpassUnknownError(msg=msg)
+
def query(self, query):
"""
Query the Overpass API
@@ -189,6 +205,8 @@ def parse_json(self, data, encoding="utf-8"):
if isinstance(data, bytes):
data = data.decode(encoding)
data = json.loads(data, parse_float=Decimal)
+ if "remark" in data:
+ self._handle_remark_msg(msg=data.get("remark"))
return Result.from_json(data, api=self)
def parse_xml(self, data, encoding="utf-8", parser=None):
@@ -210,6 +228,10 @@ def parse_xml(self, data, encoding="utf-8", parser=None):
# Python 2.x: Convert unicode strings
data = data.encode(encoding)
+ m = re.compile("(?P[^<>]*)").search(data)
+ if m:
+ self._handle_remark_msg(m.group("msg"))
+
return Result.from_xml(data, api=self, parser=parser)
diff --git a/overpy/exception.py b/overpy/exception.py
index c529364..3d8416a 100644
--- a/overpy/exception.py
+++ b/overpy/exception.py
@@ -74,6 +74,29 @@ def __str__(self):
return "\n".join(tmp_msgs)
+class OverpassError(OverPyException):
+ """
+ Base exception to report errors if the response returns a remark tag or element.
+
+ .. note::
+ If you are not sure which of the subexceptions you should use, use this one and try to parse the message.
+
+ For more information have a look at https://github.com/DinoTools/python-overpy/issues/62
+
+ :param str msg: The message from the remark tag or element
+ """
+ def __init__(self, msg=None):
+ #: The message from the remark tag or element
+ self.msg = msg
+
+ def __str__(self):
+ if self.msg is None:
+ return "No error message provided"
+ if not isinstance(self.msg, str):
+ return str(self.msg)
+ return self.msg
+
+
class OverpassGatewayTimeout(OverPyException):
"""
Raised if load of the Overpass API service is too high and it can't handle the request.
@@ -82,6 +105,22 @@ def __init__(self):
OverPyException.__init__(self, "Server load too high")
+class OverpassRuntimeError(OverpassError):
+ """
+ Raised if the server returns a remark-tag(xml) or remark element(json) with a message starting with
+ 'runtime error:'.
+ """
+ pass
+
+
+class OverpassRuntimeRemark(OverpassError):
+ """
+ Raised if the server returns a remark-tag(xml) or remark element(json) with a message starting with
+ 'runtime remark:'.
+ """
+ pass
+
+
class OverpassTooManyRequests(OverPyException):
"""
Raised if the Overpass API service returns a 429 status code.
@@ -106,6 +145,13 @@ def __str__(self):
return "Unknown content type: %s" % self.content_type
+class OverpassUnknownError(OverpassError):
+ """
+ Raised if the server returns a remark-tag(xml) or remark element(json) and we are unable to find any reason.
+ """
+ pass
+
+
class OverpassUnknownHTTPStatusCode(OverPyException):
"""
Raised if the returned HTTP status code isn't handled by OverPy.
diff --git a/tests/json/remark-runtime-error-01.json b/tests/json/remark-runtime-error-01.json
new file mode 100644
index 0000000..83b54cb
--- /dev/null
+++ b/tests/json/remark-runtime-error-01.json
@@ -0,0 +1,15 @@
+{
+ "version": 0.6,
+ "generator": "Overpass API",
+ "osm3s": {
+ "timestamp_osm_base": "2017-03-17T22:05:02Z",
+ "timestamp_areas_base": "2017-03-17T18:38:02Z",
+ "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
+ },
+ "elements": [
+
+
+
+ ],
+"remark": "runtime error: Query timed out in \"query\" at line 4 after 2 seconds."
+}
diff --git a/tests/json/remark-runtime-remark-01.json b/tests/json/remark-runtime-remark-01.json
new file mode 100644
index 0000000..fc21c88
--- /dev/null
+++ b/tests/json/remark-runtime-remark-01.json
@@ -0,0 +1,15 @@
+{
+ "version": 0.6,
+ "generator": "Overpass API",
+ "osm3s": {
+ "timestamp_osm_base": "2017-03-17T22:05:02Z",
+ "timestamp_areas_base": "2017-03-17T18:38:02Z",
+ "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
+ },
+ "elements": [
+
+
+
+ ],
+"remark": "runtime remark: Test"
+}
diff --git a/tests/json/remark-unknown-01.json b/tests/json/remark-unknown-01.json
new file mode 100644
index 0000000..815b770
--- /dev/null
+++ b/tests/json/remark-unknown-01.json
@@ -0,0 +1,15 @@
+{
+ "version": 0.6,
+ "generator": "Overpass API",
+ "osm3s": {
+ "timestamp_osm_base": "2017-03-17T22:05:02Z",
+ "timestamp_areas_base": "2017-03-17T18:38:02Z",
+ "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
+ },
+ "elements": [
+
+
+
+ ],
+"remark": "Test remark"
+}
diff --git a/tests/test_exception.py b/tests/test_exception.py
index 0c79064..4b4dd18 100644
--- a/tests/test_exception.py
+++ b/tests/test_exception.py
@@ -39,4 +39,26 @@ def test_overpass_unknown_content_type(self):
def test_overpass_unknown_http_status_code(self):
e = overpy.exception.OverpassUnknownHTTPStatusCode(123)
assert e.code == 123
- assert str(e).endswith("123")
\ No newline at end of file
+ assert str(e).endswith("123")
+
+ def test_overpass_error(self):
+ exceptions = [
+ overpy.exception.OverpassError,
+ overpy.exception.OverpassRuntimeError,
+ overpy.exception.OverpassRuntimeRemark,
+ overpy.exception.OverpassUnknownError
+ ]
+ for cls in exceptions:
+ e = cls(msg="Test message")
+ assert e.msg == "Test message"
+ assert str(e) == "Test message"
+
+ for cls in exceptions:
+ e = cls()
+ assert e.msg is None
+ assert str(e) == "No error message provided"
+
+ for cls in exceptions:
+ e = cls(msg=123)
+ assert e.msg == 123
+ assert str(e) == "123"
diff --git a/tests/test_json.py b/tests/test_json.py
index 60a1a0a..287250a 100644
--- a/tests/test_json.py
+++ b/tests/test_json.py
@@ -98,4 +98,21 @@ def test_element_wrong_type(self):
{
"type": "foo"
}
- )
\ No newline at end of file
+ )
+
+
+class TestRemark(object):
+ def test_remark_runtime_error(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassRuntimeError):
+ api.parse_json(read_file("json/remark-runtime-error-01.json"))
+
+ def test_remark_runtime_remark(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassRuntimeRemark):
+ api.parse_json(read_file("json/remark-runtime-remark-01.json"))
+
+ def test_remark_unknown(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassUnknownError):
+ api.parse_json(read_file("json/remark-unknown-01.json"))
\ No newline at end of file
diff --git a/tests/test_xml.py b/tests/test_xml.py
index c25e836..d81f003 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -169,3 +169,20 @@ def test_way_missing_data(self):
node = ET.fromstring(data)
with pytest.raises(ValueError):
overpy.Way.from_xml(node)
+
+
+class TestRemark(object):
+ def test_remark_runtime_error(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassRuntimeError):
+ api.parse_xml(read_file("xml/remark-runtime-error-01.xml"))
+
+ def test_remark_runtime_remark(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassRuntimeRemark):
+ api.parse_xml(read_file("xml/remark-runtime-remark-01.xml"))
+
+ def test_remark_unknown(self):
+ api = overpy.Overpass()
+ with pytest.raises(overpy.exception.OverpassUnknownError):
+ api.parse_xml(read_file("xml/remark-unknown-01.xml"))
diff --git a/tests/xml/remark-runtime-error-01.xml b/tests/xml/remark-runtime-error-01.xml
new file mode 100644
index 0000000..5aa0888
--- /dev/null
+++ b/tests/xml/remark-runtime-error-01.xml
@@ -0,0 +1,8 @@
+
+
+The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
+
+
+ runtime error: Query timed out in "query" at line 4 after 2 seconds.
+
+
diff --git a/tests/xml/remark-runtime-remark-01.xml b/tests/xml/remark-runtime-remark-01.xml
new file mode 100644
index 0000000..254fe97
--- /dev/null
+++ b/tests/xml/remark-runtime-remark-01.xml
@@ -0,0 +1,8 @@
+
+
+The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
+
+
+ runtime remark: Test
+
+
diff --git a/tests/xml/remark-unknown-01.xml b/tests/xml/remark-unknown-01.xml
new file mode 100644
index 0000000..ad8a047
--- /dev/null
+++ b/tests/xml/remark-unknown-01.xml
@@ -0,0 +1,8 @@
+
+
+The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.
+
+
+ Test remark
+
+