opto 1.8.7 → 1.9.0

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
- SHA1:
3
- metadata.gz: 8c5fb44e578d4ada0e75f570389edaaffb7240bf
4
- data.tar.gz: 861c45894eb143c6e3077bf0cd7700564f489d01
2
+ SHA256:
3
+ metadata.gz: 8d5546d31ee73e05adce64402dca900e55ef7159fcb277327fedf8bee0db2d00
4
+ data.tar.gz: 8dcaaf5040b306b4997f01124f2597a500c230f0a32d2ca5071c9d80e2bb536c
5
5
  SHA512:
6
- metadata.gz: 183a776b2f65a61c20b84e2c216667bc6e7fc074dd7356e4e26619850dcd60a8a437faf1882ce1fcf02e4b088224f2d89b9904818b12b1b2e64bba38882ff290
7
- data.tar.gz: 2411c527cb2e1b1028fe42a9768a7c112fb945f75f3f41811ada9241185212c7bc6f0bfde403f55b82ec0278d0cdf3353ccb2e7e419659a2457c5ec7c773abda
6
+ metadata.gz: 683dd71495e9ea808933e58416d81fb8ebc815ec0b34834bf14e4d4a7595ce478417287369184928033b6b309ff89797a39a4da0418f5f324a314b09308e7fe0
7
+ data.tar.gz: b4012a61a1a01b1a0ba7ef545956435939d329cd60400f37966b700a4ccc7e0f10c7223b19dd1a985a6383f5ce1b2d399c9914a411cdeb2d15b22597e4a383c9
@@ -1,18 +1,21 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.10
4
- - 2.2.3
5
- - 2.3.3
6
- - 2.4.1
3
+ - 2.3
4
+ - 2.4
5
+ - 2.5
7
6
  env:
8
7
  - secure: "bCu1bVzr6SP+gAbMo88GvcHHbhO3LcnJtWp+YuSZ5qW4EHhdBw+DOQeOlzoKHtYhNhptmb/65pZZctRTE6jOOSZzpOUHaeqaqHZpELldkCMu7rE8bXuCV4OfhG0CKWvURS0x5p5F5onEx1a1sjiu+MVEUqktAPDAcdTBNBW1irRwvnSifgjcZRLzfm1aRs1fqzBJpHaAXyD++2GQaWyXDtQsEsc/Eyhmnkac5Y2cTeQiYlDluqBeB885q9K16ruLp2NWx/rnR8RGMP1LSnrye/GEo2mRWOWy1MyIEwNDcVaA6MVDY2GBIQUoXg4PBrZAleVIsO3LzwR4oorFCaSgWxzqYI67g5Kb2zn8fW9Yu5lDcFEJKIHQAwBrlq3n3Mi5it/IxGQDWXQ/2fjBxCwuilvI0WTzOH0m4g8Uf6jHaQLFC6ahdWDjfs6aCzdPpbJls26/r39NIB5k/6ZO29NZkxGBsQ7E7m4wurr7a9ksLODgPOyPiB8/4Txu35Llp+IuJpbshrlkRIMwEIFVWiLi6MZhRBkxaRzlkJQ0bS3RD9W4z9UJyoBujmgXMrv0eHNTGCOC+/4tvrA+pXzJwmFQJA6TnenoDl9hc6o03gyfH/YvmMgrtJLbJ8rGoLRaY8HsQwHWgimpCl1o043kO8/UkhhS7J4wyQXYwqGnA2PC/j0="
9
- before_install: gem install bundler -v 1.12.5
10
- cache: bundler
11
- script: bundle install && bundle exec rspec spec/
8
+ bundler_args: --with test development --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
9
+ before_install:
10
+ - gem update --system
11
+ - gem install bundler
12
+ script: bundle exec rspec spec/
13
+ cache:
14
+ bundler: true
12
15
  deploy:
13
16
  provider: rubygems
14
17
  api_key: $GEM_TOKEN
15
18
  gem: opto
16
19
  on:
17
20
  tags: true
18
- rvm: 2.4.1
21
+ rvm: 2.5
data/README.md CHANGED
@@ -45,10 +45,12 @@ require 'opto'
45
45
  foo_username:
