configurability 3.2.0 → 4.2.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.
@@ -39,11 +39,22 @@ class Configurability::SettingInstaller
39
39
 
40
40
  ### Add accessors with the specified +name+ to the target.
41
41
  def add_setting_accessors( name, options, &writer_hook )
42
+ if options[:use_class_vars]
43
+ self.target.class_variable_set( "@@#{name}", nil )
44
+ else
45
+ self.target.instance_variable_set( "@#{name}", nil )
46
+ end
47
+
42
48
  reader = self.make_setting_reader( name, options )
43
49
  writer = self.make_setting_writer( name, options, &writer_hook )
44
50
 
45
51
  self.target.define_singleton_method( "#{name}", &reader )
46
52
  self.target.define_singleton_method( "#{name}=", &writer )
53
+
54
+ if options[:predicate]
55
+ predicate = self.make_setting_predicate( name, options )
56
+ self.target.define_singleton_method( "#{name}?", &predicate )
57
+ end
47
58
  end
48
59
 
49
60
 
@@ -56,7 +67,9 @@ class Configurability::SettingInstaller
56
67
  self.class_variable_get("@@#{name}")
57
68
  end
58
69
  else
59
- return lambda { self.instance_variable_get("@#{name}") }
70
+ return lambda {
71
+ self.instance_variable_get("@#{name}")
72
+ }
60
73
  end
61
74
  end
62
75
 
@@ -79,6 +92,22 @@ class Configurability::SettingInstaller
79
92
  end
80
93
 
81
94
 
95
+ ### Create the body of the setting predicate method with the specified +name+ and +options+.
96
+ def make_setting_predicate( name, options )
97
+ if options[:use_class_vars]
98
+ return lambda do
99
+ Loggability[ Configurability ].debug "Using class variables for %s of %p" %
100
+ [ name, self ]
101
+ self.class_variable_get("@@#{name}") ? true : false
102
+ end
103
+ else
104
+ return lambda {
105
+ self.instance_variable_get("@#{name}") ? true : false
106
+ }
107
+ end
108
+ end
109
+
110
+
82
111
  ### Add a default for +name+ to the CONFIG_DEFAULTS constant of the target, creating
83
112
  ### it if necessary.
84
113
  def add_default( name, options )
@@ -119,13 +119,6 @@ describe Configurability::Config do
119
119
  end
120
120
 
121
121
 
122
- it "untaints values loaded from a config" do
123
- yaml = TEST_CONFIG.dup.taint
124
- config = described_class.new( yaml )
125
- expect( config.listsection.first ).to_not be_tainted
126
- expect( config.textsection ).to_not be_tainted
127
- end
128
-
129
122
 
130
123
  context "a config with nil keys" do
131
124
 
@@ -167,6 +160,11 @@ describe Configurability::Config do
167
160
  end
168
161
 
169
162
 
163
+ it "supports two-argument respond_to?" do
164
+ expect( config.respond_to?(:section, true) ).to be_truthy
165
+ end
166
+
167
+
170
168
  it "contains values specified in the source" do
171
169
  # section:
172
170
  # subsection:
@@ -255,7 +253,7 @@ describe Configurability::Config do
255
253
  # loading from a file
256
254
  context " loaded from a file" do
257
255
  before( :all ) do
258
- filename = Dir::Tmpname.make_tmpname( './test', '.conf' )
256
+ filename = Dir::Tmpname.create( ['./test', '.conf'] ) {}
259
257
  @tmpfile = Pathname( filename )
260
258
  @tmpfile.open( 'w', 0644 ) {|io| io.print(TEST_CONFIG) }
261
259
  end
@@ -284,7 +282,7 @@ describe Configurability::Config do
284
282
 
285
283
  it "can be written to a different file" do
286
284
  begin
287
- path = Dir::Tmpname.make_tmpname( './another-', '.config' )
285
+ path = Dir::Tmpname.create( ['./another-', '.config'] ) {}
288
286
 
289
287
  config.write( path )
290
288
  expect( File.read(path) ).to match( /section: ?\n subsection/ )
@@ -333,7 +331,7 @@ describe Configurability::Config do
333
331
  context " whose file changes after loading" do
334
332
 
335
333
  before( :all ) do
336
- filename = Dir::Tmpname.make_tmpname( './test', '.conf' )
334
+ filename = Dir::Tmpname.create( ['./test', '.conf'] ) {}
337
335
  @tmpfile = Pathname( filename )
338
336
  @tmpfile.open( 'w', 0644 ) {|io| io.print(TEST_CONFIG) }
339
337
  end
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'ipaddr'
4
+ require 'socket'
3
5
  require 'ostruct'
4
6
  require 'helpers'
5
7
 
@@ -17,11 +19,13 @@ describe Configurability do
17
19
 
18
20
  before( :each ) do
