anyway_config 2.0.1 → 2.0.6

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.
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anyway
4
+ using RubyNext
5
+
6
+ module Loaders
7
+ class Registry
8
+ attr_reader :registry
9
+
10
+ def initialize
11
+ @registry = []
12
+ end
13
+
14
+ def prepend(id, handler = nil, &block)
15
+ handler ||= block
16
+ insert_at(0, id, handler)
17
+ end
18
+
19
+ def append(id, handler = nil, &block)
20
+ handler ||= block
21
+ insert_at(registry.size, id, handler)
22
+ end
23
+
24
+ def insert_before(another_id, id, handler = nil, &block)
25
+ ind = registry.find_index { |(hid, _)| hid == another_id }
26
+ raise ArgumentError, "Loader with ID #{another_id} hasn't been registered" if ind.nil?
27
+
28
+ handler ||= block
29
+ insert_at(ind, id, handler)
30
+ end
31
+
32
+ def insert_after(another_id, id, handler = nil, &block)
33
+ ind = registry.find_index { |(hid, _)| hid == another_id }
34
+ raise ArgumentError, "Loader with ID #{another_id} hasn't been registered" if ind.nil?
35
+
36
+ handler ||= block
37
+ insert_at(ind + 1, id, handler)
38
+ end
39
+
40
+ def override(id, handler)
41
+ find(id).then do |id_to_handler|
42
+ raise ArgumentError, "Loader with ID #{id} hasn't been registered" if id_to_handler.nil?
43
+ id_to_handler[1] = handler
44
+ end
45
+ end
46
+
47
+ def delete(id)
48
+ find(id).then do |id_to_handler|
49
+ raise ArgumentError, "Loader with ID #{id} hasn't been registered" if id_to_handler.nil?
50
+ registry.delete id_to_handler
51
+ end
52
+ end
53
+
54
+ def each(&block)
55
+ registry.each(&block)
56
+ end
57
+
58
+ def freeze() ; registry.freeze; end
59
+
60
+ private
61
+
62
+ def insert_at(index, id, handler)
63
+ raise ArgumentError, "Loader with ID #{id} has been already registered" unless find(id).nil?
64
+
65
+ registry.insert(index, [id, handler])
66
+ end
67
+
68
+ def find(id)
69
+ registry.find { |(hid, _)| hid == id }
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ require "anyway/loaders/base"
76
+ require "anyway/loaders/yaml"
77
+ require "anyway/loaders/env"
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anyway
4
+ module Loaders
5
+ class Base
6
+ include Tracing
7
+
8
+ class << self
9
+ def call(local: Anyway::Settings.use_local_files, **opts)
10
+ new(local: local).call(**opts)
11
+ end
12
+ end
13
+
14
+ def initialize(local:)
15
+ @local = local
16
+ end
17
+
18
+ def use_local?() ; @local == true; end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Anyway
4
+ # Provides method to trace values association
5
+ module Tracing
6
+ using Anyway::Ext::DeepDup
7
+
8
+ using(Module.new do
9
+ refine Hash do
10
+ def inspect
11
+ "{#{map { |k, v| "#{k}: #{v.inspect}" }.join(", ")}}"
12
+ end
13
+ end
14
+
15
+ refine Thread::Backtrace::Location do
16
+ def path_lineno() ; "#{path}:#{lineno}"; end
17
+ end
18
+ end)
19
+
20
+ class Trace
21
+ UNDEF = Object.new
22
+
23
+ attr_reader :type, :value, :source
24
+
25
+ def initialize(type = :trace, value = UNDEF, **source)
26
+ @type = type
27
+ @source = source
28
+ @value = value == UNDEF ? Hash.new { |h, k| h[k] = Trace.new(:trace) } : value
29
+ end
30
+
31
+ def dig(...)
32
+ value.dig(...)
33
+ end
34
+
35
+ def record_value(val, *path, **opts)
36
+ key = path.pop
37
+ trace = if val.is_a?(Hash)
38
+ Trace.new.tap { _1.merge_values(val, **opts) }
39
+ else
40
+ Trace.new(:value, val, **opts)
41
+ end
42
+
43
+ target_trace = path.empty? ? self : value.dig(*path)
44
+ target_trace.value[key.to_s] = trace
45
+
46
+ val
47
+ end
48
+
49
+ def merge_values(hash, **opts)
50
+ return hash unless hash
51
+
52
+ hash.each do |key, val|
53
+ if val.is_a?(Hash)
54
+ value[key.to_s].merge_values(val, **opts)
55
+ else
56
+ value[key.to_s] = Trace.new(:value, val, **opts)
57
+ end
58
+ end
59
+
60
+ hash
61
+ end
62
+
63
+ def merge!(another_trace)
64
+ raise ArgumentError, "You can only merge into a :trace type, and this is :#{type}" unless trace?
65
+ raise ArgumentError, "You can only merge a :trace type, but trying :#{type}" unless another_trace.trace?
66
+
67
+ another_trace.value.each do |key, sub_trace|
68
+ if sub_trace.trace?
69
+ value[key].merge! sub_trace
70
+ else
71
+ value[key] = sub_trace
72
+ end
73
+ end
74
+ end
75
+
76
+ def keep_if(...)
77
+ raise ArgumentError, "You can only filter :trace type, and this is :#{type}" unless trace?
78
+ value.keep_if(...)
79
+ end
80
+
81
+ def clear() ; value.clear; end
82
+
83
+ def trace?() ; type == :trace; end
84
+
85
+ def to_h
86
+ if trace?
87
+ value.transform_values(&:to_h).tap { _1.default_proc = nil }
88
+ else
89
+ {value: value, source: source}
90
+ end
91
+ end
92
+
93
+ def dup() ; self.class.new(type, value.dup, **source); end
94
+
95
+ def pretty_print(q)
96
+ if trace?
97
+ q.nest(2) do
98
+ q.breakable ""
99
+ q.seplist(value, nil, :each) do |k, v|
100
+ q.group do
101
+ q.text k
102
+ q.text " =>"
103
+ q.breakable " " unless v.trace?
104
+ q.pp v
105
+ end
106
+ end
107
+ end
108
+ else
109
+ q.pp value
110
+ q.group(0, " (", ")") do
111
+ q.seplist(source, lambda { q.breakable " " }, :each) do |k, v|
112
+ q.group do
113
+ q.text k.to_s
114
+ q.text "="
115
+ q.text v.to_s
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ class << self
124
+ def capture
125
+ unless Settings.tracing_enabled
126
+ yield
127
+ return
128
+ end
129
+
130
+ trace = Trace.new
131
+ trace_stack.push trace
132
+ yield
133
+ trace_stack.last
134
+ ensure
135
+ trace_stack.pop
136
+ end
137
+
138
+ def trace_stack
139
+ (Thread.current[:__anyway__trace_stack__] ||= [])
140
+ end
141
+
142
+ def current_trace() ; trace_stack.last; end
143
+
144
+ alias tracing? current_trace
145
+
146
+ def source_stack
147
+ (Thread.current[:__anyway__trace_source_stack__] ||= [])
148
+ end
149
+
150
+ def current_trace_source
151
+ source_stack.last || accessor_source(caller_locations(2, 1).first)
152
+ end
153
+
154
+ def with_trace_source(src)
155
+ source_stack << src
156
+ yield
157
+ ensure
158
+ source_stack.pop
159
+ end
160
+
161
+ private
162
+
163
+ def accessor_source(location)
164
+ {type: :accessor, called_from: location.path_lineno}
165
+ end
166
+ end
167
+
168
+ module_function
169
+
170
+ def trace!(type, *path, **opts)
171
+ return yield unless Tracing.tracing?
172
+ val = yield
173
+ if val.is_a?(Hash)
174
+ Tracing.current_trace.merge_values(val, type: type, **opts)
175
+ else
176
+ Tracing.current_trace.record_value(val, *path, type: type, **opts)
177
+ end
178
+ val
179
+ end
180
+ end
181
+ end
@@ -11,9 +11,7 @@ module Anyway # :nodoc:
11
11
 
