osmapi.relation
Relation operations for the OpenStreetMap API.
This module provides pythonic (snake_case) methods for working with OSM relations.
1""" 2Relation operations for the OpenStreetMap API. 3 4This module provides pythonic (snake_case) methods for working with OSM relations. 5""" 6 7from typing import Any, Optional, TYPE_CHECKING, cast 8from xml.dom.minidom import Element 9 10from . import dom, parser 11 12if TYPE_CHECKING: 13 from .OsmApi import OsmApi 14 15 16class RelationMixin: 17 """Mixin providing relation-related operations with pythonic method names.""" 18 19 def relation_get( 20 self: "OsmApi", relation_id: int, relation_version: int = -1 21 ) -> dict[str, Any]: 22 """ 23 Returns relation with `relation_id` as a dict. 24 25 If `relation_version` is supplied, this specific version is returned, 26 otherwise the latest version is returned. 27 28 If the requested element has been deleted, 29 `OsmApi.ElementDeletedApiError` is raised. 30 31 If the requested element can not be found, 32 `OsmApi.ElementNotFoundApiError` is raised. 33 """ 34 uri = f"/api/0.6/relation/{relation_id}" 35 if relation_version != -1: 36 uri += f"/{relation_version}" 37 data = self._session._get(uri) 38 relation = cast( 39 Element, dom.OsmResponseToDom(data, tag="relation", single=True) 40 ) 41 return dom.dom_parse_relation(relation) 42 43 def relation_create( 44 self: "OsmApi", relation_data: dict[str, Any] 45 ) -> Optional[dict[str, Any]]: 46 """ 47 Creates a relation based on the supplied `relation_data` dict. 48 49 If no authentication information are provided, 50 `OsmApi.UsernamePasswordMissingError` is raised. 51 52 If the supplied information contain an existing relation, 53 `OsmApi.OsmTypeAlreadyExistsError` is raised. 54 55 If there is no open changeset, 56 `OsmApi.NoChangesetOpenError` is raised. 57 58 If the changeset is already closed, 59 `OsmApi.ChangesetClosedApiError` is raised. 60 """ 61 return self._do("create", "relation", relation_data) 62 63 def relation_update( 64 self: "OsmApi", relation_data: dict[str, Any] 65 ) -> Optional[dict[str, Any]]: 66 """ 67 Updates relation with the supplied `relation_data` dict. 68 69 If no authentication information are provided, 70 `OsmApi.UsernamePasswordMissingError` is raised. 71 72 If there is no open changeset, 73 `OsmApi.NoChangesetOpenError` is raised. 74 75 If the changeset is already closed, 76 `OsmApi.ChangesetClosedApiError` is raised. 77 """ 78 return self._do("modify", "relation", relation_data) 79 80 def relation_delete( 81 self: "OsmApi", relation_data: dict[str, Any] 82 ) -> Optional[dict[str, Any]]: 83 """ 84 Delete relation with `relation_data`. 85 86 If no authentication information are provided, 87 `OsmApi.UsernamePasswordMissingError` is raised. 88 89 If there is no open changeset, 90 `OsmApi.NoChangesetOpenError` is raised. 91 92 If the changeset is already closed, 93 `OsmApi.ChangesetClosedApiError` is raised. 94 """ 95 return self._do("delete", "relation", relation_data) 96 97 def relation_history(self: "OsmApi", relation_id: int) -> dict[int, dict[str, Any]]: 98 """ 99 Returns dict with version as key. 100 101 If the requested element can not be found, 102 `OsmApi.ElementNotFoundApiError` is raised. 103 """ 104 uri = f"/api/0.6/relation/{relation_id}/history" 105 data = self._session._get(uri) 106 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 107 result: dict[int, dict[str, Any]] = {} 108 for relation in relations: 109 relation_data = dom.dom_parse_relation(relation) 110 result[relation_data["version"]] = relation_data 111 return result 112 113 def relation_relations(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 114 """ 115 Returns a list of dicts of relation data containing relation `relation_id`. 116 117 If the requested element can not be found, 118 `OsmApi.ElementNotFoundApiError` is raised. 119 """ 120 uri = f"/api/0.6/relation/{relation_id}/relations" 121 data = self._session._get(uri) 122 relations = cast( 123 list[Element], dom.OsmResponseToDom(data, tag="relation", allow_empty=True) 124 ) 125 result: list[dict[str, Any]] = [] 126 for relation in relations: 127 relation_data = dom.dom_parse_relation(relation) 128 result.append(relation_data) 129 return result 130 131 def relation_full_recur(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 132 """ 133 Returns the full data (all levels) for relation `relation_id` as list of dicts. 134 135 This function is useful for relations containing other relations. 136 137 If you don't need all levels, use `relation_full` instead, 138 which return only 2 levels. 139 140 If any relation (on any level) has been deleted, 141 `OsmApi.ElementDeletedApiError` is raised. 142 143 If the requested element can not be found, 144 `OsmApi.ElementNotFoundApiError` is raised. 145 """ 146 data = [] 147 todo = [relation_id] 148 done = [] 149 while todo: 150 rid = todo.pop(0) 151 done.append(rid) 152 temp = self.relation_full(rid) 153 for item in temp: 154 if item["type"] != "relation": 155 continue 156 if item["data"]["id"] in done: 157 continue 158 todo.append(item["data"]["id"]) 159 data += temp 160 return data 161 162 def relation_full(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 163 """ 164 Returns the full data (two levels) for relation `relation_id` as list of dicts. 165 166 If you need all levels, use `relation_full_recur`. 167 168 If the requested element has been deleted, 169 `OsmApi.ElementDeletedApiError` is raised. 170 171 If the requested element can not be found, 172 `OsmApi.ElementNotFoundApiError` is raised. 173 """ 174 uri = f"/api/0.6/relation/{relation_id}/full" 175 data = self._session._get(uri) 176 return parser.parse_osm(data) 177 178 def relations_get( 179 self: "OsmApi", relation_id_list: list[int] 180 ) -> dict[int, dict[str, Any]]: 181 """ 182 Returns dict with the id of the relation as a key 183 for each relation in `relation_id_list`. 184 185 `relation_id_list` is a list containing unique identifiers 186 for multiple relations. 187 """ 188 relation_list = ",".join([str(x) for x in relation_id_list]) 189 uri = f"/api/0.6/relations?relations={relation_list}" 190 data = self._session._get(uri) 191 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 192 result: dict[int, dict[str, Any]] = {} 193 for relation in relations: 194 relation_data = dom.dom_parse_relation(relation) 195 result[relation_data["id"]] = relation_data 196 return result
17class RelationMixin: 18 """Mixin providing relation-related operations with pythonic method names.""" 19 20 def relation_get( 21 self: "OsmApi", relation_id: int, relation_version: int = -1 22 ) -> dict[str, Any]: 23 """ 24 Returns relation with `relation_id` as a dict. 25 26 If `relation_version` is supplied, this specific version is returned, 27 otherwise the latest version is returned. 28 29 If the requested element has been deleted, 30 `OsmApi.ElementDeletedApiError` is raised. 31 32 If the requested element can not be found, 33 `OsmApi.ElementNotFoundApiError` is raised. 34 """ 35 uri = f"/api/0.6/relation/{relation_id}" 36 if relation_version != -1: 37 uri += f"/{relation_version}" 38 data = self._session._get(uri) 39 relation = cast( 40 Element, dom.OsmResponseToDom(data, tag="relation", single=True) 41 ) 42 return dom.dom_parse_relation(relation) 43 44 def relation_create( 45 self: "OsmApi", relation_data: dict[str, Any] 46 ) -> Optional[dict[str, Any]]: 47 """ 48 Creates a relation based on the supplied `relation_data` dict. 49 50 If no authentication information are provided, 51 `OsmApi.UsernamePasswordMissingError` is raised. 52 53 If the supplied information contain an existing relation, 54 `OsmApi.OsmTypeAlreadyExistsError` is raised. 55 56 If there is no open changeset, 57 `OsmApi.NoChangesetOpenError` is raised. 58 59 If the changeset is already closed, 60 `OsmApi.ChangesetClosedApiError` is raised. 61 """ 62 return self._do("create", "relation", relation_data) 63 64 def relation_update( 65 self: "OsmApi", relation_data: dict[str, Any] 66 ) -> Optional[dict[str, Any]]: 67 """ 68 Updates relation with the supplied `relation_data` dict. 69 70 If no authentication information are provided, 71 `OsmApi.UsernamePasswordMissingError` is raised. 72 73 If there is no open changeset, 74 `OsmApi.NoChangesetOpenError` is raised. 75 76 If the changeset is already closed, 77 `OsmApi.ChangesetClosedApiError` is raised. 78 """ 79 return self._do("modify", "relation", relation_data) 80 81 def relation_delete( 82 self: "OsmApi", relation_data: dict[str, Any] 83 ) -> Optional[dict[str, Any]]: 84 """ 85 Delete relation with `relation_data`. 86 87 If no authentication information are provided, 88 `OsmApi.UsernamePasswordMissingError` is raised. 89 90 If there is no open changeset, 91 `OsmApi.NoChangesetOpenError` is raised. 92 93 If the changeset is already closed, 94 `OsmApi.ChangesetClosedApiError` is raised. 95 """ 96 return self._do("delete", "relation", relation_data) 97 98 def relation_history(self: "OsmApi", relation_id: int) -> dict[int, dict[str, Any]]: 99 """ 100 Returns dict with version as key. 101 102 If the requested element can not be found, 103 `OsmApi.ElementNotFoundApiError` is raised. 104 """ 105 uri = f"/api/0.6/relation/{relation_id}/history" 106 data = self._session._get(uri) 107 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 108 result: dict[int, dict[str, Any]] = {} 109 for relation in relations: 110 relation_data = dom.dom_parse_relation(relation) 111 result[relation_data["version"]] = relation_data 112 return result 113 114 def relation_relations(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 115 """ 116 Returns a list of dicts of relation data containing relation `relation_id`. 117 118 If the requested element can not be found, 119 `OsmApi.ElementNotFoundApiError` is raised. 120 """ 121 uri = f"/api/0.6/relation/{relation_id}/relations" 122 data = self._session._get(uri) 123 relations = cast( 124 list[Element], dom.OsmResponseToDom(data, tag="relation", allow_empty=True) 125 ) 126 result: list[dict[str, Any]] = [] 127 for relation in relations: 128 relation_data = dom.dom_parse_relation(relation) 129 result.append(relation_data) 130 return result 131 132 def relation_full_recur(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 133 """ 134 Returns the full data (all levels) for relation `relation_id` as list of dicts. 135 136 This function is useful for relations containing other relations. 137 138 If you don't need all levels, use `relation_full` instead, 139 which return only 2 levels. 140 141 If any relation (on any level) has been deleted, 142 `OsmApi.ElementDeletedApiError` is raised. 143 144 If the requested element can not be found, 145 `OsmApi.ElementNotFoundApiError` is raised. 146 """ 147 data = [] 148 todo = [relation_id] 149 done = [] 150 while todo: 151 rid = todo.pop(0) 152 done.append(rid) 153 temp = self.relation_full(rid) 154 for item in temp: 155 if item["type"] != "relation": 156 continue 157 if item["data"]["id"] in done: 158 continue 159 todo.append(item["data"]["id"]) 160 data += temp 161 return data 162 163 def relation_full(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 164 """ 165 Returns the full data (two levels) for relation `relation_id` as list of dicts. 166 167 If you need all levels, use `relation_full_recur`. 168 169 If the requested element has been deleted, 170 `OsmApi.ElementDeletedApiError` is raised. 171 172 If the requested element can not be found, 173 `OsmApi.ElementNotFoundApiError` is raised. 174 """ 175 uri = f"/api/0.6/relation/{relation_id}/full" 176 data = self._session._get(uri) 177 return parser.parse_osm(data) 178 179 def relations_get( 180 self: "OsmApi", relation_id_list: list[int] 181 ) -> dict[int, dict[str, Any]]: 182 """ 183 Returns dict with the id of the relation as a key 184 for each relation in `relation_id_list`. 185 186 `relation_id_list` is a list containing unique identifiers 187 for multiple relations. 188 """ 189 relation_list = ",".join([str(x) for x in relation_id_list]) 190 uri = f"/api/0.6/relations?relations={relation_list}" 191 data = self._session._get(uri) 192 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 193 result: dict[int, dict[str, Any]] = {} 194 for relation in relations: 195 relation_data = dom.dom_parse_relation(relation) 196 result[relation_data["id"]] = relation_data 197 return result
Mixin providing relation-related operations with pythonic method names.
20 def relation_get( 21 self: "OsmApi", relation_id: int, relation_version: int = -1 22 ) -> dict[str, Any]: 23 """ 24 Returns relation with `relation_id` as a dict. 25 26 If `relation_version` is supplied, this specific version is returned, 27 otherwise the latest version is returned. 28 29 If the requested element has been deleted, 30 `OsmApi.ElementDeletedApiError` is raised. 31 32 If the requested element can not be found, 33 `OsmApi.ElementNotFoundApiError` is raised. 34 """ 35 uri = f"/api/0.6/relation/{relation_id}" 36 if relation_version != -1: 37 uri += f"/{relation_version}" 38 data = self._session._get(uri) 39 relation = cast( 40 Element, dom.OsmResponseToDom(data, tag="relation", single=True) 41 ) 42 return dom.dom_parse_relation(relation)
Returns relation with relation_id as a dict.
If relation_version is supplied, this specific version is returned,
otherwise the latest version is returned.
If the requested element has been deleted,
OsmApi.ElementDeletedApiError is raised.
If the requested element can not be found,
OsmApi.ElementNotFoundApiError is raised.
44 def relation_create( 45 self: "OsmApi", relation_data: dict[str, Any] 46 ) -> Optional[dict[str, Any]]: 47 """ 48 Creates a relation based on the supplied `relation_data` dict. 49 50 If no authentication information are provided, 51 `OsmApi.UsernamePasswordMissingError` is raised. 52 53 If the supplied information contain an existing relation, 54 `OsmApi.OsmTypeAlreadyExistsError` is raised. 55 56 If there is no open changeset, 57 `OsmApi.NoChangesetOpenError` is raised. 58 59 If the changeset is already closed, 60 `OsmApi.ChangesetClosedApiError` is raised. 61 """ 62 return self._do("create", "relation", relation_data)
Creates a relation based on the supplied relation_data dict.
If no authentication information are provided,
OsmApi.UsernamePasswordMissingError is raised.
If the supplied information contain an existing relation,
OsmApi.OsmTypeAlreadyExistsError is raised.
If there is no open changeset,
OsmApi.NoChangesetOpenError is raised.
If the changeset is already closed,
OsmApi.ChangesetClosedApiError is raised.
64 def relation_update( 65 self: "OsmApi", relation_data: dict[str, Any] 66 ) -> Optional[dict[str, Any]]: 67 """ 68 Updates relation with the supplied `relation_data` dict. 69 70 If no authentication information are provided, 71 `OsmApi.UsernamePasswordMissingError` is raised. 72 73 If there is no open changeset, 74 `OsmApi.NoChangesetOpenError` is raised. 75 76 If the changeset is already closed, 77 `OsmApi.ChangesetClosedApiError` is raised. 78 """ 79 return self._do("modify", "relation", relation_data)
Updates relation with the supplied relation_data dict.
If no authentication information are provided,
OsmApi.UsernamePasswordMissingError is raised.
If there is no open changeset,
OsmApi.NoChangesetOpenError is raised.
If the changeset is already closed,
OsmApi.ChangesetClosedApiError is raised.
81 def relation_delete( 82 self: "OsmApi", relation_data: dict[str, Any] 83 ) -> Optional[dict[str, Any]]: 84 """ 85 Delete relation with `relation_data`. 86 87 If no authentication information are provided, 88 `OsmApi.UsernamePasswordMissingError` is raised. 89 90 If there is no open changeset, 91 `OsmApi.NoChangesetOpenError` is raised. 92 93 If the changeset is already closed, 94 `OsmApi.ChangesetClosedApiError` is raised. 95 """ 96 return self._do("delete", "relation", relation_data)
Delete relation with relation_data.
If no authentication information are provided,
OsmApi.UsernamePasswordMissingError is raised.
If there is no open changeset,
OsmApi.NoChangesetOpenError is raised.
If the changeset is already closed,
OsmApi.ChangesetClosedApiError is raised.
98 def relation_history(self: "OsmApi", relation_id: int) -> dict[int, dict[str, Any]]: 99 """ 100 Returns dict with version as key. 101 102 If the requested element can not be found, 103 `OsmApi.ElementNotFoundApiError` is raised. 104 """ 105 uri = f"/api/0.6/relation/{relation_id}/history" 106 data = self._session._get(uri) 107 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 108 result: dict[int, dict[str, Any]] = {} 109 for relation in relations: 110 relation_data = dom.dom_parse_relation(relation) 111 result[relation_data["version"]] = relation_data 112 return result
Returns dict with version as key.
If the requested element can not be found,
OsmApi.ElementNotFoundApiError is raised.
114 def relation_relations(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 115 """ 116 Returns a list of dicts of relation data containing relation `relation_id`. 117 118 If the requested element can not be found, 119 `OsmApi.ElementNotFoundApiError` is raised. 120 """ 121 uri = f"/api/0.6/relation/{relation_id}/relations" 122 data = self._session._get(uri) 123 relations = cast( 124 list[Element], dom.OsmResponseToDom(data, tag="relation", allow_empty=True) 125 ) 126 result: list[dict[str, Any]] = [] 127 for relation in relations: 128 relation_data = dom.dom_parse_relation(relation) 129 result.append(relation_data) 130 return result
Returns a list of dicts of relation data containing relation relation_id.
If the requested element can not be found,
OsmApi.ElementNotFoundApiError is raised.
132 def relation_full_recur(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 133 """ 134 Returns the full data (all levels) for relation `relation_id` as list of dicts. 135 136 This function is useful for relations containing other relations. 137 138 If you don't need all levels, use `relation_full` instead, 139 which return only 2 levels. 140 141 If any relation (on any level) has been deleted, 142 `OsmApi.ElementDeletedApiError` is raised. 143 144 If the requested element can not be found, 145 `OsmApi.ElementNotFoundApiError` is raised. 146 """ 147 data = [] 148 todo = [relation_id] 149 done = [] 150 while todo: 151 rid = todo.pop(0) 152 done.append(rid) 153 temp = self.relation_full(rid) 154 for item in temp: 155 if item["type"] != "relation": 156 continue 157 if item["data"]["id"] in done: 158 continue 159 todo.append(item["data"]["id"]) 160 data += temp 161 return data
Returns the full data (all levels) for relation relation_id as list of dicts.
This function is useful for relations containing other relations.
If you don't need all levels, use relation_full instead,
which return only 2 levels.
If any relation (on any level) has been deleted,
OsmApi.ElementDeletedApiError is raised.
If the requested element can not be found,
OsmApi.ElementNotFoundApiError is raised.
163 def relation_full(self: "OsmApi", relation_id: int) -> list[dict[str, Any]]: 164 """ 165 Returns the full data (two levels) for relation `relation_id` as list of dicts. 166 167 If you need all levels, use `relation_full_recur`. 168 169 If the requested element has been deleted, 170 `OsmApi.ElementDeletedApiError` is raised. 171 172 If the requested element can not be found, 173 `OsmApi.ElementNotFoundApiError` is raised. 174 """ 175 uri = f"/api/0.6/relation/{relation_id}/full" 176 data = self._session._get(uri) 177 return parser.parse_osm(data)
Returns the full data (two levels) for relation relation_id as list of dicts.
If you need all levels, use relation_full_recur.
If the requested element has been deleted,
OsmApi.ElementDeletedApiError is raised.
If the requested element can not be found,
OsmApi.ElementNotFoundApiError is raised.
179 def relations_get( 180 self: "OsmApi", relation_id_list: list[int] 181 ) -> dict[int, dict[str, Any]]: 182 """ 183 Returns dict with the id of the relation as a key 184 for each relation in `relation_id_list`. 185 186 `relation_id_list` is a list containing unique identifiers 187 for multiple relations. 188 """ 189 relation_list = ",".join([str(x) for x in relation_id_list]) 190 uri = f"/api/0.6/relations?relations={relation_list}" 191 data = self._session._get(uri) 192 relations = cast(list[Element], dom.OsmResponseToDom(data, tag="relation")) 193 result: dict[int, dict[str, Any]] = {} 194 for relation in relations: 195 relation_data = dom.dom_parse_relation(relation) 196 result[relation_data["id"]] = relation_data 197 return result
Returns dict with the id of the relation as a key
for each relation in relation_id_list.
relation_id_list is a list containing unique identifiers
for multiple relations.