configurations 2.2.0 → 2.2.1
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 +4 -6
- data/Rakefile +1 -0
- data/configurations.gemspec +2 -0
- data/lib/configurations.rb +8 -4
- data/lib/configurations/arbitrary.rb +8 -13
- data/lib/configurations/blank_object.rb +5 -0
- data/lib/configurations/configurable.rb +39 -91
- data/lib/configurations/configuration.rb +30 -102
- data/lib/configurations/data.rb +44 -0
- data/lib/configurations/maps.rb +6 -0
- data/lib/configurations/maps/blocks.rb +62 -0
- data/lib/configurations/maps/data.rb +30 -0
- data/lib/configurations/maps/properties.rb +48 -0
- data/lib/configurations/maps/readers.rb +1 -0
- data/lib/configurations/maps/readers/tolerant.rb +13 -0
- data/lib/configurations/maps/types.rb +56 -0
- data/lib/configurations/maps/writers.rb +1 -0
- data/lib/configurations/maps/writers/default.rb +17 -0
- data/lib/configurations/path.rb +22 -0
- data/lib/configurations/strict.rb +25 -83
- data/lib/configurations/validators.rb +2 -0
- data/lib/configurations/validators/ambiguity.rb +26 -0
- data/lib/configurations/validators/reserved_methods.rb +39 -0
- data/test/configurations/configuration/test_configure_synchronized.rb +17 -31
- data/test/configurations/shared/hash_methods.rb +3 -3
- data/test/run +4 -0
- data/test/test_helper.rb +1 -0
- data/test/watch +9 -0
- metadata +52 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64f706300eff0c3494e39c9e560b63b198513d07
|
4
|
+
data.tar.gz: 82d0bbb8af8484bc6dbcd9c1162f659690d867a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44aa42ce5c00099190352575d9f76fd20ab2fe9135d97a3a6a1df3a24633e512303f55b4eb96d7e263b9b717c33034728d91bc3f699c6ad282db5060da64dfc4
|
7
|
+
data.tar.gz: e42634d42c69e015e6e47b499519c121b0076562983edea0a4f8c40bb0b3cb4e6024bd7f08b489bea51b0b800d1d11315e1df85a705611295ba8ec4a8b745c8a
|
data/.travis.yml
CHANGED
@@ -3,14 +3,12 @@ branches:
|
|
3
3
|
only:
|
4
4
|
- master
|
5
5
|
rvm:
|
6
|
-
- 1.9.2
|
7
|
-
- 1.9.3
|
8
6
|
- 2.0.0
|
9
|
-
- 2.1.
|
10
|
-
- 2.2.
|
11
|
-
-
|
7
|
+
- 2.1.10
|
8
|
+
- 2.2.5
|
9
|
+
- 2.3.1
|
10
|
+
- rbx-2
|
12
11
|
- jruby-19mode
|
13
12
|
- jruby-20mode
|
14
|
-
- jruby-head
|
15
13
|
|
16
14
|
script: CODECLIMATE_REPO_TOKEN=36cf84c73264d3c361003f66903eec8aa5fb2b3494496f3a9676630518ecc9f9 rake
|
data/Rakefile
CHANGED
data/configurations.gemspec
CHANGED
@@ -20,6 +20,8 @@ SUMMARY
|
|
20
20
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
21
21
|
|
22
22
|
s.add_development_dependency 'minitest', '~> 5.4'
|
23
|
+
s.add_development_dependency 'minitest-focus', '~> 1.1'
|
24
|
+
s.add_development_dependency 'test-unit', '~> 3'
|
23
25
|
s.add_development_dependency 'yard', '~> 0.8'
|
24
26
|
s.add_development_dependency 'rake', '~> 10'
|
25
27
|
end
|
data/lib/configurations.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
require_relative 'configurations/
|
1
|
+
require_relative 'configurations/arbitrary'
|
2
2
|
require_relative 'configurations/blank_object'
|
3
|
+
require_relative 'configurations/configurable'
|
3
4
|
require_relative 'configurations/configuration'
|
4
|
-
require_relative 'configurations/
|
5
|
+
require_relative 'configurations/data'
|
6
|
+
require_relative 'configurations/error'
|
7
|
+
require_relative 'configurations/maps'
|
8
|
+
require_relative 'configurations/path'
|
5
9
|
require_relative 'configurations/strict'
|
6
|
-
require_relative 'configurations/
|
10
|
+
require_relative 'configurations/validators'
|
7
11
|
|
8
12
|
# Configurations provides a unified approach to do configurations
|
9
13
|
# with the flexibility to do everything from arbitrary configurations
|
@@ -16,5 +20,5 @@ module Configurations
|
|
16
20
|
|
17
21
|
# Version number of Configurations
|
18
22
|
#
|
19
|
-
VERSION = '2.2.
|
23
|
+
VERSION = '2.2.1'
|
20
24
|
end
|
@@ -30,7 +30,9 @@ module Configurations
|
|
30
30
|
elsif __respond_to_method_for_write?(method)
|
31
31
|
@data[method]
|
32
32
|
elsif __respond_to_method_for_read?(method, *args, &block)
|
33
|
-
@data.fetch(method
|
33
|
+
@data.fetch(method) do
|
34
|
+
@not_configured_blocks.evaluate!(@path.add(method), method)
|
35
|
+
end
|
34
36
|
else
|
35
37
|
super
|
36
38
|
end
|
@@ -54,20 +56,13 @@ module Configurations
|
|
54
56
|
# (in configure block)
|
55
57
|
#
|
56
58
|
def from_h(h)
|
57
|
-
unless @
|
59
|
+
unless @writeable
|
58
60
|
fail ::ArgumentError, 'can not dynamically assign values from a hash'
|
59
61
|
end
|
60
62
|
|
61
63
|
super
|
62
64
|
end
|
63
65
|
|
64
|
-
# @param [Symbol] property The property to test for configurability
|
65
|
-
# @return [Boolean] whether the given property is configurable
|
66
|
-
#
|
67
|
-
def __configurable?(_property)
|
68
|
-
true
|
69
|
-
end
|
70
|
-
|
71
66
|
# Set the configuration to writeable or read only. Access to writer methods
|
72
67
|
# is only allowed within the configure block, this method is used to invoke
|
73
68
|
# writeability for subconfigurations.
|
@@ -75,8 +70,8 @@ module Configurations
|
|
75
70
|
# false otherwise
|
76
71
|
#
|
77
72
|
def __writeable__=(data)
|
78
|
-
@
|
79
|
-
return
|
73
|
+
@writeable = data
|
74
|
+
return unless defined?(@data) && @data
|
80
75
|
|
81
76
|
@data.each do |_k, v|
|
82
77
|
v.__writeable__ = data if v.is_a?(__class__)
|
@@ -104,7 +99,7 @@ module Configurations
|
|
104
99
|
# property as a method during writeable state
|
105
100
|
#
|
106
101
|
def __respond_to_method_for_write?(method)
|
107
|
-
!__is_writer?(method) && @
|
102
|
+
!__is_writer?(method) && @writeable && @data[method].is_a?(__class__)
|
108
103
|
end
|
109
104
|
|
110
105
|
# @param [Symbol] method the method to test for
|
@@ -120,7 +115,7 @@ module Configurations
|
|
120
115
|
# state
|
121
116
|
#
|
122
117
|
def __respond_to_writer?(method)
|
123
|
-
@
|
118
|
+
@writeable && __is_writer?(method)
|
124
119
|
end
|
125
120
|
end
|
126
121
|
end
|
@@ -31,6 +31,11 @@ module Configurations
|
|
31
31
|
:object_id,
|
32
32
|
# rbx needs the singleton class to access singleton methods
|
33
33
|
:singleton_class,
|
34
|
+
# rbx needs its private methods
|
35
|
+
:__instance_variable_defined_p__,
|
36
|
+
:__instance_variable_get__,
|
37
|
+
:__instance_variable_set__,
|
38
|
+
:__instance_variable__,
|
34
39
|
*ALIAS_KERNEL_METHODS.keys
|
35
40
|
].compact.freeze
|
36
41
|
|
@@ -117,10 +117,22 @@ module Configurations
|
|
117
117
|
# end
|
118
118
|
#
|
119
119
|
def configurable(*properties, &block)
|
120
|
-
|
120
|
+
@configurable_properties ||= Maps::Properties.new
|
121
|
+
@configurable_types ||= Maps::Types.new
|
122
|
+
@configurable_blocks ||= Maps::Blocks.new
|
123
|
+
|
124
|
+
type, properties = extract_type(properties)
|
125
|
+
@configurable_properties.add(properties)
|
126
|
+
@configurable_types.add(type, properties)
|
127
|
+
@configurable_blocks.add(block, properties)
|
128
|
+
end
|
121
129
|
|
122
|
-
|
123
|
-
|
130
|
+
def extract_type(properties)
|
131
|
+
if properties.first.is_a?(Module)
|
132
|
+
[properties.first, properties[1...properties.size]]
|
133
|
+
else
|
134
|
+
[nil, properties]
|
135
|
+
end
|
124
136
|
end
|
125
137
|
|
126
138
|
# returns whether a property is set to be configurable
|
@@ -128,7 +140,9 @@ module Configurations
|
|
128
140
|
# @return [Boolean] whether the property is configurable
|
129
141
|
#
|
130
142
|
def configurable?(property)
|
131
|
-
|
143
|
+
defined?(@configurable_properties) &&
|
144
|
+
@configurable_properties &&
|
145
|
+
@configurable_properties.configurable?(Path.new([property]))
|
132
146
|
end
|
133
147
|
|
134
148
|
# configuration method can be used to retrieve properties
|
@@ -151,14 +165,8 @@ module Configurations
|
|
151
165
|
"can't be configuration property and a method"
|
152
166
|
) if configurable?(method)
|
153
167
|
|
154
|
-
@
|
155
|
-
|
156
|
-
ingest_configuration_block!(method, &block)
|
157
|
-
else
|
158
|
-
{ method => block }
|
159
|
-
end
|
160
|
-
|
161
|
-
@configuration_methods.merge! method_hash
|
168
|
+
@configuration_method_blocks ||= Maps::Blocks.new
|
169
|
+
@configuration_method_blocks.add(block, [method])
|
162
170
|
end
|
163
171
|
|
164
172
|
# not_configured defines the behaviour when a property has not been
|
@@ -181,12 +189,11 @@ module Configurations
|
|
181
189
|
# end
|
182
190
|
#
|
183
191
|
def not_configured(*properties, &block)
|
184
|
-
@
|
192
|
+
@not_configured_blocks ||= Maps::Blocks.new
|
193
|
+
@not_configured_blocks.add(block, properties)
|
185
194
|
|
186
195
|
if properties.empty?
|
187
|
-
@
|
188
|
-
else
|
189
|
-
nested_merge_not_configured_hash(*properties, &block)
|
196
|
+
@not_configured_blocks.add_default(block)
|
190
197
|
end
|
191
198
|
end
|
192
199
|
|
@@ -207,41 +214,10 @@ module Configurations
|
|
207
214
|
# @return the class name of the configuration class to use
|
208
215
|
#
|
209
216
|
def configuration_type
|
210
|
-
if @
|
211
|
-
Configurations::Arbitrary
|
212
|
-
else
|
217
|
+
if defined?(@configurable_properties) && @configurable_properties && !@configurable_properties.empty?
|
213
218
|
Configurations::Strict
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
# Instantiates a configurable hash from a property and a type
|
218
|
-
# @param [Symbol, Hash, Array] properties configurable properties,
|
219
|
-
# either single or nested
|
220
|
-
# @param [Class] type the type to assert, if any
|
221
|
-
# @return a hash with configurable values pointing to their types
|
222
|
-
#
|
223
|
-
def to_configurable_hash(properties, type, &block)
|
224
|
-
assertion_hash = {}
|
225
|
-
assertion_hash.merge! block: block if block_given?
|
226
|
-
assertion_hash.merge! type: type if type
|
227
|
-
|
228
|
-
zip_to_hash(assertion_hash, *properties)
|
229
|
-
end
|
230
|
-
|
231
|
-
# Makes all values of hash point to block
|
232
|
-
# @param [Hash] hash the hash to modify
|
233
|
-
# @param [Proc] block the block to point to
|
234
|
-
# @return a hash with all previous values being keys pointing to block
|
235
|
-
#
|
236
|
-
def ingest_configuration_block!(hash, &block)
|
237
|
-
hash.each do |k, v|
|
238
|
-
value = if v.is_a?(Hash)
|
239
|
-
ingest_configuration_block!(v, &block)
|
240
|
-
else
|
241
|
-
zip_to_hash(block, *Array(v))
|
242
|
-
end
|
243
|
-
|
244
|
-
hash.merge! k => value
|
219
|
+
else
|
220
|
+
Configurations::Arbitrary
|
245
221
|
end
|
246
222
|
end
|
247
223
|
|
@@ -249,47 +225,19 @@ module Configurations
|
|
249
225
|
#
|
250
226
|
def configuration_options
|
251
227
|
{
|
252
|
-
defaults:
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
nested = properties.last.is_a?(Hash) ? properties.pop : {}
|
266
|
-
nested = ingest_configuration_block!(nested, &block)
|
267
|
-
props = zip_to_hash(block, *properties)
|
268
|
-
|
269
|
-
@not_configured.merge! nested, &method(:configuration_deep_merge)
|
270
|
-
@not_configured.merge! props, &method(:configuration_deep_merge)
|
271
|
-
end
|
272
|
-
|
273
|
-
# Solves merge conflicts when merging
|
274
|
-
# @param [Symbol] key the key that conflicts
|
275
|
-
# @param [Anything] oldval the value of the left side of the merge
|
276
|
-
# @param [Anything] newval the value of the right side of the merge
|
277
|
-
# @return a mergable value with conflicts solved
|
278
|
-
#
|
279
|
-
def configuration_deep_merge(_key, oldval, newval)
|
280
|
-
if oldval.is_a?(Hash) && newval.is_a?(Hash)
|
281
|
-
oldval.merge(newval, &method(:configuration_deep_merge))
|
282
|
-
else
|
283
|
-
Array(oldval) + Array(newval)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
# Zip a value with keys to a hash so all keys point to the value
|
288
|
-
# @param [Anything] value the value to point to
|
289
|
-
# @param [Array] keys the keys to install
|
290
|
-
#
|
291
|
-
def zip_to_hash(value, *keys)
|
292
|
-
Hash[keys.zip([value] * keys.size)]
|
228
|
+
defaults:
|
229
|
+
defined?(@configuration_defaults) && @configuration_defaults,
|
230
|
+
properties:
|
231
|
+
defined?(@configurable_properties) && @configurable_properties,
|
232
|
+
types:
|
233
|
+
defined?(@configurable_types) && @configurable_types,
|
234
|
+
blocks:
|
235
|
+
defined?(@configurable_blocks) && @configurable_blocks,
|
236
|
+
method_blocks:
|
237
|
+
defined?(@configuration_method_blocks) && @configuration_method_blocks,
|
238
|
+
not_configured_blocks:
|
239
|
+
defined?(@not_configured_blocks) && @not_configured_blocks,
|
240
|
+
}.keep_if { |_, value| value }
|
293
241
|
end
|
294
242
|
end
|
295
243
|
end
|
@@ -3,18 +3,6 @@ module Configurations
|
|
3
3
|
# of various properties including keywords
|
4
4
|
#
|
5
5
|
class Configuration < BlankObject
|
6
|
-
# Reserved methods are not assignable. They define behaviour needed for
|
7
|
-
# the configuration object to work properly.
|
8
|
-
#
|
9
|
-
RESERVED_METHODS = [
|
10
|
-
:initialize,
|
11
|
-
:inspect,
|
12
|
-
:method_missing,
|
13
|
-
:object_id,
|
14
|
-
:singleton_class, # needed by rbx
|
15
|
-
:to_h,
|
16
|
-
:to_s # needed by rbx / 1.9.3 for inspect
|
17
|
-
]
|
18
6
|
|
19
7
|
class << self
|
20
8
|
# Make new a private method, but allow __new__ alias. Instantiating
|
@@ -31,10 +19,16 @@ module Configurations
|
|
31
19
|
# not_configured properties
|
32
20
|
|
33
21
|
def initialize(options = {}, &block)
|
34
|
-
@
|
35
|
-
@
|
22
|
+
@data = Data.new(__configuration_hash__)
|
23
|
+
@path = options.fetch(:path) { Path.new }
|
24
|
+
@data_map = options.fetch(:data) { Maps::Data.new }
|
25
|
+
|
26
|
+
@methods = options.fetch(:methods) { ::Hash.new }
|
27
|
+
@method_blocks = options.fetch(:method_blocks) { Maps::Blocks.new }
|
28
|
+
@not_configured_blocks = options.fetch(:not_configured_blocks) { Maps::Blocks.new }
|
36
29
|
|
37
|
-
@
|
30
|
+
@reserved_method_validator = Validators::ReservedMethods.new
|
31
|
+
@key_ambiguity_validator = Validators::Ambiguity.new
|
38
32
|
|
39
33
|
__instance_eval__(&options[:defaults]) if options[:defaults]
|
40
34
|
__instance_eval__(&block) if block
|
@@ -78,7 +72,8 @@ module Configurations
|
|
78
72
|
# different values
|
79
73
|
#
|
80
74
|
def from_h(h)
|
81
|
-
|
75
|
+
@key_ambiguity_validator.validate!(h)
|
76
|
+
|
82
77
|
h.each do |property, value|
|
83
78
|
p = property.to_sym
|
84
79
|
if value.is_a?(::Hash) && __nested?(p)
|
@@ -108,8 +103,12 @@ module Configurations
|
|
108
103
|
# @param [Symbol] property The property to test for configurability
|
109
104
|
# @return [Boolean] whether the given property is configurable
|
110
105
|
#
|
111
|
-
def __configurable?(
|
112
|
-
|
106
|
+
def __configurable?(property)
|
107
|
+
if defined?(@configurable_properties) && @configurable_properties
|
108
|
+
@configurable_properties.configurable?(@path.add(property))
|
109
|
+
else
|
110
|
+
true
|
111
|
+
end
|
113
112
|
end
|
114
113
|
|
115
114
|
# @param [Symbol] property The property to test for
|
@@ -130,9 +129,10 @@ module Configurations
|
|
130
129
|
# as singleton methods
|
131
130
|
#
|
132
131
|
def __install_configuration_methods__
|
133
|
-
@
|
134
|
-
|
135
|
-
|
132
|
+
entries = @method_blocks.entries_at(@path)
|
133
|
+
entries.each do |meth, entry|
|
134
|
+
@reserved_method_validator.validate!(meth)
|
135
|
+
__define_singleton_method__(meth, &entry.block)
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
@@ -141,39 +141,17 @@ module Configurations
|
|
141
141
|
# @return [Hash] a hash to be used for configuration initialization
|
142
142
|
#
|
143
143
|
def __options_hash_for__(property)
|
144
|
-
|
145
|
-
hash[:not_configured] =
|
146
|
-
__not_configured_hash_for__(property) if @__not_configured__[property]
|
147
|
-
hash[:methods] = @__methods__[property] if @__methods__.key?(property)
|
148
|
-
|
149
|
-
hash
|
150
|
-
end
|
151
|
-
|
152
|
-
# @param [Symbol] property the property to return the callback for
|
153
|
-
# @return [Proc] a block to use when property is called before
|
154
|
-
# configuration, defaults to a block yielding nil
|
155
|
-
#
|
156
|
-
def __not_configured_callback_for__(property)
|
157
|
-
not_configured = @__not_configured__[property] || ::Proc.new { nil }
|
144
|
+
nested_path = @path.add(property)
|
158
145
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
146
|
+
hash = {}
|
147
|
+
hash[:path] = nested_path
|
148
|
+
hash[:data] = @data_map
|
149
|
+
hash[:properties] = defined?(@properties) && @properties
|
163
150
|
|
164
|
-
|
165
|
-
end
|
151
|
+
hash[:not_configured_blocks] = @not_configured_blocks
|
166
152
|
|
167
|
-
|
168
|
-
|
169
|
-
# @return [Hash] a hash which can be used as a not configured
|
170
|
-
# hash in options
|
171
|
-
#
|
172
|
-
def __not_configured_hash_for__(property)
|
173
|
-
hash = ::Hash.new(&@__not_configured__.default_proc)
|
174
|
-
hash.merge!(
|
175
|
-
@__not_configured__[property]
|
176
|
-
) if @__not_configured__[property].is_a?(::Hash)
|
153
|
+
hash[:method_blocks] = @method_blocks
|
154
|
+
hash[:methods] = @methods[property] if @methods.key?(property)
|
177
155
|
|
178
156
|
hash
|
179
157
|
end
|
@@ -192,7 +170,7 @@ module Configurations
|
|
192
170
|
# @param [Any] value the given value
|
193
171
|
#
|
194
172
|
def __assign!(property, value)
|
195
|
-
|
173
|
+
@data_map.add_entry(@path.add(property), value)
|
196
174
|
@data[property] = value
|
197
175
|
end
|
198
176
|
|
@@ -222,55 +200,5 @@ module Configurations
|
|
222
200
|
method.to_s[0..-2].to_sym
|
223
201
|
end
|
224
202
|
|
225
|
-
# @param [Symbol] method the method to test for reservedness
|
226
|
-
# @raise [Configurations::ReservedMethodError] raises this error if
|
227
|
-
# a property is a reserved method.
|
228
|
-
#
|
229
|
-
def __test_reserved!(method)
|
230
|
-
::Kernel.fail(
|
231
|
-
::Configurations::ReservedMethodError,
|
232
|
-
"#{method} is a reserved method and can not be assigned"
|
233
|
-
) if __is_reserved?(method)
|
234
|
-
end
|
235
|
-
|
236
|
-
# @param [Hash] the hash to test for ambiguity
|
237
|
-
# @raise [Configurations::ConfigurationError] raises this error if
|
238
|
-
# a property is defined ambiguously
|
239
|
-
#
|
240
|
-
def __test_ambiguity!(h)
|
241
|
-
symbols, others = h.keys.partition { |k| k.is_a?(::Symbol) }
|
242
|
-
ambiguous = symbols.map(&:to_s) & others
|
243
|
-
|
244
|
-
unless ambiguous.empty?
|
245
|
-
::Kernel.fail(
|
246
|
-
::Configurations::ConfigurationError,
|
247
|
-
"Can not resolve configuration values for #{ambiguous.join(', ')} " \
|
248
|
-
"defined as both Symbol and #{others.first.class.name} keys. " \
|
249
|
-
'Please resolve the ambiguity.'
|
250
|
-
)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# @param [Symbol] method the method to test for
|
255
|
-
# @return [TrueClass, FalseClass] whether the method is reserved
|
256
|
-
#
|
257
|
-
def __is_reserved?(method)
|
258
|
-
RESERVED_METHODS.include?(method)
|
259
|
-
end
|
260
|
-
|
261
|
-
# @param [Hash] a hash to collect blocks from
|
262
|
-
# @return [Proc] a proc to call all the procs
|
263
|
-
#
|
264
|
-
def __collect_blocks__(hash)
|
265
|
-
hash.reduce([]) do |array, (k, v)|
|
266
|
-
array << if v.is_a?(::Hash)
|
267
|
-
__collect_blocks__(v)
|
268
|
-
else
|
269
|
-
v || k
|
270
|
-
end
|
271
|
-
|
272
|
-
array
|
273
|
-
end.flatten
|
274
|
-
end
|
275
203
|
end
|
276
204
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Configurations
|
2
|
+
# Configuration is a blank object in order to allow configuration
|
3
|
+
# of various properties including keywords
|
4
|
+
#
|
5
|
+
class Data
|
6
|
+
def initialize(
|
7
|
+
data,
|
8
|
+
reserved_method_validator = Validators::ReservedMethods.new
|
9
|
+
)
|
10
|
+
@data = data
|
11
|
+
@reserved_method_validator = reserved_method_validator
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key)
|
15
|
+
@data[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(key, value)
|
19
|
+
@reserved_method_validator.validate!(key)
|
20
|
+
|
21
|
+
@data[key] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def key?(key)
|
25
|
+
@data.key?(key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def fetch(key, &block)
|
29
|
+
@data.fetch(key, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def each(&block)
|
33
|
+
@data.each(&block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def reduce(acc, &block)
|
37
|
+
@data.reduce(acc, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
@data.inspect
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Maps
|
3
|
+
class Blocks
|
4
|
+
class Entry
|
5
|
+
attr_reader :block
|
6
|
+
|
7
|
+
def initialize(block)
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def evaluate!(value)
|
12
|
+
return value unless @block
|
13
|
+
block.call(value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(reader = Readers::Tolerant.new)
|
18
|
+
@map = {}
|
19
|
+
@reader = reader
|
20
|
+
@default = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_default(block)
|
24
|
+
@default = Entry.new(block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add(block, properties)
|
28
|
+
properties.each do |property|
|
29
|
+
add_entry(property, block, @map)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def entries_at(path)
|
34
|
+
entries = @reader.read(@map, path) || {}
|
35
|
+
entries.dup.keep_if { |_, v| v.is_a?(Entry) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def evaluate!(path, value)
|
39
|
+
entry = @reader.read(@map, path) || @default
|
40
|
+
return unless entry
|
41
|
+
|
42
|
+
entry.evaluate!(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_entry(property, block, subtree)
|
46
|
+
if property.is_a?(Hash)
|
47
|
+
property.each do |key, val|
|
48
|
+
subtree[key] = add_entry(val, block, subtree.fetch(key, {}))
|
49
|
+
end
|
50
|
+
elsif property.is_a?(Array)
|
51
|
+
property.each do |val|
|
52
|
+
add_entry(val, block, subtree)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
subtree[property] = Entry.new(block)
|
56
|
+
end
|
57
|
+
|
58
|
+
subtree
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Maps
|
3
|
+
class Data
|
4
|
+
class Entry
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(
|
11
|
+
reader = Readers::Tolerant.new,
|
12
|
+
writer = Writers::Default.new { |value|
|
13
|
+
Entry.new(value)
|
14
|
+
}
|
15
|
+
)
|
16
|
+
@map = {}
|
17
|
+
@reader = reader
|
18
|
+
@writer = writer
|
19
|
+
end
|
20
|
+
|
21
|
+
def nested?(path)
|
22
|
+
@reader.read(@map, path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_entry(path, value)
|
26
|
+
@writer.write(@map, path, value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Maps
|
3
|
+
class Properties
|
4
|
+
attr_reader :map
|
5
|
+
class Entry
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(reader = Readers::Tolerant.new)
|
9
|
+
@map = {}
|
10
|
+
@reader = reader
|
11
|
+
end
|
12
|
+
|
13
|
+
def empty?
|
14
|
+
@map.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(properties)
|
18
|
+
properties.each do |property|
|
19
|
+
add_entry(property, @map)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def entries_at(path)
|
24
|
+
@reader.read(@map, path) || {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def configurable?(path)
|
28
|
+
!!@reader.read(@map, path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_entry(property, subtree)
|
32
|
+
if property.is_a?(Hash)
|
33
|
+
property.each do |key, val|
|
34
|
+
subtree[key] = add_entry(val, subtree.fetch(key, {}))
|
35
|
+
end
|
36
|
+
elsif property.is_a?(Array)
|
37
|
+
property.each do |val|
|
38
|
+
add_entry(val, subtree)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
subtree[property] = Entry.new
|
42
|
+
end
|
43
|
+
|
44
|
+
subtree
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'readers/tolerant'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Maps
|
3
|
+
class Types
|
4
|
+
attr_reader :map
|
5
|
+
class Entry
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def initialize(type)
|
9
|
+
@type = type
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid?(value)
|
13
|
+
!@type || value.is_a?(@type)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(reader = Readers::Tolerant.new)
|
18
|
+
@map = {}
|
19
|
+
@reader = reader
|
20
|
+
end
|
21
|
+
|
22
|
+
def add(type, properties)
|
23
|
+
properties.each do |property|
|
24
|
+
add_entry(property, type, @map)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test!(path, value)
|
29
|
+
entry = @reader.read(@map, path)
|
30
|
+
return unless entry
|
31
|
+
|
32
|
+
fail(
|
33
|
+
ConfigurationError,
|
34
|
+
"#{path.print} must be configured with #{entry.type} (got #{value})",
|
35
|
+
caller
|
36
|
+
) unless entry.valid?(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_entry(property, type, subtree)
|
40
|
+
if property.is_a?(Hash)
|
41
|
+
property.each do |key, val|
|
42
|
+
subtree[key] = add_entry(val, type, subtree.fetch(key, {}))
|
43
|
+
end
|
44
|
+
elsif property.is_a?(Array)
|
45
|
+
property.each do |val|
|
46
|
+
add_entry(val, type, subtree)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
subtree[property] = Entry.new(type)
|
50
|
+
end
|
51
|
+
|
52
|
+
subtree
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'writers/default'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Configurations
|
2
|
+
class Path
|
3
|
+
def initialize(path = [])
|
4
|
+
@path = path
|
5
|
+
end
|
6
|
+
|
7
|
+
def add(*path)
|
8
|
+
Path.new(@path + path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def reduce(initial, &block)
|
12
|
+
@path.reduce(initial, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@path.join(".")
|
17
|
+
end
|
18
|
+
alias :inspect :to_s
|
19
|
+
alias :print :to_s
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -16,65 +16,43 @@ module Configurations
|
|
16
16
|
# @return [HostModule::Configuration] a configuration
|
17
17
|
#
|
18
18
|
def initialize(options = {}, &block)
|
19
|
-
@
|
19
|
+
@reserved_method_validator = Validators::ReservedMethods.new
|
20
|
+
|
21
|
+
@path = options.fetch(:path) { Path.new }
|
22
|
+
@properties = options.fetch(:properties) { Maps::Properties.new }
|
23
|
+
@types = options.fetch(:types)
|
24
|
+
@blocks = options.fetch(:blocks)
|
25
|
+
|
20
26
|
__evaluate_configurable!
|
21
27
|
|
22
28
|
super
|
23
29
|
end
|
24
30
|
|
25
|
-
# @param [Symbol] property The property to test for configurability
|
26
|
-
# @return [Boolean] whether the given property is configurable
|
27
|
-
#
|
28
|
-
def __configurable?(property)
|
29
|
-
@__configurable__.key?(property) ||
|
30
|
-
@__nested_configurables__.key?(property)
|
31
|
-
end
|
32
|
-
|
33
31
|
private
|
34
32
|
|
35
33
|
# Evaluates configurable properties and passes eventual hashes
|
36
34
|
# down to subconfigurations
|
37
35
|
#
|
38
36
|
def __evaluate_configurable!
|
39
|
-
@
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
__install_nested_getter__(property)
|
44
|
-
end
|
37
|
+
entries = @properties.entries_at(@path)
|
38
|
+
entries.each do |property, value|
|
39
|
+
if value.is_a?(Maps::Properties::Entry)
|
40
|
+
__install_property__(property)
|
45
41
|
else
|
46
|
-
|
42
|
+
__install_nested_getter__(property)
|
47
43
|
end
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
51
|
-
# Add a property to a nested configurable
|
52
|
-
#
|
53
|
-
def __add_to_nested_configurables!(property, nested, assertion)
|
54
|
-
@__nested_configurables__ ||= ::Hash.new { |h, k| h[k] = {} }
|
55
|
-
@__nested_configurables__[property].merge!(
|
56
|
-
__configurable_hash__(property, nested, assertion)
|
57
|
-
)
|
58
|
-
end
|
59
|
-
|
60
47
|
# Get an options hash for a property
|
61
48
|
#
|
62
49
|
def __options_hash_for__(property)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# either single or nested
|
70
|
-
# @param [Hash] assertion assertion if any
|
71
|
-
# @return a hash with configurable values pointing to their types
|
72
|
-
#
|
73
|
-
def __configurable_hash__(_property, value, assertion)
|
74
|
-
value = [value] unless value.is_a?(::Array)
|
75
|
-
hash = ::Hash[value.zip([assertion].flatten * value.size)]
|
76
|
-
|
77
|
-
hash
|
50
|
+
_nested_path = @path.add(property)
|
51
|
+
super(property).merge(
|
52
|
+
properties: @properties,
|
53
|
+
types: @types,
|
54
|
+
blocks: @blocks
|
55
|
+
)
|
78
56
|
end
|
79
57
|
|
80
58
|
# @param [Symbol] property the property to test for
|
@@ -89,7 +67,7 @@ module Configurations
|
|
89
67
|
# @param [Symbol] property the property to install
|
90
68
|
#
|
91
69
|
def __install_property__(property)
|
92
|
-
|
70
|
+
@reserved_method_validator.validate!(property)
|
93
71
|
__install_setter__(property)
|
94
72
|
__install_getter__(property)
|
95
73
|
end
|
@@ -108,7 +86,9 @@ module Configurations
|
|
108
86
|
#
|
109
87
|
def __install_getter__(property)
|
110
88
|
__define_singleton_method__ property do
|
111
|
-
@data.fetch(property
|
89
|
+
@data.fetch(property) do
|
90
|
+
@not_configured_blocks.evaluate!(@path.add(property), property)
|
91
|
+
end
|
112
92
|
end
|
113
93
|
end
|
114
94
|
|
@@ -127,49 +107,11 @@ module Configurations
|
|
127
107
|
# @param [Any] value the given value
|
128
108
|
#
|
129
109
|
def __assign!(property, value)
|
130
|
-
|
131
|
-
v =
|
110
|
+
@types.test!(@path.add(property), value)
|
111
|
+
v = @blocks.evaluate!(@path.add(property), value)
|
112
|
+
|
132
113
|
value = v unless v.nil?
|
133
114
|
super(property, value)
|
134
115
|
end
|
135
|
-
|
136
|
-
# Type assertion for configurable properties
|
137
|
-
# @param [Symbol] property the property to type test
|
138
|
-
# @param [Any] value the given value
|
139
|
-
# @raise [ConfigurationError] if the given value has the wrong type
|
140
|
-
#
|
141
|
-
def __assert_type!(property, value)
|
142
|
-
return unless __evaluable?(property, :type)
|
143
|
-
|
144
|
-
assertion = @__configurable__[property][:type]
|
145
|
-
return if value.is_a?(assertion)
|
146
|
-
|
147
|
-
::Kernel.fail(
|
148
|
-
ConfigurationError,
|
149
|
-
"#{property} must be configured with #{assertion} (got #{value.class})",
|
150
|
-
caller
|
151
|
-
)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Block assertion for configurable properties
|
155
|
-
# @param [Symbol] property the property to type test
|
156
|
-
# @param [Any] value the given value
|
157
|
-
#
|
158
|
-
def __evaluate_block!(property, value)
|
159
|
-
return value unless __evaluable?(property, :block)
|
160
|
-
|
161
|
-
evaluation = @__configurable__[property][:block]
|
162
|
-
evaluation.call(value)
|
163
|
-
end
|
164
|
-
|
165
|
-
# @param [Symbol] property The property to test for
|
166
|
-
# @param [Symbol] assertion_type The evaluation type type to test for
|
167
|
-
# @return [Boolean] whether the given property is assertable
|
168
|
-
#
|
169
|
-
def __evaluable?(property, evaluation)
|
170
|
-
__configurable?(property) &&
|
171
|
-
@__configurable__[property].is_a?(::Hash) &&
|
172
|
-
@__configurable__[property].key?(evaluation)
|
173
|
-
end
|
174
116
|
end
|
175
117
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Validators
|
3
|
+
class Ambiguity
|
4
|
+
# @param [Hash] the hash to test for ambiguity
|
5
|
+
# @raise [Configurations::ConfigurationError] raises this error if
|
6
|
+
# a property is defined ambiguously
|
7
|
+
#
|
8
|
+
def validate!(h)
|
9
|
+
symbols, others = h.keys.partition { |k|
|
10
|
+
k.is_a?(::Symbol)
|
11
|
+
}
|
12
|
+
|
13
|
+
ambiguous = symbols.map(&:to_s) & others
|
14
|
+
|
15
|
+
unless ambiguous.empty?
|
16
|
+
::Kernel.fail(
|
17
|
+
::Configurations::ConfigurationError,
|
18
|
+
"Can not resolve configuration values for #{ambiguous.join(', ')} " \
|
19
|
+
"defined as both Symbol and #{others.first.class.name} keys. " \
|
20
|
+
'Please resolve the ambiguity.'
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Configurations
|
2
|
+
module Validators
|
3
|
+
class ReservedMethods
|
4
|
+
# @param [Symbol] method the method to test for reservedness
|
5
|
+
# @raise [Configurations::ReservedMethodError] raises this error if
|
6
|
+
# a property is a reserved method.
|
7
|
+
#
|
8
|
+
def validate!(method)
|
9
|
+
::Kernel.fail(
|
10
|
+
::Configurations::ReservedMethodError,
|
11
|
+
"#{method} is a reserved method and can not be assigned"
|
12
|
+
) if reserved?(method)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Reserved methods are not assignable. They define behaviour needed for
|
18
|
+
# the configuration object to work properly.
|
19
|
+
#
|
20
|
+
RESERVED_METHODS = [
|
21
|
+
:initialize,
|
22
|
+
:inspect,
|
23
|
+
:method_missing,
|
24
|
+
:object_id,
|
25
|
+
:singleton_class, # needed by rbx
|
26
|
+
:to_h,
|
27
|
+
:to_s # needed by rbx / 1.9.3 for inspect
|
28
|
+
]
|
29
|
+
|
30
|
+
# @param [Symbol] method the method to test for
|
31
|
+
# @return [TrueClass, FalseClass] whether the method is reserved
|
32
|
+
#
|
33
|
+
def reserved?(method)
|
34
|
+
RESERVED_METHODS.include?(method)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,50 +1,36 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class TestConfigurationSynchronized < MiniTest::Test
|
4
|
-
module
|
4
|
+
module TestModuleA
|
5
5
|
include Configurations
|
6
6
|
|
7
7
|
configuration_defaults do |c|
|
8
|
-
c.a =
|
8
|
+
c.a = -1
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
ids = []
|
15
|
-
threads = 100.times.map do |i|
|
16
|
-
Thread.new do
|
17
|
-
sleep rand(1000) / 1000.0
|
18
|
-
ids << TestModule.configure do |c|
|
19
|
-
c.a = i
|
20
|
-
end.a
|
21
|
-
end
|
22
|
-
end
|
23
|
-
threads.each(&:join)
|
12
|
+
module TestModuleB
|
13
|
+
include Configurations
|
24
14
|
|
25
|
-
|
15
|
+
configuration_defaults do |c|
|
16
|
+
c.a = -1
|
26
17
|
end
|
27
18
|
end
|
28
19
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
20
|
+
def test_configuration_synchronized
|
21
|
+
collector = []
|
22
|
+
semaphore = Mutex.new
|
23
|
+
threads = 100.times.map do |i|
|
24
|
+
Thread.new do
|
25
|
+
sleep i%50 / 1000.0
|
26
|
+
collector << TestModuleA.configure do |c|
|
27
|
+
c.a = i
|
28
|
+
end.a
|
34
29
|
end
|
35
|
-
|
36
|
-
there = TestModule.configuration.a
|
37
30
|
end
|
31
|
+
threads.each(&:join)
|
38
32
|
|
39
|
-
|
40
|
-
here = TestModule.configuration.a
|
41
|
-
|
42
|
-
assert_equal here, there
|
33
|
+
assert_equal 100, collector.uniq.size
|
43
34
|
end
|
44
35
|
|
45
|
-
def with_gc_disabled(&_block)
|
46
|
-
GC.disable
|
47
|
-
yield
|
48
|
-
GC.enable
|
49
|
-
end
|
50
36
|
end
|
@@ -49,9 +49,9 @@ module Tests
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def test_from_h_with_unambiguous_strings_and_symbols
|
52
|
-
|
53
|
-
assert_equal 2,
|
54
|
-
assert_equal 'bla',
|
52
|
+
config = @module.configure { |c| c.from_h('p1' => 'bla', :p2 => 2) }
|
53
|
+
assert_equal 2, config.p2
|
54
|
+
assert_equal 'bla', config.p1
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
data/test/run
ADDED
data/test/test_helper.rb
CHANGED
data/test/watch
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configurations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Beat Richartz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -17,13 +17,41 @@ dependencies:
|
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '5.4'
|
20
|
-
type: :development
|
21
20
|
prerelease: false
|
21
|
+
type: :development
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest-focus
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
prerelease: false
|
35
|
+
type: :development
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: test-unit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3'
|
48
|
+
prerelease: false
|
49
|
+
type: :development
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: yard
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,8 +59,8 @@ dependencies:
|
|
31
59
|
- - "~>"
|
32
60
|
- !ruby/object:Gem::Version
|
33
61
|
version: '0.8'
|
34
|
-
type: :development
|
35
62
|
prerelease: false
|
63
|
+
type: :development
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
66
|
- - "~>"
|
@@ -45,8 +73,8 @@ dependencies:
|
|
45
73
|
- - "~>"
|
46
74
|
- !ruby/object:Gem::Version
|
47
75
|
version: '10'
|
48
|
-
type: :development
|
49
76
|
prerelease: false
|
77
|
+
type: :development
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
80
|
- - "~>"
|
@@ -72,8 +100,22 @@ files:
|
|
72
100
|
- lib/configurations/blank_object.rb
|
73
101
|
- lib/configurations/configurable.rb
|
74
102
|
- lib/configurations/configuration.rb
|
103
|
+
- lib/configurations/data.rb
|
75
104
|
- lib/configurations/error.rb
|
105
|
+
- lib/configurations/maps.rb
|
106
|
+
- lib/configurations/maps/blocks.rb
|
107
|
+
- lib/configurations/maps/data.rb
|
108
|
+
- lib/configurations/maps/properties.rb
|
109
|
+
- lib/configurations/maps/readers.rb
|
110
|
+
- lib/configurations/maps/readers/tolerant.rb
|
111
|
+
- lib/configurations/maps/types.rb
|
112
|
+
- lib/configurations/maps/writers.rb
|
113
|
+
- lib/configurations/maps/writers/default.rb
|
114
|
+
- lib/configurations/path.rb
|
76
115
|
- lib/configurations/strict.rb
|
116
|
+
- lib/configurations/validators.rb
|
117
|
+
- lib/configurations/validators/ambiguity.rb
|
118
|
+
- lib/configurations/validators/reserved_methods.rb
|
77
119
|
- test/configurations/arbitrary/test.rb
|
78
120
|
- test/configurations/arbitrary/test_defaults.rb
|
79
121
|
- test/configurations/arbitrary/test_hash_methods.rb
|
@@ -121,9 +163,11 @@ files:
|
|
121
163
|
- test/configurations/strict_with_blocks/test_methods.rb
|
122
164
|
- test/configurations/strict_with_blocks/test_not_configured.rb
|
123
165
|
- test/configurations/strict_with_blocks/test_not_configured_default.rb
|
166
|
+
- test/run
|
124
167
|
- test/support/setup.rb
|
125
168
|
- test/support/shared.rb
|
126
169
|
- test/test_helper.rb
|
170
|
+
- test/watch
|
127
171
|
homepage: http://github.com/beatrichartz/configurations
|
128
172
|
licenses:
|
129
173
|
- MIT
|
@@ -144,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
188
|
version: '0'
|
145
189
|
requirements: []
|
146
190
|
rubyforge_project:
|
147
|
-
rubygems_version: 2.
|
191
|
+
rubygems_version: 2.5.1
|
148
192
|
signing_key:
|
149
193
|
specification_version: 4
|
150
194
|
summary: Configurations with a configure block from arbitrary to type-restricted for
|
@@ -197,7 +241,9 @@ test_files:
|
|
197
241
|
- test/configurations/strict_with_blocks/test_methods.rb
|
198
242
|
- test/configurations/strict_with_blocks/test_not_configured.rb
|
199
243
|
- test/configurations/strict_with_blocks/test_not_configured_default.rb
|
244
|
+
- test/run
|
200
245
|
- test/support/setup.rb
|
201
246
|
- test/support/shared.rb
|
202
247
|
- test/test_helper.rb
|
248
|
+
- test/watch
|
203
249
|
has_rdoc:
|