qonfig 0.12.0 → 0.13.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +457 -137
  4. data/lib/qonfig/command_set.rb +7 -1
  5. data/lib/qonfig/commands/add_nested_option.rb +3 -1
  6. data/lib/qonfig/commands/add_option.rb +2 -1
  7. data/lib/qonfig/commands/base.rb +2 -1
  8. data/lib/qonfig/commands/compose.rb +16 -10
  9. data/lib/qonfig/commands/expose_yaml.rb +2 -1
  10. data/lib/qonfig/commands/load_from_env.rb +2 -1
  11. data/lib/qonfig/commands/load_from_json.rb +2 -1
  12. data/lib/qonfig/commands/load_from_self.rb +2 -1
  13. data/lib/qonfig/commands/load_from_yaml.rb +2 -1
  14. data/lib/qonfig/data_set/lock.rb +46 -0
  15. data/lib/qonfig/data_set.rb +92 -23
  16. data/lib/qonfig/errors.rb +8 -0
  17. data/lib/qonfig/plugins/toml/commands/expose_toml.rb +2 -1
  18. data/lib/qonfig/plugins/toml/commands/load_from_toml.rb +2 -1
  19. data/lib/qonfig/settings/builder.rb +20 -4
  20. data/lib/qonfig/settings/callbacks.rb +43 -0
  21. data/lib/qonfig/settings/key_matcher.rb +175 -0
  22. data/lib/qonfig/settings/lock.rb +3 -3
  23. data/lib/qonfig/settings.rb +144 -33
  24. data/lib/qonfig/validator/basic.rb +53 -0
  25. data/lib/qonfig/validator/builder/attribute_consistency.rb +181 -0
  26. data/lib/qonfig/validator/builder.rb +169 -0
  27. data/lib/qonfig/validator/collection.rb +73 -0
  28. data/lib/qonfig/validator/dsl.rb +51 -0
  29. data/lib/qonfig/validator/method_based.rb +49 -0
  30. data/lib/qonfig/validator/predefined/common.rb +53 -0
  31. data/lib/qonfig/validator/predefined/registry.rb +83 -0
  32. data/lib/qonfig/validator/predefined/registry_control_mixin.rb +43 -0
  33. data/lib/qonfig/validator/predefined.rb +41 -0
  34. data/lib/qonfig/validator/proc_based.rb +53 -0
  35. data/lib/qonfig/validator.rb +58 -0
  36. data/lib/qonfig/version.rb +1 -1
  37. data/lib/qonfig.rb +1 -0
  38. data/qonfig.gemspec +1 -1
  39. metadata +19 -5
  40. data/lib/qonfig/data_set/validator.rb +0 -7
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.13.0
5
+ class Qonfig::Settings::KeyMatcher
6
+ # @return [String]
7
+ #
8
+ # @api private
9
+ # @since 0.13.0
10
+ SCOPE_SPLITTER = '.'
11
+
12
+ # @return [String]
13
+ #
14
+ # @api private
15
+ # @since 0.13.0
16
+ MATCHER_SCOPE_SPLITTER = '\.'
17
+
18
+ # @return [String]
19
+ #
20
+ # @api private
21
+ # @since 0.13.0
22
+ GENERIC_PART_PATTERN = '*'
23
+
24
+ # @return [String]
25
+ #
26
+ # @api private
27
+ # @since 0.13.0
28
+ GENERIC_REGEXP_PATTERN = '[^\.]+\.'
29
+
30
+ # @return [String]
31
+ #
32
+ # @api private
33
+ # @since 0.13.0
34
+ INFINITE_PART_PATTERN = '#'
35
+
36
+ # @return [String]
37
+ #
38
+ # @api private
39
+ # @since 0.13.0
40
+ INFINITE_REGEXP_PATTERN = '\.*.*'
41
+
42
+ # @param scope_pattern [String]
43
+ # @return [void]
44
+ #
45
+ # @raise [Qonfig::ArgumentError]
46
+ #
47
+ # @api private
48
+ # @since 0.13.0
49
+ def initialize(scope_pattern)
50
+ raise Qonfig::ArgumentError unless scope_pattern.is_a?(String)
51
+
52
+ @scope_pattern = scope_pattern
53
+ @scope_pattern_size = count_scope_pattern_size(scope_pattern)
54
+ @pattern_matcher = build_pattern_matcher(scope_pattern)
55
+ end
56
+
57
+ # @param setting_key_pattern [String]
58
+ # @return [Boolean]
59
+ #
60
+ # @api private
61
+ # @since 0.13.0
62
+ def match?(setting_key_pattern)
63
+ return false unless comparable_event_scopes?(setting_key_pattern)
64
+ !!pattern_matcher.match(setting_key_pattern)
65
+ end
66
+
67
+ private
68
+
69
+ # @return [Regexp]
70
+ #
71
+ # @api private
72
+ # @since 0.13.0
73
+ attr_reader :pattern_matcher
74
+
75
+ # @return [String]
76
+ #
77
+ # @api private
78
+ # @since 0.13.0
79
+ attr_reader :scope_pattern
80
+
81
+ # @return [Integer, Float::INFINITY]
82
+ #
83
+ # @api private
84
+ # @since 0.13.0
85
+ attr_reader :scope_pattern_size
86
+
87
+ # @param scope_pattern [String]
88
+ # @return [Integer, Float::INFINITY]
89
+ #
90
+ # @api private
91
+ # @since 0.13.0
92
+ def count_scope_pattern_size(scope_pattern)
93
+ return Float::INFINITY if scope_pattern == INFINITE_PART_PATTERN
94
+ return Float::INFINITY if scope_pattern.include?('.#')
95
+ return Float::INFINITY if scope_pattern.include?('#.')
96
+ return Float::INFINITY if scope_pattern.include?('.#.')
97
+
98
+ scope_pattern.split(SCOPE_SPLITTER).size
99
+ end
100
+
101
+ # @param setting_key_pattern [String]
102
+ # @return [Integer]
103
+ #
104
+ # @api private
105
+ # @since 0.13.0
106
+ def count_setting_key_pattern_size(setting_key_pattern)
107
+ setting_key_pattern.split(SCOPE_SPLITTER).size
108
+ end
109
+
110
+ # @param setting_key_pattern [String]
111
+ # @return [Boolean]
112
+ #
113
+ # @api private
114
+ # @since 0.13.0
115
+ def comparable_event_scopes?(setting_key_pattern)
116
+ # NOTE: Integer#finite?, Integer#infinite?, Float#finite?, Float#nfinite?
117
+ # Cant be used (backward compatability with old ruby versions)
118
+ return true if scope_pattern_size == Float::INFINITY
119
+ scope_pattern_size == count_setting_key_pattern_size(setting_key_pattern)
120
+ end
121
+
122
+ # @param pattern [String, NilClass]
123
+ # @return [Boolean]
124
+ #
125
+ # @api private
126
+ # @since 0.13.0
127
+ def non_generic_pattern?(pattern = nil)
128
+ return false unless pattern
129
+ pattern != GENERIC_REGEXP_PATTERN && pattern != INFINITE_REGEXP_PATTERN
130
+ end
131
+
132
+ # "\.test\.created\.today\." => "test\.created\.today"
133
+ #
134
+ # @param regexp_string [String]
135
+ # @option left [Boolean]
136
+ # @option right [Boolean]
137
+ # @return [String]
138
+ #
139
+ # @api private
140
+ # @since 0.13.0
141
+ def strip_regexp_string(regexp_string, left: false, right: false)
142
+ pattern = regexp_string
143
+ pattern = pattern[2..-1] if left && pattern[0..1] == MATCHER_SCOPE_SPLITTER
144
+ pattern = pattern[0..-3] if right && pattern[-2..-1] == MATCHER_SCOPE_SPLITTER
145
+ pattern
146
+ end
147
+
148
+ # @param scope_pattern [String]
149
+ # @return [Regexp]
150
+ #
151
+ # @api private
152
+ # @since 0.13.0
153
+ def build_pattern_matcher(scope_pattern)
154
+ routing_parts = scope_pattern.split(SCOPE_SPLITTER)
155
+
156
+ regexp_string = routing_parts.each_with_object([]) do |routing_part, regexp_parts|
157
+ case routing_part
158
+ when GENERIC_PART_PATTERN
159
+ regexp_parts << GENERIC_REGEXP_PATTERN
160
+ when INFINITE_PART_PATTERN
161
+ if non_generic_pattern?(regexp_parts.last)
162
+ regexp_parts[-1] = strip_regexp_string(regexp_parts.last, right: true)
163
+ end
164
+
165
+ regexp_parts << INFINITE_REGEXP_PATTERN
166
+ else
167
+ regexp_parts << (Regexp.escape(routing_part) + MATCHER_SCOPE_SPLITTER)
168
+ end
169
+ end.join
170
+
171
+ regexp_string = strip_regexp_string(regexp_string, left: true, right: true)
172
+
173
+ Regexp.new('\A' + regexp_string + '\z')
174
+ end
175
+ end
@@ -17,7 +17,7 @@ class Qonfig::Settings::Lock
17
17
  # @api private
