jeckyl 0.2.7 → 0.3.7
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 +15 -0
- data/Bugs.rdoc +14 -2
- data/Gemfile +4 -2
- data/History.txt +36 -1
- data/bin/jeckyl +89 -57
- data/bin/jeckyl-old +259 -0
- data/lib/jeckyl/helpers.rb +316 -0
- data/lib/jeckyl/version.rb +9 -8
- data/lib/jeckyl.rb +178 -251
- data/spec/jeckyl_spec.rb +25 -1
- data/test/conf.d/jeckyl +11 -2
- data/test/conf.d/jeckyl_alt.rb +55 -0
- data/test/conf.d/merger.rb +1 -1
- data/test/conf.d/not_a_hash +1 -1
- data/test/conf.d/not_positive.rb +1 -0
- data/test/test_command +42 -0
- data/test/test_configurator.rb +39 -5
- metadata +58 -78
data/lib/jeckyl.rb
CHANGED
@@ -11,8 +11,10 @@
|
|
11
11
|
#
|
12
12
|
# == JECKYL
|
13
13
|
#
|
14
|
+
require 'optparse'
|
14
15
|
require 'jeckyl/version'
|
15
16
|
require 'jeckyl/errors'
|
17
|
+
require 'jeckyl/helpers'
|
16
18
|
|
17
19
|
#
|
18
20
|
# The Jeckyl configurator module, which is just a wrapper. See {file:README.md Readme} for details.
|
@@ -37,6 +39,7 @@ module Jeckyl
|
|
37
39
|
#
|
38
40
|
# More details are available in the {file:README.md Readme} file
|
39
41
|
class Config < Hash
|
42
|
+
|
40
43
|
|
41
44
|
# create a configuration hash by evaluating the parameters defined in the given config file.
|
42
45
|
#
|
@@ -66,12 +69,18 @@ module Jeckyl
|
|
66
69
|
# hash for comments accessed with the same symbol
|
67
70
|
@_comments = {}
|
68
71
|
# hash for input defaults
|
69
|
-
@_defaults={}
|
72
|
+
@_defaults = {}
|
73
|
+
# hash for optparse options
|
74
|
+
@_options = {}
|
75
|
+
# hash for short descriptions
|
76
|
+
@_descriptions = {}
|
70
77
|
# save order in which methods are defined for generating config files
|
71
78
|
@_order = Array.new
|
72
79
|
|
73
80
|
# get the defaults defined in the config parser
|
74
81
|
get_defaults(:local=> local, :flag_errors => flag_errors_on_defaults)
|
82
|
+
|
83
|
+
self[:config_files] = Array.new
|
75
84
|
|
76
85
|
return self if config_file.nil?
|
77
86
|
|
@@ -90,20 +99,30 @@ module Jeckyl
|
|
90
99
|
|
91
100
|
# gives access to a hash containing an entry for each parameter and the comments
|
92
101
|
# defined by the class definitions - used internally by class methods
|
93
|
-
def
|
102
|
+
def _comments
|
94
103
|
@_comments
|
95
104
|
end
|
96
105
|
|
97
106
|
# This contains an array of the parameter names - used internally by class methods
|
98
|
-
def
|
107
|
+
def _order
|
99
108
|
@_order
|
100
109
|
end
|
101
110
|
|
102
111
|
# this contains a hash of the defaults for each parameter - used internally by class methods
|
103
|
-
def
|
112
|
+
def _defaults
|
104
113
|
@_defaults
|
105
114
|
end
|
106
115
|
|
116
|
+
# return hash of options - used internally to generate files etc
|
117
|
+
def _options
|
118
|
+
@_options
|
119
|
+
end
|
120
|
+
|
121
|
+
# return has of descriptions
|
122
|
+
def _descriptions
|
123
|
+
@_descriptions
|
124
|
+
end
|
125
|
+
|
107
126
|
# a class method to check a given config file one item at a time
|
108
127
|
#
|
109
128
|
# This evaluates the given config file and reports if there are any errors to the
|
@@ -165,14 +184,26 @@ module Jeckyl
|
|
165
184
|
def self.generate_config(local=false)
|
166
185
|
me = self.new(nil, :local => local)
|
167
186
|
# everything should now exist
|
168
|
-
me.
|
187
|
+
me._order.each do |key|
|
188
|
+
|
189
|
+
if me._descriptions.has_key?(key) then
|
190
|
+
puts "# #{me._descriptions[key]}"
|
191
|
+
puts "#"
|
192
|
+
end
|
169
193
|
|
170
|
-
if me.
|
171
|
-
me.
|
194
|
+
if me._comments.has_key?(key) then
|
195
|
+
me._comments[key].each do |comment|
|
172
196
|
puts "# #{comment}"
|
173
197
|
end
|
174
198
|
end
|
175
|
-
|
199
|
+
# output an option description if needed
|
200
|
+
if me._options.has_key?(key) then
|
201
|
+
puts "#"
|
202
|
+
puts "# Optparse options for this parameter:"
|
203
|
+
puts "# #{me._options[key].join(", ")}"
|
204
|
+
puts "#"
|
205
|
+
end
|
206
|
+
def_value = me._defaults[key]
|
176
207
|
default = def_value.nil? ? '' : def_value.inspect
|
177
208
|
|
178
209
|
puts "##{key.to_s} #{default}"
|
@@ -191,7 +222,7 @@ module Jeckyl
|
|
191
222
|
def self.intersection(full_config)
|
192
223
|
me = self.new # create the defaults for this class
|
193
224
|
my_hash = {}
|
194
|
-
me.
|
225
|
+
me._order.each do |my_key|
|
195
226
|
if full_config.has_key?(my_key) then
|
196
227
|
my_hash[my_key] = full_config[my_key]
|
197
228
|
end
|
@@ -212,6 +243,35 @@ module Jeckyl
|
|
212
243
|
return descs
|
213
244
|
end
|
214
245
|
|
246
|
+
# get a config file option from the given command line args
|
247
|
+
#
|
248
|
+
# This is needed with the optparse methods for obvious reasons - the options
|
249
|
+
# can only be parsed once and you may want to parse them with a config file specified
|
250
|
+
# on the command line. This does it the old-fashioned way and strips the option
|
251
|
+
# from the command line arguments.
|
252
|
+
#
|
253
|
+
# Note that the optparse method also includes this option but just for the benefit of --help
|
254
|
+
#
|
255
|
+
# @param [Array] args which should usually be set to ARGV
|
256
|
+
# @param [String] c_file being the path to the config file, which will be
|
257
|
+
# updated with the command line option if specified.
|
258
|
+
#
|
259
|
+
def self.get_config_opt(args, c_file)
|
260
|
+
#c_file = nil
|
261
|
+
if arg_index = args.index('-c') then
|
262
|
+
# got a -c option so expect a file next
|
263
|
+
c_file = args[arg_index + 1]
|
264
|
+
|
265
|
+
# check the file exists
|
266
|
+
if c_file && FileTest.readable?(c_file) then
|
267
|
+
# it does so strip the args out
|
268
|
+
args.slice!(arg_index, 2)
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|
272
|
+
return [args, c_file]
|
273
|
+
end
|
274
|
+
|
215
275
|
|
216
276
|
# set the prefix to the parameter names that should be used for corresponding
|
217
277
|
# parameter methods defined for a subclass. Parameter names in config files
|
@@ -238,15 +298,23 @@ module Jeckyl
|
|
238
298
|
|
239
299
|
# Read, check and merge another parameter file into this one, being of the same config class.
|
240
300
|
#
|
301
|
+
# If the file does not exist then silently ignore the merge
|
302
|
+
#
|
241
303
|
# @param [String] conf_file - path to file to parse
|
242
304
|
#
|
243
305
|
def merge(conf_file)
|
244
306
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
307
|
+
if conf_file.kind_of?(Hash) then
|
308
|
+
self.merge!(conf_file)
|
309
|
+
else
|
310
|
+
|
311
|
+
return unless FileTest.exists?(conf_file)
|
312
|
+
|
313
|
+
self[:config_files] << conf_file
|
314
|
+
|
315
|
+
# get the values from the config file itself
|
316
|
+
self.instance_eval(File.read(conf_file), conf_file)
|
317
|
+
end
|
250
318
|
rescue SyntaxError => err
|
251
319
|
raise ConfigSyntaxError, err.message
|
252
320
|
rescue Errno::ENOENT
|
@@ -254,12 +322,88 @@ module Jeckyl
|
|
254
322
|
raise ConfigFileMissing, "#{conf_file}"
|
255
323
|
end
|
256
324
|
|
325
|
+
# parse the given command line using the defined options
|
326
|
+
#
|
327
|
+
# @param [Array] args which should usually be ARGV
|
328
|
+
# @yield self and optparse object to allow incidental options to be added
|
329
|
+
# @return false if --help so that the caller can decide what to do (e.g. exit)
|
330
|
+
def optparse(args)
|
331
|
+
|
332
|
+
# ensure calls to parameter methods do not trample on things
|
333
|
+
@_last_symbol = nil
|
334
|
+
|
335
|
+
opts = OptionParser.new
|
336
|
+
# get the prefix for parameter methods (once)
|
337
|
+
prefix = self.prefix
|
338
|
+
|
339
|
+
opts.on('-c', '--config-file [FILENAME]', String, 'specify an alternative config file')
|
340
|
+
|
341
|
+
# need to define usage etc
|
342
|
+
|
343
|
+
# loop through each of the options saved
|
344
|
+
@_options.each_pair do |param, options|
|
345
|
+
|
346
|
+
options << @_descriptions[param] if @_descriptions.has_key?(param)
|
347
|
+
|
348
|
+
# opt_str = ''
|
349
|
+
# options.each do |os|
|
350
|
+
# opt_str << os.inspect
|
351
|
+
# end
|
352
|
+
|
353
|
+
# puts "#{param}: #{opt_str}"
|
354
|
+
|
355
|
+
# get the method itself to call with the given arg
|
356
|
+
pref_method = self.method("#{prefix}_#{param}".to_sym)
|
357
|
+
|
358
|
+
# now process the option
|
359
|
+
opts.on(*options) do |val|
|
360
|
+
# and save the results having passed it through the parameter method
|
361
|
+
self[param] = pref_method.call(val)
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# allow non-jeckyl options to be added (without the checks!)
|
367
|
+
if block_given? then
|
368
|
+
# pass out self to allow parameters to be saved and the opts object
|
369
|
+
yield(self, opts)
|
370
|
+
end
|
371
|
+
|
372
|
+
# add in a little bit of help
|
373
|
+
opts.on_tail('-h', '--help', 'you are looking at it') do
|
374
|
+
puts opts
|
375
|
+
return false
|
376
|
+
end
|
377
|
+
|
378
|
+
opts.parse!(args)
|
379
|
+
|
380
|
+
return true
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
# output the hash as a formatted set
|
385
|
+
def to_s(opts={})
|
386
|
+
keys = self.keys.collect {|k| k.to_s}
|
387
|
+
cols = 0
|
388
|
+
keys.each {|k| cols = k.length if k.length > cols}
|
389
|
+
keys.sort.each do |key_s|
|
390
|
+
print ' '
|
391
|
+
print key_s.ljust(cols)
|
392
|
+
key = key_s.to_sym
|
393
|
+
desc = @_descriptions[key]
|
394
|
+
value = self[key].inspect
|
395
|
+
print ": #{value}"
|
396
|
+
print " (#{desc})" unless desc.nil?
|
397
|
+
puts
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
257
401
|
|
258
402
|
protected
|
259
403
|
|
260
404
|
# create a description for the current parameter, to be used when generating a config template
|
261
405
|
#
|
262
|
-
# @param [*String] being one or more string arguments that are used to generate config file templates
|
406
|
+
# @param [*String] strings being one or more string arguments that are used to generate config file templates
|
263
407
|
# and documents
|
264
408
|
def comment(*strings)
|
265
409
|
@_comments[@_last_symbol] = strings unless @_last_symbol.nil?
|
@@ -273,244 +417,22 @@ module Jeckyl
|
|
273
417
|
@_defaults[@_last_symbol] = val
|
274
418
|
end
|
275
419
|
|
276
|
-
#
|
277
|
-
|
278
|
-
# file helpers - meanings should be apparent
|
279
|
-
|
280
|
-
# check that the parameter is a directory and that the directory is writable
|
281
|
-
#
|
282
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
283
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
284
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
285
|
-
# the parameter is not validly formed
|
286
|
-
#
|
287
|
-
# @param [String] - path
|
288
|
-
#
|
289
|
-
def a_writable_dir(path)
|
290
|
-
if FileTest.directory?(path) && FileTest.writable?(path) then
|
291
|
-
path
|
292
|
-
else
|
293
|
-
raise_config_error(path, "directory is not writable or does not exist")
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
# check parameter is a readable file
|
420
|
+
# set optparse options for the parameter
|
298
421
|
#
|
299
|
-
#
|
300
|
-
|
301
|
-
|
302
|
-
# the parameter is not validly formed
|
303
|
-
#
|
304
|
-
# @param [String] - path to file
|
305
|
-
#
|
306
|
-
def a_readable_file(path)
|
307
|
-
if FileTest.readable?(path) then
|
308
|
-
path
|
309
|
-
else
|
310
|
-
raise_config_error(path, "file does not exist")
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
# simple type helpers
|
315
|
-
|
316
|
-
# check the parameter is of the required type
|
317
|
-
#
|
318
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
319
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
320
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
321
|
-
# the parameter is not validly formed
|
322
|
-
#
|
323
|
-
# @param [Object] obj to check type of
|
324
|
-
# @param [Class] type, being a class constant such as Numeric, String
|
325
|
-
#
|
326
|
-
def a_type_of(obj, type)
|
327
|
-
if obj.kind_of?(type) then
|
328
|
-
obj
|
329
|
-
else
|
330
|
-
raise_config_error(obj, "value is not of required type: #{type}")
|
331
|
-
end
|
422
|
+
# @param [Array] opts - options using the same format as optparse
|
423
|
+
def option(*opts)
|
424
|
+
@_options[@_last_symbol] = opts unless @_last_symbol.nil?
|
332
425
|
end
|
333
426
|
|
334
|
-
#
|
427
|
+
# set optparse description for the parameter
|
335
428
|
#
|
336
|
-
#
|
337
|
-
|
338
|
-
|
339
|
-
# the parameter is not validly formed
|
340
|
-
#
|
341
|
-
# @param [Numeric] val to check
|
342
|
-
# @param [Numeric] lower bound of range
|
343
|
-
# @param [Numeric] upper bound of range
|
344
|
-
#
|
345
|
-
def in_range(val, lower, upper)
|
346
|
-
raise_syntax_error("#{lower.to_s}..#{upper.to_s} is not a range") unless (lower .. upper).kind_of?(Range)
|
347
|
-
if (lower .. upper) === val then
|
348
|
-
val
|
349
|
-
else
|
350
|
-
raise_config_error(val, "value is not within required range: #{lower.to_s}..#{upper.to_s}")
|
351
|
-
end
|
352
|
-
end
|
353
|
-
|
354
|
-
|
355
|
-
# boolean helpers
|
356
|
-
|
357
|
-
# check parameter is a boolean, true or false but not strings "true" or "false"
|
358
|
-
#
|
359
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
360
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
361
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
362
|
-
# the parameter is not validly formed
|
363
|
-
#
|
364
|
-
# @param [Boolean] val to check
|
365
|
-
#
|
366
|
-
def a_boolean(val)
|
367
|
-
if val.kind_of?(TrueClass) || val.kind_of?(FalseClass) then
|
368
|
-
val
|
369
|
-
else
|
370
|
-
raise_config_error(val, "Value is not a Boolean")
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
# check the parameter is a flag, being "true", "false", "yes", "no", "on", "off", or 1 , 0
|
375
|
-
# and return a proper boolean
|
376
|
-
#
|
377
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
378
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
379
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
380
|
-
# the parameter is not validly formed
|
381
|
-
#
|
382
|
-
# @param [String] val to check
|
383
|
-
#
|
384
|
-
def a_flag(val)
|
385
|
-
val = val.downcase if val.kind_of?(String)
|
386
|
-
case val
|
387
|
-
when "true", "yes", "on", 1
|
388
|
-
true
|
389
|
-
when "false", "no", "off", 0
|
390
|
-
false
|
391
|
-
else
|
392
|
-
raise_config_error(val, "Cannot convert to Boolean")
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
|
-
|
397
|
-
# compound objects
|
398
|
-
|
399
|
-
# check the parameter is an array
|
400
|
-
#
|
401
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
402
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
403
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
404
|
-
# the parameter is not validly formed
|
405
|
-
#
|
406
|
-
# @param [Array] ary to check
|
407
|
-
#
|
408
|
-
def an_array(ary)
|
409
|
-
if ary.kind_of?(Array) then
|
410
|
-
ary
|
411
|
-
else
|
412
|
-
raise_config_error(ary, "value is not an Array")
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
# check the parameter is an array and the array is of the required type
|
417
|
-
#
|
418
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
419
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
420
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
421
|
-
# the parameter is not validly formed
|
422
|
-
#
|
423
|
-
# @param [Array] ary of values to check
|
424
|
-
# @param [Class] type being the class that the values must belong to
|
425
|
-
#
|
426
|
-
def an_array_of(ary, type)
|
427
|
-
raise_syntax_error("Provided a value that is a type: #{type.to_s}") unless type.class == Class
|
428
|
-
if ary.kind_of?(Array) then
|
429
|
-
ary.each do |element|
|
430
|
-
unless element.kind_of?(type) then
|
431
|
-
raise_config_error(element, "element of array is not of type: #{type}")
|
432
|
-
end
|
433
|
-
end
|
434
|
-
return ary
|
435
|
-
else
|
436
|
-
raise_config_error(ary, "value is not an Array")
|
437
|
-
end
|
438
|
-
end
|
439
|
-
|
440
|
-
# check the parameter is a hash
|
441
|
-
#
|
442
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
443
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
444
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
445
|
-
# the parameter is not validly formed
|
446
|
-
#
|
447
|
-
# @param [Hash] hsh to check
|
448
|
-
#
|
449
|
-
def a_hash(hsh)
|
450
|
-
if hsh.kind_of?(Hash) then
|
451
|
-
true
|
452
|
-
else
|
453
|
-
raise_config_error(hsh, "value is not a Hash")
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
# strings and text and stuff
|
458
|
-
|
459
|
-
# check the parameter is a string
|
460
|
-
#
|
461
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
462
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
463
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
464
|
-
# the parameter is not validly formed
|
465
|
-
#
|
466
|
-
# @param [String] str to check
|
467
|
-
#
|
468
|
-
def a_string(str)
|
469
|
-
if str.kind_of?(String) then
|
470
|
-
str
|
471
|
-
else
|
472
|
-
raise_config_error(str.to_s, "is not a String")
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
476
|
-
# check the parameter is a string and matches the required pattern
|
477
|
-
#
|
478
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
479
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
480
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
481
|
-
# the parameter is not validly formed
|
482
|
-
#
|
483
|
-
# @param [String] str to match against the pattern
|
484
|
-
# @param [Regexp] pattern to match with
|
485
|
-
#
|
486
|
-
def a_matching_string(str, pattern)
|
487
|
-
raise_syntax_error("Attempt to pattern match without a Regexp") unless pattern.kind_of?(Regexp)
|
488
|
-
if pattern =~ a_string(str) then
|
489
|
-
str
|
490
|
-
else
|
491
|
-
raise_config_error(str, "does not match required pattern: #{pattern.source}")
|
492
|
-
end
|
493
|
-
end
|
494
|
-
|
495
|
-
# set membership - set is an array of members, usually symbols
|
496
|
-
#
|
497
|
-
# Jeckyl checking method to be used in parameter methods to check the validity of
|
498
|
-
# given parameters, returning the parameter if valid or else raising an exception
|
499
|
-
# which is either ConfigError if the parameter fails the check or ConfigSyntaxError if
|
500
|
-
# the parameter is not validly formed
|
501
|
-
#
|
502
|
-
# @param [Symbol] symb being the symbol to check
|
503
|
-
# @param [Array] set containing the valid symbols that symb should belong to
|
504
|
-
#
|
505
|
-
def a_member_of(symb, set)
|
506
|
-
raise_syntax_error("Sets to test membership must be arrays") unless set.kind_of?(Array)
|
507
|
-
if set.include?(symb) then
|
508
|
-
symb
|
509
|
-
else
|
510
|
-
raise_config_error(symb, "is not a member of: #{set.join(', ')}")
|
511
|
-
end
|
429
|
+
# @param [Array] str - options using the same format as optparse
|
430
|
+
def describe(str)
|
431
|
+
@_descriptions[@_last_symbol] = str unless @_last_symbol.nil?
|
512
432
|
end
|
513
433
|
|
434
|
+
# add in all the parameter checking helper methods
|
435
|
+
include Jeckyl::Helpers
|
514
436
|
|
515
437
|
private
|
516
438
|
|
@@ -556,15 +478,20 @@ module Jeckyl
|
|
556
478
|
self.class.instance_methods(!local).each do |method_name|
|
557
479
|
if md = /^#{self.prefix}_/.match(method_name) then
|
558
480
|
|
559
|
-
# its a prefixed method so
|
481
|
+
# its a prefixed method so get it
|
560
482
|
|
561
483
|
pref_method = self.method(method_name.to_sym)
|
562
484
|
# get the corresponding symbol for the hash
|
563
485
|
@_last_symbol = md.post_match.to_sym
|
564
486
|
@_order << @_last_symbol
|
565
|
-
# and call the method with
|
566
|
-
# call the
|
567
|
-
#
|
487
|
+
# and call the method with any parameter, which will
|
488
|
+
# call the default method where defined and capture its value
|
489
|
+
# Note that a default is defined in the same terms as the input
|
490
|
+
# to its parameter method, and may therefore need to be processed
|
491
|
+
# by the method to get the desired value. For example, if a parameter
|
492
|
+
# method expects data expressed in MBytes, but passes on bytes then
|
493
|
+
# the method has to be called with the default to get the real or final
|
494
|
+
# default. This is done in the block after this one:
|
568
495
|
begin
|
569
496
|
a_value = pref_method.call(1)
|
570
497
|
rescue Exception
|
data/spec/jeckyl_spec.rb
CHANGED
@@ -7,6 +7,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../test/test_subclass')
|
|
7
7
|
|
8
8
|
conf_path = File.expand_path(File.dirname(__FILE__) + '/../test/conf.d')
|
9
9
|
|
10
|
+
|
10
11
|
describe "Jeckyl" do
|
11
12
|
|
12
13
|
# general tests
|
@@ -30,6 +31,9 @@ describe "Jeckyl" do
|
|
30
31
|
conf[:email].should == "robert@osburn-sharp.ath.cx"
|
31
32
|
conf.has_key?(:sieve).should be_true
|
32
33
|
conf[:config_files].length.should == 1
|
34
|
+
conf[:option_set][:peter].should == 37
|
35
|
+
conf[:offset].should == 134
|
36
|
+
conf[:start_day].should == 6
|
33
37
|
end
|
34
38
|
|
35
39
|
|
@@ -89,6 +93,11 @@ describe "Jeckyl" do
|
|
89
93
|
lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[pi\]:.*value is not of required type: Float$/)
|
90
94
|
end
|
91
95
|
|
96
|
+
it "should raise an exception if it gets a negative instead of a positive" do
|
97
|
+
conf_file = conf_path + '/not_positive.rb'
|
98
|
+
lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[offset\]:.*value is not a positive number: \-\d+$/)
|
99
|
+
end
|
100
|
+
|
92
101
|
end
|
93
102
|
|
94
103
|
describe "Boolean Parameters" do
|
@@ -114,7 +123,7 @@ describe "Jeckyl" do
|
|
114
123
|
|
115
124
|
it "should raise an exception if it gets a string instead of a hash" do
|
116
125
|
conf_file = conf_path + '/not_a_hash'
|
117
|
-
lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[
|
126
|
+
lambda{conf = TestJeckyl.new(conf_file)}.should raise_error(Jeckyl::ConfigError, /^\[option_set\]:.*value is not a Hash$/)
|
118
127
|
end
|
119
128
|
|
120
129
|
it "should raise an exception if it gets an array of strings instead of a integers" do
|
@@ -197,6 +206,21 @@ describe "Jeckyl" do
|
|
197
206
|
conf[:config_files].length.should == 2
|
198
207
|
conf[:pi].should == 3.14592
|
199
208
|
end
|
209
|
+
|
210
|
+
it "should merge another hash" do
|
211
|
+
conf_file = conf_path + '/jeckyl'
|
212
|
+
conf = TestJeckyl.new(conf_file)
|
213
|
+
merge_file = File.join(conf_path, 'merger.rb')
|
214
|
+
merge = TestJeckyl.new(merge_file)
|
215
|
+
conf.merge(merge)
|
216
|
+
conf[:log_dir].should match(/reports$/)
|
217
|
+
conf[:log_level].should == :debug
|
218
|
+
conf[:log_rotation].should == 6
|
219
|
+
conf[:email].should == "robert@osburn-associates.ath.cx"
|
220
|
+
conf[:config_files].length.should == 1
|
221
|
+
conf[:pi].should == 3.14592
|
222
|
+
|
223
|
+
end
|
200
224
|
end
|
201
225
|
|
202
226
|
end
|
data/test/conf.d/jeckyl
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
# Jeckyl test file
|
3
3
|
#
|
4
4
|
|
5
|
+
root = File.expand_path('../..', File.dirname(__FILE__))
|
6
|
+
|
5
7
|
# should be a writable directory
|
6
|
-
log_dir "
|
8
|
+
log_dir File.join(root, "test")
|
7
9
|
|
8
10
|
#should be a valid symbol
|
9
11
|
log_level :verbose
|
@@ -25,7 +27,7 @@ sieve [2, 5, 7, 10, 15]
|
|
25
27
|
|
26
28
|
# hash of anything
|
27
29
|
my_opts = {:peter=>37, :paul=>40, :birds=>true}
|
28
|
-
|
30
|
+
option_set my_opts
|
29
31
|
|
30
32
|
# string formatted as email address
|
31
33
|
email "robert@osburn-sharp.ath.cx"
|
@@ -44,3 +46,10 @@ flag "no"
|
|
44
46
|
flag 1
|
45
47
|
flag 0
|
46
48
|
|
49
|
+
|
50
|
+
# new things
|
51
|
+
offset 134
|
52
|
+
|
53
|
+
start_day 6
|
54
|
+
|
55
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Jeckyl test file
|
3
|
+
#
|
4
|
+
|
5
|
+
root = File.expand_path('../..', File.dirname(__FILE__))
|
6
|
+
|
7
|
+
# should be a writable directory
|
8
|
+
log_dir File.join(root, "test")
|
9
|
+
|
10
|
+
#should be a valid symbol
|
11
|
+
log_level :debug
|
12
|
+
|
13
|
+
# should be an integer
|
14
|
+
log_rotation 10
|
15
|
+
|
16
|
+
# can be a float or any numeric
|
17
|
+
threshold 2.3
|
18
|
+
threshold 9.6
|
19
|
+
|
20
|
+
# must be a float
|
21
|
+
pi 3.1459276
|
22
|
+
|
23
|
+
# array of anything
|
24
|
+
collection ["names", 1, true ]
|
25
|
+
# array of integers
|
26
|
+
sieve [2, 5, 7, 10, 15]
|
27
|
+
|
28
|
+
# hash of anything
|
29
|
+
my_opts = {:peter=>37, :paul=>40, :birds=>true}
|
30
|
+
option_set my_opts
|
31
|
+
|
32
|
+
# string formatted as email address
|
33
|
+
email "robert@osburn-sharp.ath.cx"
|
34
|
+
|
35
|
+
# real booleans
|
36
|
+
debug false
|
37
|
+
debug true
|
38
|
+
|
39
|
+
# generous booleans
|
40
|
+
flag "true"
|
41
|
+
flag "false"
|
42
|
+
flag "off"
|
43
|
+
flag "on"
|
44
|
+
flag "yes"
|
45
|
+
flag "no"
|
46
|
+
flag 1
|
47
|
+
flag 0
|
48
|
+
|
49
|
+
|
50
|
+
# new things
|
51
|
+
offset 134
|
52
|
+
|
53
|
+
start_day 6
|
54
|
+
|
55
|
+
log_level :debug
|
data/test/conf.d/merger.rb
CHANGED