collapsium-config 0.4.3 → 0.5.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 +4 -4
- data/.travis.yml +1 -1
- data/Gemfile.lock +10 -10
- data/collapsium-config.gemspec +2 -2
- data/lib/collapsium-config.rb +19 -1
- data/lib/collapsium-config/configuration.rb +42 -15
- data/lib/collapsium-config/version.rb +1 -1
- data/spec/configuration_spec.rb +45 -8
- data/spec/data/global.yml +2 -0
- data/spec/module_spec.rb +9 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31e518d37d4cdaa12f8a8718c3ca5816939b6ab2
|
4
|
+
data.tar.gz: 3d466b1b37734a90beafa962991fd9735734ea39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7052b7b696d6b7cb5422fa2e6236656de330ffc28ecf08fdb0db52593b36a5fab2d219333ef8ea0c55b3ae83c7a18704d0c7fb998c77caece40e8ebac69fd94a
|
7
|
+
data.tar.gz: 85bddfd097bce75d0285c01e1f1da0dfc612f127be4bfc769481669e75df7425a6e67ecd9b11f551378da7edef29cd944a8ca38928a49cfd2da4305023145fc1
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
collapsium-config (0.
|
5
|
-
collapsium (~> 0.
|
4
|
+
collapsium-config (0.5.0)
|
5
|
+
collapsium (~> 0.8)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
10
|
ast (2.3.0)
|
11
|
-
codeclimate-test-reporter (1.0.
|
11
|
+
codeclimate-test-reporter (1.0.4)
|
12
12
|
simplecov
|
13
|
-
collapsium (0.
|
13
|
+
collapsium (0.8.2)
|
14
14
|
diff-lcs (1.2.5)
|
15
15
|
docile (1.1.5)
|
16
16
|
json (2.0.2)
|
17
|
-
parser (2.3.
|
17
|
+
parser (2.3.3.1)
|
18
18
|
ast (~> 2.2)
|
19
19
|
powerpack (0.1.1)
|
20
|
-
rainbow (2.1
|
20
|
+
rainbow (2.2.1)
|
21
21
|
rake (11.3.0)
|
22
22
|
rspec (3.5.0)
|
23
23
|
rspec-core (~> 3.5.0)
|
@@ -32,7 +32,7 @@ GEM
|
|
32
32
|
diff-lcs (>= 1.2.0, < 2.0)
|
33
33
|
rspec-support (~> 3.5.0)
|
34
34
|
rspec-support (3.5.0)
|
35
|
-
rubocop (0.
|
35
|
+
rubocop (0.46.0)
|
36
36
|
parser (>= 2.3.1.1, < 3.0)
|
37
37
|
powerpack (~> 0.1)
|
38
38
|
rainbow (>= 1.99.1, < 3.0)
|
@@ -44,8 +44,8 @@ GEM
|
|
44
44
|
json (>= 1.8, < 3)
|
45
45
|
simplecov-html (~> 0.10.0)
|
46
46
|
simplecov-html (0.10.0)
|
47
|
-
unicode-display_width (1.1.
|
48
|
-
yard (0.9.
|
47
|
+
unicode-display_width (1.1.2)
|
48
|
+
yard (0.9.6)
|
49
49
|
|
50
50
|
PLATFORMS
|
51
51
|
ruby
|
@@ -56,7 +56,7 @@ DEPENDENCIES
|
|
56
56
|
collapsium-config!
|
57
57
|
rake (~> 11.3)
|
58
58
|
rspec (~> 3.5)
|
59
|
-
rubocop (~> 0.
|
59
|
+
rubocop (~> 0.46)
|
60
60
|
simplecov (~> 0.12)
|
61
61
|
yard (~> 0.9)
|
62
62
|
|
data/collapsium-config.gemspec
CHANGED
@@ -38,13 +38,13 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.required_ruby_version = '>= 2.0'
|
39
39
|
|
40
40
|
spec.add_development_dependency "bundler", "~> 1.12"
|
41
|
-
spec.add_development_dependency "rubocop", "~> 0.
|
41
|
+
spec.add_development_dependency "rubocop", "~> 0.46"
|
42
42
|
spec.add_development_dependency "rake", "~> 11.3"
|
43
43
|
spec.add_development_dependency "rspec", "~> 3.5"
|
44
44
|
spec.add_development_dependency "simplecov", "~> 0.12"
|
45
45
|
spec.add_development_dependency "yard", "~> 0.9"
|
46
46
|
|
47
|
-
spec.add_dependency 'collapsium', '~> 0.
|
47
|
+
spec.add_dependency 'collapsium', '~> 0.8'
|
48
48
|
end
|
49
49
|
# rubocop:enable Metrics/BlockLength
|
50
50
|
# rubocop:enable Style/SpaceAroundOperators
|
data/lib/collapsium-config.rb
CHANGED
@@ -18,6 +18,13 @@ module Collapsium
|
|
18
18
|
# The default configuration file path
|
19
19
|
DEFAULT_CONFIG_PATH = 'config.yml'.freeze
|
20
20
|
|
21
|
+
# Default options for configuration loading
|
22
|
+
DEFAULT_CONFIG_OPTIONS = {
|
23
|
+
resolve_extensions: true,
|
24
|
+
nonexistent_base: :ignore,
|
25
|
+
data: nil,
|
26
|
+
}.freeze
|
27
|
+
|
21
28
|
##
|
22
29
|
# Modules can have class methods, too, but it's a little more verbose to
|
23
30
|
# provide them.
|
@@ -32,6 +39,16 @@ module Collapsium
|
|
32
39
|
return @config_file || DEFAULT_CONFIG_PATH
|
33
40
|
end
|
34
41
|
|
42
|
+
# Set configuration loading options
|
43
|
+
def config_options=(opts)
|
44
|
+
@config_options = opts
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Hash] configuration loading options
|
48
|
+
def config_options
|
49
|
+
return @config_options || DEFAULT_CONFIG_OPTIONS
|
50
|
+
end
|
51
|
+
|
35
52
|
# @api private
|
36
53
|
attr_accessor :config
|
37
54
|
end # module ClassMethods
|
@@ -42,7 +59,8 @@ module Collapsium
|
|
42
59
|
def config
|
43
60
|
if Config.config.nil? or Config.config.empty?
|
44
61
|
begin
|
45
|
-
Config.config = Configuration.load_config(Config.config_file
|
62
|
+
Config.config = Configuration.load_config(Config.config_file,
|
63
|
+
Config.config_options)
|
46
64
|
rescue Errno::ENOENT
|
47
65
|
Config.config = {}
|
48
66
|
end
|
@@ -98,13 +98,31 @@ module Collapsium
|
|
98
98
|
# @param options [Hash] options hash with the following keys:
|
99
99
|
# - resolve_extensions [Boolean] flag whether to resolve configuration
|
100
100
|
# hash extensions. (see `#resolve_extensions`)
|
101
|
+
# - nonexistent_base [Symbol] either of :extend or :ignore; flag that
|
102
|
+
# determines how a nonexistent base should be treated:
|
103
|
+
# - :extend behaves as if it does exist, but refers to an empty Hash
|
104
|
+
# - :ignore does not modify the `.base` or `.extends` properties,
|
105
|
+
# and simply ignores the reference.
|
101
106
|
# - data [Hash] data Hash to pass on to the templating mechanism.
|
102
107
|
def load_config(path, options = {})
|
103
108
|
# Option defaults
|
109
|
+
options = options.dup
|
104
110
|
if options[:resolve_extensions].nil?
|
105
111
|
options[:resolve_extensions] = true
|
106
112
|
end
|
113
|
+
if not [true, false].include?(options[:resolve_extensions])
|
114
|
+
raise "The :resolve_extensions option must be a boolean value!"
|
115
|
+
end
|
116
|
+
if options[:nonexistent_base].nil?
|
117
|
+
options[:nonexistent_base] = :ignore
|
118
|
+
end
|
119
|
+
if not [:extend, :ignore].include?(options[:nonexistent_base])
|
120
|
+
raise "The :nonexistent_base option must be one of :ignore or :extend!"
|
121
|
+
end
|
107
122
|
options[:data] ||= {}
|
123
|
+
if not options[:data].is_a? Hash
|
124
|
+
raise "The :data option must be a Hash!"
|
125
|
+
end
|
108
126
|
|
109
127
|
# Load base and local configuration files
|
110
128
|
base, config = load_base_config(path, options[:data])
|
@@ -121,7 +139,7 @@ module Collapsium
|
|
121
139
|
|
122
140
|
# Now resolve config hashes that extend other hashes.
|
123
141
|
if options[:resolve_extensions]
|
124
|
-
cfg.resolve_extensions!
|
142
|
+
cfg.resolve_extensions!(options)
|
125
143
|
end
|
126
144
|
|
127
145
|
return cfg
|
@@ -251,35 +269,35 @@ module Collapsium
|
|
251
269
|
# Also note that all of this means that :extends and :base are reserved
|
252
270
|
# keywords that cannot be used in configuration files other than for this
|
253
271
|
# purpose!
|
254
|
-
def resolve_extensions!
|
272
|
+
def resolve_extensions!(options)
|
255
273
|
# The root object is always a Hash, so has keys, which can be processed
|
256
274
|
# recursively.
|
257
|
-
recursive_resolve(self)
|
275
|
+
recursive_resolve(self, "", options)
|
258
276
|
end
|
259
277
|
|
260
|
-
def recursive_resolve(root, prefix = "")
|
278
|
+
def recursive_resolve(root, prefix = "", options = {})
|
261
279
|
# The self object is a Hash or an Array. Let's iterate over its children
|
262
280
|
# one by one. Defaulting to a Hash here is just convenience, it could
|
263
281
|
# equally be an Array.
|
264
282
|
children = root.fetch(prefix, {})
|
265
283
|
|
266
|
-
merge_base(root, prefix, children)
|
284
|
+
merge_base(root, prefix, children, options)
|
267
285
|
|
268
286
|
if children.is_a? Hash
|
269
287
|
children.each do |key, _|
|
270
288
|
full_key = normalize_path("#{prefix}#{separator}#{key}")
|
271
|
-
recursive_resolve(root, full_key)
|
289
|
+
recursive_resolve(root, full_key, options)
|
272
290
|
end
|
273
291
|
elsif children.is_a? Array
|
274
292
|
children.each_with_index do |_, idx|
|
275
293
|
key = idx.to_s
|
276
294
|
full_key = normalize_path("#{prefix}#{separator}#{key}")
|
277
|
-
recursive_resolve(root, full_key)
|
295
|
+
recursive_resolve(root, full_key, options)
|
278
296
|
end
|
279
297
|
end
|
280
298
|
end
|
281
299
|
|
282
|
-
def merge_base(root, path, value)
|
300
|
+
def merge_base(root, path, value, options)
|
283
301
|
# If the value is not a Hash, we can't do anything here.
|
284
302
|
if not value.is_a? Hash
|
285
303
|
return
|
@@ -292,18 +310,19 @@ module Collapsium
|
|
292
310
|
end
|
293
311
|
|
294
312
|
# Now to resolve the path to the base and remove the "extends" keyword.
|
295
|
-
bases = fetch_base_values(root, parent_path(path), value)
|
313
|
+
bases = fetch_base_values(root, parent_path(path), value, options)
|
296
314
|
|
297
315
|
# Merge the bases
|
298
|
-
merge_base_values(root, value, bases)
|
316
|
+
merge_base_values(root, value, bases, options)
|
299
317
|
|
300
318
|
# And we're done, set the value to what was being merged.
|
301
319
|
root[path] = value
|
302
320
|
end
|
303
321
|
|
304
|
-
def fetch_base_values(root, parent, value)
|
322
|
+
def fetch_base_values(root, parent, value, options)
|
305
323
|
base_paths = array_value(value["extends"])
|
306
324
|
bases = []
|
325
|
+
base_count = 0
|
307
326
|
base_paths.each do |base_path|
|
308
327
|
if not base_path.start_with?(separator)
|
309
328
|
base_path = "#{parent}#{separator}#{base_path}"
|
@@ -315,30 +334,38 @@ module Collapsium
|
|
315
334
|
# We default to nil. Only Hash base values can be processed.
|
316
335
|
base_value = root.fetch(base_path, nil)
|
317
336
|
if not base_value.is_a? Hash
|
337
|
+
bases << [base_path, nil]
|
318
338
|
next
|
319
339
|
end
|
320
340
|
|
321
341
|
bases << [base_path, base_value]
|
342
|
+
base_count += 1
|
322
343
|
end
|
323
344
|
|
324
345
|
# Only delete the "extends" keyword if we found all base.
|
325
|
-
if
|
346
|
+
if options[:nonexistent_base] == :extend or \
|
347
|
+
base_count == base_paths.length
|
326
348
|
value.delete("extends")
|
327
349
|
end
|
328
350
|
|
329
351
|
return bases
|
330
352
|
end
|
331
353
|
|
332
|
-
def merge_base_values(root, value, bases)
|
354
|
+
def merge_base_values(root, value, bases, options)
|
333
355
|
# We need to recursively resolve the base values before merging them into
|
334
356
|
# value. To preserve the override order, we need to overwrite values when
|
335
357
|
# merging bases...
|
336
358
|
merged_base = Configuration.new
|
337
359
|
bases.each do |base_path, base_value|
|
338
|
-
base_value.
|
339
|
-
|
360
|
+
if not base_value.nil?
|
361
|
+
base_value.recursive_resolve(root, base_path)
|
362
|
+
merged_base.recursive_merge!(base_value, true)
|
363
|
+
end
|
340
364
|
|
341
365
|
# Modify bases for this path: we go depth first into the hierarchy
|
366
|
+
if options[:nonexistent_base] == :ignore and base_value.nil?
|
367
|
+
next
|
368
|
+
end
|
342
369
|
base_val = merged_base.fetch("base", []).dup
|
343
370
|
base_val << base_path
|
344
371
|
base_val.uniq!
|
data/spec/configuration_spec.rb
CHANGED
@@ -49,6 +49,25 @@ describe Collapsium::Config::Configuration do
|
|
49
49
|
cfg = Collapsium::Config::Configuration.load_config(config)
|
50
50
|
expect(cfg).to be_empty
|
51
51
|
end
|
52
|
+
|
53
|
+
it "validates options" do
|
54
|
+
config = File.join(@data_path, 'hash.yml')
|
55
|
+
|
56
|
+
# :resolve_extensions must be a boolean
|
57
|
+
opts = { resolve_extensions: 42 }
|
58
|
+
expect { Collapsium::Config::Configuration.load_config(config, opts) }.to \
|
59
|
+
raise_error RuntimeError
|
60
|
+
|
61
|
+
# :data must be a Hash
|
62
|
+
opts = { data: 42 }
|
63
|
+
expect { Collapsium::Config::Configuration.load_config(config, opts) }.to \
|
64
|
+
raise_error RuntimeError
|
65
|
+
|
66
|
+
# :nonexistent_base must be one of :ignore, :extend
|
67
|
+
opts = { nonexistent_base: :foo }
|
68
|
+
expect { Collapsium::Config::Configuration.load_config(config, opts) }.to \
|
69
|
+
raise_error RuntimeError
|
70
|
+
end
|
52
71
|
end
|
53
72
|
|
54
73
|
describe "merge behaviour" do
|
@@ -175,16 +194,34 @@ describe Collapsium::Config::Configuration do
|
|
175
194
|
.drivers.branch2)
|
176
195
|
end
|
177
196
|
|
178
|
-
|
179
|
-
|
180
|
-
|
197
|
+
context "Extension" do
|
198
|
+
it "ignores nonexistent bases by default" do
|
199
|
+
# Ensure the hash contains its own value
|
200
|
+
expect(@config["drivers.base_does_not_exist.some"]).to eql "value"
|
201
|
+
|
202
|
+
# Also ensure the "base" is _not_ set properly
|
203
|
+
expect(@config["drivers.base_does_not_exist.base"]).to be_nil
|
204
|
+
|
205
|
+
# On the other hand, "extends" should stay.
|
206
|
+
expect(@config["drivers.base_does_not_exist.extends"]).to eql \
|
207
|
+
"nonexistent_base"
|
208
|
+
end
|
209
|
+
|
210
|
+
it "can pretend nonexistent bases are empty" do
|
211
|
+
opts = { nonexistent_base: :extend }
|
212
|
+
config = Collapsium::Config::Configuration.load_config(@config_path,
|
213
|
+
opts)
|
214
|
+
|
215
|
+
# Ensure the hash contains its own value
|
216
|
+
expect(config["drivers.base_does_not_exist.some"]).to eql "value"
|
181
217
|
|
182
|
-
|
183
|
-
|
218
|
+
# Here, the base must be set!
|
219
|
+
expect(config["drivers.base_does_not_exist.base"]).to eql \
|
220
|
+
%w(.drivers.nonexistent_base)
|
184
221
|
|
185
|
-
|
186
|
-
|
187
|
-
|
222
|
+
# Then "extends" needs to vanish.
|
223
|
+
expect(config["drivers.base_does_not_exist.extends"]).to be_nil
|
224
|
+
end
|
188
225
|
end
|
189
226
|
end
|
190
227
|
|
data/spec/data/global.yml
CHANGED
data/spec/module_spec.rb
CHANGED
@@ -4,11 +4,12 @@ require_relative '../lib/collapsium-config'
|
|
4
4
|
include Collapsium::Config
|
5
5
|
|
6
6
|
describe Collapsium::Config do
|
7
|
-
before do
|
7
|
+
before :each do
|
8
8
|
@data_path = File.join(File.dirname(__FILE__), 'data')
|
9
9
|
ENV.delete("SOME_PATH")
|
10
10
|
ENV.delete("SOME")
|
11
11
|
ENV.delete("PATH")
|
12
|
+
Collapsium::Config.config = nil
|
12
13
|
end
|
13
14
|
|
14
15
|
it "fails to load configuration from the default path (it does not exist)" do
|
@@ -55,5 +56,12 @@ describe Collapsium::Config do
|
|
55
56
|
expect(config["some.path"]).to eql "override"
|
56
57
|
expect(config["some"]["path"]).to eql "override"
|
57
58
|
end
|
59
|
+
|
60
|
+
it "accepts non-default options" do
|
61
|
+
Collapsium::Config.config_file = File.join(@data_path, 'global.yml')
|
62
|
+
Collapsium::Config.config_options = { resolve_extensions: false }
|
63
|
+
|
64
|
+
expect(config["foo.base"]).to be_nil
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: collapsium-config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jens Finkhaeuser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0.
|
33
|
+
version: '0.46'
|
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
|
-
version: '0.
|
40
|
+
version: '0.46'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.8'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.8'
|
111
111
|
description: "\n Using collapsium's UberHash class for easy access to configuration
|
112
112
|
values,\n this gem reads and merges various configuration sources into one\n
|
113
113
|
\ configuration object.\n "
|