enhanced_errors 3.0.1 → 3.0.3
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/.yardoc/checksums +2 -2
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/doc/Context.html +1 -1
- data/doc/Enhanced/Colors.html +1 -1
- data/doc/Enhanced.html +1 -1
- data/doc/EnhancedErrors.html +454 -899
- data/doc/EnhancedExceptionContext.html +1 -1
- data/doc/Exception.html +1 -1
- data/doc/ExceptionBindingInfos.html +1 -1
- data/doc/Minitest.html +4 -2
- data/doc/_index.html +1 -1
- data/doc/file.README.html +1 -1
- data/doc/index.html +1 -1
- data/doc/method_list.html +25 -81
- data/doc/top-level-namespace.html +4 -6
- data/enhanced_errors.gemspec +1 -1
- data/lib/enhanced/minitest_patch.rb +1 -0
- data/lib/enhanced_errors.rb +49 -106
- metadata +3 -3
data/lib/enhanced_errors.rb
CHANGED
@@ -7,11 +7,9 @@ require 'monitor'
|
|
7
7
|
require_relative 'enhanced/colors'
|
8
8
|
require_relative 'enhanced/exception'
|
9
9
|
|
10
|
-
IGNORED_EXCEPTIONS = %w[SystemExit NoMemoryError SignalException Interrupt
|
11
|
-
|
12
|
-
|
13
|
-
RSpec::Matchers::BuiltIn::RaiseError
|
14
|
-
SystemStackError Psych::BadAlias]
|
10
|
+
IGNORED_EXCEPTIONS = %w[SystemExit NoMemoryError SignalException Interrupt ScriptError LoadError
|
11
|
+
NotImplementedError SyntaxError RSpec::Expectations::ExpectationNotMetError
|
12
|
+
RSpec::Matchers::BuiltIn::RaiseError SystemStackError Psych::BadAlias]
|
15
13
|
|
16
14
|
class EnhancedErrors
|
17
15
|
extend ::Enhanced
|
@@ -24,8 +22,8 @@ class EnhancedErrors
|
|
24
22
|
attr_accessor :enabled, :config_block, :on_capture_hook, :eligible_for_capture, :exception_trace, :override_messages
|
25
23
|
|
26
24
|
GEMS_REGEX = %r{[\/\\]gems[\/\\]}
|
27
|
-
DEFAULT_MAX_CAPTURE_LENGTH =
|
28
|
-
MAX_BINDING_INFOS =
|
25
|
+
DEFAULT_MAX_CAPTURE_LENGTH = 2200
|
26
|
+
MAX_BINDING_INFOS = 2
|
29
27
|
|
30
28
|
RSPEC_SKIP_LIST = [
|
31
29
|
:@__inspect_output,
|
@@ -86,6 +84,16 @@ class EnhancedErrors
|
|
86
84
|
|
87
85
|
RSPEC_HANDLER_NAMES = ['RSpec::Expectations::PositiveExpectationHandler', 'RSpec::Expectations::NegativeExpectationHandler']
|
88
86
|
|
87
|
+
CI_ENV_VARS = {
|
88
|
+
'CI' => ENV['CI'],
|
89
|
+
'JENKINS' => ENV['JENKINS'],
|
90
|
+
'GITHUB_ACTIONS' => ENV['GITHUB_ACTIONS'],
|
91
|
+
'CIRCLECI' => ENV['CIRCLECI'],
|
92
|
+
'TRAVIS' => ENV['TRAVIS'],
|
93
|
+
'APPVEYOR' => ENV['APPVEYOR'],
|
94
|
+
'GITLAB_CI' => ENV['GITLAB_CI']
|
95
|
+
}
|
96
|
+
|
89
97
|
@enabled = nil
|
90
98
|
@max_capture_length = nil
|
91
99
|
@capture_rescue = nil
|
@@ -98,10 +106,6 @@ class EnhancedErrors
|
|
98
106
|
@exception_trace = nil
|
99
107
|
@override_messages = nil
|
100
108
|
|
101
|
-
# Default values
|
102
|
-
@max_capture_events = -1 # -1 means no limit
|
103
|
-
@capture_events_count = 0
|
104
|
-
|
105
109
|
# Thread-safe getters and setters
|
106
110
|
def enabled=(val)
|
107
111
|
mutex.synchronize { @enabled = val }
|
@@ -119,19 +123,6 @@ class EnhancedErrors
|
|
119
123
|
mutex.synchronize { @capture_rescue }
|
120
124
|
end
|
121
125
|
|
122
|
-
def capture_events_count
|
123
|
-
mutex.synchronize { @capture_events_count || 0 }
|
124
|
-
end
|
125
|
-
|
126
|
-
def capture_events_count=(val)
|
127
|
-
mutex.synchronize { @capture_events_count = val }
|
128
|
-
end
|
129
|
-
|
130
|
-
def max_capture_events
|
131
|
-
mutex.synchronize { @max_capture_events || -1 }
|
132
|
-
end
|
133
|
-
|
134
|
-
|
135
126
|
def max_capture_length
|
136
127
|
mutex.synchronize { @max_capture_length || DEFAULT_MAX_CAPTURE_LENGTH }
|
137
128
|
end
|
@@ -140,18 +131,6 @@ class EnhancedErrors
|
|
140
131
|
mutex.synchronize { @max_capture_length = value }
|
141
132
|
end
|
142
133
|
|
143
|
-
def max_capture_events=(value)
|
144
|
-
mutex.synchronize do
|
145
|
-
@max_capture_events = value
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def capture_limit_exceeded?
|
150
|
-
mutex.synchronize do
|
151
|
-
max_capture_events > 0 && capture_events_count >= max_capture_events
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
134
|
def disable_capturing!
|
156
135
|
mutex.synchronize do
|
157
136
|
@enabled = false
|
@@ -170,7 +149,6 @@ class EnhancedErrors
|
|
170
149
|
@rspec_tracepoint = nil
|
171
150
|
@minitest_trace = nil
|
172
151
|
@exception_trace = nil
|
173
|
-
@capture_events_count = 0
|
174
152
|
@enabled = true
|
175
153
|
end
|
176
154
|
end
|
@@ -183,25 +161,22 @@ class EnhancedErrors
|
|
183
161
|
|
184
162
|
def override_rspec_message(example, binding_or_bindings)
|
185
163
|
exception_obj = example.exception
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
164
|
+
return if exception_obj.nil?
|
165
|
+
|
166
|
+
from_bindings = [binding_or_bindings].flatten.compact
|
167
|
+
case exception_obj.class.to_s
|
168
|
+
when 'RSpec::Core::MultipleExceptionError'
|
190
169
|
exception_obj.all_exceptions.each do |exception|
|
191
|
-
override_exception_message(exception,
|
170
|
+
override_exception_message(exception, from_bindings + exception.binding_infos)
|
192
171
|
end
|
193
|
-
|
172
|
+
when 'RSpec::Expectations::ExpectationNotMetError'
|
194
173
|
override_exception_message(exception_obj, binding_or_bindings)
|
174
|
+
else
|
175
|
+
override_exception_message(exception_obj, from_bindings + exception_obj.binding_infos)
|
195
176
|
end
|
196
177
|
end
|
197
178
|
|
198
179
|
def override_exception_message(exception, binding_or_bindings)
|
199
|
-
return nil unless exception && exception.respond_to?(:message)
|
200
|
-
test_binding = !(binding_or_bindings.nil? || binding_or_bindings.empty?)
|
201
|
-
exception_binding = (exception.binding_infos.length > 0)
|
202
|
-
has_message = !(exception.respond_to?(:unaltered_message))
|
203
|
-
return nil unless (test_binding || exception_binding) && has_message
|
204
|
-
|
205
180
|
variable_str = EnhancedErrors.format(binding_or_bindings)
|
206
181
|
message_str = exception.message
|
207
182
|
exception.define_singleton_method(:unaltered_message) { message_str }
|
@@ -224,14 +199,8 @@ class EnhancedErrors
|
|
224
199
|
@output_format = nil
|
225
200
|
@eligible_for_capture = nil
|
226
201
|
@original_global_variables = nil
|
227
|
-
@override_messages = override_messages
|
228
|
-
|
229
|
-
# Ensure these are not nil
|
230
|
-
if @max_capture_events.nil?
|
231
|
-
@max_capture_events = -1
|
232
|
-
end
|
233
|
-
@capture_events_count ||= 0
|
234
202
|
|
203
|
+
@override_messages = override_messages
|
235
204
|
@rspec_failure_message_loaded = true
|
236
205
|
|
237
206
|
@enabled = enabled
|
@@ -252,32 +221,12 @@ class EnhancedErrors
|
|
252
221
|
|
253
222
|
validate_and_set_capture_events(capture_events)
|
254
223
|
|
255
|
-
# If max_capture_events == 0, capturing is off from the start.
|
256
|
-
if @max_capture_events == 0
|
257
|
-
@enabled = false
|
258
|
-
return
|
259
|
-
end
|
260
|
-
|
261
224
|
events = @capture_events ? @capture_events.to_a : default_capture_events
|
262
225
|
@exception_trace = TracePoint.new(*events) do |tp|
|
263
226
|
handle_tracepoint_event(tp)
|
264
227
|
end
|
265
228
|
|
266
|
-
|
267
|
-
if @enabled && (@max_capture_events == -1 || @capture_events_count < @max_capture_events)
|
268
|
-
@exception_trace.enable
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
def safe_prepend_module(target_class, mod)
|
274
|
-
mutex.synchronize do
|
275
|
-
if defined?(target_class) && target_class.is_a?(Module)
|
276
|
-
target_class.prepend(mod)
|
277
|
-
true
|
278
|
-
else
|
279
|
-
false
|
280
|
-
end
|
229
|
+
@exception_trace.enable if @enabled
|
281
230
|
end
|
282
231
|
end
|
283
232
|
|
@@ -286,6 +235,7 @@ class EnhancedErrors
|
|
286
235
|
end
|
287
236
|
|
288
237
|
def start_minitest_binding_capture
|
238
|
+
EnhancedExceptionContext.clear_all
|
289
239
|
@enabled = true if @enabled.nil?
|
290
240
|
return unless @enabled
|
291
241
|
mutex.synchronize do
|
@@ -298,7 +248,6 @@ class EnhancedErrors
|
|
298
248
|
end
|
299
249
|
|
300
250
|
def stop_minitest_binding_capture
|
301
|
-
disable_capturing! if capture_limit_exceeded?
|
302
251
|
mutex.synchronize do
|
303
252
|
@minitest_trace&.disable
|
304
253
|
@minitest_trace = nil
|
@@ -320,6 +269,7 @@ class EnhancedErrors
|
|
320
269
|
end
|
321
270
|
|
322
271
|
def start_rspec_binding_capture
|
272
|
+
EnhancedExceptionContext.clear_all
|
323
273
|
@enabled = true if @enabled.nil?
|
324
274
|
return unless @enabled
|
325
275
|
|
@@ -328,37 +278,38 @@ class EnhancedErrors
|
|
328
278
|
@capture_next_binding = false
|
329
279
|
@rspec_tracepoint&.disable
|
330
280
|
|
331
|
-
@rspec_tracepoint = TracePoint.new(:raise
|
332
|
-
# puts "name #{tp.raised_exception.class.name rescue ''} method:#{tp.method_id} tp.binding:#{tp.binding.local_variables rescue ''}"
|
333
|
-
# puts "event: #{tp.event} defined_class#{class_to_string(tp.defined_class)} #{tp.path}:#{tp.lineno} #{tp.callee_id} "
|
334
|
-
# This trickery below is to help us identify the anonymous block return we want to grab
|
335
|
-
# Very kluge-y and edge cases have grown it, but it works
|
336
|
-
if tp.event == :b_return
|
337
|
-
if RSPEC_HANDLER_NAMES.include?(class_to_string(tp.defined_class))
|
338
|
-
@capture_next_binding = :next
|
339
|
-
next
|
340
|
-
end
|
341
|
-
next unless @capture_next_binding
|
342
|
-
if @capture_next_binding == :next || @capture_next_binding == :next_matching && is_rspec_example?(tp)
|
343
|
-
@capture_next_binding = false
|
344
|
-
@rspec_example_binding = tp.binding
|
345
|
-
end
|
346
|
-
elsif tp.event == :raise
|
281
|
+
@rspec_tracepoint = TracePoint.new(:raise) do |tp|
|
347
282
|
class_name = tp.raised_exception.class.name
|
348
283
|
case class_name
|
349
284
|
when 'RSpec::Expectations::ExpectationNotMetError'
|
350
|
-
|
285
|
+
start_rspec_binding_trap
|
351
286
|
else
|
352
287
|
handle_tracepoint_event(tp)
|
353
288
|
end
|
354
289
|
end
|
355
290
|
end
|
356
291
|
@rspec_tracepoint.enable
|
292
|
+
end
|
293
|
+
|
294
|
+
# grab the next rspec binding that goes by, and then stop the expensive listening trace
|
295
|
+
def start_rspec_binding_trap
|
296
|
+
@rspec_binding_trap = TracePoint.new(:b_return) do |tp|
|
297
|
+
# kluge-y hack and will be a pain to maintain
|
298
|
+
if tp.callee_id == :handle_matcher
|
299
|
+
@capture_next_binding = :next
|
300
|
+
next
|
301
|
+
end
|
302
|
+
next unless @capture_next_binding
|
303
|
+
@capture_next_binding = false
|
304
|
+
@rspec_example_binding = tp.binding
|
305
|
+
@rspec_binding_trap.disable
|
306
|
+
@rspec_binding_trap = nil
|
357
307
|
end
|
308
|
+
@rspec_binding_trap.enable
|
358
309
|
end
|
359
310
|
|
311
|
+
|
360
312
|
def stop_rspec_binding_capture
|
361
|
-
disable_capturing! if capture_limit_exceeded?
|
362
313
|
mutex.synchronize do
|
363
314
|
@rspec_tracepoint&.disable
|
364
315
|
@rspec_tracepoint = nil
|
@@ -502,16 +453,8 @@ class EnhancedErrors
|
|
502
453
|
def running_in_ci?
|
503
454
|
mutex.synchronize do
|
504
455
|
return @running_in_ci if defined?(@running_in_ci)
|
505
|
-
|
506
|
-
|
507
|
-
'JENKINS' => ENV['JENKINS'],
|
508
|
-
'GITHUB_ACTIONS' => ENV['GITHUB_ACTIONS'],
|
509
|
-
'CIRCLECI' => ENV['CIRCLECI'],
|
510
|
-
'TRAVIS' => ENV['TRAVIS'],
|
511
|
-
'APPVEYOR' => ENV['APPVEYOR'],
|
512
|
-
'GITLAB_CI' => ENV['GITLAB_CI']
|
513
|
-
}
|
514
|
-
@running_in_ci = ci_env_vars.any? { |_, value| value.to_s.downcase == 'true' }
|
456
|
+
|
457
|
+
@running_in_ci = CI_ENV_VARS.any? { |_, value| value.to_s.downcase == 'true' }
|
515
458
|
end
|
516
459
|
end
|
517
460
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: enhanced_errors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Beland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
141
|
- !ruby/object:Gem::Version
|
142
142
|
version: '0'
|
143
143
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
144
|
+
rubygems_version: 3.5.22
|
145
145
|
signing_key:
|
146
146
|
specification_version: 4
|
147
147
|
summary: Automatically enhance your errors with messages containing variable values
|