46
46
  type: string
47
47
  required: true
48
- min_length: 1
49
- max_length: 30
50
- strip: true # remove leading / trailing whitespace
51
- upcase: true # make UPCASE
48
+ validate:
49
+ min_length: 1
50
+ max_length: 30
51
+ transform:
52
+ - strip # remove leading / trailing whitespace
53
+ - upcase # make UPCASE
52
54
  from:
53
55
  env: FOO_USER # read value from ENV variable FOO_USER
54
56
  ```
@@ -72,16 +74,18 @@ require 'opto'
72
74
  foo_instances:
73
75
  type: integer
74
76
  default: 1
75
- min: 1
76
- max: 30
77
+ validate:
78
+ min: 1
79
+ max: 30
77
80
  ```
78
81
 
79
82
  ```yaml
80
83
  # Uri validator
81
84
  host_url:
82
85
  type: uri
83
- schemes:
84
- - file # only allow file:/// uris
86
+ validate:
87
+ schemes:
88
+ - file # only allow file:/// uris
85
89
  ```
86
90
 
87
91
  ## Resolvers
@@ -343,6 +347,14 @@ end
343
347
  from: prompter
344
348
  ```
345
349
 
350
+ You can also use procs:
351
+
352
+ ```ruby
353
+ group = Opto::Group.new(
354
+ resolvers: { prompt: proc { |hint, option| print "Enter #{hint} (default: #{option.default}): "; gets }
355
+ )
356
+ ```
357
+
346
358
  ## Subclassing a predefined type handler, setter, etc
347
359
 
348
360
  ```ruby
@@ -459,6 +471,23 @@ Global validations:
459
471
  }
