xqsr3 0.39.6 → 0.39.7
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/CHANGES.md +12 -0
- data/NEWS.md +1 -0
- data/README.md +1 -0
- data/lib/xqsr3/array_utilities/join_with_or.rb +4 -4
- data/lib/xqsr3/containers/frequency_map.rb +17 -9
- data/lib/xqsr3/containers/multi_map.rb +59 -16
- data/lib/xqsr3/diagnostics/exception_utilities.rb +4 -2
- data/lib/xqsr3/diagnostics/exceptions/with_cause.rb +3 -1
- data/lib/xqsr3/extensions/enumerable/detect_map.rb +13 -7
- data/lib/xqsr3/extensions/enumerable.rb +1 -0
- data/lib/xqsr3/extensions/integer/to_s_grp.rb +1 -1
- data/lib/xqsr3/extensions.rb +3 -0
- data/lib/xqsr3/io/writelines.rb +3 -3
- data/lib/xqsr3/quality/parameter_checking.rb +4 -1
- data/lib/xqsr3/version.rb +2 -2
- data/test/unit/containers/tc_frequency_map.rb +19 -1
- data/test/unit/containers/tc_multi_map.rb +59 -0
- data/test/unit/extensions/enumerable/tc_detect_map.rb +3 -0
- data/test/unit/extensions/integer/tc_to_s_grp.rb +3 -0
- data/test/unit/extensions/tc_extensions_pack.rb +35 -0
- data/test/unit/io/tc_writelines.rb +24 -0
- metadata +3 -2
- /data/test/unit/extensions/string/{tc_bool.tb → tc_bool.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e1df2847a524be64578ba040be65911b413eccbe2affbf7e4d3bac710a505d8
|
|
4
|
+
data.tar.gz: 4c2360c637d977e9cdb2f88b01455aa565ea0dc11225b09be357a35094daff22
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52ab95d6b63616544f08c3dd482ca1695aebc51fe70d01cf60c76ce7a737d5285fb61c32d4978da6f87a0f986cc02b279f1a5ee3680aa0c47b52a3e30e52fa6f
|
|
7
|
+
data.tar.gz: f774505ffcc560824ea2671624f07907d503791f53c0963a9a22cf233d39d1337f5d1044e9814977455d9e6d5f4f2079a006a36c0d5bd3a2090b6ff8ad23c414
|
data/CHANGES.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# xqsr3 - Changes <!-- omit in toc -->
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## 0.39.7 - 19th August 2026
|
|
5
|
+
|
|
6
|
+
* fixed **MultiMap**: no longer subclasses +Hash+ (data lived only in +@inner+, so inherited +keys+/+key?+ lied); added +keys+/+key?+/+include?+/+member?+; fixed +to_hash+; deep-copy on +dup+/+clone+; +MultiMap[]+ no longer mutates nested arrays; Hash merges splat array values consistently with +MultiMap[]+ / +to_h+;
|
|
7
|
+
* fixed `IO.writelines` Hash EOL lookahead (+each_with_index+ was not destructuring key/value pairs);
|
|
8
|
+
* aligned `xqsr3/extensions` (and thus `xqsr3/all_extensions`) with documented extension packs — now loads **integer**, **kernel**, and **string** as well as **enumerable/detect_map**;
|
|
9
|
+
* fixed **FrequencyMap** (+#store(0)+ removes key; +#to_h+/+#to_hash+ return copies; +#[]+ / +#each_by_key+ docs);
|
|
10
|
+
* fixed **ParameterChecking** (+#ignore_order+ recognised; +:types+ no longer mutates caller array) and **join_with_or** (+treat_as_option:+);
|
|
11
|
+
* fixed `Enumerable#detect_map` to return falsy hits (+nil+ means continue);
|
|
12
|
+
* fixed `Integer#to_s_grp` to honour +:separator+ for the single-group path;
|
|
13
|
+
* fixed `ExceptionUtilities.raise_with_options` to use +set_backtrace+ instead of deprecated 3-arg +raise+; documented **WithCause** +#cause+ shadowing;
|
|
14
|
+
|
|
15
|
+
|
|
4
16
|
## 0.39.6 - 18th August 2026
|
|
5
17
|
|
|
6
18
|
* fixed **BoolParser** default matching to require whole-string `true`/`false` (case-insensitive), aligned `:default_value` / `:true_value` / `:false_value` options with documented names (legacy `:default` / `:true` / `:false` still accepted), and allowed falsy override values;
|
data/NEWS.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
| Date | News Item |
|
|
4
4
|
| ------------------ | --------------------------- |
|
|
5
|
+
| 19th August 2026 | [**xqsr3** 0.39.7](https://github.com/synesissoftware/xqsr3/releases/tag/0.39.7) |
|
|
5
6
|
| 18th August 2026 | [**xqsr3** 0.39.6](https://github.com/synesissoftware/xqsr3/releases/tag/0.39.6) |
|
|
6
7
|
| 14th August 2026 | [**xqsr3** 0.39.5](https://github.com/synesissoftware/xqsr3/releases/tag/0.39.5) |
|
|
7
8
|
| 12th August 2026 | [**xqsr3** 0.39.4.1](https://github.com/synesissoftware/xqsr3/releases/tag/0.39.4.1) |
|
data/README.md
CHANGED
|
@@ -77,10 +77,10 @@ module ArrayUtilities
|
|
|
77
77
|
::Xqsr3::Quality::ParameterChecking.check_parameter ar, 'ar', type: ::Array, allow_nil: true
|
|
78
78
|
::Xqsr3::Quality::ParameterChecking.check_parameter options, 'options', type: ::Hash, allow_nil: false
|
|
79
79
|
|
|
80
|
-
::Xqsr3::Quality::ParameterChecking.check_parameter options[:or], ':or', type: ::String,
|
|
81
|
-
::Xqsr3::Quality::ParameterChecking.check_parameter options[:oxford_comma], ':oxford_comma', types: [ ::FalseClass, ::TrueClass ],
|
|
82
|
-
::Xqsr3::Quality::ParameterChecking.check_parameter options[:quote_char], ':quote_char', type: ::String,
|
|
83
|
-
::Xqsr3::Quality::ParameterChecking.check_parameter options[:separator], ':separator', type: ::String,
|
|
80
|
+
::Xqsr3::Quality::ParameterChecking.check_parameter options[:or], ':or', type: ::String, treat_as_option: true, allow_nil: true
|
|
81
|
+
::Xqsr3::Quality::ParameterChecking.check_parameter options[:oxford_comma], ':oxford_comma', types: [ ::FalseClass, ::TrueClass ], treat_as_option: true, allow_nil: true
|
|
82
|
+
::Xqsr3::Quality::ParameterChecking.check_parameter options[:quote_char], ':quote_char', type: ::String, treat_as_option: true, allow_nil: true
|
|
83
|
+
::Xqsr3::Quality::ParameterChecking.check_parameter options[:separator], ':separator', type: ::String, treat_as_option: true, allow_nil: true
|
|
84
84
|
|
|
85
85
|
return '' if ar.nil?
|
|
86
86
|
return '' if ar.empty?
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
# Purpose: FrequencyMap container
|
|
6
6
|
#
|
|
7
7
|
# Created: 28th January 2005
|
|
8
|
-
# Updated:
|
|
8
|
+
# Updated: 15th August 2026
|
|
9
9
|
#
|
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
|
11
11
|
#
|
|
12
12
|
# Author: Matthew Wilson
|
|
13
13
|
#
|
|
14
|
-
# Copyright (c) 2019-
|
|
14
|
+
# Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
|
|
15
15
|
# Copyright (c) 2005-2019, Matthew Wilson and Synesis Software
|
|
16
16
|
# All rights reserved.
|
|
17
17
|
#
|
|
@@ -203,7 +203,7 @@ module Containers
|
|
|
203
203
|
false
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
# Obtains the count for a given key, or +
|
|
206
|
+
# Obtains the count for a given key, or +0+ if the key does not exist
|
|
207
207
|
#
|
|
208
208
|
# === Signature
|
|
209
209
|
#
|
|
@@ -294,7 +294,8 @@ module Containers
|
|
|
294
294
|
# Enumerates each entry pair - element + frequency - in key order
|
|
295
295
|
#
|
|
296
296
|
# Note: this method is more expensive than +each+ because an array of
|
|
297
|
-
# keys must be created and sorted from which enumeration is directed
|
|
297
|
+
# keys must be created and sorted from which enumeration is directed.
|
|
298
|
+
# Keys must be mutually comparable via +<=>+.
|
|
298
299
|
def each_by_key
|
|
299
300
|
|
|
300
301
|
sorted_elements = @elements.sort { |a, b| a[0] <=> b[0] }
|
|
@@ -588,7 +589,8 @@ module Containers
|
|
|
588
589
|
|
|
589
590
|
# Causes an element with the given +key+ and +count+ to be stored. If an
|
|
590
591
|
# element with the given +key+ already exists, its count will be adjusted,
|
|
591
|
-
# as will the total count
|
|
592
|
+
# as will the total count. A +count+ of +0+ removes the key (consistent
|
|
593
|
+
# with +#push+ reducing a count to zero).
|
|
592
594
|
#
|
|
593
595
|
# === Return
|
|
594
596
|
# +true+ if the element was inserted; +false+ if the element was
|
|
@@ -599,7 +601,13 @@ module Containers
|
|
|
599
601
|
|
|
600
602
|
old_count = @elements[key] || 0
|
|
601
603
|
|
|
602
|
-
|
|
604
|
+
if 0 == count
|
|
605
|
+
|
|
606
|
+
@elements.delete key
|
|
607
|
+
else
|
|
608
|
+
|
|
609
|
+
@elements.store key, count
|
|
610
|
+
end
|
|
603
611
|
|
|
604
612
|
@count += count - old_count
|
|
605
613
|
|
|
@@ -612,16 +620,16 @@ module Containers
|
|
|
612
620
|
@elements.to_a
|
|
613
621
|
end
|
|
614
622
|
|
|
615
|
-
# Obtains
|
|
623
|
+
# Obtains a +Hash+ copy of the instance contents
|
|
616
624
|
def to_h
|
|
617
625
|
|
|
618
|
-
@elements.
|
|
626
|
+
@elements.dup
|
|
619
627
|
end
|
|
620
628
|
|
|
621
629
|
# Obtains equivalent hash to instance
|
|
622
630
|
def to_hash
|
|
623
631
|
|
|
624
|
-
@elements.
|
|
632
|
+
@elements.dup
|
|
625
633
|
end
|
|
626
634
|
|
|
627
635
|
# A string-form of the instance
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
# Purpose: multimap container
|
|
6
6
|
#
|
|
7
7
|
# Created: 21st March 2007
|
|
8
|
-
# Updated:
|
|
8
|
+
# Updated: 15th August 2026
|
|
9
9
|
#
|
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
|
11
11
|
#
|
|
12
12
|
# Author: Matthew Wilson
|
|
13
13
|
#
|
|
14
|
-
# Copyright (c) 2019-
|
|
14
|
+
# Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
|
|
15
15
|
# Copyright (c) 2007-2019, Matthew Wilson and Synesis Software
|
|
16
16
|
# All rights reserved.
|
|
17
17
|
#
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
module Xqsr3
|
|
52
52
|
module Containers
|
|
53
53
|
|
|
54
|
-
# Hash-like class that stores
|
|
55
|
-
class MultiMap
|
|
54
|
+
# Hash-like class that stores mapped values in arrays
|
|
55
|
+
class MultiMap
|
|
56
56
|
|
|
57
57
|
include Enumerable
|
|
58
58
|
|
|
@@ -102,9 +102,10 @@ module Containers
|
|
|
102
102
|
|
|
103
103
|
raise ArgumentError, "cannot pass an empty array in array of arrays initialiser" if ar.empty?
|
|
104
104
|
|
|
105
|
-
key = ar
|
|
105
|
+
key = ar[0]
|
|
106
|
+
values = ar[1 ... ar.size]
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
values.each { |value| h[key] << value }
|
|
108
109
|
end
|
|
109
110
|
|
|
110
111
|
return self.[](h)
|
|
@@ -136,6 +137,18 @@ module Containers
|
|
|
136
137
|
@inner = Hash.new
|
|
137
138
|
end
|
|
138
139
|
|
|
140
|
+
# Deep-copies +@inner+ (and each values array) after +dup+/+clone+
|
|
141
|
+
def initialize_copy other
|
|
142
|
+
|
|
143
|
+
@merge_is_multi = other.instance_variable_get(:@merge_is_multi)
|
|
144
|
+
@inner = {}
|
|
145
|
+
|
|
146
|
+
other.instance_variable_get(:@inner).each do |k, vals|
|
|
147
|
+
|
|
148
|
+
@inner[k] = vals.dup
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
139
152
|
# Obtains the values, if any, for the given key; returns +nil+ if no
|
|
140
153
|
# values are stored
|
|
141
154
|
def [] key
|
|
@@ -412,6 +425,16 @@ module Containers
|
|
|
412
425
|
@inner.has_key? key
|
|
413
426
|
end
|
|
414
427
|
|
|
428
|
+
alias include? has_key?
|
|
429
|
+
alias key? has_key?
|
|
430
|
+
alias member? has_key?
|
|
431
|
+
|
|
432
|
+
# An array of all keys in the instance
|
|
433
|
+
def keys
|
|
434
|
+
|
|
435
|
+
@inner.keys
|
|
436
|
+
end
|
|
437
|
+
|
|
415
438
|
# Returns +true+ if any key has the given +value+; +false+ otherwise
|
|
416
439
|
#
|
|
417
440
|
# === Signature
|
|
@@ -533,18 +556,25 @@ module Containers
|
|
|
533
556
|
case other
|
|
534
557
|
when self.class
|
|
535
558
|
|
|
536
|
-
|
|
559
|
+
other.each do |k, v|
|
|
560
|
+
|
|
561
|
+
self.push k, v
|
|
562
|
+
end
|
|
537
563
|
when ::Hash
|
|
538
564
|
|
|
539
|
-
|
|
540
|
-
else
|
|
565
|
+
other.each do |k, v|
|
|
541
566
|
|
|
542
|
-
|
|
543
|
-
|
|
567
|
+
if ::Array === v
|
|
568
|
+
|
|
569
|
+
self.push k, *v
|
|
570
|
+
else
|
|
544
571
|
|
|
545
|
-
|
|
572
|
+
self.push k, v
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
else
|
|
546
576
|
|
|
547
|
-
self.
|
|
577
|
+
raise TypeError, "parameter must be an instance of #{self.class} or #{Hash}"
|
|
548
578
|
end
|
|
549
579
|
|
|
550
580
|
self
|
|
@@ -598,7 +628,13 @@ module Containers
|
|
|
598
628
|
|
|
599
629
|
other.each do |k, v|
|
|
600
630
|
|
|
601
|
-
|
|
631
|
+
if ::Array === v
|
|
632
|
+
|
|
633
|
+
self.store k, *v
|
|
634
|
+
else
|
|
635
|
+
|
|
636
|
+
self.store k, v
|
|
637
|
+
end
|
|
602
638
|
end
|
|
603
639
|
else
|
|
604
640
|
|
|
@@ -680,10 +716,17 @@ module Containers
|
|
|
680
716
|
@inner.to_h
|
|
681
717
|
end
|
|
682
718
|
|
|
683
|
-
# Obtains equivalent hash to instance
|
|
719
|
+
# Obtains equivalent hash to instance (independent copy)
|
|
684
720
|
def to_hash
|
|
685
721
|
|
|
686
|
-
|
|
722
|
+
h = {}
|
|
723
|
+
|
|
724
|
+
@inner.each do |k, vals|
|
|
725
|
+
|
|
726
|
+
h[k] = vals.dup
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
h
|
|
687
730
|
end
|
|
688
731
|
|
|
689
732
|
# A string-form of the instance
|
|
@@ -180,7 +180,8 @@ module Diagnostics
|
|
|
180
180
|
|
|
181
181
|
bt = x.backtrace
|
|
182
182
|
(0..called_indirectly).each { bt.shift }
|
|
183
|
-
|
|
183
|
+
x.set_backtrace bt
|
|
184
|
+
Kernel.raise x
|
|
184
185
|
end
|
|
185
186
|
end
|
|
186
187
|
|
|
@@ -204,7 +205,8 @@ module Diagnostics
|
|
|
204
205
|
|
|
205
206
|
bt = x.backtrace
|
|
206
207
|
(0..called_indirectly).each { bt.shift }
|
|
207
|
-
|
|
208
|
+
x.set_backtrace bt
|
|
209
|
+
Kernel.raise x
|
|
208
210
|
end
|
|
209
211
|
end
|
|
210
212
|
end # module ExceptionUtilities
|
|
@@ -133,7 +133,9 @@ module Exceptions
|
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
# The cause / inner-exception, if any, specified to the instance
|
|
136
|
-
# initialiser
|
|
136
|
+
# initialiser. This attribute shadows +Exception#cause+ (the interpreter's
|
|
137
|
+
# raise-chain cause); for includers, +#cause+ refers to this module's
|
|
138
|
+
# +@cause+.
|
|
137
139
|
attr_reader :cause
|
|
138
140
|
|
|
139
141
|
# The options passed to the initialiser, with +:cause+ removed, if
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
# Purpose: ::Enumerable#detect_map extension
|
|
6
6
|
#
|
|
7
7
|
# Created: 3rd December 2017
|
|
8
|
-
# Updated:
|
|
8
|
+
# Updated: 15th August 2026
|
|
9
9
|
#
|
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
|
11
11
|
#
|
|
12
12
|
# Author: Matthew Wilson
|
|
13
13
|
#
|
|
14
|
-
# Copyright (c) 2019-
|
|
14
|
+
# Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
|
|
15
15
|
# Copyright (c) 2017-2019, Matthew Wilson and Synesis Software
|
|
16
16
|
# All rights reserved.
|
|
17
17
|
#
|
|
@@ -54,13 +54,15 @@ module Enumerable
|
|
|
54
54
|
# of a particular value in a collection. The only constraint is that you
|
|
55
55
|
# get back the object unchanged.
|
|
56
56
|
#
|
|
57
|
-
# The +Enumerable+#+map+ method provides a way to transform the contents
|
|
58
|
-
# a collection. The only constraint is that you get back another
|
|
57
|
+
# The +Enumerable+#+map+ method provides a way to transform the contents
|
|
58
|
+
# of a collection. The only constraint is that you get back another
|
|
59
59
|
# collection.
|
|
60
60
|
#
|
|
61
61
|
# This extension method, +Enumerable+#+detect_map+ combines the features
|
|
62
62
|
# of both, in that it detects the presence of a particular value in a
|
|
63
|
-
# collection and transform the detected value.
|
|
63
|
+
# collection and transform the detected value. The block should return
|
|
64
|
+
# +nil+ to continue searching; any other value (including +false+ or +0+)
|
|
65
|
+
# is treated as a hit and returned immediately.
|
|
64
66
|
#
|
|
65
67
|
# [ 1, 2, 3 ].detect_map { |v| -2 * v if v > 2 } # => -6
|
|
66
68
|
#
|
|
@@ -75,13 +77,17 @@ module Enumerable
|
|
|
75
77
|
|
|
76
78
|
self.each do |v|
|
|
77
79
|
|
|
78
|
-
r = yield(v)
|
|
80
|
+
r = yield(v)
|
|
81
|
+
|
|
82
|
+
return r unless r.nil?
|
|
79
83
|
end
|
|
80
84
|
when 2
|
|
81
85
|
|
|
82
86
|
self.each do |k, v|
|
|
83
87
|
|
|
84
|
-
r = yield(k, v)
|
|
88
|
+
r = yield(k, v)
|
|
89
|
+
|
|
90
|
+
return r unless r.nil?
|
|
85
91
|
end
|
|
86
92
|
else
|
|
87
93
|
|
|
@@ -83,7 +83,7 @@ class Integer
|
|
|
83
83
|
return self.to_s
|
|
84
84
|
when 1
|
|
85
85
|
|
|
86
|
-
return self.to_s.chars.to_a.reverse.each_slice(numbers[0]).map(&:join).join(
|
|
86
|
+
return self.to_s.chars.to_a.reverse.each_slice(numbers[0]).map(&:join).join(separator).reverse
|
|
87
87
|
else
|
|
88
88
|
|
|
89
89
|
reversed_chars = self.to_s.chars.to_a#.reverse
|
data/lib/xqsr3/extensions.rb
CHANGED
data/lib/xqsr3/io/writelines.rb
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
# Purpose: Adds a writelines() method to the IO module
|
|
6
6
|
#
|
|
7
7
|
# Created: 13th April 2007
|
|
8
|
-
# Updated:
|
|
8
|
+
# Updated: 15th August 2026
|
|
9
9
|
#
|
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
|
11
11
|
#
|
|
12
12
|
# Author: Matthew Wilson
|
|
13
13
|
#
|
|
14
|
-
# Copyright (c) 2019-
|
|
14
|
+
# Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
|
|
15
15
|
# Copyright (c) 2007-2019, Matthew Wilson and Synesis Software
|
|
16
16
|
# All rights reserved.
|
|
17
17
|
#
|
|
@@ -125,7 +125,7 @@ module IO
|
|
|
125
125
|
|
|
126
126
|
if contents.instance_of? ::Hash
|
|
127
127
|
|
|
128
|
-
contents.each_with_index do |k, v, index|
|
|
128
|
+
contents.each_with_index do |(k, v), index|
|
|
129
129
|
|
|
130
130
|
if eol_lookahead_limit && eol_lookahead_limit == index
|
|
131
131
|
|
|
@@ -82,6 +82,7 @@ module Quality
|
|
|
82
82
|
|
|
83
83
|
allow_nil
|
|
84
84
|
ignore_case
|
|
85
|
+
ignore_order
|
|
85
86
|
message
|
|
86
87
|
nil
|
|
87
88
|
nothrow
|
|
@@ -118,6 +119,7 @@ module Quality
|
|
|
118
119
|
# - +:allow_nil+ (boolean) The +value+ must not be +nil+ unless this option is true;
|
|
119
120
|
# - +:nil+ an alias for +:allow_nil+;
|
|
120
121
|
# - +:ignore_case+ (boolean) When +:values+ is specified, comparisons of strings, or arrays of strings, will be carried out in a case-insensitive manner;
|
|
122
|
+
# - +:ignore_order+ (boolean) When +:values+ is specified and +value+ is an +Array+, comparisons may ignore element order;
|
|
121
123
|
# - +: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;
|
|
122
124
|
# - +:type+ (+Class+) A single type parameter, used only if +:types+ is not specified;
|
|
123
125
|
# - +:values+ (+Array+) an array of values one of which +value+ must be;
|
|
@@ -174,6 +176,7 @@ module Quality
|
|
|
174
176
|
# - +:allow_nil+ (boolean) The +value+ must not be +nil+ unless this option is true;
|
|
175
177
|
# - +:nil+ an alias for +:allow_nil+;
|
|
176
178
|
# - +:ignore_case+ (boolean) When +:values+ is specified, comparisons of strings, or arrays of strings, will be carried out in a case-insensitive manner;
|
|
179
|
+
# - +:ignore_order+ (boolean) When +:values+ is specified and +value+ is an +Array+, comparisons may ignore element order;
|
|
177
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;
|
|
178
181
|
# - +:type+ (+Class+) A single type parameter, used only if +:types+ is not specified;
|
|
179
182
|
# - +:values+ (+Array+) an array of values one of which +value+ must be;
|
|
@@ -328,7 +331,7 @@ module Quality
|
|
|
328
331
|
|
|
329
332
|
# types
|
|
330
333
|
|
|
331
|
-
types = options[:types] || []
|
|
334
|
+
types = (options[:types] || []).dup
|
|
332
335
|
if options.has_key? :type
|
|
333
336
|
|
|
334
337
|
types << options[:type] if types.empty?
|
data/lib/xqsr3/version.rb
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Purpose: Version for Xqsr3 library
|
|
6
6
|
#
|
|
7
7
|
# Created: 3rd April 2016
|
|
8
|
-
# Updated:
|
|
8
|
+
# Updated: 19th August 2026
|
|
9
9
|
#
|
|
10
10
|
# Home: http://github.com/synesissoftware/xqsr3
|
|
11
11
|
#
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
module Xqsr3
|
|
52
52
|
|
|
53
53
|
# Current version of the Xqsr3 library
|
|
54
|
-
VERSION = '0.39.
|
|
54
|
+
VERSION = '0.39.7'
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
VERSION_PARTS_ = VERSION.split(/[.]/).collect { |n| n.to_i } # :nodoc:
|
|
@@ -889,6 +889,13 @@ class Test_Xqsr3_Containers_FrequencyMap < Test::Unit::TestCase
|
|
|
889
889
|
assert_equal 2, fm.size
|
|
890
890
|
|
|
891
891
|
assert_raise(::TypeError) { fm.store :ghi, :blah }
|
|
892
|
+
|
|
893
|
+
fm.store :abc, 0
|
|
894
|
+
|
|
895
|
+
assert_not fm.has_key?(:abc)
|
|
896
|
+
assert_equal 2, fm.count
|
|
897
|
+
assert_equal 1, fm.size
|
|
898
|
+
assert_equal 0, fm[:abc]
|
|
892
899
|
end
|
|
893
900
|
|
|
894
901
|
def test_to_a
|
|
@@ -918,7 +925,18 @@ class Test_Xqsr3_Containers_FrequencyMap < Test::Unit::TestCase
|
|
|
918
925
|
|
|
919
926
|
fm << :def << :def << :def
|
|
920
927
|
|
|
921
|
-
|
|
928
|
+
h = fm.to_h
|
|
929
|
+
|
|
930
|
+
assert_equal ({:abc => 2, :def => 3}), h
|
|
931
|
+
assert_equal h, fm.to_hash
|
|
932
|
+
assert_not_same fm.instance_variable_get(:@elements), h
|
|
933
|
+
|
|
934
|
+
h[:abc] = 99
|
|
935
|
+
h[:xyz] = 1
|
|
936
|
+
|
|
937
|
+
assert_equal 2, fm[:abc]
|
|
938
|
+
assert_equal 5, fm.count
|
|
939
|
+
assert_not fm.has_key?(:xyz)
|
|
922
940
|
end
|
|
923
941
|
|
|
924
942
|
def test_values
|
|
@@ -69,10 +69,12 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
69
69
|
def test_class_operator_subscript_6
|
|
70
70
|
|
|
71
71
|
ar = [ [ :abc, '1' ] ]
|
|
72
|
+
nested = ar[0]
|
|
72
73
|
|
|
73
74
|
mm = MultiMap[ar]
|
|
74
75
|
|
|
75
76
|
assert_equal 1, ar.size
|
|
77
|
+
assert_equal [ :abc, '1' ], nested
|
|
76
78
|
assert_equal 1, mm.size
|
|
77
79
|
assert_equal [ '1' ], mm[:abc]
|
|
78
80
|
|
|
@@ -81,6 +83,8 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
81
83
|
mm = MultiMap[ar]
|
|
82
84
|
|
|
83
85
|
assert_equal 2, ar.size
|
|
86
|
+
assert_equal [ :abc, '1' ], ar[0]
|
|
87
|
+
assert_equal [ :def, '2' ], ar[1]
|
|
84
88
|
assert_equal 2, mm.size
|
|
85
89
|
assert_equal [ '1' ], mm[:abc]
|
|
86
90
|
assert_equal [ '2' ], mm[:def]
|
|
@@ -253,6 +257,18 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
253
257
|
mm2 = mm1.dup
|
|
254
258
|
|
|
255
259
|
assert_eql mm1, mm2
|
|
260
|
+
|
|
261
|
+
mm2.push :xyz, 'x1'
|
|
262
|
+
|
|
263
|
+
assert_not mm1.has_key?(:xyz)
|
|
264
|
+
assert mm2.has_key?(:xyz)
|
|
265
|
+
assert_equal 3, mm1.size
|
|
266
|
+
assert_equal 4, mm2.size
|
|
267
|
+
|
|
268
|
+
mm2[:abc] << 'a5'
|
|
269
|
+
|
|
270
|
+
assert_equal [ 'a1', 'a2', 'a3', 'a4' ], mm1[:abc]
|
|
271
|
+
assert_equal [ 'a1', 'a2', 'a3', 'a4', 'a5' ], mm2[:abc]
|
|
256
272
|
end
|
|
257
273
|
|
|
258
274
|
def test_each
|
|
@@ -538,16 +554,35 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
538
554
|
mm = MultiMap.new
|
|
539
555
|
|
|
540
556
|
assert_not mm.has_key? :abc
|
|
557
|
+
assert_not mm.key? :abc
|
|
558
|
+
assert_not mm.include? :abc
|
|
559
|
+
assert_not mm.member? :abc
|
|
541
560
|
|
|
542
561
|
mm.push :abc, *[ :v1, :v2 ]
|
|
543
562
|
|
|
544
563
|
assert mm.has_key? :abc
|
|
564
|
+
assert mm.key? :abc
|
|
565
|
+
assert mm.include? :abc
|
|
566
|
+
assert mm.member? :abc
|
|
545
567
|
|
|
546
568
|
mm.delete :abc
|
|
547
569
|
|
|
548
570
|
assert_not mm.has_key? :abc
|
|
549
571
|
end
|
|
550
572
|
|
|
573
|
+
def test_keys
|
|
574
|
+
|
|
575
|
+
mm = MultiMap.new
|
|
576
|
+
|
|
577
|
+
assert_equal [], mm.keys
|
|
578
|
+
|
|
579
|
+
mm.push :def
|
|
580
|
+
mm.push :abc, 'a1'
|
|
581
|
+
mm.push :ghi, 'g1', 'g2'
|
|
582
|
+
|
|
583
|
+
assert_equal [ :abc, :def, :ghi ], mm.keys.sort
|
|
584
|
+
end
|
|
585
|
+
|
|
551
586
|
def test_has_value?
|
|
552
587
|
|
|
553
588
|
mm = MultiMap.new
|
|
@@ -705,6 +740,10 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
705
740
|
mm1.multi_merge! h
|
|
706
741
|
|
|
707
742
|
assert_equal [ :abc, 1, :abc, 2, :abc, 3, :abc, 4, :abc, 5, :def, 'a', :ghi, 'x' ], mm1.flatten
|
|
743
|
+
|
|
744
|
+
mm1.multi_merge!({ abc: [ 6 ], jkl: [ 'y', 'z' ] })
|
|
745
|
+
|
|
746
|
+
assert_equal [ :abc, 1, :abc, 2, :abc, 3, :abc, 4, :abc, 5, :abc, 6, :def, 'a', :ghi, 'x', :jkl, 'y', :jkl, 'z' ], mm1.flatten
|
|
708
747
|
end
|
|
709
748
|
|
|
710
749
|
def test_strict_merge
|
|
@@ -868,6 +907,26 @@ class Test_Xqsr3_Containers_MultiMap < Test::Unit::TestCase
|
|
|
868
907
|
assert_equal ({ abc: [ 1, 2, 3, 4, 5 ], def: [] }), mm.to_h
|
|
869
908
|
end
|
|
870
909
|
|
|
910
|
+
def test_to_hash
|
|
911
|
+
|
|
912
|
+
mm = MultiMap.new
|
|
913
|
+
|
|
914
|
+
mm.push :abc, 1, 2
|
|
915
|
+
mm.push :def, 'd'
|
|
916
|
+
|
|
917
|
+
h = mm.to_hash
|
|
918
|
+
|
|
919
|
+
assert_equal ({ abc: [ 1, 2 ], def: [ 'd' ] }), h
|
|
920
|
+
assert_equal h, mm.to_h
|
|
921
|
+
assert_not_same mm.to_h, h
|
|
922
|
+
|
|
923
|
+
h[:abc] << 3
|
|
924
|
+
h[:ghi] = [ 'x' ]
|
|
925
|
+
|
|
926
|
+
assert_equal [ 1, 2 ], mm[:abc]
|
|
927
|
+
assert_not mm.has_key?(:ghi)
|
|
928
|
+
end
|
|
929
|
+
|
|
871
930
|
def test_values_unflattened
|
|
872
931
|
|
|
873
932
|
mm = MultiMap.new
|
|
@@ -22,6 +22,9 @@ class Test_Enumerable_detect_map < Test::Unit::TestCase
|
|
|
22
22
|
assert_nil [].detect_map { |v| return -2 * v }
|
|
23
23
|
assert_equal(-2, [ 1, 2, 3, 4, 5 ].detect_map { |v| -2 * v })
|
|
24
24
|
assert_equal(-4, [ 1, 2, 3, 4, 5 ].detect_map { |v| -2 * v if 2 == v })
|
|
25
|
+
|
|
26
|
+
assert_equal false, [ 1, 2, 3 ].detect_map { |v| false if 1 == v }
|
|
27
|
+
assert_equal 0, [ 1, 2, 3 ].detect_map { |v| 0 if 2 == v }
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
def test_with_hash
|
|
@@ -22,6 +22,9 @@ class Test_X_Integer_to_s_grp < Test::Unit::TestCase
|
|
|
22
22
|
assert_equal "8,7,6,5,4,3,2,1", 87654321.to_s_grp(1)
|
|
23
23
|
|
|
24
24
|
assert_equal "876,54321", 87654321.to_s_grp(5)
|
|
25
|
+
|
|
26
|
+
assert_equal "87 654 321", 87654321.to_s_grp(3, separator: ' ')
|
|
27
|
+
assert_equal "87_654_321", 87654321.to_s_grp(3, separator: '_')
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
def test_array_with_single_number
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '../../../lib')
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
require 'xqsr3/extensions'
|
|
7
|
+
|
|
8
|
+
require 'xqsr3/extensions/test/unit'
|
|
9
|
+
require 'test/unit'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Test_Xqsr3_extensions_pack < Test::Unit::TestCase
|
|
13
|
+
|
|
14
|
+
def test_extensions_pack_loads_documented_surfaces
|
|
15
|
+
|
|
16
|
+
assert [].respond_to?(:join_with_or)
|
|
17
|
+
assert [].respond_to?(:collect_with_index)
|
|
18
|
+
assert [].respond_to?(:detect_map)
|
|
19
|
+
assert [].respond_to?(:unique)
|
|
20
|
+
assert Hash.new.respond_to?(:deep_transform)
|
|
21
|
+
assert 1234.respond_to?(:to_s_grp)
|
|
22
|
+
assert ::IO.respond_to?(:writelines)
|
|
23
|
+
assert ''.respond_to?(:starts_with?)
|
|
24
|
+
assert ''.respond_to?(:truncate)
|
|
25
|
+
assert_equal 16, Integer('10', 16)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_all_extensions_loads_test_unit_assertions
|
|
29
|
+
|
|
30
|
+
require 'xqsr3/all_extensions'
|
|
31
|
+
|
|
32
|
+
assert self.respond_to?(:assert_true)
|
|
33
|
+
assert self.respond_to?(:assert_raise_with_message)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -182,6 +182,30 @@ class Test_Xqsr3_IO_writelines < Test::Unit::TestCase
|
|
|
182
182
|
assert_equal "abc\ndef\nghi\n", s.string
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
+
def test_hash_value_with_embedded_eol
|
|
186
|
+
|
|
187
|
+
input = { 'ab' => "c\nmore", 'de' => 'f' }
|
|
188
|
+
|
|
189
|
+
s = StringIO.new
|
|
190
|
+
|
|
191
|
+
r = ::Xqsr3::IO.writelines s, input
|
|
192
|
+
|
|
193
|
+
assert_equal 2, r
|
|
194
|
+
assert_equal "abc\nmoredef", s.string
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def test_hash_key_with_embedded_eol
|
|
198
|
+
|
|
199
|
+
input = { "ab\nx" => 'c', 'de' => 'f' }
|
|
200
|
+
|
|
201
|
+
s = StringIO.new
|
|
202
|
+
|
|
203
|
+
r = ::Xqsr3::IO.writelines s, input
|
|
204
|
+
|
|
205
|
+
assert_equal 2, r
|
|
206
|
+
assert_equal "ab\nxcdef", s.string
|
|
207
|
+
end
|
|
208
|
+
|
|
185
209
|
def test_strings_with_cr_in_array_and_line_sep
|
|
186
210
|
|
|
187
211
|
input = [ "abc\n", "def\n", "ghi\n" ]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: xqsr3
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.39.
|
|
4
|
+
version: 0.39.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Wilson
|
|
@@ -136,7 +136,7 @@ files:
|
|
|
136
136
|
- test/unit/extensions/kernel/ts_all.rb
|
|
137
137
|
- test/unit/extensions/object/tc_inspect.rb
|
|
138
138
|
- test/unit/extensions/object/ts_all.rb
|
|
139
|
-
- test/unit/extensions/string/tc_bool.
|
|
139
|
+
- test/unit/extensions/string/tc_bool.rb
|
|
140
140
|
- test/unit/extensions/string/tc_ends_with.rb
|
|
141
141
|
- test/unit/extensions/string/tc_map_option_string.rb
|
|
142
142
|
- test/unit/extensions/string/tc_nil_if_empty.rb
|
|
@@ -146,6 +146,7 @@ files:
|
|
|
146
146
|
- test/unit/extensions/string/tc_to_symbol.rb
|
|
147
147
|
- test/unit/extensions/string/tc_truncate.rb
|
|
148
148
|
- test/unit/extensions/string/ts_all.rb
|
|
149
|
+
- test/unit/extensions/tc_extensions_pack.rb
|
|
149
150
|
- test/unit/extensions/test/ts_all.rb
|
|
150
151
|
- test/unit/extensions/test/unit/tc_assert_raise_with_message.rb
|
|
151
152
|
- test/unit/extensions/test/unit/tc_assert_subclass_of.rb
|
|
File without changes
|