19
21
  Configurability.configurable_objects.clear
22
+ Configurability.after_configure_hooks.clear
20
23
  Configurability.reset
21
24
  end
22
25
 
23
26
  after( :all ) do
24
27
  Configurability.configurable_objects.clear
28
+ Configurability.after_configure_hooks.clear
25
29
  Configurability.reset
26
30
  end
27
31
 
@@ -404,21 +408,22 @@ describe Configurability do
404
408
  defaults = Configurability.gather_defaults
405
409
 
406
410
  expect( defaults ).to eq({ testconfig: { sect1: {sect2: { one: 1, two: 2 }} } })
411
+ expect( klass.config_key ).to eq( :testconfig__sect1__sect2 )
407
412
  end
408
413
 
409
414
 
410
415
  it "can return a Configurability::Config object with defaults, too" do
411
- klass1 = Class.new do
416
+ _klass1 = Class.new do
412
417
  extend Configurability
413
418
  config_key :testconfig
414
419
  self::CONFIG_DEFAULTS = { :one => 1, :types => {:one => true} }
415
420
  end
416
- klass2 = Class.new do
421
+ _klass2 = Class.new do
417
422
  extend Configurability
418
423
  config_key :testconfig
419
424
  self::DEFAULT_CONFIG = { :two => 2, :types => {:two => true} }
420
425
  end
421
- klass3 = Class.new do
426
+ _klass3 = Class.new do
422
427
  extend Configurability
423
428
  config_key :otherconfig
424
429
  def self::defaults; { :other => true }; end
@@ -442,7 +447,7 @@ describe Configurability do
442
447
  self::CONFIG_DEFAULTS = { :one => 1, :types => {:one => true} }
443
448
  Configurability.log.debug "Defaults: %p" % [ self.defaults ]
444
449
  end
445
- subclass = Class.new( klass ) do
450
+ _subclass = Class.new( klass ) do
446
451
  config_key :spanishconfig
447
452
  self::CONFIG_DEFAULTS = { :uno => 1 }
448
453
  end
@@ -670,7 +675,6 @@ describe Configurability do
670
675
  end
671
676
 
672
677
  child_class = Class.new( parent_class )
673
- child_class..extend( Configurability )
674
678
  child_class.configurability( :testconfig ) do
675
679
  setting :environment, default: :staging
676
680
  setting :apikey, default: 'foom'
@@ -705,6 +709,82 @@ describe Configurability do
705
709
  from( nil )
706
710
  end
707
711
 
712
+
713
+ it "allows declaration of singleton helper methods" do
714
+ mod.configurability( :testconfig ) do
715
+ def self::parse_ip_blocks( *values )
716
+ values.flatten.map do |value|
717
+ IPAddr.new( value, Socket::AF_INET )
718
+ end
719
+ end
720
+ setting :whitelisted_ip_blocks do |*values|
721
+ parse_ip_blocks( values )
722
+ end
723
+ setting :blacklisted_ip_blocks do |*values|
724
+ parse_ip_blocks( values )
725
+ end
726
+ end
727
+
728
+ expect {
729
+ mod.whitelisted_ip_blocks = ['127.0.0.1/8', '203.0.113.0/24']
730
+ }.to change { mod.whitelisted_ip_blocks }.to([
731
+ IPAddr.new( '127.0.0.0/8' ), IPAddr.new( '203.0.113.0/24' )
732
+ ])
733
+ end
734
+
735
+
736
+ it "can declare a predicate method for a setting" do
737
+ mod.configurability( :testconfig ) do
738
+ setting :use_whitelist, default: false, predicate: true
739
+ end
740
+
741
+ expect {
742
+ mod.use_whitelist = true
743
+ }.to change { mod.use_whitelist? }.from( false ).to( true )
744
+ end
745
+
746
+ end
747
+
748
+
749
+ describe "hooks" do
750
+
751
+ it "will call any registered callbacks after the config is installed" do
752
+ hook_was_called = false
753
+ Configurability.after_configure do
754
+ hook_was_called = true
755
+ end
756
+ Configurability.call_after_configure_hooks
757
+
758
+ expect( hook_was_called ).to be( true )
759
+ end
760
+
761
+
762
+ it "will immediately call after_config callbacks registered after the config is installed" do
763
+ hook_was_called = false
764
+ Configurability.call_after_configure_hooks
765
+
766
+ Configurability.after_configure do
767
+ hook_was_called = true
768
+ end
769
+
770
+ expect( hook_was_called ).to be( true )
771
+ end
772
+
773
+
774
+ it "can add new after_configure hooks even while the current ones are being run" do
775
+ hook_was_called = false
776
+ Configurability.after_configure do
777
+ Configurability.after_configure do
778
+ hook_was_called = true
779
+ end
780
+ end
781
+
782
+ Configurability.call_after_configure_hooks
783
+
784
+ expect( hook_was_called ).to be( true )
785
+ end
786
+
787
+
708
788
  end