12
12
  using(Module.new do
13
13
  refine Object do
14
- def vm_object_id
15
- (object_id << 1).to_s(16)
16
- end
14
+ def vm_object_id() = (object_id << 1).to_s(16)
17
15
  end
18
16
  end)
19
17
 
@@ -72,9 +70,7 @@ module Anyway # :nodoc:
72
70
  @name = name
73
71
  end
74
72
 
75
- def apply_to(config)
76
- config.send(name)
77
- end
73
+ def apply_to(config) = config.send(name)
78
74
  end
79
75
 
80
76
  class << self
@@ -110,23 +106,21 @@ module Anyway # :nodoc:
110
106
  def defaults
111
107
  return @defaults if instance_variable_defined?(:@defaults)
112
108
 
113
- @defaults =
114
- if superclass < Anyway::Config
115
- superclass.defaults.deep_dup
116
- else
117
- new_empty_config
118
- end
109
+ if superclass < Anyway::Config
110
+ superclass.defaults.deep_dup
111
+ else
112
+ new_empty_config
113
+ end => @defaults
119
114
  end
120
115
 
121
116
  def config_attributes
122
117
  return @config_attributes if instance_variable_defined?(:@config_attributes)
123
118
 
124
- @config_attributes =
125
- if superclass < Anyway::Config
126
- superclass.config_attributes.dup
127
- else
128
- []
129
- end
119
+ if superclass < Anyway::Config
120
+ superclass.config_attributes.dup
121
+ else
122
+ []
123
+ end => @config_attributes
130
124
  end
131
125
 
132
126
  def required(*names)
@@ -140,12 +134,11 @@ module Anyway # :nodoc:
140
134
  def required_attributes
141
135
  return @required_attributes if instance_variable_defined?(:@required_attributes)