18
18
  # @since 0.2.0
19
19
  def thread_safe_definition(&instructions)
20
- definition_lock.synchronize(&instructions)
20
+ definition_lock.owned? ? yield : definition_lock.synchronize(&instructions)
21
21
  end
22
22
 
23
23
  # @param instructions [Proc]
@@ -26,7 +26,7 @@ class Qonfig::Settings::Lock
26
26
  # @api private
27
27
  # @since 0.2.0
28
28
  def thread_safe_access(&instructions)
29
- access_lock.synchronize(&instructions)
29
+ access_lock.owned? ? yield : access_lock.synchronize(&instructions)
30
30
  end
31
31
 
32
32
  # @param instructions [Proc]
@@ -35,7 +35,7 @@ class Qonfig::Settings::Lock
35
35
  # @api private
36
36
  # @since 0.2.0
37
37
  def thread_safe_merge(&instructions)
38
- merge_lock.synchronize(&instructions)
38
+ merge_lock.owned? ? yield : merge_lock.synchronize(&instructions)
39
39
  end
40
40
 
41
41
  private
@@ -2,11 +2,13 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
- # rubocop:disable Metrics/ClassLength
6
- class Qonfig::Settings
5
+ # rubocop:disable Metrics/ClassLength, Layout/ClassStructure
6
+ class Qonfig::Settings # NOTE: Layout/ClassStructure is disabled only for CORE_METHODS constant
7
+ require_relative 'settings/callbacks'
7
8
  require_relative 'settings/lock'
