configtoolkit 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Rakefile +1 -1
- data/lib/configtoolkit/baseconfig.rb +315 -8
- data/lib/configtoolkit/toolkit.rb +8 -2
- data/lib/configtoolkit/types.rb +40 -14
- metadata +2 -2
data/History.txt
CHANGED
data/Rakefile
CHANGED
@@ -4,21 +4,69 @@ require 'pathname'
|
|
4
4
|
require 'set'
|
5
5
|
require 'uri'
|
6
6
|
|
7
|
-
#
|
8
|
-
# Tomorrow:
|
9
|
-
# 7.) Ruby gems
|
10
|
-
# 11.) Write lots of readers + writers
|
11
|
-
# 13.) Clean up cast?
|
12
|
-
# 14.) Production comments
|
13
|
-
#
|
14
7
|
module ConfigToolkit
|
15
8
|
|
9
|
+
#
|
10
|
+
# This class represents a configuration. It provides configuration
|
11
|
+
# specification, loading, and dumping functionality. A BaseConfig
|
12
|
+
# configuration can contain "scalars" (anything except an array or
|
13
|
+
# nested configuration class), ConstrainedArrays (arrays), and other
|
14
|
+
# BaseConfig child classes (which can be thought of as hashes).
|
15
|
+
# Note that ConstrainedArrays and other BaseConfig
|
16
|
+
# classes recursively can contain anything the parent BaseConfig can contain,
|
17
|
+
# so nesting to any depth is supported.
|
18
|
+
#
|
19
|
+
# BaseConfig neither parses nor writes to files directly, but instead does so
|
20
|
+
# through reader and writer classes (respectively) specified by the
|
21
|
+
# programmer. This allows BaseConfig to support virtually any underlying
|
22
|
+
# configuration file format (including YAML, UNIX key/value pairs, etc).
|
23
|
+
# BaseConfig expects reader classes to contain a read method that sources
|
24
|
+
# configuration information and returns a hash that maps strings
|
25
|
+
# (parameter names) to values, which can themselves
|
26
|
+
# be hashes or arrays. It expects writer classes to in turn support a write
|
27
|
+
# method that accepts such a hash and writes it to some underlying stream.
|
28
|
+
# The reader and writer implementations used have no effect on BaseConfig's
|
29
|
+
# validation functionality; data from whatever source (even specified
|
30
|
+
# programatically via setters) always fully is validated.
|
31
|
+
#
|
32
|
+
# Programmers wishing to create their own configuration classes
|
33
|
+
# should extend BaseConfig and, in the body of their class' definition,
|
34
|
+
# call add_required_param and add_optional_param for each parameter
|
35
|
+
# they wish to specify. If they wish to enforce a relationship between
|
36
|
+
# parameters, then they also can define validate_all_values.
|
37
|
+
#
|
16
38
|
class BaseConfig
|
39
|
+
|
40
|
+
#
|
41
|
+
# This class represents the specification for a parameter. Right now,
|
42
|
+
# a parameter specification consists of:
|
43
|
+
# 1.) The parameter name (Symbol)
|
44
|
+
# 2.) The parameter value class (Class)
|
45
|
+
# 3.) Whether or not the parameter is required
|
46
|
+
# 4.) If the parameter is not required, a default value
|
47
|
+
#
|
17
48
|
class ParamSpec
|
18
49
|
attr_reader :name
|
19
50
|
attr_reader :value_class
|
20
51
|
attr_reader :default_value # Only meaningful if is_required?
|
21
52
|
|
53
|
+
#
|
54
|
+
# ====Description:
|
55
|
+
#
|
56
|
+
#
|
57
|
+
# ====Parameters:
|
58
|
+
# [name]
|
59
|
+
# ?
|
60
|
+
# [value_class]
|
61
|
+
# ?
|
62
|
+
# [is_required]
|
63
|
+
# ?
|
64
|
+
# [default_value]
|
65
|
+
# ?
|
66
|
+
#
|
67
|
+
# ====Returns:
|
68
|
+
#
|
69
|
+
#
|
22
70
|
def initialize(name, value_class, is_required, default_value)
|
23
71
|
@name = name
|
24
72
|
@value_class = value_class
|
@@ -29,6 +77,13 @@ class BaseConfig
|
|
29
77
|
end
|
30
78
|
end
|
31
79
|
|
80
|
+
#
|
81
|
+
# ====Description:
|
82
|
+
#
|
83
|
+
#
|
84
|
+
# ====Returns:
|
85
|
+
#
|
86
|
+
#
|
32
87
|
def is_required?
|
33
88
|
return @is_required
|
34
89
|
end
|
@@ -59,6 +114,17 @@ class BaseConfig
|
|
59
114
|
attr_reader :required_params
|
60
115
|
end
|
61
116
|
|
117
|
+
#
|
118
|
+
# ====Description:
|
119
|
+
#
|
120
|
+
#
|
121
|
+
# ====Parameters:
|
122
|
+
# [child_class]
|
123
|
+
# ?
|
124
|
+
#
|
125
|
+
# ====Returns:
|
126
|
+
#
|
127
|
+
#
|
62
128
|
def self.inherited(child_class)
|
63
129
|
#
|
64
130
|
# Initialize the class instance variables.
|
@@ -71,6 +137,25 @@ class BaseConfig
|
|
71
137
|
end
|
72
138
|
end
|
73
139
|
|
140
|
+
#
|
141
|
+
# ====Description:
|
142
|
+
#
|
143
|
+
#
|
144
|
+
# ====Parameters:
|
145
|
+
# [name]
|
146
|
+
# ?
|
147
|
+
# [value_class]
|
148
|
+
# ?
|
149
|
+
# [is_required]
|
150
|
+
# ?
|
151
|
+
# [default_value]
|
152
|
+
# ?
|
153
|
+
# [validate_value_block]
|
154
|
+
# ?
|
155
|
+
#
|
156
|
+
# ====Returns:
|
157
|
+
#
|
158
|
+
#
|
74
159
|
def self.add_param(name,
|
75
160
|
value_class,
|
76
161
|
is_required,
|
@@ -132,6 +217,21 @@ class BaseConfig
|
|
132
217
|
end
|
133
218
|
private_class_method :add_param
|
134
219
|
|
220
|
+
#
|
221
|
+
# ====Description:
|
222
|
+
#
|
223
|
+
#
|
224
|
+
# ====Parameters:
|
225
|
+
# [name]
|
226
|
+
# ?
|
227
|
+
# [value_class]
|
228
|
+
# ?
|
229
|
+
# [validate_value_block]
|
230
|
+
# ?
|
231
|
+
#
|
232
|
+
# ====Returns:
|
233
|
+
#
|
234
|
+
#
|
135
235
|
def self.add_required_param(name,
|
136
236
|
value_class,
|
137
237
|
&validate_value_block)
|
@@ -139,6 +239,23 @@ class BaseConfig
|
|
139
239
|
end
|
140
240
|
private_class_method :add_required_param
|
141
241
|
|
242
|
+
#
|
243
|
+
# ====Description:
|
244
|
+
#
|
245
|
+
#
|
246
|
+
# ====Parameters:
|
247
|
+
# [name]
|
248
|
+
# ?
|
249
|
+
# [value_class]
|
250
|
+
# ?
|
251
|
+
# [default_value]
|
252
|
+
# ?
|
253
|
+
# [validate_value_block]
|
254
|
+
# ?
|
255
|
+
#
|
256
|
+
# ====Returns:
|
257
|
+
#
|
258
|
+
#
|
142
259
|
def self.add_optional_param(name,
|
143
260
|
value_class,
|
144
261
|
default_value,
|
@@ -148,6 +265,14 @@ class BaseConfig
|
|
148
265
|
private_class_method :add_optional_param
|
149
266
|
|
150
267
|
attr_reader :containing_object_name
|
268
|
+
|
269
|
+
#
|
270
|
+
# ====Description:
|
271
|
+
#
|
272
|
+
#
|
273
|
+
# ====Returns:
|
274
|
+
#
|
275
|
+
#
|
151
276
|
def initialize
|
152
277
|
@containing_object_name = ""
|
153
278
|
@params_with_values = Set.new()
|
@@ -157,6 +282,17 @@ class BaseConfig
|
|
157
282
|
end
|
158
283
|
end
|
159
284
|
|
285
|
+
#
|
286
|
+
# ====Description:
|
287
|
+
#
|
288
|
+
#
|
289
|
+
# ====Parameters:
|
290
|
+
# [operation_name]
|
291
|
+
# ?
|
292
|
+
#
|
293
|
+
# ====Returns:
|
294
|
+
#
|
295
|
+
#
|
160
296
|
def enforce_specs(operation_name)
|
161
297
|
#
|
162
298
|
# Iterate through the parameters without values. If any are
|
@@ -207,9 +343,17 @@ class BaseConfig
|
|
207
343
|
private :enforce_specs
|
208
344
|
|
209
345
|
#
|
346
|
+
# ====Description:
|
210
347
|
# Because the to_s in Ruby 1.8 for the Array and Hash classes
|
211
348
|
# are horrible...
|
212
|
-
#
|
349
|
+
#
|
350
|
+
# ====Parameters:
|
351
|
+
# [value]
|
352
|
+
# ?
|
353
|
+
#
|
354
|
+
# ====Returns:
|
355
|
+
#
|
356
|
+
#
|
213
357
|
def construct_value_str(value)
|
214
358
|
if(value.is_a?(Array))
|
215
359
|
str = "["
|
@@ -243,6 +387,21 @@ class BaseConfig
|
|
243
387
|
end
|
244
388
|
private :construct_value_str
|
245
389
|
|
390
|
+
#
|
391
|
+
# ====Description:
|
392
|
+
#
|
393
|
+
#
|
394
|
+
# ====Parameters:
|
395
|
+
# [param_name]
|
396
|
+
# ?
|
397
|
+
# [value]
|
398
|
+
# ?
|
399
|
+
# [message]
|
400
|
+
# ?
|
401
|
+
#
|
402
|
+
# ====Returns:
|
403
|
+
#
|
404
|
+
#
|
246
405
|
def construct_error_message(param_name, value, message)
|
247
406
|
if(@containing_object_name.empty?)
|
248
407
|
full_param_name = ""
|
@@ -256,10 +415,32 @@ class BaseConfig
|
|
256
415
|
end
|
257
416
|
private :construct_error_message
|
258
417
|
|
418
|
+
#
|
419
|
+
# ====Description:
|
420
|
+
#
|
421
|
+
#
|
422
|
+
# ====Parameters:
|
423
|
+
# [message]
|
424
|
+
# ?
|
425
|
+
#
|
426
|
+
# ====Returns:
|
427
|
+
#
|
428
|
+
#
|
259
429
|
def raise_error(message)
|
260
430
|
raise Error, message, caller()
|
261
431
|
end
|
262
432
|
|
433
|
+
#
|
434
|
+
# ====Description:
|
435
|
+
#
|
436
|
+
#
|
437
|
+
# ====Parameters:
|
438
|
+
# [rhs]
|
439
|
+
# ?
|
440
|
+
#
|
441
|
+
# ====Returns:
|
442
|
+
#
|
443
|
+
#
|
263
444
|
def ==(rhs)
|
264
445
|
if(rhs == nil)
|
265
446
|
return false
|
@@ -274,6 +455,19 @@ class BaseConfig
|
|
274
455
|
return true
|
275
456
|
end
|
276
457
|
|
458
|
+
#
|
459
|
+
# ====Description:
|
460
|
+
#
|
461
|
+
#
|
462
|
+
# ====Parameters:
|
463
|
+
# [value_class]
|
464
|
+
# ?
|
465
|
+
# [value]
|
466
|
+
# ?
|
467
|
+
#
|
468
|
+
# ====Returns:
|
469
|
+
#
|
470
|
+
#
|
277
471
|
def dump_value_impl(value_class, value)
|
278
472
|
if(value_class < BaseConfig)
|
279
473
|
return value.dump_impl({})
|
@@ -289,6 +483,17 @@ class BaseConfig
|
|
289
483
|
end
|
290
484
|
private :dump_value_impl
|
291
485
|
|
486
|
+
#
|
487
|
+
# ====Description:
|
488
|
+
#
|
489
|
+
#
|
490
|
+
# ====Parameters:
|
491
|
+
# [containing_object_hash]
|
492
|
+
# ?
|
493
|
+
#
|
494
|
+
# ====Returns:
|
495
|
+
#
|
496
|
+
#
|
292
497
|
def dump_impl(containing_object_hash)
|
293
498
|
#
|
294
499
|
# Configuration never will be dumped without the
|
@@ -304,6 +509,17 @@ class BaseConfig
|
|
304
509
|
end
|
305
510
|
protected :dump_impl
|
306
511
|
|
512
|
+
#
|
513
|
+
# ====Description:
|
514
|
+
#
|
515
|
+
#
|
516
|
+
# ====Parameters:
|
517
|
+
# [writer]
|
518
|
+
# ?
|
519
|
+
#
|
520
|
+
# ====Returns:
|
521
|
+
#
|
522
|
+
#
|
307
523
|
def dump(writer)
|
308
524
|
dump_hash = {}
|
309
525
|
containing_object_hash = dump_hash
|
@@ -318,6 +534,21 @@ class BaseConfig
|
|
318
534
|
writer.write(dump_hash)
|
319
535
|
end
|
320
536
|
|
537
|
+
#
|
538
|
+
# ====Description:
|
539
|
+
#
|
540
|
+
#
|
541
|
+
# ====Parameters:
|
542
|
+
# [param_name]
|
543
|
+
# ?
|
544
|
+
# [value_class]
|
545
|
+
# ?
|
546
|
+
# [value]
|
547
|
+
# ?
|
548
|
+
#
|
549
|
+
# ====Returns:
|
550
|
+
#
|
551
|
+
#
|
321
552
|
def load_value_impl(param_name, value_class, value)
|
322
553
|
if(value.class <= value_class)
|
323
554
|
#
|
@@ -409,6 +640,19 @@ class BaseConfig
|
|
409
640
|
end
|
410
641
|
private :load_value_impl
|
411
642
|
|
643
|
+
#
|
644
|
+
# ====Description:
|
645
|
+
#
|
646
|
+
#
|
647
|
+
# ====Parameters:
|
648
|
+
# [containing_object_hash]
|
649
|
+
# ?
|
650
|
+
# [containing_object_name]
|
651
|
+
# ?
|
652
|
+
#
|
653
|
+
# ====Returns:
|
654
|
+
#
|
655
|
+
#
|
412
656
|
def load_impl(containing_object_hash, containing_object_name)
|
413
657
|
@containing_object_name = containing_object_name
|
414
658
|
@params_with_values.clear()
|
@@ -438,6 +682,19 @@ class BaseConfig
|
|
438
682
|
end
|
439
683
|
protected :load_impl
|
440
684
|
|
685
|
+
#
|
686
|
+
# ====Description:
|
687
|
+
#
|
688
|
+
#
|
689
|
+
# ====Parameters:
|
690
|
+
# [reader]
|
691
|
+
# ?
|
692
|
+
# [containing_object_name = ""]
|
693
|
+
# ?
|
694
|
+
#
|
695
|
+
# ====Returns:
|
696
|
+
#
|
697
|
+
#
|
441
698
|
def load(reader, containing_object_name = "")
|
442
699
|
param_hash = reader.read
|
443
700
|
|
@@ -478,12 +735,42 @@ class BaseConfig
|
|
478
735
|
load_impl(containing_object_hash, containing_object_name)
|
479
736
|
end
|
480
737
|
|
738
|
+
#
|
739
|
+
# ====Description:
|
740
|
+
#
|
741
|
+
#
|
742
|
+
# ====Parameters:
|
743
|
+
# [reader]
|
744
|
+
# ?
|
745
|
+
# [containing_object_name = ""]
|
746
|
+
# ?
|
747
|
+
#
|
748
|
+
# ====Returns:
|
749
|
+
#
|
750
|
+
#
|
481
751
|
def self.load(reader, containing_object_name = "")
|
482
752
|
instance = new()
|
483
753
|
instance.load(reader, containing_object_name)
|
484
754
|
return instance
|
485
755
|
end
|
486
756
|
|
757
|
+
#
|
758
|
+
# ====Description:
|
759
|
+
#
|
760
|
+
#
|
761
|
+
# ====Parameters:
|
762
|
+
# [str]
|
763
|
+
# ?
|
764
|
+
# [indent]
|
765
|
+
# ?
|
766
|
+
# [value_class]
|
767
|
+
# ?
|
768
|
+
# [value]
|
769
|
+
# ?
|
770
|
+
#
|
771
|
+
# ====Returns:
|
772
|
+
#
|
773
|
+
#
|
487
774
|
def write_value_impl(str, indent, value_class, value)
|
488
775
|
nesting_indent = indent + NESTING_INDENT
|
489
776
|
if(value != nil)
|
@@ -522,6 +809,19 @@ class BaseConfig
|
|
522
809
|
end
|
523
810
|
private :write_value_impl
|
524
811
|
|
812
|
+
#
|
813
|
+
# ====Description:
|
814
|
+
#
|
815
|
+
#
|
816
|
+
# ====Parameters:
|
817
|
+
# [str]
|
818
|
+
# ?
|
819
|
+
# [indent]
|
820
|
+
# ?
|
821
|
+
#
|
822
|
+
# ====Returns:
|
823
|
+
#
|
824
|
+
#
|
525
825
|
def write_impl(str, indent)
|
526
826
|
self.class.param_spec_list.each do |param_spec|
|
527
827
|
name_field_length = self.class.longest_param_name_length
|
@@ -533,6 +833,13 @@ class BaseConfig
|
|
533
833
|
end
|
534
834
|
protected :write_impl
|
535
835
|
|
836
|
+
#
|
837
|
+
# ====Description:
|
838
|
+
#
|
839
|
+
#
|
840
|
+
# ====Returns:
|
841
|
+
#
|
842
|
+
#
|
536
843
|
def to_s
|
537
844
|
#
|
538
845
|
# Print out config file name and the containing object_name and then
|
@@ -2,13 +2,19 @@
|
|
2
2
|
module ConfigToolkit
|
3
3
|
|
4
4
|
#
|
5
|
-
# All exceptions thrown from the
|
6
|
-
# this one;
|
5
|
+
# All exceptions thrown from the ConfigToolkit descend from
|
6
|
+
# this one; while right now it is the only exception thrown
|
7
|
+
# from the ConfigToolkit, at some point, an exception class hierarchy
|
7
8
|
# rooted in this class might be developed.
|
8
9
|
#
|
9
10
|
class Error < RuntimeError; end
|
10
11
|
|
11
12
|
end
|
12
13
|
|
14
|
+
#
|
15
|
+
# Load up the files necessary to specify a config.
|
16
|
+
# Users will need to load explicitly whichever readers
|
17
|
+
# and writers they wish to use.
|
18
|
+
#
|
13
19
|
require 'configtoolkit/types'
|
14
20
|
require 'configtoolkit/baseconfig'
|
data/lib/configtoolkit/types.rb
CHANGED
@@ -3,27 +3,27 @@ module ConfigToolkit
|
|
3
3
|
|
4
4
|
#
|
5
5
|
# Since Ruby does not have a boolean type (TrueClass and FalseClass classes
|
6
|
-
# exist, but they descend from
|
7
|
-
# can be passed into the BaseConfig methods
|
8
|
-
# to indicate that the parameter is a boolean
|
9
|
-
# be FalseClass or TrueClass, however).
|
6
|
+
# for boolean values exist, but they descend from Object),
|
7
|
+
# define an empty marker class that can be passed into the BaseConfig methods
|
8
|
+
# to add new parameters in order to indicate that the parameter is a boolean
|
9
|
+
# (the value of the parameter will be FalseClass or TrueClass, however).
|
10
10
|
#
|
11
11
|
class Boolean; end
|
12
12
|
|
13
13
|
#
|
14
14
|
# The ConstrainedArray models an Array with a specified size
|
15
|
-
# and with all elements being a specified
|
16
|
-
# the arrays generally offerred by
|
15
|
+
# and with all elements being a specified class (basically, it models
|
16
|
+
# the arrays generally offerred by statically typed languages).
|
17
17
|
# A ConstrainedArray has:
|
18
|
-
# 1.) A minimum number of elements
|
19
|
-
# 2.) A maximum number of elements
|
20
|
-
# 3.) An element
|
18
|
+
# 1.) A minimum number of elements (could be zero)
|
19
|
+
# 2.) A maximum number of elements (could be infinity)
|
20
|
+
# 3.) An element class
|
21
21
|
#
|
22
22
|
# A future enhancement might be to allow users to specify a different
|
23
|
-
#
|
24
|
-
# elements to be instances of a child class of its element
|
25
|
-
# just instances of its element
|
26
|
-
#
|
23
|
+
# class for each element. Note that the ConstrainedArray also allows
|
24
|
+
# elements to be instances of a child class of its element class, not
|
25
|
+
# just instances of its element class. Thus, a ConstrainedArray containing
|
26
|
+
# class Object essentially would have no class constraints.
|
27
27
|
#
|
28
28
|
# class ConstrainedArray actually is a class generator, similar to Struct.
|
29
29
|
# Its new() method does *not* return a ConstrainedArray instance, but
|
@@ -31,7 +31,7 @@ class Boolean; end
|
|
31
31
|
# descends from ConstrainedArray. The class returned by new() is meant
|
32
32
|
# to be used in the BaseConfig methods to add new parameters. The
|
33
33
|
# value of one of these parameters actually will be a native Ruby
|
34
|
-
# Array,
|
34
|
+
# Array, but one that satisifes the constraints contained in
|
35
35
|
# the ConstrainedArray class.
|
36
36
|
#
|
37
37
|
class ConstrainedArray
|
@@ -45,6 +45,32 @@ class ConstrainedArray
|
|
45
45
|
attr_reader :max_num_elements
|
46
46
|
end
|
47
47
|
|
48
|
+
#
|
49
|
+
# ====Description:
|
50
|
+
# This method does *not* return a ConstrainedArray instance. Instead,
|
51
|
+
# it returns a new ConstrainedArray child class that represents
|
52
|
+
# an array with the constraints specified in the method arguments.
|
53
|
+
# This class can be passed as a parameter class into the BaseConfig methods
|
54
|
+
# to add parameters.
|
55
|
+
#
|
56
|
+
# ====Parameters:
|
57
|
+
# [element_class]
|
58
|
+
# This constrains all elements of the generated ConstrainedArray
|
59
|
+
# class to be of this class or one of its child classes.
|
60
|
+
# If this argument is object, then this constraint effectively
|
61
|
+
# disappears.
|
62
|
+
# [min_num_elements = nil]
|
63
|
+
# This constrains the generated ConstrainedArray class to have
|
64
|
+
# at least min_num_elements elements; if this argument is nil or zero,
|
65
|
+
# the constraint effectively disappears.
|
66
|
+
# [max_num_elements = nil]
|
67
|
+
# This constrains the generated ConstrainedArray class to have
|
68
|
+
# at most max_num_elements elements; if this argument is nil,
|
69
|
+
# the constraint effectively disappears.
|
70
|
+
#
|
71
|
+
# ====Returns:
|
72
|
+
# A ConstrainedArray child class with the specified constraints.
|
73
|
+
#
|
48
74
|
def self.new(element_class, min_num_elements = nil, max_num_elements = nil)
|
49
75
|
return Class.new(ConstrainedArray) do
|
50
76
|
@element_class = element_class
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configtoolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DesigningPatterns
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-05-
|
12
|
+
date: 2008-05-14 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|