enhanced_errors 2.0.4 → 2.0.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 +4 -4
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/README.md +2 -16
- data/enhanced_errors.gemspec +1 -1
- data/lib/enhanced/colors.rb +5 -3
- data/lib/enhanced_errors.rb +63 -50
- metadata +2 -3
- data/lib/enhanced/integrations/rspec_error_failure_message.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e6ed241407a54376e0c64f2c1adc087e3dae4980ac5b7e84c947d92ff787392
|
4
|
+
data.tar.gz: 4f949a5145869e73e7f795a9c009800433956162a6d25695c2a9e8ba3a39da05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02312f5287c4214c59b4b4a53e723d53d4dff511f24c335a7f7a84f049bb06638f77ea22f488cba5682fba66f581116b2bb1a4b3a79d8b6a5a290f5f822f1ea8
|
7
|
+
data.tar.gz: 13d06fa670a3f34bb67624ec40bc9a87810536aace8c2867e64620092c13d8e48d25675241491d821491cb2f3a893c1d8faa2ede7ff2f22c45b50fb506fbbd74
|
data/.yardoc/checksums
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
lib/
|
2
|
-
lib/
|
3
|
-
lib/
|
4
|
-
lib/
|
1
|
+
lib/colors.rb a4314ef9531d4713907c3fea22955c943fdb8cf3
|
2
|
+
lib/binding.rb fdd7d5a2dd2edde22e3b10773510738dcdce4aeb
|
3
|
+
lib/enhanced_errors.rb d12ce0629f2565e5179ae5076be8a495e19ecda2
|
4
|
+
lib/error_enhancements.rb a97d0f139d35f6e1b5bf49386271b1f4cf71761c
|
data/.yardoc/object_types
CHANGED
Binary file
|
data/.yardoc/objects/root.dat
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -79,33 +79,19 @@ exceptions except those that pass by during the RSpec run.
|
|
79
79
|
```ruby
|
80
80
|
|
81
81
|
RSpec.configure do |config|
|
82
|
-
|
83
|
-
# add these config changes to your RSpec config to get variable messages
|
84
|
-
config.before(:suite) do
|
85
|
-
RSpec::Core::Example.prepend(Enhanced::Integrations::RSpecErrorFailureMessage)
|
86
|
-
end
|
87
|
-
|
88
82
|
config.before(:example) do |_example|
|
89
83
|
EnhancedErrors.start_rspec_binding_capture
|
90
84
|
end
|
91
85
|
|
92
86
|
config.after(:example) do |example|
|
93
87
|
example.metadata[:expect_binding] = EnhancedErrors.stop_rspec_binding_capture
|
88
|
+
EnhancedErrors.override_exception_message(example.exception, example.metadata[:expect_binding])
|
94
89
|
end
|
95
|
-
|
96
90
|
end
|
97
|
-
|
98
91
|
```
|
99
92
|
|
100
|
-
## Minitest
|
101
|
-
|
102
|
-
Untested as of yet, but enhance_exceptions!(override_messages: true) is likely to work.
|
93
|
+
## TODO: Minitest
|
103
94
|
|
104
|
-
If anyone wants to look into an integration implementation like RSpec, it would
|
105
|
-
be welcomed. With a more targeted approach like the RSpec one, exceptions could be captured and
|
106
|
-
modified only during test time, like the RSpec approach. This would be advantageous as
|
107
|
-
it wouldn't modify the exception message itself, but still makes the variable output available in
|
108
|
-
test messages.
|
109
95
|
|
110
96
|
## Enhancing .message
|
111
97
|
|
data/enhanced_errors.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "enhanced_errors"
|
3
|
-
spec.version = "2.0.
|
3
|
+
spec.version = "2.0.6"
|
4
4
|
spec.authors = ["Eric Beland"]
|
5
5
|
|
6
6
|
spec.summary = "Automatically enhance your errors with messages containing variable values from the moment they were raised."
|
data/lib/enhanced/colors.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Enhanced
|
2
2
|
class Colors
|
3
|
-
COLORS = { red: 31, green: 32, yellow: 33, blue: 34, purple: 35, cyan: 36, white: 0 }
|
3
|
+
COLORS = { red: 31, green: 32, yellow: 33, blue: 34, purple: 35, cyan: 36, white: 0 }.freeze
|
4
|
+
RESET_CODE = "\e[0m".freeze
|
4
5
|
|
5
6
|
class << self
|
6
7
|
def enabled?
|
@@ -12,11 +13,12 @@ module Enhanced
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def color(num, string)
|
15
|
-
|
16
|
+
return string unless @enabled
|
17
|
+
"#{code(num)}#{string}#{RESET_CODE}"
|
16
18
|
end
|
17
19
|
|
18
20
|
def code(num)
|
19
|
-
"\e[#{num}m"
|
21
|
+
"\e[#{num}m".freeze
|
20
22
|
end
|
21
23
|
|
22
24
|
COLORS.each do |color, code|
|
data/lib/enhanced_errors.rb
CHANGED
@@ -3,15 +3,13 @@
|
|
3
3
|
require 'set'
|
4
4
|
require 'json'
|
5
5
|
|
6
|
-
require_relative 'enhanced/integrations/rspec_error_failure_message'
|
7
6
|
require_relative 'enhanced/colors'
|
8
7
|
|
9
8
|
IGNORED_EXCEPTIONS = %w[SystemExit NoMemoryError SignalException Interrupt
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
ScriptError LoadError NotImplementedError SyntaxError
|
10
|
+
RSpec::Expectations::ExpectationNotMetError
|
11
|
+
RSpec::Matchers::BuiltIn::RaiseError
|
12
|
+
SystemStackError Psych::BadAlias]
|
15
13
|
|
16
14
|
class EnhancedErrors
|
17
15
|
extend ::Enhanced
|
@@ -22,17 +20,19 @@ class EnhancedErrors
|
|
22
20
|
:override_messages
|
23
21
|
|
24
22
|
GEMS_REGEX = %r{[\/\\]gems[\/\\]}
|
25
|
-
|
23
|
+
RSPEC_EXAMPLE_REGEXP = /RSpec::ExampleGroups::[A-Z0-9]+.*/
|
24
|
+
DEFAULT_MAX_LENGTH = 2000
|
26
25
|
|
27
26
|
# Maximum binding infos we will track per-exception instance. This is intended as an extra
|
28
27
|
# safety rail, not a normal scenario.
|
29
|
-
MAX_BINDING_INFOS =
|
28
|
+
MAX_BINDING_INFOS = 3
|
30
29
|
|
31
30
|
# Add @__memoized and @__inspect_output to the skip list so they don't appear in output
|
32
31
|
RSPEC_SKIP_LIST = Set.new([
|
33
32
|
:@assertions,
|
34
33
|
:@integration_session,
|
35
34
|
:@example,
|
35
|
+
:@assertion_delegator,
|
36
36
|
:@fixture_cache,
|
37
37
|
:@fixture_cache_key,
|
38
38
|
:@fixture_connections,
|
@@ -45,7 +45,7 @@ class EnhancedErrors
|
|
45
45
|
:@matcher_definitions,
|
46
46
|
:@__memoized,
|
47
47
|
:@__inspect_output
|
48
|
-
])
|
48
|
+
]).freeze
|
49
49
|
|
50
50
|
RAILS_SKIP_LIST = Set.new([
|
51
51
|
:@new_record,
|
@@ -53,8 +53,11 @@ class EnhancedErrors
|
|
53
53
|
:@association_cache,
|
54
54
|
:@readonly,
|
55
55
|
:@previously_new_record,
|
56
|
-
:@
|
56
|
+
:@_routes, # usually just shows #<ActionDispatch::Routing::RouteSet:0x000000016087d708>
|
57
|
+
:@routes,
|
58
|
+
:@app,
|
57
59
|
:@destroyed,
|
60
|
+
:@response, #usually big, gets truncated anyway
|
58
61
|
:@marked_for_destruction,
|
59
62
|
:@destroyed_by_association,
|
60
63
|
:@primary_key,
|
@@ -63,13 +66,16 @@ class EnhancedErrors
|
|
63
66
|
:@strict_loading_mode,
|
64
67
|
:@mutations_before_last_save,
|
65
68
|
:@mutations_from_database,
|
69
|
+
:@integration_session,
|
66
70
|
:@relation_delegate_cache,
|
67
71
|
:@predicate_builder,
|
68
72
|
:@generated_relation_method,
|
69
73
|
:@find_by_statement_cache,
|
70
74
|
:@arel_table,
|
71
75
|
:@response_klass,
|
72
|
-
])
|
76
|
+
]).freeze
|
77
|
+
|
78
|
+
DEFAULT_SKIP_LIST = (RAILS_SKIP_LIST + RSPEC_SKIP_LIST).freeze
|
73
79
|
|
74
80
|
@enabled = false
|
75
81
|
|
@@ -92,18 +98,15 @@ class EnhancedErrors
|
|
92
98
|
end
|
93
99
|
|
94
100
|
def skip_list
|
95
|
-
@skip_list ||=
|
96
|
-
end
|
97
|
-
|
98
|
-
def default_skip_list
|
99
|
-
Set.new(RAILS_SKIP_LIST).merge(RSPEC_SKIP_LIST)
|
101
|
+
@skip_list ||= DEFAULT_SKIP_LIST.dup
|
100
102
|
end
|
101
103
|
|
102
104
|
# takes an exception and bindings, calculates the variables message
|
103
105
|
# and modifies the exceptions .message to display the variables
|
104
106
|
def override_exception_message(exception, binding_or_bindings)
|
105
107
|
# Ensure binding_or_bindings is always an array for compatibility
|
106
|
-
return exception if binding_or_bindings.nil? || binding_or_bindings.empty?
|
108
|
+
return exception if binding_or_bindings.nil? || binding_or_bindings.empty?
|
109
|
+
return exception if exception.respond_to?(:unaltered_message)
|
107
110
|
variable_str = EnhancedErrors.format(binding_or_bindings)
|
108
111
|
message_str = exception.message
|
109
112
|
exception.define_singleton_method(:unaltered_message) { message_str }
|
@@ -125,21 +128,19 @@ class EnhancedErrors
|
|
125
128
|
@original_global_variables = nil
|
126
129
|
@override_messages = override_messages
|
127
130
|
|
128
|
-
if enabled
|
131
|
+
if !enabled
|
129
132
|
@original_global_variables = nil
|
130
133
|
@enabled = false
|
131
134
|
@trace&.disable
|
132
|
-
@trace = nil
|
133
135
|
else
|
134
136
|
# if there's an old one, disable it before replacing it
|
135
137
|
# this seems to actually matter, although it seems like it
|
136
138
|
# shouldn't
|
137
139
|
@trace&.disable
|
138
|
-
@trace = nil
|
139
140
|
|
140
141
|
@enabled = true
|
141
142
|
@debug = debug
|
142
|
-
@original_global_variables = global_variables
|
143
|
+
@original_global_variables = global_variables if @debug
|
143
144
|
|
144
145
|
options.each do |key, value|
|
145
146
|
setter_method = "#{key}="
|
@@ -177,36 +178,44 @@ class EnhancedErrors
|
|
177
178
|
|
178
179
|
def safely_prepend_rspec_custom_failure_message
|
179
180
|
return if @rspec_failure_message_loaded
|
180
|
-
if defined?(RSpec::Core::Example)
|
181
|
+
if defined?(RSpec::Core::Example) && !RSpec::Core::Example < Enhanced::Integrations::RSpecErrorFailureMessage
|
181
182
|
RSpec::Core::Example.prepend(Enhanced::Integrations::RSpecErrorFailureMessage)
|
182
183
|
@rspec_failure_message_loaded = true
|
183
|
-
else
|
184
|
-
|
185
184
|
end
|
186
185
|
rescue => e
|
187
|
-
puts "Failed "
|
186
|
+
puts "Failed to prepend RSpec custom failure message: #{e.message}"
|
188
187
|
end
|
189
188
|
|
190
189
|
def start_rspec_binding_capture
|
191
190
|
@rspec_example_binding = nil
|
191
|
+
@capture_next_binding = false
|
192
192
|
|
193
193
|
# In the Exception binding infos, I observed that re-setting
|
194
194
|
# the tracepoint without disabling it seemed to accumulate traces
|
195
195
|
# in the test suite where things are disabled and re-enabled often.
|
196
196
|
@rspec_tracepoint&.disable
|
197
|
-
@rspec_tracepoint = nil
|
198
197
|
|
199
|
-
@rspec_tracepoint = TracePoint.new(:b_return) do |tp|
|
198
|
+
@rspec_tracepoint = TracePoint.new(:raise, :b_return) do |tp|
|
200
199
|
# This is super-kluge-y and should be replaced with... something TBD
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
if
|
206
|
-
|
200
|
+
# only look at block returns once we have seen an ExpectationNotMetError
|
201
|
+
|
202
|
+
case tp.event
|
203
|
+
when :b_return
|
204
|
+
# only active if we are capturing the next binding
|
205
|
+
next unless @capture_next_binding && @rspec_example_binding.nil?
|
206
|
+
# early easy checks to nope out of the object name and other checks
|
207
|
+
if @capture_next_binding && tp.method_id.nil? && !(tp.path.include?('rspec')) && tp.path.end_with?('_spec.rb')
|
208
|
+
# fixes cases where class and name are screwed up or overridden
|
209
|
+
if determine_object_name(tp) =~ RSPEC_EXAMPLE_REGEXP
|
210
|
+
@rspec_example_binding = tp.binding
|
211
|
+
end
|
212
|
+
end
|
213
|
+
when :raise
|
214
|
+
# turn on capture of next binding
|
215
|
+
if tp.raised_exception.class.name == 'RSpec::Expectations::ExpectationNotMetError'
|
216
|
+
@capture_next_binding ||= true
|
207
217
|
end
|
208
218
|
end
|
209
|
-
|
210
219
|
end
|
211
220
|
|
212
221
|
@rspec_tracepoint.enable
|
@@ -214,8 +223,8 @@ class EnhancedErrors
|
|
214
223
|
|
215
224
|
def stop_rspec_binding_capture
|
216
225
|
@rspec_tracepoint&.disable
|
217
|
-
@rspec_tracepoint = nil
|
218
226
|
binding_info = convert_binding_to_binding_info(@rspec_example_binding) if @rspec_example_binding
|
227
|
+
@capture_next_binding = false
|
219
228
|
@rspec_example_binding = nil
|
220
229
|
binding_info
|
221
230
|
end
|
@@ -261,8 +270,7 @@ class EnhancedErrors
|
|
261
270
|
|
262
271
|
# Apply skip list to remove @__memoized and @__inspect_output from output
|
263
272
|
# but only after extracting let variables.
|
264
|
-
|
265
|
-
binding_info
|
273
|
+
default_on_capture(binding_info)
|
266
274
|
end
|
267
275
|
|
268
276
|
def eligible_for_capture(&block)
|
@@ -358,12 +366,11 @@ class EnhancedErrors
|
|
358
366
|
end
|
359
367
|
|
360
368
|
def apply_skip_list(binding_info)
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
end
|
369
|
+
variables = binding_info[:variables]
|
370
|
+
variables[:instances]&.reject! { |var, _| skip_list.include?(var) || (var.to_s.start_with?('@_') && !@debug) }
|
371
|
+
variables[:locals]&.reject! { |var, _| skip_list.include?(var) }
|
372
|
+
return binding_info unless @debug
|
373
|
+
variables[:globals]&.reject! { |var, _| skip_list.include?(var) }
|
367
374
|
binding_info
|
368
375
|
end
|
369
376
|
|
@@ -394,7 +401,7 @@ class EnhancedErrors
|
|
394
401
|
|
395
402
|
instance_vars_to_display = variables[:instances] || {}
|
396
403
|
|
397
|
-
|
404
|
+
unless instance_vars_to_display.empty?
|
398
405
|
result += "\n#{Colors.green('Instances:')}\n#{variable_description(instance_vars_to_display)}"
|
399
406
|
end
|
400
407
|
|
@@ -520,11 +527,12 @@ class EnhancedErrors
|
|
520
527
|
end
|
521
528
|
|
522
529
|
def default_capture_events
|
530
|
+
return @default_capture_events if @default_capture_events
|
523
531
|
events = [:raise]
|
524
532
|
if capture_rescue && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
|
525
533
|
events << :rescue
|
526
534
|
end
|
527
|
-
|
535
|
+
@default_capture_events = events
|
528
536
|
end
|
529
537
|
|
530
538
|
def validate_and_set_capture_events(capture_events)
|
@@ -624,7 +632,7 @@ class EnhancedErrors
|
|
624
632
|
|
625
633
|
def variable_description(vars_hash)
|
626
634
|
vars_hash.map do |name, value|
|
627
|
-
"
|
635
|
+
" #{Colors.purple(name)}: #{format_variable(value)}\n"
|
628
636
|
end.join
|
629
637
|
rescue
|
630
638
|
''
|
@@ -647,15 +655,20 @@ class EnhancedErrors
|
|
647
655
|
end
|
648
656
|
|
649
657
|
def safe_inspect(variable)
|
650
|
-
variable.inspect
|
658
|
+
str = variable.inspect
|
659
|
+
if str.length > 1200
|
660
|
+
str[0...1200] + '...'
|
661
|
+
else
|
662
|
+
str
|
663
|
+
end
|
651
664
|
rescue
|
652
665
|
safe_to_s(variable)
|
653
666
|
end
|
654
667
|
|
655
668
|
def safe_to_s(variable)
|
656
669
|
str = variable.to_s
|
657
|
-
if str.length >
|
658
|
-
str[0...
|
670
|
+
if str.length > 120
|
671
|
+
str[0...120] + '...'
|
659
672
|
else
|
660
673
|
str
|
661
674
|
end
|
@@ -689,4 +702,4 @@ class EnhancedErrors
|
|
689
702
|
!ignored && !rspec
|
690
703
|
end
|
691
704
|
end
|
692
|
-
end
|
705
|
+
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: 2.0.
|
4
|
+
version: 2.0.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-12-
|
11
|
+
date: 2024-12-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -96,7 +96,6 @@ files:
|
|
96
96
|
- examples/example_spec.rb
|
97
97
|
- lib/enhanced/colors.rb
|
98
98
|
- lib/enhanced/exception.rb
|
99
|
-
- lib/enhanced/integrations/rspec_error_failure_message.rb
|
100
99
|
- lib/enhanced_errors.rb
|
101
100
|
homepage: https://github.com/ericbeland/enhanced_errors
|
102
101
|
licenses: []
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Enhanced
|
2
|
-
module Integrations
|
3
|
-
module RSpecErrorFailureMessage
|
4
|
-
def execution_result
|
5
|
-
result = super
|
6
|
-
if result.exception
|
7
|
-
EnhancedErrors.override_exception_message(result.exception, self.metadata[:expect_binding])
|
8
|
-
end
|
9
|
-
result
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|