cartocss_helper 1.2.1 → 4.0.0
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 +7 -0
- data/lib/cartocss_helper.rb +56 -71
- data/lib/cartocss_helper/configuration.rb +84 -37
- data/lib/cartocss_helper/data_file_handling.rb +32 -35
- data/lib/cartocss_helper/git.rb +17 -27
- data/lib/cartocss_helper/heuristic.rb +39 -41
- data/lib/cartocss_helper/image_generator.rb +36 -38
- data/lib/cartocss_helper/notes_downloader.rb +46 -0
- data/lib/cartocss_helper/overpass_downloader.rb +42 -0
- data/lib/cartocss_helper/overpass_query_generator.rb +248 -0
- data/lib/cartocss_helper/renderer_handler.rb +116 -0
- data/lib/cartocss_helper/style_specific/default_osm_style.rb +722 -546
- data/lib/cartocss_helper/style_specific/style_specific.rb +4 -3
- data/lib/cartocss_helper/tag_lister.rb +136 -112
- data/lib/cartocss_helper/util/filehelper.rb +1 -1
- data/lib/cartocss_helper/util/generic_cached_downloader.rb +49 -0
- data/lib/cartocss_helper/util/generic_downloader.rb +65 -0
- data/lib/cartocss_helper/util/logger.rb +30 -0
- data/lib/cartocss_helper/util/rest-client_wrapper.rb +53 -0
- data/lib/cartocss_helper/util/systemhelper.rb +55 -0
- data/lib/cartocss_helper/validator.rb +142 -81
- data/lib/cartocss_helper/visualise_changes_diff_from_images.rb +36 -34
- data/lib/cartocss_helper/visualise_changes_image_generation.rb +72 -100
- data/lib/data/testing_locations.rb +17 -15
- data/readme.md +34 -9
- metadata +140 -39
- data/lib/cartocss_helper/downloader.rb +0 -301
- data/lib/cartocss_helper/tilemill_handler.rb +0 -38
@@ -1,11 +1,12 @@
|
|
1
1
|
module CartoCSSHelper
|
2
2
|
class StyleSpecificData
|
3
|
-
attr_reader :min_z, :max_z, :list_of_documented_tags, :list_of_documented_compositions
|
4
|
-
def initialize(min_z, max_z, list_of_documented_tags, list_of_documented_compositions)
|
3
|
+
attr_reader :min_z, :max_z, :list_of_documented_tags, :list_of_documented_compositions, :name_label_is_not_required
|
4
|
+
def initialize(min_z, max_z, list_of_documented_tags, list_of_documented_compositions, name_label_is_not_required)
|
5
5
|
@min_z = min_z
|
6
6
|
@max_z = max_z
|
7
7
|
@list_of_documented_tags = list_of_documented_tags
|
8
8
|
@list_of_documented_compositions = list_of_documented_compositions
|
9
|
+
@name_label_is_not_required = name_label_is_not_required
|
9
10
|
end
|
10
11
|
end
|
11
|
-
end
|
12
|
+
end
|
@@ -6,12 +6,13 @@ include CartoCSSHelper::Heuristic
|
|
6
6
|
module CartoCSSHelper
|
7
7
|
class TagRenderingStatus
|
8
8
|
attr_accessor :key, :value, :state, :composite
|
9
|
-
def initialize(key, value, state, composite=nil)
|
9
|
+
def initialize(key, value, state, composite = nil)
|
10
10
|
@key = key
|
11
11
|
@value = value
|
12
12
|
@state = state
|
13
13
|
@composite = composite
|
14
14
|
end
|
15
|
+
|
15
16
|
def print
|
16
17
|
composite_string = ''
|
17
18
|
if composite
|
@@ -19,60 +20,103 @@ module CartoCSSHelper
|
|
19
20
|
end
|
20
21
|
puts "#{@key}=#{@value} #{@state} #{composite_string}"
|
21
22
|
end
|
23
|
+
|
22
24
|
def code_print
|
23
25
|
string = "Status.new('#{@key}', '#{@value}', :#{@state}"
|
24
|
-
if @composite != nil
|
25
|
-
string << ", #{@composite.to_s}"
|
26
|
-
end
|
26
|
+
string << ", #{@composite}" if @composite != nil
|
27
27
|
string << '),'
|
28
28
|
puts string
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
class Info
|
33
|
-
def
|
34
|
-
CartoCSSHelper::Configuration.get_style_specific_data.list_of_documented_tags.each
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
33
|
+
def self.get_expected_state(key, value)
|
34
|
+
CartoCSSHelper::Configuration.get_style_specific_data.list_of_documented_tags.each do |documented|
|
35
|
+
next unless documented.key == key
|
36
|
+
return documented.state if documented.value == value
|
37
|
+
end
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_expected_composite(key, value)
|
42
|
+
CartoCSSHelper::Configuration.get_style_specific_data.list_of_documented_tags.each do |documented|
|
43
|
+
next unless documented.key == key
|
44
|
+
return documented.composite if documented.value == value
|
45
|
+
end
|
41
46
|
return nil
|
42
47
|
end
|
43
48
|
|
44
49
|
def print_render_state_of_tags(git_branch)
|
45
50
|
Git.checkout git_branch
|
46
|
-
get_render_state_of_tags.each
|
51
|
+
get_render_state_of_tags.each do |state|
|
47
52
|
state.code_print
|
48
|
-
|
53
|
+
end
|
49
54
|
end
|
50
55
|
|
51
|
-
def get_render_state_of_tags
|
56
|
+
def get_render_state_of_tags(quick_and_more_prone_to_errors)
|
52
57
|
states = []
|
53
58
|
@last_composite = nil
|
54
|
-
Heuristic.get_tags.each
|
59
|
+
Heuristic.get_tags.each do |tag|
|
55
60
|
key = tag[0]
|
56
61
|
value = tag[1]
|
57
|
-
#print_render_state_of_tag key, value
|
58
|
-
state = get_render_state_of_tag(key, value)
|
62
|
+
# print_render_state_of_tag key, value
|
63
|
+
state = get_render_state_of_tag(key, value, quick_and_more_prone_to_errors)
|
59
64
|
states.push(TagRenderingStatus.new(key, value, state, @last_composite))
|
60
|
-
|
65
|
+
end
|
61
66
|
return states
|
62
67
|
end
|
63
68
|
|
64
|
-
def get_render_state_of_tag(key, value)
|
65
|
-
if
|
69
|
+
def get_render_state_of_tag(key, value, quick_and_more_prone_to_errors)
|
70
|
+
if Info.get_expected_state(key, value) == :ignored
|
66
71
|
@last_composite = nil
|
72
|
+
return :ignored
|
73
|
+
end
|
74
|
+
zlevels = [22, 13] # TODO: - this is specially tuned for Default
|
75
|
+
expected_composite = Info.get_expected_composite(key, value)
|
76
|
+
if quick_and_more_prone_to_errors
|
77
|
+
return get_render_state_of_tag_quick_heurestic(key, value, expected_composite, zlevels)
|
78
|
+
end
|
79
|
+
return get_render_state_of_tag_thorough(key, value, expected_composite, zlevels)
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_render_state_of_tag_quick_heurestic
|
83
|
+
if expected_composite != nil
|
84
|
+
return assume_that_only_this_composite_can_match(key, value, zlevels, expected_composite)
|
85
|
+
else
|
86
|
+
return asssume_that_no_composite_will_match(key, value, zlevels)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def assume_that_only_this_composite_can_match(key, value, zlevels, expected_composite)
|
91
|
+
if is_rendered_as_composite key, value, expected_composite, zlevels
|
92
|
+
@last_composite = how_rendered_as_composite key, value, expected_composite, zlevels
|
93
|
+
return :composite
|
94
|
+
else
|
95
|
+
@last_composite = nil
|
96
|
+
return :ignored
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def asssume_that_no_composite_will_match(key, value, zlevels)
|
101
|
+
@last_composite = nil
|
102
|
+
if is_rendered key, value, zlevels
|
67
103
|
return :primary
|
68
104
|
else
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
105
|
+
return :ignored
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_render_state_of_tag_thorough(key, value, expected_composite, zlevels)
|
110
|
+
if is_rendered key, value, zlevels
|
111
|
+
@last_composite = nil
|
112
|
+
return :primary
|
113
|
+
end
|
114
|
+
if is_rendered_as_composite key, value, expected_composite
|
115
|
+
@last_composite = how_rendered_as_composite key, value, expected_composite
|
116
|
+
return :composite
|
117
|
+
else
|
118
|
+
@last_composite = nil
|
119
|
+
return :ignored
|
76
120
|
end
|
77
121
|
end
|
78
122
|
|
@@ -83,82 +127,69 @@ module CartoCSSHelper
|
|
83
127
|
puts "#{key}=#{value} - primary generic tag value"
|
84
128
|
elsif is_key_rendered_and_value_ignored(key, value)
|
85
129
|
puts "#{key}=#{value} - primary, but rendering the same as generic value"
|
86
|
-
elsif
|
87
|
-
puts "#{key}=#{value} - primary"
|
88
|
-
end
|
89
|
-
else
|
90
|
-
if is_rendered_as_composite key, value, @last_composite
|
91
|
-
@last_composite = how_rendered_as_composite key, value, @last_composite
|
92
|
-
puts "#{key}=#{value} - composite with #{@last_composite} - and maybe other tags"
|
93
130
|
else
|
94
|
-
|
95
|
-
puts "#{key}=#{value} - not displayed"
|
131
|
+
puts "#{key}=#{value} - primary"
|
96
132
|
end
|
133
|
+
elsif is_rendered_as_composite key, value, @last_composite
|
134
|
+
@last_composite = how_rendered_as_composite key, value, @last_composite
|
135
|
+
puts "#{key}=#{value} - composite with #{@last_composite} - and maybe other tags"
|
136
|
+
else
|
137
|
+
@last_composite = nil
|
138
|
+
puts "#{key}=#{value} - not displayed"
|
97
139
|
end
|
98
140
|
end
|
99
141
|
|
100
142
|
def is_key_rendered_and_value_ignored(key, value)
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
if !is_key_rendered_and_value_ignored_set(key, value, type, zlevel, on_water)
|
109
|
-
return false
|
110
|
-
end
|
143
|
+
return false if notis_rendered key, get_generic_tag_value
|
144
|
+
[false, true].each do |on_water|
|
145
|
+
[Configuration.get_max_z].each do |zlevel|
|
146
|
+
['area', 'closed_way', 'way', 'node'].each do |type|
|
147
|
+
next unless CartoCSSHelper::Info.rendered_on_zlevel({ key => value }, type, zlevel, on_water)
|
148
|
+
unless is_key_rendered_and_value_ignored_set(key, value, type, zlevel, on_water)
|
149
|
+
return false
|
111
150
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
115
154
|
return true
|
116
155
|
end
|
117
156
|
|
118
157
|
def is_key_rendered_and_value_ignored_set(key, value, type, zlevel, on_water)
|
119
|
-
with_tested_value = Scene.new({key => value}, zlevel, on_water, type)
|
120
|
-
with_generic_value = Scene.new({key => get_generic_tag_value}, zlevel, on_water, type)
|
158
|
+
with_tested_value = Scene.new({ key => value }, zlevel, on_water, type, true)
|
159
|
+
with_generic_value = Scene.new({ key => get_generic_tag_value }, zlevel, on_water, type, true)
|
121
160
|
return !with_tested_value.is_output_different(with_generic_value)
|
122
161
|
end
|
123
162
|
|
124
|
-
def is_rendered(key, value)
|
125
|
-
[false, true].each
|
126
|
-
|
127
|
-
['area', 'closed_way', 'way', 'node'].each
|
128
|
-
if CartoCSSHelper::Info.rendered_on_zlevel({key => value}, type, zlevel, on_water)
|
163
|
+
def is_rendered(key, value, zlevels = [Configuration.get_max_z]) # TODO: - note that some tags may be rendered up to X zoom level, but checking all zlevels would take too much time
|
164
|
+
[false, true].each do |on_water|
|
165
|
+
zlevels.each do |zlevel| #
|
166
|
+
['area', 'closed_way', 'way', 'node'].each do |type|
|
167
|
+
if CartoCSSHelper::Info.rendered_on_zlevel({ key => value }, type, zlevel, on_water)
|
129
168
|
return true
|
130
169
|
end
|
131
|
-
|
132
|
-
|
133
|
-
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
134
173
|
return false
|
135
174
|
end
|
136
175
|
|
137
|
-
def is_rendered_as_composite(key, value, suggested_composite=nil)
|
138
|
-
reason = how_rendered_as_composite key, value, suggested_composite
|
139
|
-
if reason == nil
|
140
|
-
return false
|
141
|
-
end
|
176
|
+
def is_rendered_as_composite(key, value, suggested_composite = nil, zlevels = [Configuration.get_max_z]) # TODO: - note that some tags may be rendered up to X zoom level, but checking all zlevels would take too much time
|
177
|
+
reason = how_rendered_as_composite key, value, suggested_composite, zlevels
|
178
|
+
return false if reason == nil
|
142
179
|
return true
|
143
180
|
end
|
144
181
|
|
145
|
-
def how_rendered_as_composite(key, value, suggested_composite)
|
146
|
-
[false, true].each
|
147
|
-
|
148
|
-
result = how_rendered_on_zlevel_as_composite({key => value}, 'closed_way', zlevel, on_water, suggested_composite)
|
149
|
-
if result != nil
|
150
|
-
|
151
|
-
|
152
|
-
result = how_rendered_on_zlevel_as_composite({key => value}, '
|
153
|
-
if result != nil
|
154
|
-
|
155
|
-
|
156
|
-
result = how_rendered_on_zlevel_as_composite({key => value}, 'node', zlevel, on_water, suggested_composite)
|
157
|
-
if result != nil
|
158
|
-
return result
|
159
|
-
end
|
160
|
-
}
|
161
|
-
}
|
182
|
+
def how_rendered_as_composite(key, value, suggested_composite, zlevels = [Configuration.get_max_z]) # TODO: - note that some tags may be rendered up to X zoom level, but checking all zlevels would take too much time
|
183
|
+
[false, true].each do |on_water|
|
184
|
+
zlevels.each do |zlevel|
|
185
|
+
result = how_rendered_on_zlevel_as_composite({ key => value }, 'closed_way', zlevel, on_water, suggested_composite)
|
186
|
+
return result if result != nil
|
187
|
+
result = how_rendered_on_zlevel_as_composite({ key => value }, 'way', zlevel, on_water, suggested_composite)
|
188
|
+
return result if result != nil
|
189
|
+
result = how_rendered_on_zlevel_as_composite({ key => value }, 'node', zlevel, on_water, suggested_composite)
|
190
|
+
return result if result != nil
|
191
|
+
end
|
192
|
+
end
|
162
193
|
if suggested_composite != nil
|
163
194
|
return how_rendered_as_composite key, value, nil
|
164
195
|
end
|
@@ -166,8 +197,8 @@ module CartoCSSHelper
|
|
166
197
|
end
|
167
198
|
|
168
199
|
def self.rendered_on_zlevel(tags, type, zlevel, on_water)
|
169
|
-
empty = Scene.new({}, zlevel, on_water, type)
|
170
|
-
tested = Scene.new(tags, zlevel, on_water, type)
|
200
|
+
empty = Scene.new({}, zlevel, on_water, type, true)
|
201
|
+
tested = Scene.new(tags, zlevel, on_water, type, true)
|
171
202
|
return tested.is_output_different(empty)
|
172
203
|
end
|
173
204
|
|
@@ -180,44 +211,37 @@ module CartoCSSHelper
|
|
180
211
|
end
|
181
212
|
return nil
|
182
213
|
end
|
183
|
-
CartoCSSHelper::Configuration.get_style_specific_data.list_of_documented_compositions.each
|
214
|
+
CartoCSSHelper::Configuration.get_style_specific_data.list_of_documented_compositions.each do |composite|
|
184
215
|
if is_rendered_with_this_composite tags, type, composite, zlevel, on_water
|
185
216
|
return composite
|
186
217
|
end
|
187
|
-
|
218
|
+
end
|
188
219
|
return nil
|
189
220
|
end
|
190
221
|
|
222
|
+
def deep_clone(input)
|
223
|
+
return Marshal.load(Marshal.dump(input))
|
224
|
+
end
|
225
|
+
|
191
226
|
def is_rendered_with_this_composite(tags, type, provided_composite, zlevel, on_water)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
tags_with_composite = Marshal.load(Marshal.dump(tags))
|
196
|
-
# noinspection RubyResolve
|
197
|
-
# see https://youtrack.jetbrains.com/issue/RUBY-16061
|
198
|
-
composite = Marshal.load(Marshal.dump(provided_composite))
|
199
|
-
composite.each { |key, value|
|
227
|
+
tags_with_composite = deep_clone(tags)
|
228
|
+
composite = deep_clone(provided_composite)
|
229
|
+
composite.each do |key, value|
|
200
230
|
if tags_with_composite[key] != nil
|
201
|
-
return false #shadowing
|
231
|
+
return false # shadowing
|
202
232
|
end
|
203
233
|
tags_with_composite[key] = value
|
204
|
-
}
|
205
|
-
with_composite = Scene.new(tags_with_composite, zlevel, on_water, type)
|
206
|
-
only_composite = Scene.new(composite, zlevel, on_water, type)
|
207
|
-
empty = Scene.new({}, zlevel, on_water, type)
|
208
|
-
if with_composite.is_output_different(empty)
|
209
|
-
if with_composite.is_output_different(only_composite)
|
210
|
-
if composite['area'] != nil
|
211
|
-
return true
|
212
|
-
end
|
213
|
-
composite['area'] = 'yes'
|
214
|
-
composite_interpreted_as_area = Scene.new(composite, zlevel, on_water, type)
|
215
|
-
if with_composite.is_output_different(composite_interpreted_as_area)
|
216
|
-
return true
|
217
|
-
end
|
218
|
-
end
|
219
234
|
end
|
220
|
-
|
235
|
+
with_composite = Scene.new(tags_with_composite, zlevel, on_water, type, true)
|
236
|
+
only_composite = Scene.new(composite, zlevel, on_water, type, true)
|
237
|
+
empty = Scene.new({}, zlevel, on_water, type, true)
|
238
|
+
return false if with_composite.is_output_identical(empty)
|
239
|
+
return false if with_composite.is_output_identical(only_composite)
|
240
|
+
return true if composite['area'] != nil
|
241
|
+
composite['area'] = 'yes'
|
242
|
+
composite_interpreted_as_area = Scene.new(composite, zlevel, on_water, type, true)
|
243
|
+
return false if with_composite.is_output_identical(composite_interpreted_as_area)
|
244
|
+
return true
|
221
245
|
end
|
222
246
|
end
|
223
|
-
end
|
247
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'generic_downloader.rb'
|
2
|
+
|
3
|
+
class GenericCachedDownloader
|
4
|
+
def initialize(timeout: 20, error_message: nil, stop_on_timeout: true, wrapper: RestClientWrapper.new)
|
5
|
+
@request_timeout = timeout
|
6
|
+
@error_message = error_message
|
7
|
+
@stop_on_timeout = stop_on_timeout
|
8
|
+
@wrapper = wrapper
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_specified_resource(url, cache_filename, description: nil, invalidate_cache: false)
|
12
|
+
cache = read_from_cache(cache_filename)
|
13
|
+
cache = nil if invalidate_cache
|
14
|
+
return cache if cache != nil
|
15
|
+
response = download(url, description)
|
16
|
+
write_cache(response, cache_filename)
|
17
|
+
|
18
|
+
return response
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_from_cache(cache_filename)
|
22
|
+
if File.exist?(cache_filename)
|
23
|
+
file = File.new(cache_filename)
|
24
|
+
cached = file.read
|
25
|
+
file.close
|
26
|
+
return cached
|
27
|
+
end
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_cache_timestamp(cache_filename)
|
32
|
+
return nil unless File.exist?(cache_filename)
|
33
|
+
f = File.new(cache_filename)
|
34
|
+
timestamp = f.mtime.to_i
|
35
|
+
f.close
|
36
|
+
return timestamp
|
37
|
+
end
|
38
|
+
|
39
|
+
def download(url, description)
|
40
|
+
downloader = GenericDownloader.new(timeout: @request_timeout, error_message: @error_message, stop_on_timeout: @stop_on_timeout, wrapper: @wrapper)
|
41
|
+
return downloader.get_specified_resource(url, description: description)
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_cache(response, cache_filename)
|
45
|
+
file = File.new(cache_filename, 'w')
|
46
|
+
file.write response
|
47
|
+
file.close
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'ruby-progressbar'
|
2
|
+
require_relative 'rest-client_wrapper.rb'
|
3
|
+
require_relative 'logger.rb'
|
4
|
+
|
5
|
+
class BuggyRestClient < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class ExceptionWithResponse < StandardError
|
9
|
+
attr_accessor :http_code, :response
|
10
|
+
end
|
11
|
+
|
12
|
+
class ExceptionWithoutResponse < StandardError
|
13
|
+
attr_accessor :http_code, :response
|
14
|
+
end
|
15
|
+
|
16
|
+
class RequestTimeout < StandardError
|
17
|
+
end
|
18
|
+
|
19
|
+
class GenericDownloader
|
20
|
+
def initialize(timeout: 20, error_message: nil, stop_on_timeout: true, wrapper: RestClientWrapper.new)
|
21
|
+
@request_timeout = timeout
|
22
|
+
@retry_count = 0
|
23
|
+
@error_message = error_message
|
24
|
+
@stop_on_timeout = stop_on_timeout
|
25
|
+
@wrapper = wrapper
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_retry_count
|
29
|
+
5
|
30
|
+
end
|
31
|
+
|
32
|
+
def output_shared_error_part(url, e)
|
33
|
+
Log.warn @error_message unless @error_message.nil?
|
34
|
+
Log.warn
|
35
|
+
Log.warn url
|
36
|
+
Log.warn
|
37
|
+
Log.warn e.class
|
38
|
+
Log.warn e
|
39
|
+
end
|
40
|
+
|
41
|
+
def retry_allowed(exception_with_response)
|
42
|
+
raise exception_with_response if @retry_count > max_retry_count
|
43
|
+
if @stop_on_timeout
|
44
|
+
raise exception_with_response if exception_with_response.is_a?(RequestTimeout)
|
45
|
+
end
|
46
|
+
if [429, 503, 504].include?(exception_with_response.http_code)
|
47
|
+
@retry_count += 1
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
raise exception_with_response
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_specified_resource(url, description: nil)
|
54
|
+
Log.info description if description
|
55
|
+
return @wrapper.fetch_data_from_url(url, @request_timeout)
|
56
|
+
rescue ExceptionWithResponse => e
|
57
|
+
output_shared_error_part(url, e)
|
58
|
+
Log.warn e.response
|
59
|
+
Log.warn e.http_code
|
60
|
+
get_specified_resource(url) if retry_allowed(e)
|
61
|
+
rescue ExceptionWithoutResponse => e
|
62
|
+
output_shared_error_part(url, e)
|
63
|
+
raise e
|
64
|
+
end
|
65
|
+
end
|