diff --git a/overpy/__init__.py b/overpy/__init__.py index 9bee8ae..4675a16 100644 --- a/overpy/__init__.py +++ b/overpy/__init__.py @@ -611,7 +611,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 @@ -627,6 +627,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) @@ -750,6 +754,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": @@ -764,6 +770,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 = 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.") way_id = child.attrib.get("id") if way_id is not None: @@ -776,7 +787,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): @@ -1009,7 +1021,7 @@ class OSMSAXHandler(handler.ContentHandler): #: Tuple of opening elements to ignore ignore_start = ('osm', 'meta', 'note', 'bounds', 'remark') #: Tuple of closing elements to ignore - ignore_end = ('osm', 'meta', 'note', 'bounds', 'remark', 'tag', 'nd', 'member') + ignore_end = ('osm', 'meta', 'note', 'bounds', 'remark', 'tag', 'nd', 'member', 'center') def __init__(self, result): """ @@ -1049,9 +1061,21 @@ 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_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 @@ -1104,6 +1128,8 @@ def _handle_start_way(self, attrs): :type attrs: Dict """ self._curr = { + 'center_lat': None, + 'center_lon': None, 'attributes': dict(attrs), 'node_ids': [], 'tags': {}, diff --git a/tests/base_class.py b/tests/base_class.py index fe77ff6..ae5f4e2 100644 --- a/tests/base_class.py +++ b/tests/base_class.py @@ -289,4 +289,59 @@ 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) == 6 + 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") + + nodes = way.nodes + + 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..13b4019 --- /dev/null +++ b/tests/xml/way-03.xml @@ -0,0 +1,24 @@ + + +The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. + + + + + + + + + +
+ + + + + + + + + + +