8
9
  require_relative 'settings/builder'
9
10
  require_relative 'settings/key_guard'
11
+ require_relative 'settings/key_matcher'
10
12
 
11
13
  # @return [Proc]
12
14
  #
@@ -26,11 +28,49 @@ class Qonfig::Settings
26
28
  # @since 0.1.0
27
29
  attr_reader :__options__
28
30
 
31
+ # @return [Qonfig::Settings::Callbacks]
32
+ #
33
+ # @api private
34
+ # @since 0.13.0
35
+ attr_reader :__mutation_callbacks__
36
+
29
37
  # @api private
30
38
  # @since 0.1.0
31
- def initialize
39
+ def initialize(__mutation_callbacks__)
32
40
  @__options__ = {}
33
41
  @__lock__ = Lock.new
42
+ @__mutation_callbacks__ = __mutation_callbacks__
43
+ end
44
+
45
+ # @param block [Proc]
46
+ # @return [Enumerable]
47
+ #
48
+ # @yield [key, value]
49
+ # @yieldparam key [String]
50
+ # @yieldparam value [Object]
51
+ #
52
+ # @api private
53
+ # @since 0.13.0
54
+ def __each_setting__(&block)
55
+ __lock__.thread_safe_access do
56
+ __each_key_value_pair__(&block)
57
+ end
58
+ end
59
+
60
+ # @param initial_setting_key [String, NilClass]
61
+ # @param block [Proc]
62
+ # @return [Enumerable]
63
+ #
64
+ # @yield [key, value]
65
+ # @yieldparam key [String]
66
+ # @yieldparam value [Object]
67
+ #
68
+ # @api private
69
+ # @since 0.13.0
70
+ def __deep_each_setting__(initial_setting_key = nil, &block)
71
+ __lock__.thread_safe_access do
72
+ __deep_each_key_value_pair__(initial_setting_key, &block)
73
+ end
34
74
  end