460
472
  ```
461
473
 
474
+ ### group
475
+
476
+ Allows nesting of Opto::Groups:
477
+
478
+ ```yaml
479
+ subgroup:
480
+ type: group
481
+ value:
482
+ subvariable:
483
+ type: string
484
+ value: world
485
+ greeting:
486
+ type: string
487
+ from:
488
+ interpolate: hello, ${subgroup.subvariable} # becomes hello, world
489
+ ```
490
+
462
491
  ## Default resolvers
463
492
  Hint is the value that gets passed to the resolver when doing for example: `env: FOO` (FOO is the hint)
464
493
 
@@ -598,6 +627,44 @@ When an "else" is not defined and none of the conditions match, a null value wil
598
627
 
599
628
  The syntax for conditionals and complex conditionals is documented above in the chapter about conditionals.
600
629
 
630
+ ### yaml
631
+
632
+ Hint is a hash defining filename or variable containing YAML source and optionally a key
633
+
634
+ Example:
635
+ ```yaml
636
+ # Read a string value from a key in YAML file
637
+ str:
638
+ type: string
639
+ from:
640
+ yaml:
641
+ file: .env
642
+ key: STR
643
+
644
+ # Read an array from a nested key in a YAML file
645
+ str2:
646
+ type: array
647
+ from:
648
+ yaml:
649
+ file: variables.yml
650
+ key: variables.str2.value # assuming { variables: { str2: { value: ["abcd", "defg"] } } }
651
+
652
+ # Read a YAML file into a string
653
+ yaml_content:
654
+ type: string
655
+ from:
656
+ file: /etc/config.yml
657
+
658
+ # Read YAML content from a variable and fetch a key from it
659
+ str3:
660
+ type: string
661
+ from:
662
+ yaml:
663
+ variable: yaml_content
664
+ key: settings.cpu_arch
665
+ ```
666
+
667
+
601
668
  ## Default setters
602
669
 
603
670
  ### env
@@ -11,35 +11,52 @@ module Opto
11
11
 
12
12
  using Opto::Extension::HashStringOrSymbolKey
13
13
 
14
- attr_reader :options, :defaults
15
-
16
14
  extend Forwardable
17
15
 
18
16
  # Initialize a new Option Group. You can also pass in :defaults.
19
17
  #
20
18
  # @param [Array<Hash,Opto::Option>,Hash,NilClass] opts An array of Option definition hashes or Option objects or a hash like { var_name: { opts } }.
21
19
  # @return [Opto::Group]
22
- def initialize(*options)
23
- if options.size > 0
24
- if options.last.kind_of?(Hash) && options.last[:defaults]
25
- @defaults = options.pop[:defaults]
26
- end
27
- @options =
28
- case options.first
29
- when NilClass
30
- []
31
- when Hash
32
- options.first.map {|k,v| Option.new({name: k.to_s, group: self}.merge(v))}
33
- when ::Array
34
- options.first.map {|opt| opt.kind_of?(Opto::Option) ? opt : Option.new(opt.merge(group: self)) }
35
- else
36
- raise TypeError, "Invalid type #{options.first.class} for Opto::Group.new"
20
+ def initialize(*opts)
21
+ case opts.first
22
+ when NilClass
23
+ when Hash
24
+ defaults.merge!(opts.first.delete(:defaults)) if opts.first.key?(:defaults)
25
+ setters.merge!(opts.first.delete(:setters)) if opts.first.key?(:setters)
26
+ resolvers.merge!(opts.first.delete(:resolvers)) if opts.first.key?(:resolvers)
27
+ options.concat(opts.first.map {|k,v| Option.new({name: k.to_s, group: self}.merge(v))})
28
+ when ::Array
29
+ if opts.last.is_a?(Hash) && !opts.last.key?(:type)
30
+ opts.pop.tap do |settings|
31
+ defaults.merge!(settings[:defaults]) if settings.key?(:defaults)
32
+ setters.merge!(settings[:setters]) if settings.key?(:setters)
33
+ resolvers.merge!(settings[:resolvers]) if settings.key?(:resolvers)
37
34
  end
35
+ end
36
+ if opts.first.kind_of?(Array)
37
+ options.concat(opts.first.map { |opt| opt.kind_of?(Opto::Option) ? opt : Option.new(opt.merge(group: self)) })
38
+ end
38
39
  else
39
- @options = []
40
+ raise TypeError, "Invalid type #{opts.class} for Opto::Group.new"
40
41
  end
41
42
  end
42
43
 
44
+ def options
45
+ @options ||= []
46
+ end
47
+
48
+ def setters
49
+ @setters ||= {}
50
+ end
51
+
52
+ def resolvers
53
+ @resolvers ||= {}
54
+ end
55
+
56
+ def defaults
57
+ @defaults ||= {}
58
+ end
59
+
43
60
  # Are all options valid? (Option value passes validation)
44
61
  # @return [Boolean]
45
62
  def valid?
@@ -91,7 +108,25 @@ module Opto
91
108
  # @param [String] option_name
92
109
  # @return [Opto::Option]
93
110
  def option(option_name)
94
- options.find { |opt| opt.name == option_name }
111
+ if option_name.to_s.include?('.')
112
+ parts = option_name.to_s.split('.')
113
+ var_name = parts.pop
114
+ group = parts.inject(self) do |base, part|
115
+ grp = base.option(part).value
116
+ if grp.nil?
117
+ raise NameError, "No such group: #{base.name}.#{part}"
118
+ elsif grp.kind_of?(Opto::Group)
119
+ grp
120
+ else
121
+ raise TypeError, "Is not a group: #{base.name}.#{part}"
122
+ end
123
+ end
124
+ else
125
+ group = self
126
+ var_name = option_name
127
+ end
128
+
129
+ group.options.find { |opt| opt.name == var_name }
95
130
  end
96
131
 
97
132
  # Get a value of a member by option name
@@ -180,6 +215,6 @@ module Opto
180
215
  end
181
216
  end
182
217
 
183
- def_delegators :@options, *(::Array.instance_methods - [:__send__, :object_id, :to_h, :to_a, :is_a?, :kind_of?, :instance_of?, :self, :inspect, :nil?])
218
+ def_delegators :options, *(::Array.instance_methods - [:__send__, :object_id, :to_h, :to_a, :is_a?, :kind_of?, :instance_of?, :self, :inspect, :nil?])
184
219
  end
185
220
  end
@@ -86,12 +86,27 @@ module Opto
86
86
  @only_if = opts.delete(:only_if)
87
87
  @from = normalize_from_to(opts.delete(:from))
88
88
  @to = normalize_from_to(opts.delete(:to))
89
- @type_options = opts
89
+ validations = opts.delete(:validate).to_h
90
+ transforms = opts.delete(:transform)
91
+ transforms = case transforms
92
+ when NilClass then {}
93
+ when Hash then transforms
94
+ when Array then
95
+ transforms.each_with_object({}) { |t, hash| hash[t] = true }
96
+ else
97
+ raise TypeError, 'Transform has to be a hash or an array'
98
+ end
99
+ @type_options = opts.merge(validations).merge(transforms)
100
+ @tried_resolve = false
90
101
 
91
102
  set_initial(val) if val
92
103
  deep_merge_defaults
93
104
  end
94
105
 
106
+ def has_group?
107
+ !group.nil?
108
+ end
109
+
95
110
  def deep_merge_defaults
96
111
  return nil unless group && group.defaults
97
112
  if group.defaults[:from]
@@ -140,7 +155,7 @@ module Opto
140
155
  # Returns true if this field should not be processed because of the conditionals
141
156
  # @return [Boolean]
142
157
  def skip?
143
- return false if group.nil?
158
+ return false unless has_group?
144
159
  return true if group.any_true?(skip_if)
145
160
  return true unless group.all_true?(only_if)
146
161
  false
@@ -150,7 +165,8 @@ module Opto
150
165
  # @param [String] option_name
151
166
  def value_of(option_name)
152
167
  return value if option_name == self.name
153
- group.nil? ? nil : group.value_of(option_name)
168
+ return nil unless has_group?
169
+ group.value_of(option_name)
154
170
  end
155
171
 
156
172
  # Run validators
@@ -181,11 +197,11 @@ module Opto
181
197
  # Accessor to defined resolvers for this option.
182
198
  # @return [Array<Opto::Resolver>]
183
199
  def resolvers
184
- @resolvers ||= from.merge(default: self).map { |origin, hint| Resolver.for(origin).new(hint, self) }
200
+ @resolvers ||= from.merge(default: self).map { |origin, hint| { origin: origin, hint: hint, resolver: ((has_group? && group.resolvers[origin]) || Resolver.for(origin)) } }
185
201
  end
186
202
 
187
203
  def setters
188
- @setters ||= to.map { |target, hint| Setter.for(target).new(hint, self) }
204
+ @setters ||= to.map { |target, hint| { target: target, hint: hint, setter: ((has_group? && group.setters[target]) || Setter.for(target)) } }
189
205
  end
190
206
 
191
207
  # True if this field is defined as required: true
@@ -194,32 +210,55 @@ module Opto
194
210
  handler.required?
195
211
  end
196
212
 
213
+ def tried_resolve?
214
+ @tried_resolve
215
+ end
216
+
217
+ def set_tried
218
+ @tried_resolve = true
219
+ end
220
+
221
+ def unset_tried!
222
+ @tried_resolve = false
223
+ end
224
+
197
225
  # Run resolvers
198
226
  # @raise [TypeError, ArgumentError]
199
227
  def resolve
200
- resolvers.each do |resolver|
228
+ return nil if tried_resolve?
229
+ resolvers.each do |resolver_config|
201
230
  begin
202
- result = resolver.try_resolve
231
+ resolver = resolver_config[:resolver]
232
+ if resolver.respond_to?(:call)
233
+ result = resolver.call(resolver_config[:hint], self)
234
+ else
235
+ result = resolver.new(resolver_config[:hint], self).resolve
236
+ end
203
237
  rescue StandardError => ex
204
- raise ex, "Resolver '#{resolver.origin}' for '#{name}' : #{ex.message}"
238
+ raise ex, "Resolver '#{resolver_config[:origin]}' for '#{name}' : #{ex.message}"
205
239
  end
206
240
  unless result.nil?
207
- @origin = resolver.origin
241
+ @origin = resolver_config[:origin]
208
242
  return result
209
243
  end
210
244
  end
211
245
  nil
246
+ ensure
247
+ set_tried
212
248
  end
213
249
 
214
250
  # Run setters
215
251
  def output
216
- setters.each do |setter|
252
+ setters.each do |setter_config|
217
253
  begin
218
- setter.respond_to?(:before) && setter.before(self)
219
- setter.set(value)
220
- setter.respond_to?(:after) && setter.after(self)
254
+ setter = setter_config[:setter]
255
+ if setter.respond_to?(:call)
256
+ setter.call(setter_config[:hint], value, self)
257
+ else
258
+ setter.new(setter_config[:hint], self).set(value)
259
+ end
221
260
  rescue StandardError => ex
222
- raise ex, "Setter '#{setter.target}' for '#{name}' : #{ex.message}"
261
+ raise ex, "Setter '#{setter_config[:target]}' for '#{name}' : #{ex.message}"
223
262
  end
224
263
  end
225
264
  end
@@ -43,28 +43,6 @@ module Opto
43
43
  def initialize(hint = nil, option = nil)
44
44
  @hint = hint
45
45
  @option = option
46
- @tried = false
47
- end
48
-
49
- def tried?
50
- !!@tried
51
- end
52
-
53
- def set_tried
54
- @tried = true
55
- end
56
-
57
- def reset_tried
58
- @tried = false
59
- end
60
-
61
- def try_resolve
62
- return nil if tried?
63
- set_tried
64
- self.respond_to?(:before) && self.before
65
- result = resolve
66
- self.respond_to?(:after) && self.after
67
- result
68
46
  end
69
47
 
70
48
  # This is a "base" class, you're supposed to inherit from this in your resolver and define a #resolve method.
@@ -79,10 +79,6 @@ module Opto
79
79
  matching_condition = conditions.find {|c| c.true? }
80
80
  matching_condition.result
81
81
  end
82
-
83
- def after
84
- reset_tried # conditional value can change if some of the depending variables change values
85
- end
86
82
  end
87
83
  end
88
84
  end
@@ -10,7 +10,7 @@ module Opto
10
10
 
11
11
  def resolve
12
12
  raise TypeError, "String required" unless hint.kind_of?(String)
13
- interpolated_hint = hint.gsub(/(?<!\$)\$(?!\$)\{?\w+\}?/) do |v|
13
+ interpolated_hint = hint.gsub(/(?<!\$)\$(?!\$)\{?[\w\.]+\}?/) do |v|
14
14
  var = v.tr('${}', '')
15
15
  if option.group.nil? || option.group.option(var).nil?
16
16
  raise RuntimeError, "Variable #{var} not declared"
@@ -27,10 +27,6 @@ module Opto
27
27
  raise TypeError, "Syntax error: '#{interpolated_hint}' does not look like a number or a calculation"
28
28
  end
29
29
  end
30
-
31
- def after
32
- reset_tried
33
- end
34
30
  end
35
31
  end
36
32
  end
@@ -14,20 +14,16 @@ module Opto
14
14
 
15
15
  def resolve
16
16
  raise TypeError, "String expected" unless hint.kind_of?(String)
17
- hint.gsub(/(?<!\$)\$(?!\$)\{?\w+\}?/) do |v|
17
+ hint.gsub(/(?<!\$)\$(?!\$)\{?[\w\.]+\}?/) do |v|
18
18
  var = v.tr('${}', '')
19
- if option.group.nil? || option.group.option(var).nil?
20
- raise RuntimeError, "Variable #{var} not declared"
21
- end
22
- if option.value_of(var).nil?
23
- raise RuntimeError, "No value for #{var}, note that the order is meaningful"
24
- end
25
- option.value_of(var)
26
- end
27
- end
28
19
 
29
- def after
30
- reset_tried
20
+ raise RuntimeError, "Variable #{var} not declared" if option.group.nil?
21
+ opt = option.group.option(var)
22
+ raise RuntimeError, "Variable #{var} not declared" if opt.nil?
23
+ value = opt.value
24
+ raise RuntimeError, "No value for #{var}, note that the order is meaningful" if value.nil?
25
+ value
26
+ end
31
27
  end
32
28
  end
33
29
  end
@@ -0,0 +1,45 @@
1
+ require 'opto/extensions/snake_case'
2
+ require 'opto/extensions/hash_string_or_symbol_key'
3
+
4
+ module Opto
5
+ module Resolvers
6
+ # Loads values from YAML files
7
+ #
8
+ # Example:
9
+ # from:
10
+ # yaml:
11
+ # file: foofoo.yml
12
+ # key: foo
13
+ class Yaml < Opto::Resolver
14
+
15
+ using Opto::Extension::HashStringOrSymbolKey
16
+
17
+ def resolve
18
+ raise TypeError, "Hash expected" unless hint.kind_of?(Hash)
19
+
20
+ require 'yaml' unless Kernel.const_defined?(:YAML)
21
+
22
+ if hint[:file]
23
+ yaml = YAML.safe_load(::File.read(hint[:file]), [], [], true, hint[:file])
24
+ elsif hint[:variable]
25
+ raise TypeError, "Option not in a group" unless option.has_group?
26
+ other_opt = option.group.option(hint[:variable])
27
+ raise ArgumentError, "No such option: #{hint[:variable]}" if other_opt.nil?
28
+ yaml = YAML.safe_load(other_opt.value.to_s, [], [], true, hint[:variable])
29
+ else
30
+ raise TypeError, "Missing file/variable definition"
31
+ end
32
+ if hint[:key]
33
+ raise TypeError, "Source is not a hash" unless yaml.kind_of?(Hash)
34
+ if yaml.key?(hint[:key])
35
+ yaml[hint[:key]]
36
+ elsif hint[:key].include?('.')
37
+ yaml.dig(*hint[:key].split('.'))
38
+ end
39
+ else
40
+ yaml
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../type'
2
+
3
+ module Opto
4
+ module Types
5
+ # A subgroup
6
+ class Group < Opto::Type
7
+ using Opto::Extension::HashStringOrSymbolKey
8
+
9
+ true_when do |value|
10
+ value.kind_of?(Opto::Group) && !value.empty?
11
+ end
12
+
13
+ sanitizer :init do |value|
14
+ if options[:variables]
15
+ Opto::Group.new(options[:variables])
16
+ elsif value.kind_of?(::Hash) || value.kind_of?(::Array)
17
+ Opto::Group.new(value)
18
+ elsif value.kind_of?(Opto::Group)
19
+ value
20
+ elsif value.nil?
21
+ Opto::Group.new
22
+ else
23
+ raise TypeError, "Invalid type #{value.class.name} for a group"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Opto
2
- VERSION = "1.8.7"
2
+ VERSION = "1.9.0"
3
3
  end
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = ">= 2.1.0"
21
+ spec.required_ruby_version = ">= 2.3.0"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.12"
24
- spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rake", ">= 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.0"
26
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opto
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.7
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kimmo Lehto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-14 00:00:00.000000000 Z
11
+ date: 2018-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
@@ -83,12 +83,14 @@ files:
83
83
  - lib/opto/resolvers/random_string.rb
84
84
  - lib/opto/resolvers/random_uuid.rb
85
85
  - lib/opto/resolvers/variable.rb
86
+ - lib/opto/resolvers/yaml.rb
86
87
  - lib/opto/setter.rb
87
88
  - lib/opto/setters/environment_variable.rb
88
89
  - lib/opto/type.rb
89
90
  - lib/opto/types/array.rb
90
91
  - lib/opto/types/boolean.rb
91
92
  - lib/opto/types/enum.rb
93
+ - lib/opto/types/group.rb
92
94
  - lib/opto/types/integer.rb
93
95
  - lib/opto/types/string.rb
94
96
  - lib/opto/types/uri.rb
@@ -106,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
108
  requirements:
107
109
  - - ">="
108
110
  - !ruby/object:Gem::Version
109
- version: 2.1.0
111
+ version: 2.3.0
110
112
  required_rubygems_version: !ruby/object:Gem::Requirement
111
113
  requirements:
112
114
  - - ">="
@@ -114,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
116
  version: '0'
115
117
  requirements: []
116
118
  rubyforge_project:
117
- rubygems_version: 2.6.13
119
+ rubygems_version: 2.7.7
118
120
  signing_key:
119
121
  specification_version: 4
120
122
  summary: Option validator / resolver