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.
@@ -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