709
789
 
710
790
  end
@@ -35,6 +35,8 @@ RSpec.configure do |config|
35
35
  config.mock_with( :rspec ) do |mock|
36
36
  mock.syntax = :expect
37
37
  end
38
+ config.warnings = true
39
+ config.profile_examples = 5
38
40
 
39
41
  config.include( Loggability::SpecHelpers )
40
42
  end
metadata CHANGED
@@ -1,42 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configurability
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
8
8
  - Mahlon E. Smith
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- +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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- inYLQagqAF6goWTXgAJCdPd6SNeeSNqA6vlY7CV1Jh5kfNJJ6xu/CVij1GzCLu/5
33
- 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
- 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
- 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
- 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
- p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
14
+ MIID+DCCAmCgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBdnZWQv
15
+ REM9RmFlcmllTVVEL0RDPW9yZzAeFw0yMDEyMjQyMDU1MjlaFw0yMTEyMjQyMDU1
16
+ MjlaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
17
+ hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvyVhkRzvlEs0fe7145BYLfN6njX9ih5H
18
+ L60U0p0euIurpv84op9CNKF9tx+1WKwyQvQP7qFGuZxkSUuWcP/sFhDXL1lWUuIl
19
+ M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO+Vew8tSQmlDsosxLUx+VB7DrVFO
20
+ 5PU2AEbf04GGSrmqADGWXeaslaoRdb1fu/0M5qfPTRn5V39sWD9umuDAF9qqil/x
21
+ Sl6phTvgBrG8GExHbNZpLARd3xrBYLEFsX7RvBn2UPfgsrtvpdXjsHGfpT3IPN+B
22
+ vQ66lts4alKC69TE5cuKasWBm+16A4aEe3XdZBRNmtOu/g81gvwA7fkJHKllJuaI
23
+ dXzdHqq+zbGZVSQ7pRYHYomD0IiDe1DbIouFnPWmagaBnGHwXkDT2bKKP+s2v21m
24
+ ozilJg4aar2okb/RA6VS87o+d7g6LpDDMMQjH4G9OPnJENLdhu8KnPw/ivSVvQw7
25
+ N2I4L/ZOIe2DIVuYH7aLHfjZDQv/mNgpAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYD
26
+ VR0PBAQDAgSwMB0GA1UdDgQWBBRyjf55EbrHagiRLqt5YAd3yb8k4DANBgkqhkiG
27
+ 9w0BAQsFAAOCAYEAMYegZanJi8zq7QKPT7wqXefX4C88I5JWeBHR3PvvWK0CwyMV
28
+ peyiu5I13w/lYX+HUZjE4qsSpJMJFXWl4WZCOo+AMprOcf0PxfuJpxCej5D4tavf
29
+ vRfhahSw7XJrcZih/3J+/UgoH7R05MJ+8LTcy3HGrB3a0vTafjm8OY7Xpa0LJDoN
30
+ JDqxK321VIHyTibbKeA1hWSE6ljlQDvFbTqiCj3Ulp1jTv3TOlvRl8fqcfhxUJI0
31
+ +5Q82jJODjEN+GaWs0V+NlrbU94cXwS2PH5dXogftB5YYA5Ex8A0ikZ73xns4Hdo
32
+ XxdLdd92F5ovxA23j/rKe/IDwqr6FpDkU3nPXH/Qp0TVGv9zZnVJc/Z6ChkuWj8z
33
+ pW7JAyyiiHZgKKDReDrA2LA7Zs3o/7KA6UtUH0FHf8LYhcK+pfHk6RtjRe65ffw+
34
+ MCh97sQ/Z/MOusb5+QddBmB+k8EicXyGNl4b5L4XpL7fIQu+Y96TB3JEJlShxFD9
35
+ k9FjI4d9EP54gS/4
38
36
  -----END CERTIFICATE-----
39
- date: 2017-04-18 00:00:00.000000000 Z
37
+ date: 2020-12-28 00:00:00.000000000 Z
40
38
  dependencies:
41
39
  - !ruby/object:Gem::Dependency
42
40
  name: loggability
@@ -44,56 +42,28 @@ dependencies:
44
42
  requirements:
45
43
  - - "~>"
46
44
  - !ruby/object:Gem::Version
47
- version: '0.12'
45
+ version: '0.15'
48
46
  type: :runtime
49
47
  prerelease: false
50
48
  version_requirements: !ruby/object:Gem::Requirement
51
49
  requirements:
52
50
  - - "~>"
53
51
  - !ruby/object:Gem::Version
54
- version: '0.12'
55
- - !ruby/object:Gem::Dependency
56
- name: hoe-mercurial
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.4'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.4'
52
+ version: '0.15'
69
53
  - !ruby/object:Gem::Dependency
