enhanced_errors 3.0.1 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- ScriptError LoadError NotImplementedError SyntaxError
12
- RSpec::Expectations::ExpectationNotMetError
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 = 2500
28
- MAX_BINDING_INFOS = 3
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
- case exception_obj
187
- when nil
188
- return nil
189
- when RSpec::Core::MultipleExceptionError
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, binding_or_bindings)
170
+ override_exception_message(exception, from_bindings + exception.binding_infos)
192
171
  end
193
- else
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
- # Only enable trace if still enabled and not limited
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, :b_return) do |tp|
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
- @capture_next_binding = :next_matching
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
- ci_env_vars = {
506
- 'CI' => ENV['CI'],
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.1
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-17 00:00:00.000000000 Z
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.3.26
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