35
75
 
36
76
  # @param key [Symbol, String]
@@ -39,7 +79,7 @@ class Qonfig::Settings
39
79
  #
40
80
  # @api private
41
81
  # @since 0.1.0
42
- def __define_setting__(key, value)
82
+ def __define_setting__(key, value) # rubocop:disable Metrics/AbcSize
43
83
  __lock__.thread_safe_definition do
44
84
  key = __indifferently_accessable_option_key__(key)
45
85
 
@@ -48,13 +88,15 @@ class Qonfig::Settings
48
88
  case
49
89
  when !__options__.key?(key)
50
90
  __options__[key] = value
51
- when __options__[key].is_a?(Qonfig::Settings) && value.is_a?(Qonfig::Settings)
91
+ when __is_a_setting__(__options__[key]) && __is_a_setting__(value)
52
92
  __options__[key].__append_settings__(value)
53
93
  else
54
94
  __options__[key] = value
55
95
  end
56
96
 
57
- __define_accessor__(key)
97
+ __define_option_reader__(key)
98
+ __define_option_writer__(key)
99
+ __define_option_predicate__(key)
58
100
  end
59
101
  end
60
102
 
@@ -71,6 +113,14 @@ class Qonfig::Settings
71
113
  end
72
114
  end
73
115
 
116
+ # @return [void]
117
+ #
118
+ # @api private
119
+ # @since 0.13.0
120
+ def __invoke_mutation_callbacks__
121
+ __mutation_callbacks__.call
122
+ end
123
+
74
124
  # @param key [Symbol, String]
75
125
  # @return [Object]
76
126
  #
@@ -90,13 +140,13 @@ class Qonfig::Settings
90
140
  __lock__.thread_safe_access { __set_value__(key, value) }
91
141
  end
92
142
 
93
- # @param options_map [Hash]
143
+ # @param settings_map [Hash]
94
144
  # @return [void]
95
145
  #
96
146
  # @api private
97
147
  # @since 0.3.0
98
- def __apply_values__(options_map)
99
- __lock__.thread_safe_access { __set_values_from_map__(options_map) }
148
+ def __apply_values__(settings_map)
149
+ __lock__.thread_safe_access { __set_values_from_map__(settings_map) }
100
150
  end
101
151
 
102
152
  # @param keys [Array<String, Symbol>]
@@ -191,7 +241,7 @@ class Qonfig::Settings
191
241
  __options__.freeze
192
242
 
193
243
  __options__.each_value do |value|
194
- value.__freeze__ if value.is_a?(Qonfig::Settings)
244
+ value.__freeze__ if __is_a_setting__(value)
195
245
  end
196
246
  end
197
247
  end
@@ -204,6 +254,15 @@ class Qonfig::Settings
204
254
  __lock__.thread_safe_access { __options__.frozen? }
205
255
  end
206
256
 
257
+ # @param value [Any]
258
+ # @return [Boolean]
259
+ #
260
+ # @api private
261
+ # @since 0.13.0
262
+ def __is_a_setting__(value)
263
+ value.is_a?(Qonfig::Settings)
264
+ end
265
+
207
266
  private
208
267
 
209
268
  # @return [Qonfig::Settings::Lock]
@@ -212,7 +271,47 @@ class Qonfig::Settings
212
271
  # @since 0.2.0
213
272
  attr_reader :__lock__
214
273
 
215
- # @param options_map [Hash]
274
+ # @param block [Proc]
275
+ # @return [Enumerable]
276
+ #
277
+ # @yield [setting_key, setting_value]
278
+ # @yieldparam key [String]
279
+ # @yieldparam value [Object]
280
+ #
281
+ # @api private
282
+ # @since 0.13.0
283
+ def __each_key_value_pair__(&block)
284
+ __options__.each_pair(&block)
285
+ end
286
+
287
+ # @param initial_setting_key [String, NilClass]
288
+ # @param block [Proc]
289
+ # @return [Enumerable]
290
+ #
291
+ # @yield [setting_key, setting_value]
292
+ # @yieldparam setting_key [String]
293
+ # @yieldparam setting_value [Object]
294
+ #
295
+ # @api private
296
+ # @since 0.13.0
297
+ def __deep_each_key_value_pair__(initial_setting_key = nil, &block)
298
+ enumerator = Enumerator.new do |yielder|
299
+ __each_key_value_pair__ do |setting_key, setting_value|
300
+ final_setting_key =
301
+ initial_setting_key ? "#{initial_setting_key}.#{setting_key}" : setting_key
302
+
303
+ if __is_a_setting__(setting_value)
304
+ setting_value.__deep_each_setting__(final_setting_key, &block)
305
+ else
306
+ yielder.yield(final_setting_key, setting_value)
307
+ end
308
+ end
309
+ end
310
+
311
+ block_given? ? enumerator.each(&block) : enumerator
312
+ end
313
+
314
+ # @param settings_map [Hash]
216
315
  # @return [void]
