enhanced_errors 0.1.4 → 0.1.6
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/README.md +57 -10
- data/benchmark/memory_bench.rb +78 -0
- data/doc/Binding.html +1 -1
- data/doc/Colors.html +1 -1
- data/doc/Debugging.html +1 -1
- data/doc/EnhancedErrors.html +197 -183
- data/doc/ErrorEnhancements.html +15 -9
- data/doc/_index.html +1 -1
- data/doc/file.README.html +42 -53
- data/doc/index.html +42 -53
- data/doc/top-level-namespace.html +38 -1
- data/enhanced_errors.gemspec +2 -2
- data/lib/enhanced_errors.rb +69 -12
- data/lib/error_enhancements.rb +7 -4
- metadata +6 -5
data/lib/enhanced_errors.rb
CHANGED
@@ -5,6 +5,20 @@ require_relative 'colors'
|
|
5
5
|
require_relative 'error_enhancements'
|
6
6
|
require_relative 'binding'
|
7
7
|
|
8
|
+
# While we could just catch StandardError, we would miss a number of things.
|
9
|
+
|
10
|
+
IGNORED_EXCEPTIONS = [
|
11
|
+
SystemExit,
|
12
|
+
NoMemoryError,
|
13
|
+
SignalException,
|
14
|
+
Interrupt,
|
15
|
+
ScriptError,
|
16
|
+
LoadError,
|
17
|
+
NotImplementedError,
|
18
|
+
SyntaxError,
|
19
|
+
SystemStackError
|
20
|
+
]
|
21
|
+
|
8
22
|
# The EnhancedErrors class provides mechanisms to enhance exception handling by capturing
|
9
23
|
# additional context such as binding information, variables, and method arguments when exceptions are raised.
|
10
24
|
# It offers customization options for formatting and filtering captured data.
|
@@ -147,7 +161,8 @@ class EnhancedErrors
|
|
147
161
|
# @param options [Hash] Additional configuration options.
|
148
162
|
# @yield [void] A block for additional configuration.
|
149
163
|
# @return [void]
|
150
|
-
def enhance!(enabled: true, debug: false, **options, &block)
|
164
|
+
def enhance!(enabled: true, debug: false, capture_events: default_capture_events, **options, &block)
|
165
|
+
capture_events = Array(capture_events)
|
151
166
|
@output_format = nil
|
152
167
|
@eligible_for_capture = nil
|
153
168
|
@original_global_variables = nil
|
@@ -160,6 +175,7 @@ class EnhancedErrors
|
|
160
175
|
@debug = debug
|
161
176
|
@original_global_variables = global_variables
|
162
177
|
|
178
|
+
validate_and_set_capture_events(capture_events)
|
163
179
|
options.each do |key, value|
|
164
180
|
setter_method = "#{key}="
|
165
181
|
if respond_to?(setter_method)
|
@@ -311,7 +327,7 @@ class EnhancedErrors
|
|
311
327
|
def apply_skip_list(binding_info)
|
312
328
|
unless @debug
|
313
329
|
variables = binding_info[:variables]
|
314
|
-
variables[:instances]&.reject! { |var, _| skip_list.include?(var) || var.to_s.start_with?('@
|
330
|
+
variables[:instances]&.reject! { |var, _| skip_list.include?(var) || (var.to_s.start_with?('@_') && !@debug) }
|
315
331
|
variables[:locals]&.reject! { |var, _| skip_list.include?(var) }
|
316
332
|
variables[:globals]&.reject! { |var, _| skip_list.include?(var) }
|
317
333
|
end
|
@@ -323,7 +339,7 @@ class EnhancedErrors
|
|
323
339
|
# @param binding_info [Hash] The binding information to validate.
|
324
340
|
# @return [Hash, nil] The validated binding information or `nil` if invalid.
|
325
341
|
def validate_binding_format(binding_info)
|
326
|
-
unless binding_info.keys.include?(:
|
342
|
+
unless binding_info.keys.include?(:capture_event) && binding_info[:variables].is_a?(Hash)
|
327
343
|
puts "Invalid binding_info format."
|
328
344
|
return nil
|
329
345
|
end
|
@@ -335,8 +351,8 @@ class EnhancedErrors
|
|
335
351
|
# @param binding_info [Hash] The binding information to format.
|
336
352
|
# @return [String] The formatted string.
|
337
353
|
def binding_info_string(binding_info)
|
338
|
-
|
339
|
-
result = "#{Colors.red(
|
354
|
+
capture_event = binding_info[:capture_event].to_s.capitalize
|
355
|
+
result = "#{Colors.red(capture_event)}: #{Colors.blue(binding_info[:source])}"
|
340
356
|
|
341
357
|
result += method_and_args_desc(binding_info[:method_and_args])
|
342
358
|
|
@@ -348,7 +364,6 @@ class EnhancedErrors
|
|
348
364
|
|
349
365
|
instance_vars_to_display = variables[:instances] || {}
|
350
366
|
|
351
|
-
|
352
367
|
if instance_vars_to_display && !instance_vars_to_display.empty?
|
353
368
|
result += "\n#{Colors.green('Instances:')}\n#{variable_description(instance_vars_to_display)}"
|
354
369
|
end
|
@@ -365,6 +380,11 @@ class EnhancedErrors
|
|
365
380
|
result = result[0...max_length] + "... (truncated)"
|
366
381
|
end
|
367
382
|
result + "\n"
|
383
|
+
rescue => e
|
384
|
+
# we swallow and don't re-raise to avoid any recursion problems. We don't want to
|
385
|
+
# mess up the original exception handling.
|
386
|
+
puts "EnhancedErrors error in binding_info_string: #{e.message} #{e.backtrace}"
|
387
|
+
return ''
|
368
388
|
end
|
369
389
|
|
370
390
|
private
|
@@ -375,11 +395,10 @@ class EnhancedErrors
|
|
375
395
|
def start_tracing
|
376
396
|
return if @trace && @trace.enabled?
|
377
397
|
|
378
|
-
events = [:raise]
|
379
|
-
events << :rescue if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
|
398
|
+
events = @capture_events ? @capture_events.to_a : [:raise]
|
380
399
|
|
381
400
|
@trace = TracePoint.new(*events) do |tp|
|
382
|
-
next if Thread.current[:enhanced_errors_processing] || tp.raised_exception
|
401
|
+
next if Thread.current[:enhanced_errors_processing] || IGNORED_EXCEPTIONS.include?(tp.raised_exception)
|
383
402
|
Thread.current[:enhanced_errors_processing] = true
|
384
403
|
exception = tp.raised_exception
|
385
404
|
capture_me = EnhancedErrors.eligible_for_capture.call(exception)
|
@@ -425,10 +444,9 @@ class EnhancedErrors
|
|
425
444
|
globals = (global_variables - @original_global_variables).map { |var|
|
426
445
|
[var, get_global_variable_value(var)]
|
427
446
|
}.to_h
|
428
|
-
puts "Global Variables: #{globals.inspect}"
|
429
447
|
end
|
430
448
|
|
431
|
-
|
449
|
+
capture_event = tp.event.to_s # 'raise' or 'rescue'
|
432
450
|
location = "#{tp.path}:#{tp.lineno}"
|
433
451
|
|
434
452
|
binding_info = {
|
@@ -444,7 +462,7 @@ class EnhancedErrors
|
|
444
462
|
globals: globals
|
445
463
|
},
|
446
464
|
exception: exception.class.name,
|
447
|
-
|
465
|
+
capture_event: capture_event.to_s
|
448
466
|
}
|
449
467
|
|
450
468
|
if on_capture_hook
|
@@ -469,6 +487,7 @@ class EnhancedErrors
|
|
469
487
|
@trace.enable
|
470
488
|
end
|
471
489
|
|
490
|
+
|
472
491
|
# Retrieves the current test name from RSpec, if available.
|
473
492
|
#
|
474
493
|
# @return [String, nil] The current test name or `nil` if not in a test context.
|
@@ -480,6 +499,42 @@ class EnhancedErrors
|
|
480
499
|
nil
|
481
500
|
end
|
482
501
|
|
502
|
+
# Helper method to determine the default capture types based on Ruby version
|
503
|
+
#
|
504
|
+
# @return [Set<Symbol>] The default set of capture types
|
505
|
+
def default_capture_events
|
506
|
+
default_events = [:raise]
|
507
|
+
default_events << :rescue if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
|
508
|
+
Set.new(default_events)
|
509
|
+
end
|
510
|
+
|
511
|
+
def validate_and_set_capture_events(capture_events)
|
512
|
+
if capture_events.nil? || !valid_capture_events?(capture_events)
|
513
|
+
puts "EnhancedErrors: Invalid capture_events provided. Falling back to defaults."
|
514
|
+
capture_events = default_capture_events
|
515
|
+
end
|
516
|
+
|
517
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.3.0') && capture_events.include?(:rescue)
|
518
|
+
puts "EnhancedErrors: Warning: :rescue capture_event is not supported in Ruby versions below 3.3.0 and will be ignored."
|
519
|
+
capture_events.delete(:rescue)
|
520
|
+
end
|
521
|
+
|
522
|
+
if capture_events.empty?
|
523
|
+
puts "No valid capture_events provided to EnhancedErrors.enhance! Falling back to defaults."
|
524
|
+
capture_events = default_capture_events
|
525
|
+
end
|
526
|
+
|
527
|
+
@capture_events = capture_events.to_a
|
528
|
+
end
|
529
|
+
|
530
|
+
|
531
|
+
# Validate capture_events: must be an Array or Set containing only :raise and/or :rescue.
|
532
|
+
def valid_capture_events?(capture_events)
|
533
|
+
return false unless capture_events.is_a?(Array) || capture_events.is_a?(Set)
|
534
|
+
valid_types = [:raise, :rescue].to_set
|
535
|
+
capture_events.to_set.subset?(valid_types)
|
536
|
+
end
|
537
|
+
|
483
538
|
# Extracts method arguments from the TracePoint binding.
|
484
539
|
#
|
485
540
|
# @param tp [TracePoint] The current TracePoint.
|
@@ -560,6 +615,8 @@ class EnhancedErrors
|
|
560
615
|
# @return [String] The formatted variable.
|
561
616
|
def format_variable(variable)
|
562
617
|
(awesome_print_available? && Colors.enabled?) ? variable.ai : variable.inspect
|
618
|
+
rescue => e
|
619
|
+
return "#{variable.to_s.truncate(30)}: [Inspection Error]"
|
563
620
|
end
|
564
621
|
|
565
622
|
# Checks if the `AwesomePrint` gem is available.
|
data/lib/error_enhancements.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
module ErrorEnhancements
|
2
2
|
def message
|
3
3
|
original_message = super()
|
4
|
-
|
4
|
+
if original_message.include?(variables_message)
|
5
|
+
original_message
|
6
|
+
else
|
7
|
+
"#{original_message}\n#{variables_message}"
|
8
|
+
end
|
5
9
|
rescue => e
|
6
|
-
puts "Error in message method: #{e.message}"
|
7
10
|
original_message
|
8
11
|
end
|
9
12
|
|
@@ -31,7 +34,7 @@ module ErrorEnhancements
|
|
31
34
|
bindings_of_interest = []
|
32
35
|
|
33
36
|
binding_infos.each do |info|
|
34
|
-
if info[:
|
37
|
+
if info[:capture_event] == 'raise' && !info[:library]
|
35
38
|
bindings_of_interest << info
|
36
39
|
break
|
37
40
|
end
|
@@ -43,7 +46,7 @@ module ErrorEnhancements
|
|
43
46
|
|
44
47
|
# find the last rescue binding if there is one
|
45
48
|
binding_infos.reverse.each do |info|
|
46
|
-
if info[:
|
49
|
+
if info[:capture_event] == 'rescue'
|
47
50
|
bindings_of_interest << info
|
48
51
|
break
|
49
52
|
end
|
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: 0.1.
|
4
|
+
version: 0.1.6
|
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-10
|
11
|
+
date: 2024-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -52,9 +52,9 @@ dependencies:
|
|
52
52
|
- - ">"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.9'
|
55
|
-
description:
|
56
|
-
|
57
|
-
|
55
|
+
description: 'EnhancedErrors will automatically enhance your errors with messages
|
56
|
+
containing variable values from the moment they were raised, using no extra dependencies,
|
57
|
+
and only Ruby''s built-in TracePoint. '
|
58
58
|
email:
|
59
59
|
executables: []
|
60
60
|
extensions: []
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- LICENSE
|
69
69
|
- README.md
|
70
70
|
- benchmark/benchmark.rb
|
71
|
+
- benchmark/memory_bench.rb
|
71
72
|
- benchmark/stackprofile.rb
|
72
73
|
- doc/Binding.html
|
73
74
|
- doc/Colors.html
|