opto 1.8.7 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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