xqsr3 0.17.2 → 0.18.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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdaa43c901071d88f6fe3737998e4cd6a741c69b
|
4
|
+
data.tar.gz: c6876d3f0814a79a4c9a37bcb313c834ebae4096
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 308f153ed24f39fa50494df2099e8978b5aa55c99b5b016a48ab03e73f9cff058f00d8056364a87695fe16497a0c1b3d70225c9146b4fb1e23bd4fd2cef250ca
|
7
|
+
data.tar.gz: 7590f907009d95b6057aec1573d7841c39ea2bbd8ff0713fa29356ae3d3836e39121c587285144db6d6f8e05019744caf493c6ead4682d1e648354b2e66c4c46
|
@@ -0,0 +1,194 @@
|
|
1
|
+
|
2
|
+
# ######################################################################## #
|
3
|
+
# File: lib/xqsr3/diagnostics/exceptions/with_cause.rb
|
4
|
+
#
|
5
|
+
# Purpose: Definition of the WithCause inclusion module
|
6
|
+
#
|
7
|
+
# Created: 16th December 2017
|
8
|
+
# Updated: 17th December 2017
|
9
|
+
#
|
10
|
+
# Home: http://github.com/synesissoftware/xqsr3
|
11
|
+
#
|
12
|
+
# Author: Matthew Wilson
|
13
|
+
#
|
14
|
+
# Copyright (c) 2017, Matthew Wilson and Synesis Software
|
15
|
+
# All rights reserved.
|
16
|
+
#
|
17
|
+
# Redistribution and use in source and binary forms, with or without
|
18
|
+
# modification, are permitted provided that the following conditions are
|
19
|
+
# met:
|
20
|
+
#
|
21
|
+
# * Redistributions of source code must retain the above copyright notice,
|
22
|
+
# this list of conditions and the following disclaimer.
|
23
|
+
#
|
24
|
+
# * Redistributions in binary form must reproduce the above copyright
|
25
|
+
# notice, this list of conditions and the following disclaimer in the
|
26
|
+
# documentation and/or other materials provided with the distribution.
|
27
|
+
#
|
28
|
+
# * Neither the names of the copyright holder nor the names of its
|
29
|
+
# contributors may be used to endorse or promote products derived from
|
30
|
+
# this software without specific prior written permission.
|
31
|
+
#
|
32
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
33
|
+
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
34
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
35
|
+
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
36
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
37
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
38
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
39
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
40
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
41
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
42
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
43
|
+
#
|
44
|
+
# ######################################################################## #
|
45
|
+
|
46
|
+
|
47
|
+
# ##########################################################
|
48
|
+
# ::Xqsr3::Diagnostics::Exceptions::WithCause
|
49
|
+
|
50
|
+
=begin
|
51
|
+
=end
|
52
|
+
|
53
|
+
module Xqsr3
|
54
|
+
module Diagnostics
|
55
|
+
module Exceptions
|
56
|
+
|
57
|
+
# This inclusion module adds to an exception class the means to chain a
|
58
|
+
# cause (aka inner-exception), which is then exposed with the +cause+
|
59
|
+
# attribute
|
60
|
+
#
|
61
|
+
# *Examples:*
|
62
|
+
#
|
63
|
+
# Passing an exception cause as a parameter
|
64
|
+
#
|
65
|
+
#
|
66
|
+
#
|
67
|
+
module WithCause
|
68
|
+
|
69
|
+
# Defines an initializer for an exception class that allows a cause (aka
|
70
|
+
# an inner exception) to be specified, either as the first or last
|
71
|
+
# argument or as a +:cause+ option
|
72
|
+
#
|
73
|
+
# === Signature
|
74
|
+
#
|
75
|
+
# * *Parameters:*
|
76
|
+
# -
|
77
|
+
# - +option+::
|
78
|
+
#
|
79
|
+
# * *Options:*
|
80
|
+
# - +:cause+ - The exception to be used as a cause, and ensures that
|
81
|
+
# that is not inferred from the arguments. May be +nil+ to ensure
|
82
|
+
# that no cause is inferred
|
83
|
+
def initialize(*args, **options)
|
84
|
+
|
85
|
+
@uses_cause_message = false
|
86
|
+
|
87
|
+
cz = options[:cause]
|
88
|
+
|
89
|
+
if cz
|
90
|
+
|
91
|
+
options = options.reject { |k, v| k == :cause }
|
92
|
+
|
93
|
+
@has_implicit_message = args.empty?
|
94
|
+
|
95
|
+
super *args
|
96
|
+
|
97
|
+
warn 'unexpected implicit message' if @has_implicit_message && self.message != self.class.to_s
|
98
|
+
|
99
|
+
@cause = cz
|
100
|
+
else
|
101
|
+
|
102
|
+
cz_ix = args.index { |arg| ::Exception === arg }
|
103
|
+
|
104
|
+
if cz_ix
|
105
|
+
|
106
|
+
args = args.dup
|
107
|
+
|
108
|
+
cz = args.delete_at cz_ix
|
109
|
+
|
110
|
+
if args.empty?
|
111
|
+
|
112
|
+
if !(cz.message || '').empty? && cz.class.to_s != cz.message
|
113
|
+
|
114
|
+
@uses_cause_message = true
|
115
|
+
|
116
|
+
args = [ cz.message ]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
else
|
120
|
+
|
121
|
+
cz = $!
|
122
|
+
end
|
123
|
+
|
124
|
+
@has_implicit_message = args.empty?
|
125
|
+
|
126
|
+
super *args
|
127
|
+
|
128
|
+
warn 'unexpected implicit message' if @has_implicit_message && self.message != self.class.to_s
|
129
|
+
|
130
|
+
@cause = cz
|
131
|
+
end
|
132
|
+
|
133
|
+
@options = options
|
134
|
+
end
|
135
|
+
|
136
|
+
# The cause / inner-exception, if any, specified to the instance
|
137
|
+
# initialiser
|
138
|
+
attr_reader :cause
|
139
|
+
|
140
|
+
# The options passed to the initialiser, with +:cause+ removed, if
|
141
|
+
# present
|
142
|
+
attr_reader :options
|
143
|
+
|
144
|
+
def chained_message **options
|
145
|
+
|
146
|
+
return message unless cause
|
147
|
+
return message if @uses_cause_message
|
148
|
+
|
149
|
+
m = message
|
150
|
+
c = cause
|
151
|
+
cm = c.respond_to?(:chained_message) ? c.chained_message(**options) : c.message
|
152
|
+
|
153
|
+
return m if (cm || '').empty?
|
154
|
+
return cm if (m || '').empty?
|
155
|
+
|
156
|
+
sep = options[:separator] || ': '
|
157
|
+
|
158
|
+
"#{m}#{sep}#{cm}"
|
159
|
+
end
|
160
|
+
|
161
|
+
# An array of exceptions in the chain, excluding +self+
|
162
|
+
def chainees
|
163
|
+
|
164
|
+
return [] unless cause
|
165
|
+
|
166
|
+
r = [ cause ]
|
167
|
+
|
168
|
+
r += cause.chainees if cause.respond_to? :chainees
|
169
|
+
|
170
|
+
r
|
171
|
+
end
|
172
|
+
|
173
|
+
# An array of exceptions in the chain, including +self+
|
174
|
+
def exceptions
|
175
|
+
|
176
|
+
[ self ] + chainees
|
177
|
+
end
|
178
|
+
|
179
|
+
# A combination of the backtrace(s) of all chained exception(s)
|
180
|
+
def chained_backtrace
|
181
|
+
|
182
|
+
b = backtrace
|
183
|
+
|
184
|
+
return b unless cause
|
185
|
+
|
186
|
+
cb = cause.respond_to?(:chained_backtrace) ? cause.chained_backtrace : cause.backtrace
|
187
|
+
|
188
|
+
(cb - b) + b
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end # module Exceptions
|
193
|
+
end # module Diagnostics
|
194
|
+
end # module Xqsr3
|
data/lib/xqsr3/version.rb
CHANGED
@@ -0,0 +1,262 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '../../../../lib')
|
4
|
+
|
5
|
+
require 'xqsr3/diagnostics/exceptions/with_cause'
|
6
|
+
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
class Test_WithCause < Test::Unit::TestCase
|
10
|
+
|
11
|
+
class SomeExceptionWithCause < ::Exception
|
12
|
+
|
13
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_no_ctor_args
|
17
|
+
|
18
|
+
x = SomeExceptionWithCause.new
|
19
|
+
|
20
|
+
assert_nil x.cause
|
21
|
+
assert_equal SomeExceptionWithCause.to_s, x.message
|
22
|
+
assert_equal SomeExceptionWithCause.to_s, x.chained_message
|
23
|
+
assert_empty x.chainees
|
24
|
+
assert_equal [ x ], x.exceptions
|
25
|
+
assert_nil x.backtrace
|
26
|
+
assert_empty x.options
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_1_ctor_arg_that_is_a_message
|
30
|
+
|
31
|
+
msg = 'stuff'
|
32
|
+
|
33
|
+
x = SomeExceptionWithCause.new msg
|
34
|
+
|
35
|
+
assert_nil x.cause
|
36
|
+
assert_equal msg, x.message
|
37
|
+
assert_equal msg, x.chained_message
|
38
|
+
assert_empty x.chainees
|
39
|
+
assert_equal [ x ], x.exceptions
|
40
|
+
assert_nil x.backtrace
|
41
|
+
assert_empty x.options
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_1_ctor_arg_that_is_a_cause_and_has_no_message
|
45
|
+
|
46
|
+
c = RuntimeError.new
|
47
|
+
|
48
|
+
x = SomeExceptionWithCause.new c
|
49
|
+
|
50
|
+
assert_not_nil x.cause
|
51
|
+
assert_equal SomeExceptionWithCause.to_s, x.message
|
52
|
+
assert_equal "#{SomeExceptionWithCause.to_s}: #{RuntimeError.to_s}", x.chained_message
|
53
|
+
assert_not_empty x.chainees
|
54
|
+
assert_equal [ c ], x.chainees
|
55
|
+
assert_equal [ x, c ], x.exceptions
|
56
|
+
assert_nil x.backtrace
|
57
|
+
assert_empty x.options
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_1_ctor_arg_that_is_a_cause_and_has_a_message
|
61
|
+
|
62
|
+
c = RuntimeError.new 'blah'
|
63
|
+
|
64
|
+
x = SomeExceptionWithCause.new c
|
65
|
+
|
66
|
+
assert_not_nil x.cause
|
67
|
+
assert_equal 'blah', x.message
|
68
|
+
assert_equal 'blah', x.chained_message
|
69
|
+
assert_not_empty x.chainees
|
70
|
+
assert_equal [ c ], x.chainees
|
71
|
+
assert_equal [ x, c ], x.exceptions
|
72
|
+
assert_nil x.backtrace
|
73
|
+
assert_empty x.options
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_2_ctor_args_that_are_message_and_cause
|
77
|
+
|
78
|
+
msg = 'stuff'
|
79
|
+
|
80
|
+
c = RuntimeError.new
|
81
|
+
|
82
|
+
x = SomeExceptionWithCause.new msg, c
|
83
|
+
|
84
|
+
assert_not_nil x.cause
|
85
|
+
assert_equal msg, x.message
|
86
|
+
assert_equal "#{msg}: #{RuntimeError.to_s}", x.chained_message
|
87
|
+
assert_not_empty x.chainees
|
88
|
+
assert_equal [ c ], x.chainees
|
89
|
+
assert_equal [ x, c ], x.exceptions
|
90
|
+
assert_nil x.backtrace
|
91
|
+
assert_empty x.options
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_2_ctor_args_that_are_message_and_cause_that_has_a_message
|
95
|
+
|
96
|
+
msg = 'stuff'
|
97
|
+
|
98
|
+
c = RuntimeError.new 'blah'
|
99
|
+
|
100
|
+
x = SomeExceptionWithCause.new msg, c
|
101
|
+
|
102
|
+
assert_not_nil x.cause
|
103
|
+
assert_equal msg, x.message
|
104
|
+
assert_equal 'stuff: blah', x.chained_message
|
105
|
+
|
106
|
+
assert_not_empty x.chainees
|
107
|
+
assert_equal [ c ], x.chainees
|
108
|
+
assert_equal [ x, c ], x.exceptions
|
109
|
+
assert_nil x.backtrace
|
110
|
+
assert_empty x.options
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_cause_in_options
|
114
|
+
|
115
|
+
c = RuntimeError.new 'inner'
|
116
|
+
|
117
|
+
x = SomeExceptionWithCause.new 'outer', cause: c
|
118
|
+
|
119
|
+
assert_not_nil x.cause
|
120
|
+
assert_equal 'outer', x.message
|
121
|
+
assert_equal 'outer: inner', x.chained_message
|
122
|
+
|
123
|
+
assert_not_empty x.chainees
|
124
|
+
assert_equal [ c ], x.chainees
|
125
|
+
assert_equal [ x, c ], x.exceptions
|
126
|
+
assert_nil x.backtrace
|
127
|
+
assert_empty x.options
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
class GrandchildException < Exception
|
133
|
+
|
134
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
135
|
+
end
|
136
|
+
|
137
|
+
class ChildException < Exception
|
138
|
+
|
139
|
+
def initialize(*args, **options)
|
140
|
+
|
141
|
+
super *args, **options
|
142
|
+
end
|
143
|
+
|
144
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
145
|
+
end
|
146
|
+
|
147
|
+
class ParentException < Exception
|
148
|
+
|
149
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
150
|
+
|
151
|
+
def initialize(*args, **options)
|
152
|
+
|
153
|
+
super *args, **options
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class GrandparentException < Exception
|
158
|
+
|
159
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def test_four_levels
|
164
|
+
|
165
|
+
gc = GrandchildException.new 'gc'
|
166
|
+
|
167
|
+
c = ChildException.new 'c', gc
|
168
|
+
|
169
|
+
p = ParentException.new c, 'p'
|
170
|
+
|
171
|
+
gp = GrandparentException.new 'gp', cause: p
|
172
|
+
|
173
|
+
assert_equal 'gp: p: c: gc', gp.chained_message
|
174
|
+
assert_equal 'gp-p-c-gc', gp.chained_message(separator: '-')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class Test_WithCause_throwing < Test::Unit::TestCase
|
179
|
+
|
180
|
+
class SomeExceptionWithCause < ::Exception
|
181
|
+
|
182
|
+
include ::Xqsr3::Diagnostics::Exceptions::WithCause
|
183
|
+
end
|
184
|
+
|
185
|
+
def f m
|
186
|
+
|
187
|
+
raise SomeExceptionWithCause, m
|
188
|
+
end
|
189
|
+
|
190
|
+
def g m, n
|
191
|
+
|
192
|
+
begin
|
193
|
+
|
194
|
+
f n
|
195
|
+
rescue Exception => x
|
196
|
+
|
197
|
+
raise SomeExceptionWithCause.new m, x
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def h m, n, o
|
202
|
+
|
203
|
+
begin
|
204
|
+
|
205
|
+
g n, 0
|
206
|
+
rescue Exception => x
|
207
|
+
|
208
|
+
raise SomeExceptionWithCause.new m, x
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_one_level
|
213
|
+
|
214
|
+
begin
|
215
|
+
|
216
|
+
f 'one-level'
|
217
|
+
|
218
|
+
assert false, 'should not get here!'
|
219
|
+
rescue Exception => x
|
220
|
+
|
221
|
+
assert_nil x.cause
|
222
|
+
assert_equal 'one-level', x.message
|
223
|
+
assert_equal 'one-level', x.chained_message
|
224
|
+
assert_empty x.chainees
|
225
|
+
assert_not_empty x.backtrace
|
226
|
+
|
227
|
+
x_bt0 = x.backtrace[0]
|
228
|
+
|
229
|
+
assert /:in\s+\`f\'\s*$/ =~ x_bt0, 'not receieved from f()'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_two_levels
|
234
|
+
|
235
|
+
begin
|
236
|
+
|
237
|
+
g 'two-levels', 'one-level'
|
238
|
+
|
239
|
+
assert false, 'should not get here!'
|
240
|
+
rescue Exception => x
|
241
|
+
|
242
|
+
assert_not_nil x.cause
|
243
|
+
assert_equal 'two-levels', x.message
|
244
|
+
assert_equal 'two-levels: one-level', x.chained_message
|
245
|
+
assert_not_empty x.chainees
|
246
|
+
assert_kind_of SomeExceptionWithCause, x.chainees[0]
|
247
|
+
assert_not_empty x.backtrace
|
248
|
+
assert_not_empty x.cause.backtrace
|
249
|
+
|
250
|
+
x_bt0 = x.backtrace[0]
|
251
|
+
|
252
|
+
assert /:in\s+\`rescue in g\'\s*$/ =~ x_bt0, 'not receieved from g()'
|
253
|
+
|
254
|
+
c_bt0 = x.cause.backtrace[0]
|
255
|
+
|
256
|
+
assert /:in\s+\`f\'\s*$/ =~ c_bt0, 'not receieved from f()'
|
257
|
+
|
258
|
+
assert_not_empty x.chained_backtrace
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# executes all other tests
|
4
|
+
|
5
|
+
this_dir = File.expand_path(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
# all tc_*rb in current directory
|
8
|
+
Dir[File.join(this_dir, 'tc_*rb')].each { |file| require file }
|
9
|
+
|
10
|
+
# all ts_*rb in immediate sub-directories
|
11
|
+
Dir[File.join(this_dir, '*', 'ts_*rb')].each { |file| require file }
|
12
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xqsr3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Wilson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
eXtensions by fine Quantum for Standard Ruby and 3rd-party libraries is a
|
@@ -25,6 +25,7 @@ files:
|
|
25
25
|
- lib/xqsr3/containers/multi_map.rb
|
26
26
|
- lib/xqsr3/conversion/bool_parser.rb
|
27
27
|
- lib/xqsr3/diagnostics/exception_utilities.rb
|
28
|
+
- lib/xqsr3/diagnostics/exceptions/with_cause.rb
|
28
29
|
- lib/xqsr3/doc_.rb
|
29
30
|
- lib/xqsr3/extensions/array/join_with_or.rb
|
30
31
|
- lib/xqsr3/extensions/enumerable/collect_with_index.rb
|
@@ -73,6 +74,8 @@ files:
|
|
73
74
|
- test/unit/containers/ts_all.rb
|
74
75
|
- test/unit/conversion/tc_to_bool.rb
|
75
76
|
- test/unit/conversion/ts_all.rb
|
77
|
+
- test/unit/diagnostics/exceptions/tc_with_cause.rb
|
78
|
+
- test/unit/diagnostics/exceptions/ts_all.rb
|
76
79
|
- test/unit/diagnostics/tc_exception_utilities.rb
|
77
80
|
- test/unit/diagnostics/ts_all.rb
|
78
81
|
- test/unit/extensions/enumerable/tc_collect_with_index.rb
|