217
316
  #
218
317
  # @raise [Qonfig::ArgumentError]
@@ -220,21 +319,21 @@ class Qonfig::Settings
220
319
  #
221
320
  # @api private
222
321
  # @since 0.3.0
223
- def __set_values_from_map__(options_map)
322
+ def __set_values_from_map__(settings_map)
224
323
  ::Kernel.raise(
225
324
  Qonfig::ArgumentError, 'Options map should be represented as a hash'
226
- ) unless options_map.is_a?(Hash)
325
+ ) unless settings_map.is_a?(Hash)
227
326
 
228
- options_map.each_pair do |key, value|
327
+ settings_map.each_pair do |key, value|
229
328
  current_value = __get_value__(key)
230
329
 
231
330
  # NOTE: some duplications here was made only for the better code readability
232
331
  case
233
- when !current_value.is_a?(Qonfig::Settings)
332
+ when !__is_a_setting__(current_value)
234
333
  __set_value__(key, value)
235
- when current_value.is_a?(Qonfig::Settings) && value.is_a?(Hash)
334
+ when __is_a_setting__(current_value) && value.is_a?(Hash)
236
335
  current_value.__apply_values__(value)
237
- when current_value.is_a?(Qonfig::Settings) && !value.is_a?(Hash)
336
+ when __is_a_setting__(current_value) && !value.is_a?(Hash)
238
337
  ::Kernel.raise(
239
338
  Qonfig::AmbiguousSettingValueError,
240
339
  "Can not redefine option <#{key}> that contains nested options"
@@ -255,12 +354,10 @@ class Qonfig::Settings
255
354
  ) if __options__.frozen?
256
355
 
257
356
  __options__.each_pair do |key, value|
258
- if value.is_a?(Qonfig::Settings)
259
- value.__clear__
260
- else
261
- __options__[key] = nil
262
- end
357
+ __is_a_setting__(value) ? value.__clear__ : __options__[key] = nil
263
358
  end
359
+
360
+ __invoke_mutation_callbacks__
264
361
  end
265
362
 
266
363
  # @param key [String, Symbol]
@@ -301,14 +398,16 @@ class Qonfig::Settings
301
398
  ::Kernel.raise(Qonfig::FrozenSettingsError, 'Can not modify frozen settings')
302
399
  end
303
400
 
304
- if __options__[key].is_a?(Qonfig::Settings)
401
+ if __is_a_setting__(__options__[key])
305
402
  ::Kernel.raise(
306
403
  Qonfig::AmbiguousSettingValueError,
307
404
  "Can not redefine option <#{key}> that contains nested options"
308
405
  )
309
406
  end
310
407
 
311
- __options__[key] = value
408
+ (__options__[key] = value)
409
+
410
+ __invoke_mutation_callbacks__
312
411
  end
313
412
 
314
413
  # @param keys [Array<Symbol, String>]
@@ -328,12 +427,12 @@ class Qonfig::Settings
328
427
  case
329
428
  when rest_keys.empty?
330
429
  result
331
- when !result.is_a?(Qonfig::Settings)
430
+ when !__is_a_setting__(result)
332
431
  ::Kernel.raise(
333
432
  Qonfig::UnknownSettingError,
334
433
  'Setting with required digging sequence does not exist!'
335
434
  )
336
- when result.is_a?(Qonfig::Settings)
435
+ when __is_a_setting__(result)
337
436
  result.__dig__(*rest_keys)
338
437
  end
339
438
  end
