flex_args 0.1.2 → 0.1.3
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/.rdoc_options +1 -1
- data/README.md +1 -1
- data/lib/flex_args/constraint.rb +71 -0
- data/lib/flex_args/transform.rb +23 -0
- data/lib/flex_args/version.rb +1 -1
- data/lib/flex_args.rb +71 -5
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e573bedff931ba6d00a805a59c72c1501b454ce2de48efd1787d4e9d3582541
|
4
|
+
data.tar.gz: a33de0609ca8726513b5576f9ce5b9dec7c6ae7a0d9438d3151ce2e03a87c0c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6a44342146b8d223a593a2982f2930bec00db7c93ee8f604ddfa10fd0380562d0ce8577bd636e8fe54082acaf49a39627e4c1dd969898a79c363e911bcf968b
|
7
|
+
data.tar.gz: 45955b80f48f89a16d0b64caf3fbb6a14fbbf0e39fb84e625a7201678bd656d246c73c6d6bb86930e4b8e8a3d5bd9ab5fa927ea4489723674cc69f19448bcca5
|
data/.rdoc_options
CHANGED
data/README.md
CHANGED
data/lib/flex_args/constraint.rb
CHANGED
@@ -31,8 +31,44 @@ class FlexArgs
|
|
31
31
|
# new(:for_some_int, 1..9).("1") => [:ok, 1]
|
32
32
|
# new(:for_some_int, 1..9).("0") => [:error, "range constraint for_some_int: 1..9 violated by value \"0\""]
|
33
33
|
# new(:for_some_int, 1..9).("y") => [:error, "range constraint for_some_int: 1..9 violated by value \"y\""]
|
34
|
+
#
|
35
|
+
# new(:for_string, "a".."c").("a") => [:ok, "a"]
|
36
|
+
# new(:for_string, "a".."c").("d") => [:error, 'member constraint for_string: "a".."c" violated by value "d"']
|
34
37
|
#
|
35
38
|
# ```
|
39
|
+
#
|
40
|
+
# **N.B.** that ranges not of type integer are treated as `Member` contraints below.
|
41
|
+
#
|
42
|
+
# ### `Member` constraint
|
43
|
+
#
|
44
|
+
# While the `Range` constraint above does int type casting if needed, the `Member` constraint cannot do
|
45
|
+
# that, because it cannot access the type of the container against which membership will be tested.
|
46
|
+
#
|
47
|
+
# `Member` constraints can be triggered by providing a `Set`, `Array` or `Hash` second parameter
|
48
|
+
#
|
49
|
+
# ```spec # Various membership rdoc specs
|
50
|
+
# vowels = %w[a e i o u y]
|
51
|
+
# hashy = Hash[vowels.product([true])]
|
52
|
+
# set = Set.new(vowels)
|
53
|
+
# in_array = new(:in_array, vowels)
|
54
|
+
# in_set = new(:in_set, set)
|
55
|
+
# in_hash = new(:in_hash, hashy)
|
56
|
+
#
|
57
|
+
# expect(in_array.("a")).to eq([:ok, "a"])
|
58
|
+
# expect(in_array.("y")).to eq([:ok, "y"])
|
59
|
+
# expect(in_set.("y")).to eq([:ok, "y"])
|
60
|
+
# expect(in_hash.("o")).to eq([:ok, "o"])
|
61
|
+
#
|
62
|
+
# expect(in_array.("b"))
|
63
|
+
# .to eq([:error, "member constraint in_array: #{vowels.inspect} violated by value \"b\""])
|
64
|
+
#
|
65
|
+
# expect(in_hash.("ec"))
|
66
|
+
# .to eq([:error, "member constraint in_hash: #{hashy.inspect} violated by value \"ec\""])
|
67
|
+
#
|
68
|
+
# expect(in_set.("aa"))
|
69
|
+
# .to eq([:error, "member constraint in_set: #{set.inspect} violated by value \"aa\""])
|
70
|
+
# ```
|
71
|
+
#
|
36
72
|
# ### Custom constraint
|
37
73
|
#
|
38
74
|
# This is easily implemented by passing a block which will return a pair as described above, but also note
|
@@ -71,6 +107,12 @@ class FlexArgs
|
|
71
107
|
_init_regexp(name, constraint)
|
72
108
|
in [Range => range]
|
73
109
|
_init_range(name, range)
|
110
|
+
in [Array | Hash | Set => container]
|
111
|
+
_init_membership(name, container, false)
|
112
|
+
in [Array | Hash | Set => container, :autocast]
|
113
|
+
_init_membership(name, container, true)
|
114
|
+
in [:member, container]
|
115
|
+
_init_membership(name, container)
|
74
116
|
else
|
75
117
|
raise ArgumentError,
|
76
118
|
"illegal constraint spec #{constraints.inspect} for value #{name}" unless block
|
@@ -102,7 +144,36 @@ class FlexArgs
|
|
102
144
|
end
|
103
145
|
end
|
104
146
|
|
147
|
+
def _init_membership(name, container, autocast)
|
148
|
+
@constrainer = -> value do
|
149
|
+
if container.member?(value)
|
150
|
+
[:ok, value]
|
151
|
+
elsif autocast
|
152
|
+
case _to_int(value)
|
153
|
+
in [:ok, int_val]
|
154
|
+
if container.member(int_val)
|
155
|
+
[:ok, int_val]
|
156
|
+
else
|
157
|
+
_make_error(:member, name, container.inspect, int_value)
|
158
|
+
end
|
159
|
+
else
|
160
|
+
_make_error(:member, name, container.inspect, value)
|
161
|
+
end
|
162
|
+
else
|
163
|
+
_make_error(:member, name, container.inspect, value)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
105
168
|
def _init_range(name, range)
|
169
|
+
if Integer === range.first
|
170
|
+
_init_int_range(name, range)
|
171
|
+
else
|
172
|
+
_init_membership(name, range, false)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def _init_int_range(name, range)
|
106
177
|
@constrainer = -> value do
|
107
178
|
case _to_int(value)
|
108
179
|
in [:ok, int_val]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FlexArgs
|
4
|
+
class Transform
|
5
|
+
|
6
|
+
def call(value) = [:ok, @transformer.(value)]
|
7
|
+
|
8
|
+
private
|
9
|
+
def initialize(*transformers, &transformer)
|
10
|
+
case transformers
|
11
|
+
in [_]
|
12
|
+
raise ArgumentError, "NOT YET IMPLEMENTED"
|
13
|
+
else
|
14
|
+
_init_transformer(&transformer)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def _init_transformer(&transformer)
|
19
|
+
@transformer = transformer
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
data/lib/flex_args/version.rb
CHANGED
data/lib/flex_args.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'ostruct'
|
4
4
|
require_relative 'flex_args/constraint'
|
5
5
|
require_relative 'flex_args/parser'
|
6
|
+
require_relative 'flex_args/transform'
|
6
7
|
|
7
8
|
##
|
8
9
|
# ## Abstract
|
@@ -91,8 +92,8 @@ require_relative 'flex_args/parser'
|
|
91
92
|
# - required
|
92
93
|
# - domain checks
|
93
94
|
# - format checks
|
94
|
-
# -
|
95
|
-
# - Semantic Checks (v0.2)
|
95
|
+
# - Transformations
|
96
|
+
# - Semantic Checks - between multiple values (v0.2)
|
96
97
|
#
|
97
98
|
# and they are documented in the rdocs of the corresponding methods
|
98
99
|
#
|
@@ -225,11 +226,76 @@ class FlexArgs
|
|
225
226
|
#
|
226
227
|
# ```
|
227
228
|
#
|
228
|
-
#
|
229
|
+
# #### Combining Constraints
|
230
|
+
#
|
231
|
+
# More than one constraint can be imposed on a value
|
232
|
+
#
|
233
|
+
# Firstly one can combine any constraint with a custom constraint.
|
234
|
+
#
|
235
|
+
# **N.B.** That in this case the custom constraint is executed last, therefore
|
236
|
+
#
|
237
|
+
# ```spec # Order of constraints
|
238
|
+
# parser = FlexArgs.new
|
239
|
+
# .constrain(:n, 1..10) { it == 5 ? [:ok, 100] : [:ok, 2*it] }
|
240
|
+
#
|
241
|
+
# expect(parser.parse(%w[n:5]).values).to eq(n: 100)
|
242
|
+
#
|
243
|
+
# ```
|
244
|
+
#
|
245
|
+
# However if we had defined the custom constraint (which actually is a transformer
|
246
|
+
# as it _always_ returns an `:ok` value, the range constraint would fail
|
247
|
+
#
|
248
|
+
# ```spec # Bad order
|
249
|
+
# parser = FlexArgs.new
|
250
|
+
# .constrain(:n) { it == 5 ? [:ok, 100] : [:ok, 2*it] }
|
251
|
+
# .constrain(:n, 1..10)
|
252
|
+
#
|
253
|
+
# expect { parser.parse(%w[n:5]) }
|
254
|
+
# .to raise_error(ArgumentError)
|
255
|
+
#
|
256
|
+
# ```
|
257
|
+
#
|
258
|
+
# As mentioned before, custom constraints that always return `:ok` values are indeed
|
259
|
+
# _transformers_ and can be written more with the `transform` [method below](/FlexArgs.html#method-i-transform-label-Transformers)
|
260
|
+
#
|
261
|
+
#
|
262
|
+
# Please find the documentation about more constraints [here](/FlexArgs/Constraint.html)
|
229
263
|
#
|
230
264
|
def constrain(value, *constraints, &block)
|
231
265
|
@allowed_values << value.to_sym if @allowed_values
|
232
|
-
@constraints[value.to_sym] << Constraint.new(value, *constraints
|
266
|
+
@constraints[value.to_sym] << Constraint.new(value, *constraints) unless constraints.empty?
|
267
|
+
@constraints[value.to_sym] << Constraint.new(value, &block) if block
|
268
|
+
self
|
269
|
+
end
|
270
|
+
|
271
|
+
##
|
272
|
+
# ## Transformers
|
273
|
+
#
|
274
|
+
# Transformers and Constraints are executed in the order they are defined
|
275
|
+
#
|
276
|
+
# ```spec # Transformer assures constraint passes
|
277
|
+
#
|
278
|
+
# parser = FlexArgs.new
|
279
|
+
# .transform(:word) { it.downcase }
|
280
|
+
# .constrain(:word, "a".."z")
|
281
|
+
#
|
282
|
+
# expect(parser.parse(%w[word:A]).values).to eq(word: "a")
|
283
|
+
# ```
|
284
|
+
#
|
285
|
+
# And therefore
|
286
|
+
#
|
287
|
+
# ```spec # Transformer called too late to assure constraint passes
|
288
|
+
#
|
289
|
+
# parser = FlexArgs.new
|
290
|
+
# .constrain(:word, "a".."z")
|
291
|
+
# .transform(:word) { it.downcase }
|
292
|
+
#
|
293
|
+
# expect { parser.parse(%w[word:A]) }.to raise_error(ArgumentError)
|
294
|
+
# ```
|
295
|
+
def transform(value, *transforms, &transformer)
|
296
|
+
@allowed_values << value.to_sym if @allowed_values
|
297
|
+
@constraints[value.to_sym] << Transform.new(*transforms) unless transforms.empty?
|
298
|
+
@constraints[value.to_sym] << Transform.new(&transformer) if transformer
|
233
299
|
self
|
234
300
|
end
|
235
301
|
|
@@ -241,7 +307,7 @@ class FlexArgs
|
|
241
307
|
def values
|
242
308
|
default_values.merge(values_from_args)
|
243
309
|
end
|
244
|
-
|
310
|
+
|
245
311
|
private
|
246
312
|
def initialize
|
247
313
|
@alias_definitions = Hash.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flex_args
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/flex_args/constraint.rb
|
39
39
|
- lib/flex_args/enumerable.rb
|
40
40
|
- lib/flex_args/parser.rb
|
41
|
+
- lib/flex_args/transform.rb
|
41
42
|
- lib/flex_args/version.rb
|
42
43
|
homepage: https://codeberg.org/lab419/flex_args
|
43
44
|
licenses:
|