Conditions | 57 |
Total Lines | 124 |
Lines | 24 |
Ratio | 19.35 % |
Changes | 9 | ||
Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like _trees_to_overpassql() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | ## ~*~ coding: utf-8 ~*~ |
||
155 | # Look for a known operator |
||
156 | if op in _ops.keys(): |
||
157 | # Get string representation |
||
158 | op = _ops[op] |
||
159 | else: |
||
160 | # Right now, we cannot cope with anything else |
||
161 | return None |
||
162 | |||
163 | # Return polish notation tuple of this clause |
||
164 | return (op, clauses) |
||
165 | else: |
||
166 | # We hit an unsupported type of clause |
||
167 | return None |
||
168 | |||
169 | 1 | def _trees_to_overpassql(tree_dict): |
|
170 | """ Transform an expression tree (from _where_to_tree) into OverpassQL. """ |
||
171 | |||
172 | # Called recursively on all subtrees |
||
173 | 1 | def _tree_to_overpassql_recursive(tree, type_, op): |
|
174 | # Empty result string |
||
175 | 1 | result = "" |
|
176 | |||
177 | # Test if we got a tree or an atom |
||
178 | 1 | if isinstance(tree[1], list): |
|
179 | # We are in a subtree |
||
180 | |||
181 | # Store operation of subtree (conjunction/disjunction) |
||
182 | 1 | View Code Duplication | op = tree[0] |
183 | |||
184 | # Empty bounding box |
||
185 | 1 | bbox = [None, None, None, None] |
|
186 | |||
187 | # List of genrated set names |
||
188 | 1 | set_names = [] |
|
189 | View Code Duplication | ||
190 | # Iterate over all elements in the conjunction/disjunction |
||
191 | 1 | for t in tree[1]: |
|
192 | # Check if element is a tree or an atom |
||
193 | 1 | if isinstance(t[1], list): |
|
194 | # Recurse into inner tree |
||
195 | result_inner_tree = _tree_to_overpassql_recursive(tree[1], op) |
||
196 | View Code Duplication | # Store resulting query and its name |
|
197 | result += "%s" % result_inner_tree[1] |
||
198 | set_names.append(result_inner_tree[0]) |
||
199 | else: |
||
200 | # Parse atom |
||
201 | |||
202 | # latitude and longitude comparisons form a bounding box |
||
203 | 1 | View Code Duplication | if t[1] == "latitude" and t[0] == ">": |
204 | # South edge |
||
205 | 1 | if bbox[0] is None: |
|
206 | 1 | bbox[0] = float(t[2]) |
|
207 | elif op == "&&" and bbox[0] <= t[2]: |
||
208 | bbox[0] = float(t[2]) |
||
209 | elif op == "||" and bbox[0] >= t[2]: |
||
210 | bbox[0] = float(t[2]) |
||
211 | 1 | elif t[1] == "latitude" and t[0] == "<": |
|
212 | # North edge |
||
213 | 1 | if bbox[2] is None: |
|
214 | 1 | bbox[2] = float(t[2]) |
|
215 | elif op == "&&" and bbox[2] >= t[2]: |
||
216 | bbox[2] = float(t[2]) |
||
217 | elif op == "||" and bbox[2] <= t[2]: |
||
218 | bbox[2] = float(t[2]) |
||
219 | 1 | elif t[1] == "longitude" and t[0] == ">": |
|
220 | # West edge |
||
221 | 1 | if bbox[1] is None: |
|
222 | 1 | bbox[1] = float(t[2]) |
|
223 | elif op == "&&" and bbox[1] <= t[2]: |
||
224 | bbox[1] = float(t[2]) |
||
225 | elif op == "||" and bbox[1] >= t[2]: |
||
226 | bbox[1] = float(t[2]) |
||
227 | 1 | elif t[1] == "longitude" and t[0] == "<": |
|
228 | # East edge |
||
229 | 1 | if bbox[3] is None: |
|
230 | 1 | bbox[3] = float(t[2]) |
|
231 | elif op == "&&" and bbox[3] >= t[2]: |
||
232 | bbox[3] = float(t[2]) |
||
233 | elif op == "||" and bbox[3] <= t[2]: |
||
234 | bbox[3] = float(t[2]) |
||
235 | # Query for an element with specific id |
||
236 | 1 | elif t[1] == "id" and t[0] == "==": |
|
237 | # Build query |
||
238 | idquery = "%s(%i)" % (type_, t[2]) |
||
239 | # Store resulting query and its name |
||
240 | set_name = "s%i" % id(idquery) |
||
241 | result += "%s->.%s;" % (idquery, set_name) |
||
242 | set_names.append(set_name) |
||
243 | 1 | elif t[1] == "id": |
|
244 | # We got an id query, but not with equality comparison |
||
245 | raise ValueError("id can only be queried with equality") |
||
246 | # Everything else must be a tag query |
||
247 | else: |
||
248 | # Build query |
||
249 | 1 | tagquery = "%s[\"%s\"=\"%s\"]" % (type_, t[1], t[2]) |
|
250 | # Store resulting query and its name |
||
251 | 1 | set_name = "s%i" % id(tagquery) |
|
252 | 1 | result += "%s->.%s;" % (tagquery, set_name) |
|
253 | 1 | set_names.append(set_name) |
|
254 | |||
255 | # Check if any component of the bounding box was set |
||
256 | 1 | if bbox != [None, None, None, None]: |
|
257 | # Amend minima/maxima |
||
258 | 1 | if bbox[0] is None: |
|
259 | 1 | bbox[0] = -90.0 |
|
260 | 1 | if bbox[1] is None: |
|
261 | 1 | bbox[1] = -180.0 |
|
262 | 1 | if bbox[2] is None: |
|
263 | 1 | bbox[2] = 90.0 |
|
264 | 1 | if bbox[3] is None: |
|
265 | 1 | bbox[3] = 180.0 |
|
266 | |||
267 | # Build query |
||
268 | 1 | bboxquery = "%s(%s,%s,%s,%s)" % (type_, bbox[0], bbox[1], bbox[2], bbox[3]) |
|
269 | # Store resulting query and its name |
||
270 | 1 | set_name = "s%i" % id(bboxquery) |
|
271 | 1 | result += "%s->.%s;" % (bboxquery, set_name) |
|
272 | 1 | set_names.append(set_name) |
|
273 | |||
274 | # Build conjunction or disjunction according to current operation |
||
275 | 1 | if op == "&&": |
|
276 | # Conjunction, build an intersection |
||
277 | 1 | result += "%s." % type_ |
|
278 | 1 | result += ".".join(set_names) |
|
279 | 1 | elif op == "||": |
|
335 |