@@ -350,7 +449,7 @@ class Qonfig::Settings
350
449
  {}.tap do |result|
351
450
  __deep_access__(*keys).tap do |setting|
352
451
  required_key = __indifferently_accessable_option_key__(keys.last)
353
- result[required_key] = setting.is_a?(Qonfig::Settings) ? setting.__to_h__ : setting
452
+ result[required_key] = __is_a_setting__(setting) ? setting.__to_h__ : setting
354
453
  end
355
454
  end
356
455
  end
@@ -386,7 +485,7 @@ class Qonfig::Settings
386
485
  transform_key: transform_key,
387
486
  transform_value: transform_value
388
487
  )
389
- when value.is_a?(Qonfig::Settings)
488
+ when __is_a_setting__(value)
390
489
  hash[final_key] = value.__to_hash__(
391
490
  transform_key: transform_key,
392
491
  transform_value: transform_value
@@ -402,16 +501,30 @@ class Qonfig::Settings
402
501
  # @return [void]
403
502
  #
404
503
  # @api private
405
- # @since 0.1.0
406
- def __define_accessor__(key)
504
+ # @since 0.13.0
505
+ def __define_option_reader__(key)
407
506
  define_singleton_method(key) do
408
507
  self.[](key)
409
508
  end
509
+ end
410
510
 
511
+ # @param key [Symbol, String]
512
+ # @return [void]
513
+ #
514
+ # @api private
515
+ # @since 0.13.0
516
+ def __define_option_writer__(key)
411
517
  define_singleton_method("#{key}=") do |value|
412
518
  self.[]=(key, value)
413
519
  end
520
+ end
414
521
 
522
+ # @param key [Symbol, String]
523
+ # @return [void]
524
+ #
525
+ # @api private
526
+ # @since 0.13.0
527
+ def __define_option_predicate__(key)
415
528
  define_singleton_method("#{key}?") do
416
529
  !!self.[](key)
417
530
  end
@@ -442,7 +555,6 @@ class Qonfig::Settings
442
555
  KeyGuard.new(key).prevent_core_method_intersection!
443
556
  end
444
557
 
445
- # rubocop:disable Layout/ClassStructure
446
558
  # @return [Array<String>]
447
559
  #
448
560
  # @api private
@@ -452,6 +564,5 @@ class Qonfig::Settings
452
564
  private_instance_methods(false) |
453
565
  %i[super define_singleton_method self]
454
566
  ).map(&:to_s).freeze
455
- # rubocop:enable Layout/ClassStructure
456
567
  end
457
- # rubocop:enable Metrics/ClassLength
568
+ # rubocop:enable Metrics/ClassLength, Layout/ClassStructure
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.13.0
5
+ class Qonfig::Validator::Basic
6
+ # @return [String, Symbol, NilClass]
7
+ #
8
+ # @api private
9
+ # @since 0.13.0
10
+ attr_reader :setting_key_matcher
11
+
12
+ # @param setting_key_matcher [Qonfig::Settings::KeyMatcher, NilClass]
13
+ # @return [void]
14
+ #
15
+ # @api private
16
+ # @since 0.13.0
17
+ def initialize(setting_key_matcher)
18
+ @setting_key_matcher = setting_key_matcher
19
+ end
20
+
21
+ # @param data_set [Qonfig::DataSet]
22
+ # @return [Boolean]
23
+ #
24
+ # @api private
25
+ # @since 0.13.0
26
+ def validate(data_set)
27
+ setting_key_provided? ? validate_concrete(data_set) : validate_full(data_set)
28
+ end
29
+
30
+ private
31
+
32
+ # @return [Boolean]
33
+ #
34
+ # @api private
35
+ # @since 0.13.0
36
+ def setting_key_provided?
37
+ !setting_key_matcher.nil?
38
+ end
39
+
40
+ # @param data_set [Qonfig::DataSet]
41
+ # @return [Any]
42
+ #
43
+ # @api private
44
+ # @since 0.13.0
45
+ def validate_full(data_set); end
46
+
47
+ # @param data_set [Qonfig::DataSet]
48
+ # @return [Any]
49
+ #
50
+ # @api private
51
+ # @since 0.13.0
52
+ def validate_concrete(data_set); end
53
+ end