xqsr3 0.38.2 → 0.39.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -6
- data/examples/count_word_frequencies.md +12 -12
- data/examples/count_word_frequencies.rb +4 -4
- data/lib/xqsr3/array_utilities/join_with_or.rb +47 -47
- data/lib/xqsr3/array_utilities.rb +2 -2
- data/lib/xqsr3/command_line_utilities/map_option_string.rb +60 -60
- data/lib/xqsr3/command_line_utilities.rb +2 -2
- data/lib/xqsr3/containers/frequency_map.rb +399 -399
- data/lib/xqsr3/containers/multi_map.rb +448 -448
- data/lib/xqsr3/containers.rb +3 -3
- data/lib/xqsr3/conversion/bool_parser.rb +51 -51
- data/lib/xqsr3/conversion/integer_parser.rb +87 -87
- data/lib/xqsr3/conversion.rb +3 -3
- data/lib/xqsr3/diagnostics/exception_utilities.rb +145 -145
- data/lib/xqsr3/diagnostics/exceptions/with_cause.rb +90 -90
- data/lib/xqsr3/diagnostics/inspect_builder.rb +80 -80
- data/lib/xqsr3/diagnostics.rb +3 -3
- data/lib/xqsr3/doc_.rb +130 -130
- data/lib/xqsr3/extensions/array/join_with_or.rb +9 -9
- data/lib/xqsr3/extensions/enumerable/collect_with_index.rb +12 -12
- data/lib/xqsr3/extensions/enumerable/detect_map.rb +35 -35
- data/lib/xqsr3/extensions/enumerable/unique.rb +29 -28
- data/lib/xqsr3/extensions/hash/deep_transform.rb +1 -1
- data/lib/xqsr3/extensions/hash/except.rb +16 -16
- data/lib/xqsr3/extensions/hash/has_match.rb +10 -10
- data/lib/xqsr3/extensions/hash/match.rb +10 -10
- data/lib/xqsr3/extensions/hash/slice.rb +11 -11
- data/lib/xqsr3/extensions/hash.rb +1 -1
- data/lib/xqsr3/extensions/integer/to_s_grp.rb +118 -0
- data/lib/xqsr3/extensions/integer.rb +3 -0
- data/lib/xqsr3/extensions/io/writelines.rb +28 -28
- data/lib/xqsr3/extensions/kernel/integer.rb +20 -20
- data/lib/xqsr3/extensions/kernel/raise_with_options.rb +8 -8
- data/lib/xqsr3/extensions/kernel.rb +1 -0
- data/lib/xqsr3/extensions/string/ends_with.rb +1 -1
- data/lib/xqsr3/extensions/string/map_option_string.rb +4 -4
- data/lib/xqsr3/extensions/string/nil_if_empty.rb +1 -1
- data/lib/xqsr3/extensions/string/nil_if_whitespace.rb +1 -1
- data/lib/xqsr3/extensions/string/quote_if.rb +1 -1
- data/lib/xqsr3/extensions/string/starts_with.rb +1 -1
- data/lib/xqsr3/extensions/string/to_bool.rb +8 -8
- data/lib/xqsr3/extensions/string/to_symbol.rb +1 -1
- data/lib/xqsr3/extensions/string/truncate.rb +1 -1
- data/lib/xqsr3/extensions/test/unit/assert_eql.rb +10 -7
- data/lib/xqsr3/extensions/test/unit/assert_false.rb +9 -6
- data/lib/xqsr3/extensions/test/unit/assert_not.rb +9 -6
- data/lib/xqsr3/extensions/test/unit/assert_not_eql.rb +10 -7
- data/lib/xqsr3/extensions/test/unit/assert_raise_with_message.rb +61 -61
- data/lib/xqsr3/extensions/test/unit/assert_subclass_of.rb +10 -7
- data/lib/xqsr3/extensions/test/unit/assert_superclass_of.rb +10 -7
- data/lib/xqsr3/extensions/test/unit/assert_true.rb +9 -6
- data/lib/xqsr3/extensions/test/unit/assert_type_has_instance_methods.rb +39 -36
- data/lib/xqsr3/extensions.rb +5 -5
- data/lib/xqsr3/hash_utilities/deep_transform.rb +65 -65
- data/lib/xqsr3/hash_utilities/key_matching.rb +77 -77
- data/lib/xqsr3/hash_utilities.rb +3 -3
- data/lib/xqsr3/internal_/test_unit_version_.rb +83 -83
- data/lib/xqsr3/io/writelines.rb +122 -120
- data/lib/xqsr3/quality/parameter_checking.rb +445 -445
- data/lib/xqsr3/quality.rb +2 -2
- data/lib/xqsr3/string_utilities/ends_with.rb +59 -59
- data/lib/xqsr3/string_utilities/nil_if_empty.rb +28 -28
- data/lib/xqsr3/string_utilities/nil_if_whitespace.rb +29 -29
- data/lib/xqsr3/string_utilities/quote_if.rb +50 -50
- data/lib/xqsr3/string_utilities/starts_with.rb +59 -59
- data/lib/xqsr3/string_utilities/to_symbol.rb +75 -75
- data/lib/xqsr3/string_utilities/truncate.rb +55 -55
- data/lib/xqsr3/string_utilities.rb +8 -8
- data/lib/xqsr3/version.rb +12 -12
- data/test/performance/frequency_map.rb +12 -12
- data/test/scratch/test_assert_raise_with_message.rb +11 -11
- data/test/unit/array_utilities/tc_join_with_or.rb +140 -140
- data/test/unit/command_line_utilities/tc_map_option_string.rb +18 -18
- data/test/unit/containers/tc_frequency_map.rb +591 -591
- data/test/unit/containers/tc_multi_map.rb +558 -558
- data/test/unit/conversion/tc_integer_parser.rb +72 -72
- data/test/unit/conversion/tc_to_bool.rb +25 -25
- data/test/unit/diagnostics/exceptions/tc_with_cause.rb +165 -165
- data/test/unit/diagnostics/tc_exception_utilities.rb +156 -156
- data/test/unit/extensions/enumerable/tc_collect_with_index.rb +14 -14
- data/test/unit/extensions/enumerable/tc_detect_map.rb +20 -20
- data/test/unit/extensions/enumerable/tc_unique.rb +34 -34
- data/test/unit/extensions/hash/tc_deep_transform.rb +22 -22
- data/test/unit/extensions/hash/tc_except.rb +28 -28
- data/test/unit/extensions/hash/tc_slice.rb +13 -13
- data/test/unit/extensions/integer/tc_to_s_grp.rb +60 -0
- data/test/unit/extensions/integer/ts_all.rb +12 -0
- data/test/unit/extensions/io/tc_writelines.rb +149 -77
- data/test/unit/extensions/kernel/tc_integer.rb +75 -75
- data/test/unit/extensions/kernel/tc_raise_with_options.rb +155 -155
- data/test/unit/extensions/object/tc_inspect.rb +50 -50
- data/test/unit/extensions/string/tc_bool.tb +24 -24
- data/test/unit/extensions/string/tc_ends_with.rb +53 -53
- data/test/unit/extensions/string/tc_map_option_string.rb +15 -15
- data/test/unit/extensions/string/tc_nil_if_empty.rb +8 -8
- data/test/unit/extensions/string/tc_nil_if_whitespace.rb +8 -8
- data/test/unit/extensions/string/tc_quote_if.rb +18 -18
- data/test/unit/extensions/string/tc_starts_with.rb +53 -53
- data/test/unit/extensions/string/tc_to_symbol.rb +26 -26
- data/test/unit/extensions/string/tc_truncate.rb +18 -18
- data/test/unit/extensions/test/unit/tc_assert_raise_with_message.rb +16 -16
- data/test/unit/extensions/test/unit/tc_assert_subclass_of.rb +9 -9
- data/test/unit/extensions/test/unit/tc_assert_superclass_of.rb +9 -9
- data/test/unit/hash_utilities/tc_has_match.rb +70 -70
- data/test/unit/hash_utilities/tc_match.rb +83 -83
- data/test/unit/io/tc_writelines.rb +166 -106
- data/test/unit/quality/tc_parameter_checking.rb +389 -389
- data/test/unit/string_utilities/tc_truncate.rb +27 -27
- data/test/unit/tc_version.rb +15 -15
- metadata +6 -2
@@ -5,7 +5,7 @@
|
|
5
5
|
# Purpose: Definition of the ParameterChecking module
|
6
6
|
#
|
7
7
|
# Created: 12th February 2015
|
8
|
-
# Updated:
|
8
|
+
# Updated: 29th March 2024
|
9
9
|
#
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
11
11
|
#
|
@@ -60,627 +60,627 @@ module Quality
|
|
60
60
|
#
|
61
61
|
module ParameterChecking
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
63
|
+
private
|
64
|
+
# @!visibility private
|
65
|
+
module Util_ # :nodoc: all
|
66
|
+
|
67
|
+
def self.join_with_or a
|
68
|
+
|
69
|
+
case a.size
|
70
|
+
when 1
|
71
|
+
|
72
|
+
a[0]
|
73
|
+
when 2
|
74
|
+
|
75
|
+
"#{a[0]} or #{a[1]}"
|
76
|
+
else
|
77
|
+
|
78
|
+
"#{a[0...-1].join(', ')}, or #{a[-1]}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module Constants # :nodoc:
|
83
|
+
|
84
|
+
RECOGNISED_OPTION_NAMES = %w{
|
85
|
+
|
86
|
+
allow_nil
|
87
|
+
ignore_case
|
88
|
+
message
|
89
|
+
nil
|
90
|
+
nothrow
|
91
|
+
reject_empty
|
92
|
+
require_empty
|
93
|
+
responds_to
|
94
|
+
strip_str_whitespace
|
95
|
+
treat_as_option
|
96
|
+
type
|
97
|
+
types
|
98
|
+
values
|
99
|
+
}.map { |v| v.to_sym }
|
100
|
+
|
101
|
+
end # module Constants
|
102
|
+
end # module Util_
|
103
|
+
public
|
104
|
+
|
105
|
+
def self.included base # :nodoc:
|
106
|
+
|
107
|
+
base.extend self
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
# Check a given parameter (value=+value+, name=+name+) for type and value
|
112
|
+
#
|
113
|
+
# === Signature
|
114
|
+
#
|
115
|
+
# * *Parameters:*
|
116
|
+
# - +value+ the parameter whose value and type is to be checked
|
117
|
+
# - +name+ (::String, ::Symbol) the name of the parameter to be checked
|
118
|
+
# - +options+ (::Hash) options that moderate the behaviour
|
119
|
+
#
|
120
|
+
# * *Options:*
|
121
|
+
# - +:allow_nil+ (boolean) The +value+ must not be +nil+ unless this option is true
|
122
|
+
# - +:nil+ an alias for +:allow_nil+
|
123
|
+
# - +:ignore_case+ (boolean) When +:values+ is specified, comparisons of strings, or arrays of strings, will be carried out in a case-insensitive manner
|
124
|
+
# - +:types+ (::Array) An array of types one of which +value+ must be (or must be derived from). One of these types may be an array of types, in which case +value+ may be an array that must consist wholly of those types
|
125
|
+
# - +:type+ (::Class) A single type parameter, used only if +:types+ is not specified
|
126
|
+
# - +:values+ (::Array) an array of values one of which +value+ must be
|
127
|
+
# - +:responds_to+ (::Array) An array of symbols specifying all messages to which the parameter will respond
|
128
|
+
# - +:reject_empty+ (boolean) requires value to respond to +empty?+ message and to do so with false, unless +nil+
|
129
|
+
# - +:require_empty+ (boolean) requires value to respond to +empty?+ message and to do so with true, unless +nil+
|
130
|
+
# - +:nothrow+ (boolean) causes failure to be indicated by a +nil+ return rather than a thrown exception
|
131
|
+
# - +:message+ (::String) specifies a message to be used in any thrown exception, which suppresses internal message preparation
|
132
|
+
# - +:strip_str_whitespace+ (boolean) If +value+ is a string (as determined by responding to +to_str+ message), then it will be stripped - leading and trailing whitespace removed - before any processing
|
133
|
+
# - +:treat_as_option+ (boolean) If true, the value will be treated as an option when reporting check failure
|
134
|
+
#
|
135
|
+
# This method is private, because it should only be used within methods
|
136
|
+
def check_parameter value, name, options = {}, &block
|
137
|
+
|
138
|
+
Util_.check_parameter value, name, options, &block
|
139
|
+
end
|
140
|
+
|
141
|
+
# @see check_parameter
|
142
|
+
#
|
143
|
+
# @note This is obsolete, and will be removed in a future version.
|
144
|
+
# Please use +check_parameter+ instead
|
145
|
+
def check_param value, name, options = {}, &block
|
146
|
+
|
147
|
+
Util_.check_parameter value, name, options, &block
|
148
|
+
end
|
149
|
+
|
150
|
+
# Specific form of the +check_parameter()+ that is used to check
|
151
|
+
# options, taking instead the hash and the key
|
152
|
+
#
|
153
|
+
# === Signature
|
154
|
+
#
|
155
|
+
# * *Parameters:*
|
156
|
+
# - +h+ (::Hash) The options hash from which the named element is to be tested. May not be +nil+
|
157
|
+
# - +name+ (::String, ::Symbol, [ ::String, ::Symbol ]) The options key name, or an array of names. May not be +nil+
|
158
|
+
# - +options+ (::Hash) options that moderate the behaviour in the same way as for +check_parameter()+ except that the +:treat_as_option+ option (with the value +true+) is merged in before calling +check_parameter()+
|
159
|
+
#
|
160
|
+
# * *Options:*
|
161
|
+
def check_option h, name, options = {}, &block
|
162
|
+
|
163
|
+
Util_.check_option h, name, options, &block
|
164
|
+
end
|
165
|
+
|
166
|
+
public
|
167
|
+
# Check a given parameter (value=+value+, name=+name+) for type and value
|
168
|
+
#
|
169
|
+
# === Signature
|
170
|
+
#
|
171
|
+
# * *Parameters:*
|
172
|
+
# - +value+ the parameter whose value and type is to be checked
|
173
|
+
# - +name+ the name of the parameter to be checked
|
174
|
+
# - +options+ options
|
175
|
+
#
|
176
|
+
# * *Options:*
|
177
|
+
# - +:allow_nil+ (boolean) The +value+ must not be +nil+ unless this option is true
|
178
|
+
# - +:nil+ an alias for +:allow_nil+
|
179
|
+
# - +:ignore_case+ (boolean) When +:values+ is specified, comparisons of strings, or arrays of strings, will be carried out in a case-insensitive manner
|
180
|
+
# - +:types+ (::Array) An array of types one of which +value+ must be (or must be derived from). One of these types may be an array of types, in which case +value+ may be an array that must consist wholly of those types
|
181
|
+
# - +:type+ (::Class) A single type parameter, used only if +:types+ is not specified
|
182
|
+
# - +:values+ (::Array) an array of values one of which +value+ must be
|
183
|
+
# - +:responds_to+ (::Array) An array of symbols specifying all messages to which the parameter will respond
|
184
|
+
# - +:reject_empty+ (boolean) requires value to respond to +empty?+ message and to do so with false, unless +nil+
|
185
|
+
# - +:require_empty+ (boolean) requires value to respond to +empty?+ message and to do so with true, unless +nil+
|
186
|
+
# - +:nothrow+ (boolean) causes failure to be indicated by a +nil+ return rather than a thrown exception
|
187
|
+
# - +:message+ (boolean) specifies a message to be used in any thrown exception, which suppresses internal message preparation
|
188
|
+
# - +:treat_as_option+ (boolean) If true, the value will be treated as an option when reporting check failure
|
189
|
+
#
|
190
|
+
def self.check_parameter value, name, options = {}, &block
|
191
|
+
|
192
|
+
Util_.check_parameter value, name, options, &block
|
193
|
+
end
|
194
|
+
|
195
|
+
# @see check_parameter
|
196
|
+
#
|
197
|
+
# @note This is obsolete, and will be removed in a future version.
|
198
|
+
# Please use +check_parameter+ instead
|
199
|
+
def self.check_param value, name, options = {}, &block
|
200
|
+
|
201
|
+
Util_.check_parameter value, name, options, &block
|
202
|
+
end
|
203
|
+
|
204
|
+
# Specific form of the +check_parameter()+ that is used to check
|
205
|
+
# options, taking instead the hash and the key
|
206
|
+
#
|
207
|
+
# === Signature
|
208
|
+
#
|
209
|
+
# * *Parameters:*
|
210
|
+
# - +h+ (::Hash) The options hash from which the named element is to be tested. May not be +nil+
|
211
|
+
# - +name+ (::String, ::Symbol, [ ::String, ::Symbol ]) The options key name, or an array of names. May not be +nil+
|
212
|
+
# - +options+ (::Hash) options that moderate the behaviour in the same way as for +check_parameter()+ except that the +:treat_as_option+ option (with the value +true+) is merged in before calling +check_parameter()+
|
213
|
+
#
|
214
|
+
# * *Options:*
|
215
|
+
def self.check_option h, name, options = {}, &block
|
216
216
|
|
217
|
-
|
218
|
-
|
217
|
+
Util_.check_option h, name, options, &block
|
218
|
+
end
|
219
219
|
|
220
|
-
|
221
|
-
|
220
|
+
private
|
221
|
+
def Util_.check_option h, names, options = {}, &block
|
222
222
|
|
223
|
-
|
223
|
+
warn "#{self}::#{__method__}: given parameter h - value '#{h.inspect}' - must be a #{::Hash} but is a #{h.class}" unless ::Hash === h
|
224
224
|
|
225
|
-
|
226
|
-
|
225
|
+
case names
|
226
|
+
when ::Array
|
227
227
|
|
228
|
-
|
228
|
+
allow_nil = options[:allow_nil] || options[:nil]
|
229
229
|
|
230
|
-
|
230
|
+
# find the first item whose name is in the hash ...
|
231
231
|
|
232
|
-
|
232
|
+
found_name = names.find { |name| h.has_key?(name) }
|
233
233
|
|
234
|
-
|
234
|
+
if found_name.nil? && allow_nil
|
235
235
|
|
236
|
-
|
237
|
-
|
236
|
+
return nil
|
237
|
+
end
|
238
238
|
|
239
|
-
|
239
|
+
# ... or use the first (just to get a name for reporting)
|
240
240
|
|
241
|
-
|
241
|
+
found_name ||= names[0]
|
242
242
|
|
243
|
-
|
244
|
-
|
243
|
+
Util_.check_parameter h[found_name], found_name, options.merge({ treat_as_option: true }), &block
|
244
|
+
else
|
245
245
|
|
246
|
-
|
246
|
+
name = names
|
247
247
|
|
248
|
-
|
249
|
-
|
250
|
-
|
248
|
+
Util_.check_parameter h[name], name, options.merge({ treat_as_option: true }), &block
|
249
|
+
end
|
250
|
+
end
|
251
251
|
|
252
|
-
|
252
|
+
def Util_.check_parameter value, name, options, &block
|
253
253
|
|
254
|
-
|
254
|
+
if $DEBUG
|
255
255
|
|
256
|
-
|
256
|
+
unrecognised_option_names = options.keys - Util_::Constants::RECOGNISED_OPTION_NAMES
|
257
257
|
|
258
|
-
|
258
|
+
unless unrecognised_option_names.empty?
|
259
259
|
|
260
|
-
|
260
|
+
s = "#{self}::check_parameter: the following options are not recognised:"
|
261
261
|
|
262
|
-
|
262
|
+
unrecognised_option_names.each { |n| s += "\n\t'#{n}'" }
|
263
263
|
|
264
|
-
|
265
|
-
|
266
|
-
|
264
|
+
warn s
|
265
|
+
end
|
266
|
+
end
|
267
267
|
|
268
|
-
|
268
|
+
# strip whitespace
|
269
269
|
|
270
|
-
|
270
|
+
if !value.nil? && options[:strip_str_whitespace]
|
271
271
|
|
272
|
-
|
272
|
+
if value.respond_to? :to_str
|
273
273
|
|
274
|
-
|
275
|
-
|
274
|
+
value = value.to_str.strip
|
275
|
+
else
|
276
276
|
|
277
|
-
|
278
|
-
|
279
|
-
|
277
|
+
warn "#{self}::#{__method__}: options[:strip_str_whitespace] specified but value - '#{value}' (#{value.class}) - does not respond to to_str" unless value.respond_to? :to_str
|
278
|
+
end
|
279
|
+
end
|
280
280
|
|
281
281
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
282
|
+
failed_check = false
|
283
|
+
options ||= {}
|
284
|
+
message = options[:message]
|
285
|
+
treat_as_option = options[:treat_as_option]
|
286
|
+
param_s = treat_as_option ? 'option' : 'parameter'
|
287
|
+
allow_nil = options[:allow_nil] || options[:nil]
|
288
288
|
|
289
|
-
|
289
|
+
warn "#{self}::check_parameter: invoked with non-string/non-symbol name: name.class=#{name.class}" unless name && [ ::String, ::Symbol ].any? { |c| name.is_a?(c) }
|
290
290
|
|
291
|
-
|
291
|
+
if treat_as_option
|
292
292
|
|
293
|
-
|
294
|
-
|
293
|
+
case name
|
294
|
+
when ::String
|
295
295
|
|
296
|
-
|
297
|
-
|
296
|
+
;
|
297
|
+
when ::Symbol
|
298
298
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
299
|
+
name = ':' + name.to_s
|
300
|
+
else
|
301
|
+
end
|
302
|
+
end
|
303
303
|
|
304
304
|
|
305
|
-
|
305
|
+
# nil check
|
306
306
|
|
307
|
-
|
307
|
+
if value.nil? && !allow_nil
|
308
308
|
|
309
|
-
|
309
|
+
failed_check = true
|
310
310
|
|
311
|
-
|
311
|
+
unless options[:nothrow]
|
312
312
|
|
313
|
-
|
313
|
+
unless message
|
314
314
|
|
315
|
-
|
315
|
+
if name.nil?
|
316
316
|
|
317
|
-
|
318
|
-
|
317
|
+
message = "#{param_s} may not be nil"
|
318
|
+
else
|
319
319
|
|
320
|
-
|
321
|
-
|
322
|
-
|
320
|
+
message = "#{param_s} '#{name}' may not be nil"
|
321
|
+
end
|
322
|
+
end
|
323
323
|
|
324
|
-
|
325
|
-
|
326
|
-
|
324
|
+
raise ArgumentError, message
|
325
|
+
end
|
326
|
+
end
|
327
327
|
|
328
|
-
|
328
|
+
# check type(s)
|
329
329
|
|
330
|
-
|
330
|
+
unless value.nil?
|
331
331
|
|
332
|
-
|
332
|
+
# types
|
333
333
|
|
334
|
-
|
335
|
-
|
334
|
+
types = options[:types] || []
|
335
|
+
if options.has_key? :type
|
336
336
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
337
|
+
types << options[:type] if types.empty?
|
338
|
+
end
|
339
|
+
types = [value.class] if types.empty?
|
340
|
+
types = types.map { |type| :boolean == type ? [ ::TrueClass, ::FalseClass ] : type }.flatten if types.include?(:boolean)
|
341
341
|
|
342
|
-
|
343
|
-
|
342
|
+
warn "#{self}::check_parameter: options[:types] of type #{types.class} - should be #{::Array}" unless types.is_a?(Array)
|
343
|
+
warn "#{self}::check_parameter: options[:types] - '#{types}' - should contain only classes or arrays of classes" if types.is_a?(::Array) && !types.all? { |c| ::Class === c || (::Array === c && c.all? { |c2| ::Class === c2 }) }
|
344
344
|
|
345
|
-
|
345
|
+
unless types.any? do |t|
|
346
346
|
|
347
|
-
|
348
|
-
|
347
|
+
case t
|
348
|
+
when ::Class
|
349
349
|
|
350
|
-
|
351
|
-
|
352
|
-
|
350
|
+
# the (presumed) scalar argument is of type t?
|
351
|
+
value.is_a?(t)
|
352
|
+
when ::Array
|
353
353
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
354
|
+
# the (presumed) vector argument's elements are the
|
355
|
+
# possible types
|
356
|
+
value.all? { |v| t.any? { |t2| v.is_a?(t2) }} if ::Array === value
|
357
|
+
else
|
358
358
|
|
359
|
-
|
360
|
-
|
359
|
+
end
|
360
|
+
end then
|
361
361
|
|
362
|
-
|
362
|
+
failed_check = true
|
363
363
|
|
364
|
-
|
364
|
+
unless options[:nothrow]
|
365
365
|
|
366
|
-
|
366
|
+
unless message
|
367
367
|
|
368
|
-
|
368
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
369
369
|
|
370
|
-
|
371
|
-
|
370
|
+
types_0 = types.select { |t| ::Class === t }.uniq
|
371
|
+
types_ar = types.select { |t| ::Array === t }.flatten.uniq
|
372
372
|
|
373
|
-
|
373
|
+
if types_ar.empty?
|
374
374
|
|
375
|
-
|
375
|
+
s_types_0 = Util_.join_with_or types_0
|
376
376
|
|
377
|
-
|
378
|
-
|
377
|
+
message = "#{param_s} #{s_name}(#{value.class}) must be an instance of #{s_types_0}"
|
378
|
+
elsif types_0.empty?
|
379
379
|
|
380
|
-
|
380
|
+
s_types_ar = Util_.join_with_or types_ar
|
381
381
|
|
382
|
-
|
383
|
-
|
382
|
+
message = "#{param_s} #{s_name}(#{value.class}) must be an array containing instance(s) of #{s_types_ar}"
|
383
|
+
else
|
384
384
|
|
385
|
-
|
385
|
+
s_types_0 = Util_.join_with_or types_0
|
386
386
|
|
387
|
-
|
387
|
+
s_types_ar = Util_.join_with_or types_ar
|
388
388
|
|
389
|
-
|
390
|
-
|
391
|
-
|
389
|
+
message = "#{param_s} #{s_name}(#{value.class}) must be an instance of #{s_types_0}, or an array containing instance(s) of #{s_types_ar}"
|
390
|
+
end
|
391
|
+
end
|
392
392
|
|
393
|
-
|
394
|
-
|
395
|
-
|
393
|
+
raise TypeError, message
|
394
|
+
end
|
395
|
+
end
|
396
396
|
|
397
397
|
|
398
|
-
|
398
|
+
# messages
|
399
399
|
|
400
|
-
|
401
|
-
|
400
|
+
messages = options[:responds_to] || []
|
401
|
+
messages = [ messages ] unless messages.respond_to? :each
|
402
402
|
|
403
|
-
|
404
|
-
|
403
|
+
warn "#{self}::check_parameter: options[:responds_to] of type #{messages.class} - should be #{::Array}" unless messages.is_a?(Array)
|
404
|
+
warn "#{self}::check_parameter: options[:responds_to] should contain only symbols or strings" if messages.is_a?(::Array) && !messages.all? { |m| ::Symbol === m || ::String === m }
|
405
405
|
|
406
|
-
|
406
|
+
messages.each do |m|
|
407
407
|
|
408
|
-
|
408
|
+
unless value.respond_to? m
|
409
409
|
|
410
|
-
|
410
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
411
411
|
|
412
|
-
|
413
|
-
|
414
|
-
|
412
|
+
raise TypeError, "#{param_s} #{s_name}(#{value.class}) must respond to the '#{m}' message"
|
413
|
+
end
|
414
|
+
end
|
415
415
|
|
416
|
-
|
416
|
+
end
|
417
417
|
|
418
|
-
|
418
|
+
# reject/require empty?
|
419
419
|
|
420
|
-
|
420
|
+
unless value.nil?
|
421
421
|
|
422
|
-
|
422
|
+
if options[:reject_empty]
|
423
423
|
|
424
|
-
|
424
|
+
warn "#{self}::check_parameter: value '#{value}' of type #{value.class} does not respond to empty?" unless value.respond_to? :empty?
|
425
425
|
|
426
|
-
|
426
|
+
if value.empty?
|
427
427
|
|
428
|
-
|
428
|
+
failed_check = true
|
429
429
|
|
430
|
-
|
430
|
+
unless options[:nothrow]
|
431
431
|
|
432
|
-
|
433
|
-
|
432
|
+
unless message
|
433
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
434
434
|
|
435
|
-
|
436
|
-
|
435
|
+
message = "#{param_s} #{s_name}must not be empty"
|
436
|
+
end
|
437
437
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
438
|
+
raise ArgumentError, message
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
442
|
|
443
|
-
|
443
|
+
if options[:require_empty]
|
444
444
|
|
445
|
-
|
445
|
+
warn "#{self}::check_parameter: value '#{value}' of type #{value.class} does not respond to empty?" unless value.respond_to? :empty?
|
446
446
|
|
447
|
-
|
447
|
+
unless value.empty?
|
448
448
|
|
449
|
-
|
449
|
+
failed_check = true
|
450
450
|
|
451
|
-
|
451
|
+
unless options[:nothrow]
|
452
452
|
|
453
|
-
|
453
|
+
unless message
|
454
454
|
|
455
|
-
|
455
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
456
456
|
|
457
|
-
|
458
|
-
|
457
|
+
message = "#{param_s} #{s_name}must be empty"
|
458
|
+
end
|
459
459
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
460
|
+
raise ArgumentError, message
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
465
|
|
466
|
-
|
466
|
+
# run block
|
467
467
|
|
468
|
-
|
468
|
+
if value and block
|
469
469
|
|
470
|
-
|
470
|
+
warn "#{self}::check_parameter: block arity must be 1 or 2" unless (1..2).include? block.arity
|
471
471
|
|
472
|
-
|
472
|
+
r = nil
|
473
473
|
|
474
|
-
|
474
|
+
begin
|
475
475
|
|
476
|
-
|
476
|
+
if 1 == block.arity
|
477
477
|
|
478
|
-
|
479
|
-
|
478
|
+
r = block.call(value)
|
479
|
+
else
|
480
480
|
|
481
|
-
|
482
|
-
|
481
|
+
r = block.call(value, options)
|
482
|
+
end
|
483
483
|
|
484
|
-
|
484
|
+
rescue StandardError => x
|
485
485
|
|
486
|
-
|
486
|
+
xmsg = x.message || ''
|
487
487
|
|
488
|
-
|
488
|
+
if xmsg.empty?
|
489
489
|
|
490
|
-
|
490
|
+
xmsg ||= message
|
491
491
|
|
492
|
-
|
492
|
+
if xmsg.empty?
|
493
493
|
|
494
|
-
|
495
|
-
|
496
|
-
|
494
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
495
|
+
xmsg = "#{param_s} #{s_name}failed validation against caller-supplied block"
|
496
|
+
end
|
497
497
|
|
498
|
-
|
499
|
-
|
498
|
+
raise $!, xmsg, $!.backtrace
|
499
|
+
end
|
500
500
|
|
501
|
-
|
502
|
-
|
501
|
+
raise
|
502
|
+
end
|
503
503
|
|
504
|
-
|
504
|
+
if r.is_a?(::Exception)
|
505
505
|
|
506
|
-
|
507
|
-
|
506
|
+
# An exception returned from the block, so raise it, with
|
507
|
+
# its message or a custom message
|
508
508
|
|
509
|
-
|
510
|
-
|
509
|
+
x = r
|
510
|
+
xmsg = x.message || ''
|
511
511
|
|
512
|
-
|
512
|
+
if xmsg.empty?
|
513
513
|
|
514
|
-
|
514
|
+
xmsg ||= message
|
515
515
|
|
516
|
-
|
516
|
+
if xmsg.empty?
|
517
517
|
|
518
|
-
|
519
|
-
|
520
|
-
|
518
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
519
|
+
xmsg = "#{param_s} #{s_name}failed validation against caller-supplied block"
|
520
|
+
end
|
521
521
|
|
522
|
-
|
523
|
-
|
522
|
+
raise x, xmsg
|
523
|
+
end
|
524
524
|
|
525
|
-
|
525
|
+
raise x
|
526
526
|
|
527
|
-
|
527
|
+
elsif !r
|
528
528
|
|
529
|
-
|
529
|
+
failed_check = true
|
530
530
|
|
531
|
-
|
531
|
+
unless options[:nothrow]
|
532
532
|
|
533
|
-
|
534
|
-
|
533
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
534
|
+
xmsg = "#{param_s} #{s_name}failed validation against caller-supplied block"
|
535
535
|
|
536
|
-
|
536
|
+
if value.is_a?(::Numeric)
|
537
537
|
|
538
|
-
|
539
|
-
|
538
|
+
raise RangeError, xmsg
|
539
|
+
else
|
540
540
|
|
541
|
-
|
542
|
-
|
543
|
-
|
541
|
+
raise ArgumentError, xmsg
|
542
|
+
end
|
543
|
+
end
|
544
544
|
|
545
|
-
|
545
|
+
elsif r.is_a?(::TrueClass)
|
546
546
|
|
547
|
-
|
548
|
-
|
547
|
+
;
|
548
|
+
else
|
549
549
|
|
550
|
-
|
551
|
-
|
552
|
-
|
550
|
+
value = r
|
551
|
+
end
|
552
|
+
end
|
553
553
|
|
554
|
-
|
554
|
+
# check value(s)
|
555
555
|
|
556
|
-
|
556
|
+
unless value.nil? || !(values = options[:values])
|
557
557
|
|
558
|
-
|
558
|
+
warn "#{self}::check_parameter: options[:values] of type #{values.class} - should be #{::Array}" unless values.is_a?(Array)
|
559
559
|
|
560
|
-
|
560
|
+
found = false
|
561
561
|
|
562
|
-
|
562
|
+
io = options[:ignore_order] && ::Array === value
|
563
563
|
|
564
|
-
|
564
|
+
do_case = options[:ignore_case] ? lambda do |v|
|
565
565
|
|
566
|
-
|
567
|
-
|
566
|
+
case v
|
567
|
+
when ::String
|
568
568
|
|
569
|
-
|
570
|
-
|
569
|
+
:string
|
570
|
+
when ::Array
|
571
571
|
|
572
|
-
|
573
|
-
|
572
|
+
:array_of_strings if v.all? { |s| ::String === s }
|
573
|
+
else
|
574
574
|
|
575
|
-
|
576
|
-
|
577
|
-
|
575
|
+
nil
|
576
|
+
end
|
577
|
+
end : lambda { |v| nil }
|
578
578
|
|
579
|
-
|
580
|
-
|
581
|
-
|
579
|
+
value_ic = do_case.call(value)
|
580
|
+
value_io = nil
|
581
|
+
value_uc = nil
|
582
582
|
|
583
|
-
|
583
|
+
values.each do |v|
|
584
584
|
|
585
|
-
|
585
|
+
if ::Range === v && !(::Range === value) && v.cover?(value)
|
586
586
|
|
587
|
-
|
588
|
-
|
589
|
-
|
587
|
+
found = true
|
588
|
+
break
|
589
|
+
end
|
590
590
|
|
591
|
-
|
591
|
+
if value == v
|
592
592
|
|
593
|
-
|
594
|
-
|
595
|
-
|
593
|
+
found = true
|
594
|
+
break
|
595
|
+
end
|
596
596
|
|
597
|
-
|
597
|
+
# ignore-case comparing
|
598
598
|
|
599
|
-
|
599
|
+
if value_ic
|
600
600
|
|
601
|
-
|
601
|
+
unless value_uc
|
602
602
|
|
603
|
-
|
604
|
-
|
603
|
+
case value_ic
|
604
|
+
when :string
|
605
605
|
|
606
|
-
|
607
|
-
|
606
|
+
value_uc = value.upcase
|
607
|
+
when :array_of_strings
|
608
608
|
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
609
|
+
value_uc = value.map { |s| s.upcase }
|
610
|
+
value_uc = value_uc.sort if io
|
611
|
+
end
|
612
|
+
end
|
613
613
|
|
614
|
-
|
614
|
+
v_ic = do_case.call(v)
|
615
615
|
|
616
|
-
|
616
|
+
if v_ic == value_ic
|
617
617
|
|
618
|
-
|
619
|
-
|
618
|
+
case v_ic
|
619
|
+
when :string
|
620
620
|
|
621
|
-
|
621
|
+
if value_uc == v.upcase
|
622
622
|
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
623
|
+
found = true
|
624
|
+
break
|
625
|
+
end
|
626
|
+
when :array_of_strings
|
627
627
|
|
628
|
-
|
629
|
-
|
628
|
+
v_uc = v.map { |s| s.upcase }
|
629
|
+
v_uc = v_uc.sort if io
|
630
630
|
|
631
|
-
|
631
|
+
if value_uc == v_uc
|
632
632
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
633
|
+
found = true
|
634
|
+
break
|
635
|
+
end
|
636
|
+
end
|
637
|
+
end
|
638
|
+
elsif io
|
639
639
|
|
640
|
-
|
640
|
+
unless value_io
|
641
641
|
|
642
|
-
|
643
|
-
|
642
|
+
value_io = value.sort
|
643
|
+
end
|
644
644
|
|
645
|
-
|
645
|
+
if ::Array === v
|
646
646
|
|
647
|
-
|
647
|
+
v_io = v.sort
|
648
648
|
|
649
|
-
|
649
|
+
if value_io == v_io
|
650
650
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
651
|
+
found = true
|
652
|
+
break
|
653
|
+
end
|
654
|
+
end
|
655
|
+
end
|
656
|
+
end
|
657
657
|
|
658
|
-
|
658
|
+
unless found
|
659
659
|
|
660
|
-
|
660
|
+
failed_check = true
|
661
661
|
|
662
|
-
|
662
|
+
unless options[:nothrow]
|
663
663
|
|
664
|
-
|
664
|
+
unless message
|
665
665
|
|
666
|
-
|
666
|
+
s_name = name.is_a?(String) ? "'#{name}' " : ''
|
667
667
|
|
668
|
-
|
669
|
-
|
668
|
+
message = "#{param_s} #{s_name}value '#{value}' not found equal/within any of required values or ranges"
|
669
|
+
end
|
670
670
|
|
671
|
-
|
671
|
+
if value.is_a?(::Numeric)
|
672
672
|
|
673
|
-
|
674
|
-
|
673
|
+
raise RangeError, message
|
674
|
+
else
|
675
675
|
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
676
|
+
raise ArgumentError, message
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
end
|
681
681
|
|
682
|
-
|
683
|
-
|
682
|
+
failed_check ? nil : value
|
683
|
+
end
|
684
684
|
|
685
685
|
end # module ParameterChecking
|
686
686
|
|