backtracer 0.0.1
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.
- data/README +39 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/examples/crash.rb +10 -0
- data/examples/crash_longer.rb +22 -0
- data/examples/example_test_all_output +39 -0
- data/examples/example_test_large_output +42 -0
- data/examples/run_all_styles_of_backtracer.rb +12 -0
- data/examples/run_large_style_output.rb +1 -0
- data/lib/backtrace_nothing_swallowed.rb +6 -0
- data/lib/backtrace_with_code_and_locals.rb +2 -0
- data/lib/backtracer.rb +16 -0
- data/lib/core_backtracer.rb +277 -0
- metadata +70 -0
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
ruby_backtracer: a library to output higher quality backtraces if an unhandled exception is raised
|
2
|
+
|
3
|
+
ex:
|
4
|
+
running given script examples/crash.rb used to output:
|
5
|
+
examples>ruby crash.rb
|
6
|
+
crash.rb:2:in `go2': unhandled exception
|
7
|
+
from crash.rb:6:in `go'
|
8
|
+
from crash.rb:9
|
9
|
+
|
10
|
+
now outputs:
|
11
|
+
examples>ruby -r../backtrace_with_code_and_locals crash.rb
|
12
|
+
|
13
|
+
unhandled exception: crash.rb:2: raise
|
14
|
+
locals: {"a"=>"3", "b"=>55}
|
15
|
+
from:
|
16
|
+
crash.rb:1 go2(a=>3, b=>55)
|
17
|
+
locals: {"a"=>"3", "b"=>55}
|
18
|
+
crash.rb:5 go(a=>3)
|
19
|
+
locals: {"a"=>"3"}
|
20
|
+
|
21
|
+
Now wasn't that prettier?
|
22
|
+
|
23
|
+
There are several other tracing options provided, if you don't want as much output, or want more speed. Specify which by script name.
|
24
|
+
|
25
|
+
ex: backtrace_nothing_swallowed.rb outputs the same as the default exception output, except it doesn't have the
|
26
|
+
...skip 24 lines...
|
27
|
+
line in the middle (also no speed slowdown, and no local variables displayed).
|
28
|
+
|
29
|
+
Try them out by running test_all.rb in the examples folder, or eyeball the example output files in examples/example_output*
|
30
|
+
|
31
|
+
http://github.com/rogerdpack/ruby_backtracer/tree/master
|
32
|
+
|
33
|
+
Note: some options depends on ruby-debug [MRI] gem, some don't.
|
34
|
+
|
35
|
+
To install clone from github, above, then ruby -rscriptname your_script.
|
36
|
+
|
37
|
+
related projects: unroller, http://eigenclass.org/hiki/method+arguments+via+introspection, liveconsole, ruby-debug
|
38
|
+
|
39
|
+
send comments to rogerdpack on github.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "backtracer"
|
5
|
+
gemspec.summary = gemspec.description = "Quality backtraces for ruby"
|
6
|
+
gemspec.email = "rogerdpack@gmail.com"
|
7
|
+
# gemspec.homepage = "http://github.com/technicalpickles/the-perfect-gem"
|
8
|
+
# gemspec.description = "TODO"
|
9
|
+
# gemspec.authors = ["Josh Nichols"]
|
10
|
+
# gemspec.dependency
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
14
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/examples/crash.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# more "complicated" file to show off backtraces
|
2
|
+
def go2(a, b)
|
3
|
+
3
|
4
|
+
b = 3
|
5
|
+
within_go2 = 4
|
6
|
+
raise
|
7
|
+
end
|
8
|
+
def go(a);
|
9
|
+
within_go = 2
|
10
|
+
go2(a, 55);
|
11
|
+
'abc'
|
12
|
+
end
|
13
|
+
|
14
|
+
def does_nothing a
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
does_nothing 3
|
19
|
+
does_nothing 4
|
20
|
+
does_nothing 5
|
21
|
+
|
22
|
+
go '3'
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
running ruby -r../backtrace_nothing_swallowed.rb crash.rb
|
5
|
+
crash.rb:2:in `go2': unhandled exception
|
6
|
+
from crash.rb:6:in `go'
|
7
|
+
from crash.rb:9
|
8
|
+
====
|
9
|
+
crash.rb:2:in `go2'
|
10
|
+
crash.rb:6:in `go'
|
11
|
+
crash.rb:9
|
12
|
+
====
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
running ruby -r../backtrace_with_code.rb crash.rb
|
17
|
+
crash.rb:2:in `go2': unhandled exception
|
18
|
+
from crash.rb:6:in `go'
|
19
|
+
from crash.rb:9
|
20
|
+
====
|
21
|
+
crash.rb:2:in `go2'
|
22
|
+
raise
|
23
|
+
crash.rb:6:in `go'
|
24
|
+
go2(a, 55);
|
25
|
+
crash.rb:9
|
26
|
+
go '3'
|
27
|
+
====
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
running ruby -r../backtrace_with_code_and_locals.rb crash.rb
|
32
|
+
|
33
|
+
unhandled exception: crash.rb:2: raise
|
34
|
+
locals: {"a"=>"3", "b"=>55}
|
35
|
+
from:
|
36
|
+
crash.rb:1 go2(a=>3, b=>55)
|
37
|
+
locals: {"a"=>"3", "b"=>55}
|
38
|
+
crash.rb:5 go(a=>3)
|
39
|
+
locals: {"a"=>"3"}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
ruby 1.8.6 (2009-3-4 mbari 8B/0x8770 on patchlevel 287) [i686-linux]
|
2
|
+
#0:crash.rb:1::-: def go2(a, b)
|
3
|
+
|#0:crash.rb:1:Module:>: def go2(a, b)
|
4
|
+
args were []
|
5
|
+
#0:crash.rb:1:Module:<: def go2(a, b)
|
6
|
+
#0:crash.rb:5::-: def go(a);
|
7
|
+
|#0:crash.rb:5:Module:>: def go(a);
|
8
|
+
args were []
|
9
|
+
#0:crash.rb:5:Module:<: def go(a);
|
10
|
+
#0:crash.rb:9::-: go '3'
|
11
|
+
|#0:crash.rb:5:Object:>: def go(a);
|
12
|
+
args were [["a", "3"]]
|
13
|
+
|#0:crash.rb:6:Object:-: go2(a, 55);
|
14
|
+
| |#0:crash.rb:1:Object:>: def go2(a, b)
|
15
|
+
args were [["a", "3"], ["b", 55]]
|
16
|
+
| |#0:crash.rb:2:Object:-: raise
|
17
|
+
| | |#0:crash.rb:2:Kernel:>: raise
|
18
|
+
args were []
|
19
|
+
| | | |#0:crash.rb:2:Class:>: raise
|
20
|
+
args were []
|
21
|
+
| | | | |#0:crash.rb:2:Exception:>: raise
|
22
|
+
args were []
|
23
|
+
| | | |#0:crash.rb:2:Exception:<: raise
|
24
|
+
| | |#0:crash.rb:2:Class:<: raise
|
25
|
+
| | | |#0:crash.rb:2:Exception:>: raise
|
26
|
+
args were []
|
27
|
+
| | |#0:crash.rb:2:Exception:<: raise
|
28
|
+
| | | |#0:crash.rb:2:Exception:>: raise
|
29
|
+
args were []
|
30
|
+
| | |#0:crash.rb:2:Exception:<: raise
|
31
|
+
| | |#0:crash.rb:2:Object:R: raise
|
32
|
+
| |#0:crash.rb:2:Kernel:<: raise
|
33
|
+
|#0:crash.rb:3:Object:<: end
|
34
|
+
#0:crash.rb:7:Object:<: end
|
35
|
+
|
36
|
+
unhandled exception: crash.rb:2: raise
|
37
|
+
locals: {"a"=>"3", "b"=>55}
|
38
|
+
from:
|
39
|
+
crash.rb:1 go2(a=>3, b=>55)
|
40
|
+
locals: {"a"=>"3", "b"=>55}
|
41
|
+
crash.rb:5 go(a=>3)
|
42
|
+
locals: {"a"=>"3"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
for file in Dir.glob("../lib/backtrace_*") do
|
2
|
+
commands = []
|
3
|
+
for crash_file in ['crash.rb'] do
|
4
|
+
commands << "ruby -r#{file} #{crash_file}"
|
5
|
+
end
|
6
|
+
#commands << "ruby -v -r../backtrace_with_code_and_locals.rb ../crash.rb"
|
7
|
+
for command in commands
|
8
|
+
puts "\n\n\nrunning #{command}\n"
|
9
|
+
system(command)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
system "ruby -v -r../lib/backtrace_with_code_and_locals.rb crash.rb"
|
data/lib/backtracer.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# this one display full BT with code, at the end [no performance loss]
|
2
|
+
SCRIPT_LINES__ = {}
|
3
|
+
at_exit {
|
4
|
+
puts "==== "
|
5
|
+
|
6
|
+
backtrace_with_code = $!.backtrace.map{|bt|
|
7
|
+
file, line, junk = bt.split(":")
|
8
|
+
line = line.to_i - 1
|
9
|
+
actual_file = SCRIPT_LINES__[file]
|
10
|
+
actual_line = actual_file[line] if actual_file
|
11
|
+
"#{bt}\n\t#{actual_line.strip if actual_line}"
|
12
|
+
}
|
13
|
+
|
14
|
+
puts backtrace_with_code
|
15
|
+
puts "===="
|
16
|
+
}
|
@@ -0,0 +1,277 @@
|
|
1
|
+
#
|
2
|
+
# backtracer.rb - display backtrace of most recent error on exit [quality back trace, mind you]
|
3
|
+
# based off tracer.rb, unroller, python
|
4
|
+
# original tracer.rb by Keiju ISHITSUKA(Nippon Rational Inc.)
|
5
|
+
# Tons of the code is useless and could be removed, but at least it works
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'ruby-debug'
|
9
|
+
Debugger.start # we use this to track args.
|
10
|
+
|
11
|
+
#Debugger.keep_frame_binding = true # whatever this did :P
|
12
|
+
#
|
13
|
+
# tracer main class
|
14
|
+
#
|
15
|
+
class Tracer
|
16
|
+
@RCS_ID='-$Id: tracer.rb,v 1.8 1998/05/19 03:42:49 keiju Exp keiju $-'
|
17
|
+
|
18
|
+
@stdout = STDOUT
|
19
|
+
@verbose = false
|
20
|
+
class << self
|
21
|
+
attr :verbose, true
|
22
|
+
alias verbose? verbose
|
23
|
+
attr :stdout, true
|
24
|
+
end
|
25
|
+
|
26
|
+
EVENT_SYMBOL = {
|
27
|
+
"line" => "-",
|
28
|
+
"call" => ">",
|
29
|
+
"return" => "<",
|
30
|
+
"class" => "C",
|
31
|
+
"end" => "E",
|
32
|
+
"c-call" => ">",
|
33
|
+
"c-return" => "<",
|
34
|
+
"raise" => "R"
|
35
|
+
}
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@threads = Hash.new
|
39
|
+
if defined? Thread.main
|
40
|
+
@threads[Thread.main.object_id] = 0
|
41
|
+
else
|
42
|
+
@threads[Thread.current.object_id] = 0
|
43
|
+
end
|
44
|
+
|
45
|
+
@get_line_procs = {}
|
46
|
+
|
47
|
+
@filters = []
|
48
|
+
end
|
49
|
+
|
50
|
+
def stdout
|
51
|
+
Tracer.stdout
|
52
|
+
end
|
53
|
+
|
54
|
+
def on
|
55
|
+
if block_given?
|
56
|
+
on
|
57
|
+
begin
|
58
|
+
yield
|
59
|
+
ensure
|
60
|
+
off
|
61
|
+
end
|
62
|
+
else
|
63
|
+
set_trace_func method(:trace_func).to_proc
|
64
|
+
stdout.print "Trace on\n" if Tracer.verbose?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def off
|
69
|
+
set_trace_func nil
|
70
|
+
stdout.print "Trace off\n" if Tracer.verbose?
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_filter(p = proc)
|
74
|
+
@filters.push p
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_get_line_procs(file, p = proc)
|
78
|
+
@get_line_procs[file] = p
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_line(file, line)
|
82
|
+
self.class.get_line(file, line)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.get_line(file, line)
|
86
|
+
@get_line_procs ||= {}
|
87
|
+
if p = @get_line_procs[file]
|
88
|
+
return p.call(line)
|
89
|
+
end
|
90
|
+
|
91
|
+
unless list = SCRIPT_LINES__[file]
|
92
|
+
begin
|
93
|
+
f = open(file)
|
94
|
+
begin
|
95
|
+
SCRIPT_LINES__[file] = list = f.readlines
|
96
|
+
ensure
|
97
|
+
f.close
|
98
|
+
end
|
99
|
+
rescue
|
100
|
+
SCRIPT_LINES__[file] = list = []
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if l = list[line - 1]
|
105
|
+
l
|
106
|
+
else
|
107
|
+
"-\n"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_thread_no
|
112
|
+
if no = @threads[Thread.current.object_id]
|
113
|
+
no
|
114
|
+
else
|
115
|
+
@threads[Thread.current.object_id] = @threads.size
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
require 'pp'
|
120
|
+
@@depths = {} # I think I added this [rdp]
|
121
|
+
@@last_line = nil
|
122
|
+
@@last_file = nil
|
123
|
+
@@last_symbol = nil
|
124
|
+
def trace_func(event, file, line, id, binding, klass, *nothing)
|
125
|
+
begin
|
126
|
+
return if file == __FILE__
|
127
|
+
|
128
|
+
type = EVENT_SYMBOL[event] # "<" or ">"
|
129
|
+
thread_no = get_thread_no
|
130
|
+
Thread.current['backtrace'] ||= []
|
131
|
+
@@depths[thread_no] ||= 0
|
132
|
+
Thread.current['backtrace'] << nil if Thread.current['backtrace'].length < (@@depths[thread_no] ) # pad it :)
|
133
|
+
if type == ">"
|
134
|
+
@@depths[thread_no] += 1
|
135
|
+
elsif type == "<"
|
136
|
+
@@depths[thread_no] -= 1
|
137
|
+
end
|
138
|
+
|
139
|
+
for p in @filters
|
140
|
+
return unless p.call event, file, line, id, binding, klass
|
141
|
+
end
|
142
|
+
return if file.include? 'ruby-debug' # debugger output
|
143
|
+
|
144
|
+
saved_crit = Thread.critical
|
145
|
+
Thread.critical = true
|
146
|
+
# TODO only do the backtrace if last command was 'raise'
|
147
|
+
if type == 'R'
|
148
|
+
Thread.current['backtrace'][@@depths[thread_no] - 1] = [[file, line], [], binding]
|
149
|
+
Thread.current['backtrace'] = Thread.current['backtrace'][0..@@depths[thread_no]] # clear old stuffs
|
150
|
+
end
|
151
|
+
|
152
|
+
if [file, line] != @@last_line # for output sake [not output too many lines]
|
153
|
+
if @@last_symbol == '>' # then we need to add to the backtrace--we've advanced down a call in the callstack and can now glean its variables' values
|
154
|
+
previous_frame_binding = Debugger.current_context.frame_binding(2)
|
155
|
+
collected = []
|
156
|
+
args = Debugger.current_context.frame_args 1 rescue nil # maybe it had no arguments [ltodo check]
|
157
|
+
|
158
|
+
if args
|
159
|
+
for arg in args
|
160
|
+
value = eval(arg, previous_frame_binding)
|
161
|
+
collected << [arg, value]
|
162
|
+
end
|
163
|
+
else
|
164
|
+
print "WEIRD--please report err spot 1, how to reproduce"
|
165
|
+
end
|
166
|
+
print 'args were ', collected.inspect, "\n" if $VERBOSE
|
167
|
+
|
168
|
+
Thread.current['backtrace'][@@depths[thread_no] - 1] = [[@@last_file, @@last_line], collected, previous_frame_binding]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
out = " |" * @@depths[thread_no] + sprintf("#%d:%s:%d:%s:%s: %s",
|
173
|
+
get_thread_no,
|
174
|
+
file,
|
175
|
+
line,
|
176
|
+
klass || '',
|
177
|
+
type,
|
178
|
+
get_line(file, line))
|
179
|
+
|
180
|
+
print out if $VERBOSE
|
181
|
+
@@last_line = line
|
182
|
+
@@last_file = file
|
183
|
+
@@last_symbol = type
|
184
|
+
|
185
|
+
Thread.critical = saved_crit
|
186
|
+
rescue Exception => e
|
187
|
+
# TODO investigate print "BAD" + e.to_s + e.backtrace.inspect
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
Single = new
|
192
|
+
def Tracer.on
|
193
|
+
if block_given?
|
194
|
+
Single.on{yield}
|
195
|
+
else
|
196
|
+
Single.on
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def Tracer.off
|
201
|
+
Single.off
|
202
|
+
end
|
203
|
+
|
204
|
+
def Tracer.set_get_line_procs(file_name, p = proc)
|
205
|
+
Single.set_get_line_procs(file_name, p)
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def Tracer.add_filter(p = proc)
|
210
|
+
Single.add_filter(p)
|
211
|
+
end
|
212
|
+
|
213
|
+
def Tracer.output_locals(previous_binding, prefix="\t\t")
|
214
|
+
locals_name = Kernel.eval("local_variables", previous_binding)
|
215
|
+
locals = {}
|
216
|
+
for name in locals_name do
|
217
|
+
locals[name] = Kernel.eval(name, previous_binding)
|
218
|
+
end
|
219
|
+
|
220
|
+
puts "#{prefix}locals: " + locals.inspect
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
at_exit do # at_exit seems to be run by the last running Thread. Or an exiting thread? Not sure for always.
|
225
|
+
off
|
226
|
+
raise_location = Thread.current['backtrace'].pop
|
227
|
+
loc = raise_location[0]
|
228
|
+
puts
|
229
|
+
puts "unhandled exception: #{loc[0]}:#{loc[1]}: #{get_line loc[0], loc[1]}"
|
230
|
+
if(defined?($NO_LOCALS))
|
231
|
+
no_locals = true
|
232
|
+
else
|
233
|
+
no_locals = false
|
234
|
+
end
|
235
|
+
output_locals(raise_location[2], "\t") unless no_locals
|
236
|
+
puts "\t from:\n"
|
237
|
+
|
238
|
+
# last most one is redundant with the raise one...
|
239
|
+
Thread.current['backtrace'].pop
|
240
|
+
|
241
|
+
for loc, params, binding in Thread.current['backtrace'].reverse do
|
242
|
+
original_line = get_line loc[0], loc[1]
|
243
|
+
# TODO handle non parentheses
|
244
|
+
line_no_params = original_line.split('(')[0]
|
245
|
+
line_no_params.gsub!('def ', '')
|
246
|
+
line_params = line_no_params + "("
|
247
|
+
comma = ""
|
248
|
+
for param in params do
|
249
|
+
line_params += param[0].to_s + "=>" + param[1].to_s + ", "
|
250
|
+
comma = ", "
|
251
|
+
end
|
252
|
+
line_params = line_params[0..-3] # strip off ending comma
|
253
|
+
line_params += ")" if line_params =~ /\(/
|
254
|
+
puts "\t#{loc[0]}:#{loc[1]} #{line_params}"
|
255
|
+
output_locals binding unless no_locals
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
exit!
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
264
|
+
Tracer::on
|
265
|
+
if $0 == __FILE__
|
266
|
+
# direct call
|
267
|
+
|
268
|
+
$0 = ARGV[0]
|
269
|
+
ARGV.shift
|
270
|
+
Tracer.on
|
271
|
+
require $0
|
272
|
+
elsif caller(0).size == 1
|
273
|
+
Tracer.on
|
274
|
+
end
|
275
|
+
|
276
|
+
# TODO: do are arg snapshots capture it right [soon enough]?
|
277
|
+
# TODO: don't output error if none thrown :)
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: backtracer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors: []
|
7
|
+
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-29 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Quality backtraces for ruby
|
17
|
+
email: rogerdpack@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- Rakefile
|
27
|
+
- VERSION
|
28
|
+
- examples/crash.rb
|
29
|
+
- examples/crash_longer.rb
|
30
|
+
- examples/example_test_all_output
|
31
|
+
- examples/example_test_large_output
|
32
|
+
- examples/run_all_styles_of_backtracer.rb
|
33
|
+
- examples/run_large_style_output.rb
|
34
|
+
- lib/backtrace_nothing_swallowed.rb
|
35
|
+
- lib/backtrace_with_code_and_locals.rb
|
36
|
+
- lib/backtracer.rb
|
37
|
+
- lib/core_backtracer.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage:
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- --charset=UTF-8
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.3.5
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Quality backtraces for ruby
|
66
|
+
test_files:
|
67
|
+
- examples/crash.rb
|
68
|
+
- examples/crash_longer.rb
|
69
|
+
- examples/run_all_styles_of_backtracer.rb
|
70
|
+
- examples/run_large_style_output.rb
|