justified 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/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Petr Chalupa <git@pitr.ch>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ require 'justified'
2
+
3
+ class StandardError
4
+ include Justified::Error
5
+ end
6
+
7
+
data/lib/justified.rb ADDED
@@ -0,0 +1,74 @@
1
+ module Justified
2
+ SKIP_STR = ' ... skipped %s lines'
3
+ CAUSED_STR = 'caused by:'
4
+
5
+ module Error
6
+ def initialize(message = nil, cause = $!)
7
+ super(message)
8
+ set_cause cause
9
+ @backtrace = nil
10
+ end
11
+
12
+ # Set cause of the exception
13
+ # @param [nil, Exception] exception
14
+ def cause=(exception)
15
+ set_cause exception
16
+ set_backtrace
17
+ end
18
+
19
+ # @return [Exception] cause of the exception
20
+ def cause
21
+ @cause
22
+ end
23
+
24
+ def set_backtrace(backtrace = nil)
25
+ @backtrace ||= backtrace
26
+ backtrace ||= @backtrace
27
+
28
+ if backtrace
29
+ unless cause
30
+ super backtrace
31
+ else
32
+ cause_backtrace, rest = split_cause_backtrace
33
+ same_line_count = calculate_same_line_count backtrace, cause_backtrace
34
+ cause_backtrace_striped = cause_backtrace[0..-(same_line_count+1)]
35
+
36
+ super backtrace +
37
+ ["#{CAUSED_STR} (#{cause.class}) #{cause.message}"] +
38
+ cause_backtrace_striped +
39
+ [SKIP_STR % same_line_count] +
40
+ recalculate_rest(rest, same_line_count)
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def set_cause(cause)
48
+ cause.nil? or exception.kind_of? Exception or
49
+ raise ArgumentError, 'cause must be kind of Exception'
50
+ @cause = cause
51
+ end
52
+
53
+ def split_cause_backtrace
54
+ _, cause_index = cause.backtrace.each_with_index.find { |line, _| line =~ /^#{CAUSED_STR}/ }
55
+ if cause_index
56
+ [cause.backtrace[0...cause_index], cause.backtrace[cause_index..-1]]
57
+ else
58
+ [cause.backtrace, []]
59
+ end
60
+ end
61
+
62
+ def recalculate_rest(rest, same_line_count)
63
+ rest.map do |line|
64
+ line.gsub(/^#{SKIP_STR % '(\d+)'}$/) do
65
+ SKIP_STR % ($1.to_i - same_line_count)
66
+ end
67
+ end
68
+ end
69
+
70
+ def calculate_same_line_count(backtrace, cause_backtrace)
71
+ backtrace.reverse.zip(cause_backtrace.reverse).select { |a, b| a == b }.size
72
+ end
73
+ end
74
+ end
data/spec/justified.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'pp'
4
+ require 'justified/standard_error'
5
+
6
+ class AnError < StandardError
7
+ end
8
+
9
+ class Test
10
+ def bad_code
11
+ raise AnError, 'bad'
12
+ end
13
+
14
+ def handle_error
15
+ raise AnError, 'something'
16
+ end
17
+
18
+ def something
19
+ bad_code
20
+ rescue
21
+ handle_error
22
+ end
23
+
24
+ def do_something
25
+ something
26
+ end
27
+ end
28
+
29
+
30
+ describe 'justified' do
31
+ let :error do
32
+ Test.new.do_something rescue $!
33
+ end
34
+
35
+ describe 'normal raise' do
36
+ it { error.message.must_equal 'something' }
37
+ it { error.cause.message.must_equal 'bad' }
38
+ it { error.backtrace.must_include 'caused by: (AnError) bad' }
39
+ it do
40
+ assert error.backtrace.any? { |l| l =~ %r"/justified/spec/justified\.rb:\d+:in `bad_code'" }
41
+ end
42
+ end
43
+
44
+ describe 'erasing cause' do
45
+ let :error2 do
46
+ error.tap { |e| e.cause = nil }
47
+ end
48
+
49
+ it { error2.message.must_equal 'something' }
50
+ it { error2.cause.must_be_nil }
51
+ it { error2.backtrace.wont_include 'caused by: (AnError) bad' }
52
+ it do
53
+ refute error2.backtrace.
54
+ any? { |l| l =~ %r"/justified/spec/justified\.rb:15:in `bad_code'" }
55
+ end
56
+ end
57
+
58
+ describe 'set different cause' do
59
+ let :error2 do
60
+ cause = raise('other') rescue $!
61
+ error.tap { |e| e.cause = cause }
62
+ end
63
+
64
+ it { error2.message.must_equal 'something' }
65
+ it { error2.cause.message.must_equal 'other' }
66
+ it { error2.backtrace.must_include 'caused by: (RuntimeError) other' }
67
+ it do
68
+ assert error2.backtrace.any? do |l|
69
+ l =~ %r"/justified/spec/justified\.rb:\d+:in `block \(\d levels\)'"
70
+ end
71
+ end
72
+ end
73
+
74
+ describe 'manual creation' do
75
+ let :error do
76
+ cause = raise('other') rescue $!
77
+ error = AnError.new 'something'
78
+ error.cause = cause
79
+ raise(error) rescue $!
80
+ end
81
+
82
+ it { error.message.must_equal 'something' }
83
+ it { error.cause.message.must_equal 'other' }
84
+ it { error.backtrace.must_include 'caused by: (RuntimeError) other' }
85
+ it do
86
+ assert error.backtrace.any? do |l|
87
+ l =~ %r"/justified/spec/justified\.rb:\d+:in `block \(\d levels\)'"
88
+ end
89
+ end
90
+ end
91
+
92
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: justified
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Petr Chalupa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: pry
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: yard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: redcarpet
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: github-markup
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: ! ' Provides causes for exceptions.
95
+
96
+ '
97
+ email: git@pitr.ch
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files:
101
+ - MIT-LICENSE
102
+ files:
103
+ - lib/justified/standard_error.rb
104
+ - lib/justified.rb
105
+ - MIT-LICENSE
106
+ - spec/justified.rb
107
+ homepage: https://github.com/pitr-ch/justified
108
+ licenses: []
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 1.8.23
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Exception causes
131
+ test_files:
132
+ - spec/justified.rb
133
+ has_rdoc: