From abeeb761e71bd9aa322cdd1fce6ba35cbf690f53 Mon Sep 17 00:00:00 2001 From: Gregrs Date: Thu, 7 Apr 2016 11:46:11 +0100 Subject: [PATCH 1/6] Correct mistake in 'Unknown element end' KeyError message --- overpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overpy/__init__.py b/overpy/__init__.py index 1d23cf6..4c97c3c 100644 --- a/overpy/__init__.py +++ b/overpy/__init__.py @@ -1030,7 +1030,7 @@ def endElement(self, name): try: handler = getattr(self, '_handle_end_%s' % name) except AttributeError: - raise KeyError("Unknown element start '%s'" % name) + raise KeyError("Unknown element end '%s'" % name) handler() def _handle_start_tag(self, attrs): From ebaba3e1398016b21993d7acb69bdcbabb44efb6 Mon Sep 17 00:00:00 2001 From: Gregrs Date: Thu, 7 Apr 2016 11:52:36 +0100 Subject: [PATCH 2/6] Support parsing of
element for ways (XML only) N.B. ideally this should be implemented for JSON and relations --- overpy/__init__.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/overpy/__init__.py b/overpy/__init__.py index 4c97c3c..8a80688 100644 --- a/overpy/__init__.py +++ b/overpy/__init__.py @@ -592,7 +592,7 @@ class Way(Element): _type_value = "way" - def __init__(self, way_id=None, node_ids=None, **kwargs): + def __init__(self, way_id=None, center_lat=None, center_lon=None, node_ids=None, **kwargs): """ :param node_ids: List of node IDs :type node_ids: List or Tuple @@ -608,6 +608,10 @@ def __init__(self, way_id=None, node_ids=None, **kwargs): #: List of Ids of the associated nodes self._node_ids = node_ids + + #: The lat/lon of the center of the way (optional depending on query) + self.center_lat = center_lat + self.center_lon = center_lon def __repr__(self): return "".format(self.id, self._node_ids) @@ -745,6 +749,11 @@ def from_xml(cls, child, result=None): raise ValueError("Unable to find required ref value.") ref_id = int(ref_id) node_ids.append(ref_id) + if sub_child.tag.lower() == "center": + center_lat = sub_child.attrib.get("lat") + center_lon = sub_child.attrib.get("lon") + if center_lat is None or center_lon is None: + raise ValueError("Unable to get lat/lon of way center.") way_id = child.attrib.get("id") if way_id is not None: @@ -757,7 +766,8 @@ def from_xml(cls, child, result=None): continue attributes[n] = v - return cls(way_id=way_id, attributes=attributes, node_ids=node_ids, tags=tags, result=result) + return cls(way_id=way_id, center_lat=center_lat, center_lon=center_lon, + attributes=attributes, node_ids=node_ids, tags=tags, result=result) class Relation(Element): @@ -990,7 +1000,7 @@ class OSMSAXHandler(handler.ContentHandler): #: Tuple of opening elements to ignore ignore_start = ('osm', 'meta', 'note') #: Tuple of closing elements to ignore - ignore_end = ('osm', 'meta', 'note', 'tag', 'nd', 'member') + ignore_end = ('osm', 'meta', 'note', 'center', 'tag', 'nd', 'member') def __init__(self, result): """ @@ -1033,6 +1043,18 @@ def endElement(self, name): raise KeyError("Unknown element end '%s'" % name) handler() + def _handle_start_center(self, attrs): + """ + Handle opening center element + + :param attrs: Attributes of the element + :type attrs: Dict + """ + if attrs.get('lat', None) is not None: + self._curr['center_lat'] = Decimal(attrs['lat']) + if attrs.get('lon', None) is not None: + self._curr['center_lon'] = Decimal(attrs['lon']) + def _handle_start_tag(self, attrs): """ Handle opening tag element @@ -1085,6 +1107,8 @@ def _handle_start_way(self, attrs): :type attrs: Dict """ self._curr = { + 'center_lat': None, + 'center_lon': None, 'attributes': dict(attrs), 'node_ids': [], 'tags': {}, From 0df600d57b85fbd6eeba96a1e27e630daf46262e Mon Sep 17 00:00:00 2001 From: Gregrs Date: Wed, 13 Apr 2016 17:34:17 +0100 Subject: [PATCH 3/6] Fix UnboundLocalError for ways with no
--- overpy/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/overpy/__init__.py b/overpy/__init__.py index e797c30..0eceea8 100644 --- a/overpy/__init__.py +++ b/overpy/__init__.py @@ -735,6 +735,8 @@ def from_xml(cls, child, result=None): tags = {} node_ids = [] + center_lat = None + center_lon = None for sub_child in child: if sub_child.tag.lower() == "tag": From 94496fc0d4f3ed8e3f441047e54e9e6970b6a783 Mon Sep 17 00:00:00 2001 From: Gregrs Date: Wed, 13 Apr 2016 18:10:07 +0100 Subject: [PATCH 4/6] Change center_lat and center_lon to Decimals --- overpy/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/overpy/__init__.py b/overpy/__init__.py index 0eceea8..2b0d1eb 100644 --- a/overpy/__init__.py +++ b/overpy/__init__.py @@ -752,8 +752,8 @@ def from_xml(cls, child, result=None): ref_id = int(ref_id) node_ids.append(ref_id) if sub_child.tag.lower() == "center": - center_lat = sub_child.attrib.get("lat") - center_lon = sub_child.attrib.get("lon") + center_lat = Decimal(sub_child.attrib.get("lat")) + center_lon = Decimal(sub_child.attrib.get("lon")) if center_lat is None or center_lon is None: raise ValueError("Unable to get lat/lon of way center.") From b40afd5bf8ce5c4ab573fd7e9532883cd1b15db1 Mon Sep 17 00:00:00 2001 From: Gregrs Date: Wed, 13 Apr 2016 18:10:48 +0100 Subject: [PATCH 5/6] Test for way
tags (XML only) --- tests/base_class.py | 58 +++++++++++++++++++++++++++++++++++++++++++- tests/test_xml.py | 9 +++++++ tests/xml/way-03.xml | 18 ++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 tests/xml/way-03.xml diff --git a/tests/base_class.py b/tests/base_class.py index 92ddc22..0ede82f 100644 --- a/tests/base_class.py +++ b/tests/base_class.py @@ -278,4 +278,60 @@ def _test_way02(self, result): # way_ids is an alias for get_way_ids() and should return the same data for way_ids in (result.way_ids, result.get_way_ids()): assert len(way_ids) == 1 - assert way_ids[0] == 317146077 \ No newline at end of file + assert way_ids[0] == 317146077 + + def _test_way03(self, result): + assert len(result.nodes) == 0 + assert len(result.relations) == 0 + assert len(result.ways) == 1 + + way = result.ways[0] + + assert isinstance(way, overpy.Way) + assert isinstance(way.id, int) + assert way.id == 317146077 + + assert isinstance(way.tags, dict) + assert len(way.tags) == 1 + assert way.tags["building"] == "yes" + + assert isinstance(way.center_lat, Decimal) + assert isinstance(way.center_lon, Decimal) + assert way.center_lat == Decimal("50.7494852") + assert way.center_lon == Decimal("7.1757466") + + # the three assertions following this could break if the live OSM data changes + nodes = way.get_nodes(resolve_missing=True) + + assert len(nodes) == 7 + + node = nodes[0] + + assert isinstance(node, overpy.Node) + assert node.id == 3233854241 + + # try to get a single way by id + way = result.get_way(317146077) + assert way.id == 317146077 + + # try to get a single way by id not available in the result + with pytest.raises(overpy.exception.DataIncomplete): + result.get_way(123456) + + # node_ids is an alias for get_node_ids() and should return the same data + for node_ids in (result.node_ids, result.get_node_ids()): + assert len(node_ids) == 6 + assert node_ids[0] == 3233854233 + assert node_ids[1] == 3233854234 + assert node_ids[2] == 3233854236 + assert node_ids[3] == 3233854237 + assert node_ids[4] == 3233854238 + assert node_ids[5] == 3233854241 + + assert len(result.relation_ids) == 0 + assert len(result.get_relation_ids()) == 0 + + # way_ids is an alias for get_way_ids() and should return the same data + for way_ids in (result.way_ids, result.get_way_ids()): + assert len(way_ids) == 1 + assert way_ids[0] == 317146077 diff --git a/tests/test_xml.py b/tests/test_xml.py index e0c7397..84623f5 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -56,6 +56,15 @@ def test_way02(self): result = api.parse_xml(read_file("xml/way-02.xml"), parser=overpy.XML_PARSER_SAX) self._test_way02(result) + def test_way03(self): + api = overpy.Overpass() + # DOM + result = api.parse_xml(read_file("xml/way-03.xml"), parser=overpy.XML_PARSER_DOM) + self._test_way03(result) + # SAX + result = api.parse_xml(read_file("xml/way-03.xml"), parser=overpy.XML_PARSER_SAX) + self._test_way03(result) + class TestDataError(object): def _get_element_wrong_type(self): diff --git a/tests/xml/way-03.xml b/tests/xml/way-03.xml new file mode 100644 index 0000000..dfde115 --- /dev/null +++ b/tests/xml/way-03.xml @@ -0,0 +1,18 @@ + + +The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. + + + +
+ + + + + + + + + + + From 82c233992c73731b44488f6dea22af161307a839 Mon Sep 17 00:00:00 2001 From: Gregrs Date: Wed, 13 Apr 2016 18:21:53 +0100 Subject: [PATCH 6/6] Use XML file from different query to avoid needing to resolve missing nodes using live OSM data --- tests/base_class.py | 5 ++--- tests/xml/way-03.xml | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/base_class.py b/tests/base_class.py index 0ede82f..cdf223d 100644 --- a/tests/base_class.py +++ b/tests/base_class.py @@ -281,7 +281,7 @@ def _test_way02(self, result): assert way_ids[0] == 317146077 def _test_way03(self, result): - assert len(result.nodes) == 0 + assert len(result.nodes) == 6 assert len(result.relations) == 0 assert len(result.ways) == 1 @@ -300,8 +300,7 @@ def _test_way03(self, result): assert way.center_lat == Decimal("50.7494852") assert way.center_lon == Decimal("7.1757466") - # the three assertions following this could break if the live OSM data changes - nodes = way.get_nodes(resolve_missing=True) + nodes = way.nodes assert len(nodes) == 7 diff --git a/tests/xml/way-03.xml b/tests/xml/way-03.xml index dfde115..13b4019 100644 --- a/tests/xml/way-03.xml +++ b/tests/xml/way-03.xml @@ -1,8 +1,14 @@ The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. - + + + + + + +