underpass 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -0
- data/lib/underpass/error_parser.rb +41 -12
- data/lib/underpass/shape.rb +9 -2
- data/lib/underpass/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5537c4b977692f332de7f6b4432f000da4c025005118521df1272d74719a6245
|
|
4
|
+
data.tar.gz: 83455326c173828d22cb7f983612e4c726e13047ef4dea721b304f5d722472b3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e91f105de2883607534d05c777c1bf83ae7f160461f33dbbb6a2ab273faf6ef9f93cfdf312c7bf21a161e7355325488c1ca4cb0c99c29251a94eabdbfbe85ab7
|
|
7
|
+
data.tar.gz: 0fca925ecf8188fb6aa16d62162b51c671336d90124c490bff82a9e02e31158d3b92a8f816338f1178f2a8dfdf6e50adfb61888eec15fb6fb31ccef29161b187
|
data/README.md
CHANGED
|
@@ -420,6 +420,19 @@ rescue Underpass::ApiError => e
|
|
|
420
420
|
end
|
|
421
421
|
```
|
|
422
422
|
|
|
423
|
+
For syntax errors (the most common 400 from Overpass), the structured data is just as rich:
|
|
424
|
+
|
|
425
|
+
```ruby
|
|
426
|
+
begin
|
|
427
|
+
Underpass::QL::Query.perform_raw('nod["amenity"="cafe"];')
|
|
428
|
+
rescue Underpass::ApiError => e
|
|
429
|
+
e.code # => "syntax"
|
|
430
|
+
e.http_status # => 400
|
|
431
|
+
e.error_message # => "Error: line 3: parse error: Unknown type \"nod\""
|
|
432
|
+
e.details # => { line: 3 }
|
|
433
|
+
end
|
|
434
|
+
```
|
|
435
|
+
|
|
423
436
|
### Error Codes
|
|
424
437
|
|
|
425
438
|
| Code | Description | HTTP Status |
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'cgi'
|
|
4
|
+
|
|
3
5
|
module Underpass
|
|
4
6
|
# Parses HTML error responses from the Overpass API into structured data.
|
|
5
7
|
#
|
|
@@ -35,26 +37,53 @@ module Underpass
|
|
|
35
37
|
|
|
36
38
|
# Extracts error text from HTML or returns the body as-is.
|
|
37
39
|
#
|
|
40
|
+
# Overpass sometimes wraps the real error message in a <p> and uses
|
|
41
|
+
# <strong> only as an inline label (e.g. "<p><strong>Error</strong>:
|
|
42
|
+
# line 3: parse error: ...</p>"). Scan every <p> first and prefer one
|
|
43
|
+
# whose stripped text matches a known pattern, so label-only <strong>
|
|
44
|
+
# tags don't swallow the useful content.
|
|
45
|
+
#
|
|
38
46
|
# @param body [String] the response body
|
|
39
47
|
# @return [String] the extracted error text
|
|
40
48
|
def self.extract_error_text(body)
|
|
41
49
|
return '' if body.nil? || body.empty?
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
end
|
|
51
|
+
paragraphs = extract_paragraphs(body)
|
|
52
|
+
from_paragraphs = pick_paragraph(paragraphs)
|
|
53
|
+
return CGI.unescapeHTML(from_paragraphs) if from_paragraphs
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return match[1].gsub(/<[^>]+>/, '').strip
|
|
51
|
-
end
|
|
55
|
+
from_strong = extract_strong_text(body)
|
|
56
|
+
return CGI.unescapeHTML(from_strong) unless from_strong.empty?
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
body.gsub(/<[^>]+>/, ' ').gsub(/\s+/, ' ').strip
|
|
58
|
+
CGI.unescapeHTML(body.gsub(/<[^>]+>/, ' ').gsub(/\s+/, ' ').strip)
|
|
55
59
|
end
|
|
56
60
|
private_class_method :extract_error_text
|
|
57
61
|
|
|
62
|
+
def self.extract_paragraphs(body)
|
|
63
|
+
body.scan(%r{<p[^>]*>(.*?)</p>}im)
|
|
64
|
+
.map { |m| m[0].gsub(/<[^>]+>/, '').strip }
|
|
65
|
+
.reject(&:empty?)
|
|
66
|
+
end
|
|
67
|
+
private_class_method :extract_paragraphs
|
|
68
|
+
|
|
69
|
+
# Picks the first paragraph matching a known pattern, or the last
|
|
70
|
+
# paragraph as a general-context fallback.
|
|
71
|
+
def self.pick_paragraph(paragraphs)
|
|
72
|
+
return if paragraphs.empty?
|
|
73
|
+
|
|
74
|
+
matched = paragraphs.find { |p| PATTERNS.each_value.any? { |rx| p.match?(rx) } }
|
|
75
|
+
matched || paragraphs.last
|
|
76
|
+
end
|
|
77
|
+
private_class_method :pick_paragraph
|
|
78
|
+
|
|
79
|
+
def self.extract_strong_text(body)
|
|
80
|
+
match = body.match(%r{<strong[^>]*>(.*?)</strong>}im)
|
|
81
|
+
return '' unless match
|
|
82
|
+
|
|
83
|
+
match[1].gsub(/<[^>]+>/, '').strip
|
|
84
|
+
end
|
|
85
|
+
private_class_method :extract_strong_text
|
|
86
|
+
|
|
58
87
|
# Parses the error text against known patterns.
|
|
59
88
|
#
|
|
60
89
|
# @param text [String] the extracted error text
|
|
@@ -84,9 +113,9 @@ module Underpass
|
|
|
84
113
|
private_class_method :parse_memory
|
|
85
114
|
|
|
86
115
|
def self.parse_syntax(text)
|
|
87
|
-
return unless
|
|
116
|
+
return unless text.match(PATTERNS[:syntax])
|
|
88
117
|
|
|
89
|
-
{ code: 'syntax', message:
|
|
118
|
+
{ code: 'syntax', message: text.strip, details: extract_syntax_details(text) }
|
|
90
119
|
end
|
|
91
120
|
private_class_method :parse_syntax
|
|
92
121
|
|
data/lib/underpass/shape.rb
CHANGED
|
@@ -20,8 +20,11 @@ module Underpass
|
|
|
20
20
|
#
|
|
21
21
|
# @param way [Hash] a parsed way element
|
|
22
22
|
# @param nodes [Hash{Integer => Hash}] node lookup table
|
|
23
|
-
# @return [RGeo::Feature::Polygon] the polygon geometry
|
|
23
|
+
# @return [RGeo::Feature::Polygon, nil] the polygon geometry, or +nil+
|
|
24
|
+
# if the way has fewer than 4 points
|
|
24
25
|
def polygon_from_way(way, nodes)
|
|
26
|
+
return nil if way[:nodes].size < 4
|
|
27
|
+
|
|
25
28
|
factory.polygon(line_string_from_way(way, nodes))
|
|
26
29
|
end
|
|
27
30
|
|
|
@@ -103,7 +106,11 @@ module Underpass
|
|
|
103
106
|
return [] if way_ids.empty?
|
|
104
107
|
|
|
105
108
|
sequences = WayChain.new(way_ids, ways).merged_sequences
|
|
106
|
-
sequences.
|
|
109
|
+
sequences.filter_map do |ids|
|
|
110
|
+
next if ids.size < 4
|
|
111
|
+
|
|
112
|
+
factory.linear_ring(points_from_node_ids(ids, nodes))
|
|
113
|
+
end
|
|
107
114
|
end
|
|
108
115
|
|
|
109
116
|
def matching_inner_rings(outer_ring, inner_rings)
|
data/lib/underpass/version.rb
CHANGED