70
- name: hoe-deveiate
54
+ name: rake-deveiate
71
55
  requirement: !ruby/object:Gem::Requirement
72
56
  requirements:
73
57
  - - "~>"
74
58
  - !ruby/object:Gem::Version
75
- version: '0.8'
59
+ version: '0.17'
76
60
  type: :development
77
61
  prerelease: false
78
62
  version_requirements: !ruby/object:Gem::Requirement
79
63
  requirements:
80
64
  - - "~>"
81
65
  - !ruby/object:Gem::Version
82
- version: '0.8'
83
- - !ruby/object:Gem::Dependency
84
- name: hoe-highline
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '0.2'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '0.2'
66
+ version: '0.17'
97
67
  - !ruby/object:Gem::Dependency
98
68
  name: simplecov
99
69
  requirement: !ruby/object:Gem::Requirement
@@ -114,58 +84,25 @@ dependencies:
114
84
  requirements:
115
85
  - - "~>"
116
86
  - !ruby/object:Gem::Version
117
- version: '3.5'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '3.5'
125
- - !ruby/object:Gem::Dependency
126
- name: rdoc
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '4.0'
87
+ version: '3.9'
132
88
  type: :development
133
89
  prerelease: false
134
90
  version_requirements: !ruby/object:Gem::Requirement
135
91
  requirements:
136
92
  - - "~>"
137
93
  - !ruby/object:Gem::Version
138
- version: '4.0'
139
- - !ruby/object:Gem::Dependency
140
- name: hoe
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '3.15'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '3.15'
153
- description: |-
154
- Configurability is a unified, non-intrusive, assume-nothing configuration system
155
- for Ruby. It lets you keep the configuration for multiple objects in a single
156
- config file, load the file when it's convenient for you, and distribute the
157
- configuration when you're ready, sending it everywhere it needs to go with a
94
+ version: '3.9'
95
+ description: Configurability is a unified, non-intrusive, assume-nothing configuration
96
+ system for Ruby. It lets you keep the configuration for multiple objects in a single
97
+ config file, load the file when it's convenient for you, and distribute the
98
+ configuration when you're ready, sending it everywhere it needs to go with a
158
99
  single action.
159
100
  email:
160
- - ged@FaerieMUD.org
101
+ - ged@faeriemud.org
161
102
  - mahlon@martini.nu
162
- executables:
163
- - configurability
103
+ executables: []
164
104
  extensions: []
165
- extra_rdoc_files:
166
- - History.md
167
- - Manifest.txt
168
- - README.md
105
+ extra_rdoc_files: []
169
106
  files:
170
107
  - ChangeLog
171
108
  - History.md
@@ -173,7 +110,6 @@ files:
173
110
  - Manifest.txt
174
111
  - README.md
175
112
  - Rakefile
176
- - bin/configurability
177
113
  - examples/basicconfig.rb
178
114
  - examples/config.yml
179
115
  - examples/readme.rb
@@ -186,31 +122,33 @@ files:
186
122
  - spec/configurability/deferred_config_spec.rb
187
123
  - spec/configurability_spec.rb
188
124
  - spec/helpers.rb
189
- homepage: http://deveiate.org/projects/configurability
125
+ homepage: https://configur.ability.guide/
190
126
  licenses:
191
127
  - BSD-3-Clause
192
- metadata: {}
193
- post_install_message:
194
- rdoc_options:
195
- - "--main"
196
- - README.md
128
+ metadata:
129
+ homepage_uri: https://configur.ability.guide/
130
+ documentation_uri: http://deveiate.org/code/configurability
131
+ changelog_uri: http://deveiate.org/code/configurability/History_md.html
132
+ source_uri: https://hg.sr.ht/~ged/Configurability
133
+ bug_tracker_uri: https://todo.sr.ht/~ged/Configurability
134
+ post_install_message:
135
+ rdoc_options: []
197
136
  require_paths:
198
137
  - lib
199
138
  required_ruby_version: !ruby/object:Gem::Requirement
200
139
  requirements:
201
140
  - - ">="
202
141
  - !ruby/object:Gem::Version
203
- version: 2.2.0
142
+ version: '2.5'
204
143
  required_rubygems_version: !ruby/object:Gem::Requirement
205
144
  requirements:
206
145
  - - ">="
207
146
  - !ruby/object:Gem::Version
208
147
  version: '0'
209
148
  requirements: []
210
- rubyforge_project:
211
- rubygems_version: 2.6.8
212
- signing_key:
149
+ rubygems_version: 3.2.3
150
+ signing_key:
213
151
  specification_version: 4
214
152
  summary: Configurability is a unified, non-intrusive, assume-nothing configuration
215
- system for Ruby
153
+ system for Ruby.
216
154
  test_files: []