142
136
 
143
- @required_attributes =
144
- if superclass < Anyway::Config
145
- superclass.required_attributes.dup
146
- else
147
- []
148
- end
137
+ if superclass < Anyway::Config
138
+ superclass.required_attributes.dup
139
+ else
140
+ []
141
+ end => @required_attributes
149
142
  end
150
143
 
151
144
  def on_load(*names, &block)
@@ -161,12 +154,11 @@ module Anyway # :nodoc:
161
154
  def load_callbacks
162
155
  return @load_callbacks if instance_variable_defined?(:@load_callbacks)
163
156
 
164
- @load_callbacks =
165
- if superclass <= Anyway::Config
166
- superclass.load_callbacks.dup
167
- else
168
- []
169
- end
157
+ if superclass <= Anyway::Config
158
+ superclass.load_callbacks.dup
159
+ else
160
+ []
161
+ end => @load_callbacks
170
162
  end
171
163
 
172
164
  def config_name(val = nil)
@@ -186,26 +178,21 @@ module Anyway # :nodoc:
186
178
  end
187
179
  end
188
180
 
189
- def explicit_config_name?
190
- !explicit_config_name.nil?
191
- end
181
+ def explicit_config_name?() = !explicit_config_name.nil?
192
182
 
193
183
  def env_prefix(val = nil)
194
184
  return (@env_prefix = val.to_s.upcase) unless val.nil?
195
185
 
196
186
  return @env_prefix if instance_variable_defined?(:@env_prefix)
197
187
 
198
- @env_prefix =
199
- if superclass < Anyway::Config && superclass.explicit_config_name?
200
- superclass.env_prefix
201
- else
202
- config_name.upcase
203
- end
188
+ if superclass < Anyway::Config && superclass.explicit_config_name?
189
+ superclass.env_prefix
190
+ else
191
+ config_name.upcase
192
+ end => @env_prefix
204
193
  end
205
194
 
206
- def new_empty_config
207
- {}
208
- end
195
+ def new_empty_config() = {}
209
196
 
210
197
  private
211
198
 
@@ -213,7 +200,7 @@ module Anyway # :nodoc:
213
200
  names.each do |name|
214
201
  accessors_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
215
202
  def #{name}=(val)
216
- __trace__&.record_value(val, \"#{name}\", Tracing.current_trace_source)
203
+ __trace__&.record_value(val, \"#{name}\", **Tracing.current_trace_source)
217
204
  # DEPRECATED: instance variable set will be removed in 2.1
218
205
  @#{name} = values[:#{name}] = val
219
206
  end
@@ -228,9 +215,9 @@ module Anyway # :nodoc:
228
215
  def accessors_module
229
216
  return @accessors_module if instance_variable_defined?(:@accessors_module)
230
217
 
231
- @accessors_module = Module.new.tap do |mod|
218
+ Module.new.tap do |mod|
232
219
  include mod
233
- end
220
+ end => @accessors_module
234
221
  end
235
222
 
236
223
  def build_config_name
@@ -298,7 +285,7 @@ module Anyway # :nodoc:
298
285
  def load(overrides = nil)
299
286
  base_config = self.class.defaults.deep_dup
300
287
 
301
- trace = Tracing.capture do
288
+ Tracing.capture do
302
289
  Tracing.trace!(:defaults) { base_config }
303
290
 
304
291
  load_from_sources(
@@ -313,7 +300,7 @@ module Anyway # :nodoc:
313
300
 
314
301
  base_config.deep_merge!(overrides)
315
302
  end
316
- end
303
+ end => trace
317
304
 
318
305
  base_config.each do |key, val|
319
306
  write_config_attr(key.to_sym, val)
@@ -339,13 +326,9 @@ module Anyway # :nodoc:
339
326
  base_config
340
327
  end
341
328
 
342
- def dig(*keys)
343
- values.dig(*keys)
344
- end
329
+ def dig(*keys) = values.dig(*keys)
345
330
 
346
- def to_h
347
- values.deep_dup.deep_freeze
348
- end
331
+ def to_h() = values.deep_dup.deep_freeze
349
332
 
350
333
  def dup
351
334
  self.class.allocate.tap do |new_config|
@@ -360,13 +343,9 @@ module Anyway # :nodoc:
360
343
  Anyway.env.fetch(env_prefix).delete("conf") || Settings.default_config_path.call(name)
361
344
  end
362
345
 
363
- def deconstruct_keys(keys)
364
- values.deconstruct_keys(keys)
365
- end
346
+ def deconstruct_keys(keys) = values.deconstruct_keys(keys)
366
347
 
367
- def to_source_trace
368
- __trace__&.to_h
369
- end
348
+ def to_source_trace() = __trace__&.to_h
370
349
 
371
350
  def inspect
372
351
  "#<#{self.class}:0x#{vm_object_id.rjust(16, "0")} config_name=\"#{config_name}\" env_prefix=\"#{env_prefix}\" " \