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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +853 -786
- data/History.md +65 -0
- data/LICENSE +1 -1
- data/Manifest.txt +0 -1
- data/README.md +47 -5
- data/Rakefile +5 -85
- data/lib/configurability.rb +51 -10
- data/lib/configurability/config.rb +10 -38
- data/lib/configurability/setting_installer.rb +30 -1
- data/spec/configurability/config_spec.rb +8 -10
- data/spec/configurability_spec.rb +85 -5
- data/spec/helpers.rb +2 -0
- metadata +52 -114
- metadata.gz.sig +0 -0
- data/bin/configurability +0 -335
data/History.md
CHANGED
@@ -1,3 +1,68 @@
|
|
1
|
+
# Release History for configurability
|
2
|
+
|
3
|
+
---
|
4
|
+
|
5
|
+
## v4.2.0 [2020-12-28] Michael Granger <ged@faeriemud.org>
|
6
|
+
|
7
|
+
Improvements:
|
8
|
+
|
9
|
+
- Updates for Ruby 3
|
10
|
+
|
11
|
+
|
12
|
+
## v4.1.0 [2020-02-19] Michael Granger <ged@faeriemud.org>
|
13
|
+
|
14
|
+
Improvements:
|
15
|
+
|
16
|
+
- Add support for two-argument #respond_to? to Configurability::Config
|
17
|
+
|
18
|
+
|
19
|
+
## v4.0.0 [2020-01-08] Michael Granger <ged@faeriemud.org>
|
20
|
+
|
21
|
+
Breaking changes:
|
22
|
+
|
23
|
+
- Remove tainting, which is deprecated in 2.7 and beyond.
|
24
|
+
|
25
|
+
Enhancements:
|
26
|
+
|
27
|
+
- Enable SafeYAML if it's loaded
|
28
|
+
|
29
|
+
|
30
|
+
## v3.4.1 [2019-09-03] Michael Granger <ged@FaerieMUD.org>
|
31
|
+
|
32
|
+
Bugfixes:
|
33
|
+
|
34
|
+
- Bump minimal Ruby version to 2.5.
|
35
|
+
|
36
|
+
Documentation:
|
37
|
+
|
38
|
+
- Change URLs to Sourcehut/ability.guide
|
39
|
+
- Fix license years, README title
|
40
|
+
|
41
|
+
|
42
|
+
## v3.4.0 [2019-09-01] Michael Granger <ged@FaerieMUD.org>
|
43
|
+
|
44
|
+
(Yanked due to inaccurate minimum Ruby version)
|
45
|
+
|
46
|
+
Bugfixes:
|
47
|
+
|
48
|
+
- Remove old command that depended on Trollop
|
49
|
+
|
50
|
+
Enhancements:
|
51
|
+
|
52
|
+
- Add a predicate setting option
|
53
|
+
- Add a test for declaring helper methods inside a settings block
|
54
|
+
- Add after-configure hooks to execute a block after the configuration
|
55
|
+
has been loaded
|
56
|
+
|
57
|
+
|
58
|
+
## v3.3.0 [2018-09-12] Michael Granger <ged@FaerieMUD.org>
|
59
|
+
|
60
|
+
Enhancements:
|
61
|
+
|
62
|
+
- Declare the class/class-instance variable when declaring a setting
|
63
|
+
- Add a 'defaults' subcommand to the configurability executable
|
64
|
+
|
65
|
+
|
1
66
|
## v3.2.0 [2017-04-17] Michael Granger <ged@FaerieMUD.org>
|
2
67
|
|
3
68
|
Enhancements:
|
data/LICENSE
CHANGED
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Configurability
|
2
2
|
|
3
3
|
home
|
4
|
-
: https://
|
4
|
+
: https://configur.ability.guide/
|
5
5
|
|
6
6
|
code
|
7
|
-
: https://
|
7
|
+
: https://hg.sr.ht/~ged/Configurability
|
8
8
|
|
9
9
|
docs
|
10
10
|
: http://deveiate.org/code/configurability
|
@@ -117,6 +117,42 @@ After this happens you can access the configuration values like this:
|
|
117
117
|
Database.password
|
118
118
|
# => "pXVvVY,YjWNRRi[yPWx4"
|
119
119
|
|
120
|
+
You can add helper methods inside the `configurability` block to eliminate
|
121
|
+
repeated code in your setting blocks:
|
122
|
+
|
123
|
+
configurability( :server ) do
|
124
|
+
def self::make_path( value )
|
125
|
+
return nil unless value
|
126
|
+
pn = Pathname( value )
|
127
|
+
raise "Can't read from %s!" % [ pn ] unless pn.readable?
|
128
|
+
return pn
|
129
|
+
end
|
130
|
+
|
131
|
+
setting :template_path do |value|
|
132
|
+
make_path( value )
|
133
|
+
end
|
134
|
+
|
135
|
+
setting :plugin_path do |*values|
|
136
|
+
make_path( value )
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
If a setting is a boolean, you can also have a predicate method created for it
|
141
|
+
alongside its getter and setter:
|
142
|
+
|
143
|
+
class Mailer
|
144
|
+
extend Configurability
|
145
|
+
configurability( :db ) do
|
146
|
+
setting :use_whitelist, default: false, predicate: true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
Mailer.use_whitelist?
|
151
|
+
# => false
|
152
|
+
Mailer.use_whitelist = true
|
153
|
+
Mailer.use_whitelist?
|
154
|
+
# => true
|
155
|
+
|
120
156
|
|
121
157
|
### More Details
|
122
158
|
|
@@ -387,9 +423,9 @@ default_config
|
|
387
423
|
|
388
424
|
You can submit bug reports, suggestions, clone it with Mercurial, and
|
389
425
|
read more about future plans at
|
390
|
-
|
426
|
+
[the project page](http://hg.sr.ht/ged/configurability). If you
|
391
427
|
prefer Git, there is also a
|
392
|
-
|
428
|
+
[Github mirror](https://github.com/ged/configurability).
|
393
429
|
|
394
430
|
After checking out the source, run:
|
395
431
|
|
@@ -399,9 +435,15 @@ This task will install any missing dependencies, run the tests/specs,
|
|
399
435
|
and generate the API documentation.
|
400
436
|
|
401
437
|
|
438
|
+
## Authors
|
439
|
+
|
440
|
+
- Michael Granger <ged@faeriemud.org>
|
441
|
+
- Mahlon E. Smith <mahlon@martini.nu>
|
442
|
+
|
443
|
+
|
402
444
|
## License
|
403
445
|
|
404
|
-
Copyright (c) 2010-
|
446
|
+
Copyright (c) 2010-2020 Michael Granger and Mahlon E. Smith
|
405
447
|
All rights reserved.
|
406
448
|
|
407
449
|
Redistribution and use in source and binary forms, with or without
|
data/Rakefile
CHANGED
@@ -1,89 +1,9 @@
|
|
1
|
-
#!/usr/bin/env rake
|
1
|
+
#!/usr/bin/env ruby -S rake
|
2
2
|
|
3
|
-
|
4
|
-
require 'hoe'
|
5
|
-
rescue LoadError
|
6
|
-
abort "This Rakefile requires 'hoe' (gem install hoe)"
|
7
|
-
end
|
8
|
-
|
9
|
-
GEMSPEC = 'configurability.gemspec'
|
10
|
-
|
11
|
-
Hoe.plugin :mercurial
|
12
|
-
Hoe.plugin :signing
|
13
|
-
Hoe.plugin :deveiate
|
14
|
-
|
15
|
-
Hoe.plugins.delete :rubyforge
|
16
|
-
|
17
|
-
Encoding.default_internal = Encoding::UTF_8
|
18
|
-
|
19
|
-
hoespec = Hoe.spec 'configurability' do |spec|
|
20
|
-
spec.readme_file = 'README.md'
|
21
|
-
spec.history_file = 'History.md'
|
22
|
-
spec.extra_rdoc_files = FileList[ '*.rdoc', '*.md' ]
|
23
|
-
spec.license 'BSD-3-Clause'
|
24
|
-
spec.urls = {
|
25
|
-
home: 'http://deveiate.org/projects/configurability',
|
26
|
-
code: 'http://bitbucket.org/ged/configurability',
|
27
|
-
docs: 'http://deveiate.org/code/configurability',
|
28
|
-
github: 'http://github.com/ged/configurability',
|
29
|
-
}
|
3
|
+
require 'rake/deveiate'
|
30
4
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
spec.dependency 'loggability', '~> 0.12'
|
35
|
-
|
36
|
-
spec.dependency 'hoe-deveiate', '~> 0.8', :developer
|
37
|
-
spec.dependency 'simplecov', '~> 0.12', :developer
|
38
|
-
spec.dependency 'rspec', '~> 3.5', :developer
|
39
|
-
|
40
|
-
spec.require_ruby_version( '>= 2.2.0' )
|
41
|
-
|
42
|
-
spec.hg_sign_tags = true if spec.respond_to?( :hg_sign_tags= )
|
43
|
-
spec.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
|
5
|
+
Rake::DevEiate.setup( 'configurability' ) do |project|
|
6
|
+
project.required_ruby_version = '>= 2.5'
|
7
|
+
project.publish_to = 'deveiate:/usr/local/www/public/code'
|
44
8
|
end
|
45
9
|
|
46
|
-
ENV['VERSION'] ||= hoespec.spec.version.to_s
|
47
|
-
|
48
|
-
# Ensure the specs pass before checking in
|
49
|
-
task 'hg:precheckin' => [ :check_history, :check_manifest, :gemspec, :spec ]
|
50
|
-
|
51
|
-
|
52
|
-
desc "Build a coverage report"
|
53
|
-
task :coverage do
|
54
|
-
ENV["COVERAGE"] = 'yes'
|
55
|
-
Rake::Task[:spec].invoke
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
# Use the fivefish formatter for docs generated from development checkout
|
60
|
-
if File.directory?( '.hg' )
|
61
|
-
require 'rdoc/task'
|
62
|
-
|
63
|
-
Rake::Task[ 'docs' ].clear
|
64
|
-
RDoc::Task.new( 'docs' ) do |rdoc|
|
65
|
-
rdoc.main = "README.md"
|
66
|
-
rdoc.rdoc_files.include( "*.rdoc", "*.md", "ChangeLog", "lib/**/*.rb" )
|
67
|
-
rdoc.generator = :fivefish
|
68
|
-
rdoc.title = 'Configurability'
|
69
|
-
rdoc.rdoc_dir = 'doc'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
task :gemspec => [ 'ChangeLog', GEMSPEC ]
|
75
|
-
file GEMSPEC => __FILE__ do |task|
|
76
|
-
spec = $hoespec.spec
|
77
|
-
spec.files.delete( '.gemtest' )
|
78
|
-
spec.files.delete( 'LICENSE' )
|
79
|
-
spec.signing_key = nil
|
80
|
-
spec.version = "#{spec.version.bump}.0.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
|
81
|
-
spec.cert_chain = [ 'certs/ged.pem' ]
|
82
|
-
File.open( task.name, 'w' ) do |fh|
|
83
|
-
fh.write( spec.to_ruby )
|
84
|
-
end
|
85
|
-
end
|
86
|
-
CLOBBER.include( GEMSPEC )
|
87
|
-
|
88
|
-
task :default => :gemspec
|
89
|
-
|
data/lib/configurability.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'set'
|
3
4
|
require 'loggability'
|
4
5
|
require 'yaml'
|
5
6
|
|
@@ -13,10 +14,10 @@ module Configurability
|
|
13
14
|
|
14
15
|
|
15
16
|
# Library version constant
|
16
|
-
VERSION = '
|
17
|
+
VERSION = '4.2.0'
|
17
18
|
|
18
19
|
# Version-control revision constant
|
19
|
-
REVISION = %q$Revision
|
20
|
+
REVISION = %q$Revision$
|
20
21
|
|
21
22
|
require 'configurability/deferred_config'
|
22
23
|
|
@@ -25,20 +26,58 @@ module Configurability
|
|
25
26
|
|
26
27
|
|
27
28
|
### The objects that have had Configurability added to them
|
29
|
+
##
|
30
|
+
# the Array of objects that have had Configurability added to them
|
31
|
+
singleton_class.attr_accessor :configurable_objects
|
28
32
|
@configurable_objects = []
|
29
33
|
|
30
|
-
|
34
|
+
##
|
35
|
+
# the loaded configuration (after ::configure_objects has been called at least once)
|
36
|
+
singleton_class.attr_accessor :loaded_config
|
31
37
|
@loaded_config = nil
|
32
38
|
|
39
|
+
##
|
40
|
+
# An Array of callbacks to be run after the config is loaded
|
41
|
+
@after_configure_hooks = Set.new
|
42
|
+
singleton_class.attr_reader :after_configure_hooks
|
33
43
|
|
34
|
-
class << self
|
35
44
|
|
36
|
-
|
37
|
-
attr_accessor :configurable_objects
|
45
|
+
@after_configure_hooks_run = false
|
38
46
|
|
39
|
-
|
40
|
-
|
47
|
+
### Returns +true+ if the after-configuration hooks have run at least once.
|
48
|
+
def self::after_configure_hooks_run?
|
49
|
+
return @after_configure_hooks_run ? true : false
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### Set the flag that indicates that the after-configure hooks have run at least
|
54
|
+
### once.
|
55
|
+
def self::after_configure_hooks_run=( new_value )
|
56
|
+
@after_configure_hooks_run = new_value ? true : false
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
### Register a callback to be run after the config is loaded.
|
61
|
+
def self::after_configure( &block )
|
62
|
+
raise LocalJumpError, "no block given" unless block
|
63
|
+
self.after_configure_hooks << block
|
41
64
|
|
65
|
+
# Call the block immediately if the hooks have already been called or are in
|
66
|
+
# the process of being called.
|
67
|
+
block.call if self.after_configure_hooks_run?
|
68
|
+
end
|
69
|
+
singleton_class.alias_method :after_configuration, :after_configure
|
70
|
+
|
71
|
+
|
72
|
+
### Call the post-configuration callbacks.
|
73
|
+
def self::call_after_configure_hooks
|
74
|
+
self.log.debug " calling %d post-config hooks" % [ self.after_configure_hooks.length ]
|
75
|
+
@after_configure_hooks_run = true
|
76
|
+
|
77
|
+
self.after_configure_hooks.to_a.each do |hook|
|
78
|
+
# self.log.debug " %s line %s..." % hook.source_location
|
79
|
+
hook.call
|
80
|
+
end
|
42
81
|
end
|
43
82
|
|
44
83
|
|
@@ -103,12 +142,15 @@ module Configurability
|
|
103
142
|
self.configurable_objects.each do |obj|
|
104
143
|
self.install_config( config, obj )
|
105
144
|
end
|
145
|
+
|
146
|
+
self.call_after_configure_hooks
|
106
147
|
end
|
107
148
|
|
108
149
|
|
109
150
|
### If a configuration has been loaded (via {#configure_objects}), clear it.
|
110
151
|
def self::reset
|
111
152
|
self.loaded_config = nil
|
153
|
+
self.after_configure_hooks_run = false
|
112
154
|
end
|
113
155
|
|
114
156
|
|
@@ -259,8 +301,7 @@ module Configurability
|
|
259
301
|
@config.each_pair do |key, value|
|
260
302
|
Configurability.log.debug "Looking for %p config attribute" % [ key ]
|
261
303
|
next unless self.respond_to?( "#{key}=" )
|
262
|
-
Configurability.log.debug " setting %p to %p
|
263
|
-
[ key, value ]
|
304
|
+
Configurability.log.debug " setting %p to %p" % [ key, value ]
|
264
305
|
self.public_send( "#{key}=", value )
|
265
306
|
end
|
266
307
|
else
|
@@ -43,6 +43,10 @@ class Configurability::Config
|
|
43
43
|
log_to :configurability
|
44
44
|
|
45
45
|
|
46
|
+
# Make safe loading the default if SafeYAML is loaded
|
47
|
+
SafeYAML::OPTIONS[:default_mode] = :safe if defined?( SafeYAML )
|
48
|
+
|
49
|
+
|
46
50
|
#############################################################
|
47
51
|
### C L A S S M E T H O D S
|
48
52
|
#############################################################
|
@@ -84,7 +88,7 @@ class Configurability::Config
|
|
84
88
|
|
85
89
|
# Make a deep copy of the defaults before loading so we don't modify
|
86
90
|
# the argument
|
87
|
-
@defaults = Marshal.load( Marshal.dump(defaults) )
|
91
|
+
@defaults = defaults ? Marshal.load( Marshal.dump(defaults) ) : nil
|
88
92
|
@time_created = Time.now
|
89
93
|
@path = path
|
90
94
|
|
@@ -162,7 +166,7 @@ class Configurability::Config
|
|
162
166
|
|
163
167
|
|
164
168
|
### Returns +true+ for methods which can be autoloaded
|
165
|
-
def respond_to?( sym )
|
169
|
+
def respond_to?( sym, include_all=false )
|
166
170
|
return true if @struct.member?( sym.to_s.sub(/(=|\?)$/, '').to_sym )
|
167
171
|
super
|
168
172
|
end
|
@@ -256,7 +260,7 @@ class Configurability::Config
|
|
256
260
|
end
|
257
261
|
end
|
258
262
|
|
259
|
-
ihash = symbolify_keys(
|
263
|
+
ihash = symbolify_keys( hash )
|
260
264
|
idefaults = symbolify_keys( defaults )
|
261
265
|
mergedhash = idefaults.merge( ihash, &mergefunc )
|
262
266
|
|
@@ -285,41 +289,9 @@ class Configurability::Config
|
|
285
289
|
|
286
290
|
|
287
291
|
# A collection of data-structure-manipulation functions.
|
292
|
+
# :TODO: Replace with #transform_keys after 2.4's EOL
|
288
293
|
module DataUtilities
|
289
294
|
|
290
|
-
### Return a copy of the specified +hash+ with all of its values
|
291
|
-
### untainted.
|
292
|
-
def untaint_hash( hash )
|
293
|
-
newhash = {}
|
294
|
-
hash.each_key do |key|
|
295
|
-
newhash[ key ] = untaint_value( hash[key] )
|
296
|
-
end
|
297
|
-
return newhash
|
298
|
-
end
|
299
|
-
|
300
|
-
|
301
|
-
### Return an untainted copy of the specified +val+.
|
302
|
-
def untaint_value( val )
|
303
|
-
case val
|
304
|
-
when Hash
|
305
|
-
return untaint_hash( val )
|
306
|
-
|
307
|
-
when Array
|
308
|
-
return val.collect {|v| untaint_value(v) }
|
309
|
-
|
310
|
-
when NilClass, TrueClass, FalseClass, Numeric, Symbol, Encoding
|
311
|
-
return val
|
312
|
-
|
313
|
-
else
|
314
|
-
if val.respond_to?( :dup ) && val.respond_to?( :untaint )
|
315
|
-
return val.dup.untaint
|
316
|
-
else
|
317
|
-
return val
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
|
323
295
|
### Return a duplicate of the given +hash+ with its identifier-like keys
|
324
296
|
### transformed into symbols from whatever they were before.
|
325
297
|
def symbolify_keys( hash )
|
@@ -400,7 +372,7 @@ class Configurability::Config
|
|
400
372
|
# Return the value associated with the specified +key+, or another
|
401
373
|
# Configurability::Config::ConfigStruct if +key+ is a section name.
|
402
374
|
def []( key )
|
403
|
-
key = key.
|
375
|
+
key = key.to_sym if key.respond_to?( :to_sym )
|
404
376
|
|
405
377
|
# Convert Hashes to Struct on the fly for subsections
|
406
378
|
@hash[ key ] = self.class.new( @hash[key] ) if @hash[ key ].is_a?( Hash )
|
@@ -411,7 +383,7 @@ class Configurability::Config
|
|
411
383
|
|
412
384
|
### Set the value associated with the specified +key+ to +value+.
|
413
385
|
def []=( key, value )
|
414
|
-
key = key.
|
386
|
+
key = key.to_sym
|
415
387
|
self.mark_dirty if @hash[ key ] != value
|
416
388
|
@hash[ key ] = value
|
417
389
|
end
|