params 0.0.9 → 1.0.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.
data/lib/params.rb CHANGED
@@ -7,10 +7,12 @@
7
7
  #
8
8
  # Examples of definitions:
9
9
  # Params.string('parameter_str', 'this is a string' ,'description_for_string')
10
+ # Params.path('parameter_path', '/Users/username/example/ect' ,'description_for_directory')
10
11
  # Params.integer('parameter_int',1 , 'description_for_integer')
11
12
  # Params.float('parameter_float',2.6 , 'description_for_float')
12
13
  # Params.boolean('parameter_true', true, 'description_for_true')
13
14
  # Params.boolean('parameter_false',false , 'description_for_false')
15
+ # Params.complex('parameter_complex', [a,b,{b=>c}], 'description for dict or list of strings.')
14
16
  # Note. Parameters have to be defined before they are accessed.
15
17
  #
16
18
  # Examples of usages (get\set access is through the [] operator).
@@ -52,280 +54,363 @@
52
54
  # More examples in bbfs/examples/params/rb
53
55
 
54
56
  require 'optparse'
57
+ require 'stringio'
55
58
  require 'yaml'
56
59
 
57
- module BBFS
58
- module Params
59
-
60
- @init_debug_messages = []
61
- @help_messages = []
62
-
63
- def Params.get_init_messages
64
- return @init_debug_messages
65
- end
66
-
67
- # Represents a parameter.
68
- class Param
69
- attr_accessor :name
70
- attr_accessor :value
71
- attr_accessor :desc
72
- attr_accessor :type
73
-
74
- # value_type_check method:
75
- # 1. Check if member:'type' is one of:Integer, Float, String or Boolean.
76
- # 2. input parameter:'value' class type is valid to override this parameter.
77
- # 3. Return value. The value to override with correct type. A cast from integer to Float will
78
- # be made for Float parameters which are set with integer values.
79
- # 4. Check will be skipped for nil value.
80
- def value_type_check(value)
81
- if value.nil?
82
- return value
83
- end
60
+ module Params
61
+
62
+ @init_debug_messages = []
63
+ @show_help_and_exit = false
64
+
65
+ def Params.get_init_messages
66
+ return @init_debug_messages
67
+ end
68
+
69
+ # Represents a parameter.
70
+ class Param
71
+ attr_accessor :name
72
+ attr_accessor :value
73
+ attr_accessor :desc
74
+ attr_accessor :type
75
+
76
+ # value_type_check method:
77
+ # 1. Check if member:'type' is one of:Integer, Float, String or Boolean.
78
+ # 2. input parameter:'value' class type is valid to override this parameter.
79
+ # 3. Return value. The value to override with correct type. A cast from integer to Float will
80
+ # be made for Float parameters which are set with integer values.
81
+ # 4. Check will be skipped for nil value.
82
+ def value_type_check(value)
83
+ if value.nil?
84
+ return value
85
+ end
84
86
 
85
- case( @type )
86
- when 'Integer' then
87
- if not @value.nil?
88
- if not ((value.class.eql? Integer) or
89
- (value.class.eql? Fixnum))
90
- raise "Parameter:'#{@name}' type:'Integer' but value type to override " \
87
+ case( @type )
88
+ when 'Integer' then
89
+ if not @value.nil?
90
+ if not ((value.class.eql? Integer) or
91
+ (value.class.eql? Fixnum))
92
+ raise "Parameter:'#{@name}' type:'Integer' but value type to override " \
91
93
  "is:'#{value.class}'."
92
- end
93
94
  end
94
- when 'Float' then
95
- if not @value.nil?
96
- if not value.class.eql? Float
97
- if not ((value.class.eql? Integer) or
98
- (value.class.eql? Fixnum))
99
- raise("Parameter:'#{@name}' type:'Float' but value type to override " \
95
+ end
96
+ when 'Float' then
97
+ if not @value.nil?
98
+ if not value.class.eql? Float
99
+ if not ((value.class.eql? Integer) or
100
+ (value.class.eql? Fixnum))
101
+ raise("Parameter:'#{@name}' type:'Float' but value type to override " \
100
102
  "is:'#{value.class}'.")
101
- else
102
- return value.to_f
103
- end
103
+ else
104
+ return value.to_f
104
105
  end
105
106
  end
106
- when 'String' then
107
- if not @value.nil?
108
- if not value.class.eql? String
109
- raise("Parameter:'#{@name}' type:'String' but value type to override " \
107
+ end
108
+ when 'String' then
109
+ when 'Path' then
110
+ # TODO(kolman): Override the type check with regexp of path in Linux and/or Windows
111
+ if not @value.nil?
112
+ if not value.class.eql? String
113
+ raise("Parameter:'#{@name}' type:'String' but value type to override " \
110
114
  "is:'#{value.class}'.")
111
- end
112
115
  end
113
- when 'Boolean' then
114
- if not @value.nil?
115
- if not((value.class.eql? TrueClass) or (value.class.eql? FalseClass))
116
- raise("Parameter:'#{@name}' type:'Boolean' but value type to override " \
116
+ end
117
+ when 'Boolean' then
118
+ if not @value.nil?
119
+ if not((value.class.eql? TrueClass) or (value.class.eql? FalseClass))
120
+ raise("Parameter:'#{@name}' type:'Boolean' but value type to override " \
117
121
  "is:'#{value.class}'.")
118
- end
119
122
  end
120
- else
121
- raise("Parameter:'#{@name}' type:'#{@value.class}' but parameter " \
123
+ end
124
+ when 'Complex' then
125
+ unless @value.nil?
126
+ unless (value.class.eql? Hash) or (value.class.eql? Array)
127
+ raise("Parameter:'#{@name}' type:'Complex' but value type to override " \
128
+ "is:'#{value.class}'.")
129
+ end
130
+ end
131
+ else
132
+ raise("Parameter:'#{@name}' type:'#{@value.class}' but parameter " \
122
133
  "type to override:'#{value.class}' is not supported. " + \
123
134
  "Supported types are:Integer, Float, String or Boolean.")
124
- end
125
- return value
126
- end
127
-
128
- # supported types are: String, Integer, Float and Boolean
129
- def initialize(name, value, type, desc)
130
- @name = name
131
- @type = type
132
- @desc = desc
133
- @value = value_type_check value
134
135
  end
136
+ return value
135
137
  end
136
138
 
137
- # The globals data structure.
138
- @globals_db = Hash.new
139
-
140
- def Params.raise_error_if_param_does_not_exist(name)
141
- if not @globals_db[name]
142
- raise("before using parameter:'#{name}', it should first be defined through Param module methods:" \
143
- "Params.string, Params.integer, Params.float or Params.boolean.")
144
- end
139
+ # supported types are: String, Integer, Float, Boolean, Path or Complex
140
+ def initialize(name, value, type, desc)
141
+ @name = name
142
+ @type = type
143
+ @desc = desc
144
+ @value = value_type_check value
145
145
  end
146
+ end
146
147
 
147
- def Params.raise_error_if_param_exists(name)
148
- if @globals_db[name]
149
- raise("Parameter:'#{name}', can only be defined once.")
150
- end
151
- end
148
+ # The globals data structure.
149
+ @globals_db = Hash.new
152
150
 
153
- # Read global param value by other modules.
154
- # Note that this operator should only be used, after parameter has been defined through
155
- # one of Param module methods: Params.string, Params.integer,
156
- # Params.float or Params.boolean."
157
- def Params.[](name)
158
- raise_error_if_param_does_not_exist(name)
159
- @globals_db[name].value
151
+ def Params.raise_error_if_param_does_not_exist(name)
152
+ if not @globals_db[name]
153
+ raise("before using parameter:'#{name}', it should first be defined through Param module methods:" \
154
+ "Params.string, Params.path, Params.integer, Params.float or Params.boolean.")
160
155
  end
156
+ end
161
157
 
162
- # Write global param value by other modules.
163
- # Note that this operator should only be used, after parameter has been defined through
164
- # one of Param module methods: Params.string, Params.integer,
165
- # Params.float or Params.boolean."
166
- def Params.[]=(name, value)
167
- raise_error_if_param_does_not_exist(name)
168
- set_value = @globals_db[name].value_type_check(value)
169
- @globals_db[name].value = set_value
158
+ def Params.raise_error_if_param_exists(name)
159
+ if @globals_db[name]
160
+ raise("Parameter:'#{name}', can only be defined once.")
170
161
  end
171
-
172
- #override parameter should only be called by Params module methods.
173
- def Params.override_param(name, value)
174
- existing_param = @globals_db[name]
175
- if existing_param.nil?
176
- raise("Parameter:'#{name}' has not been defined and can not be overridden. " \
162
+ end
163
+
164
+ # Read global param value by other modules.
165
+ # Note that this operator should only be used, after parameter has been defined through
166
+ # one of Param module methods: Params.string, Params.integer,
167
+ # Params.float or Params.boolean."
168
+ def Params.[](name)
169
+ raise_error_if_param_does_not_exist(name)
170
+ @globals_db[name].value
171
+ end
172
+
173
+ def Params.each(&block)
174
+ @globals_db.each(&block)
175
+ end
176
+
177
+ # Write global param value by other modules.
178
+ # Note that this operator should only be used, after parameter has been defined through
179
+ # one of Param module methods: Params.string, Params.integer,
180
+ # Params.float or Params.boolean."
181
+ def Params.[]=(name, value)
182
+ raise_error_if_param_does_not_exist(name)
183
+ set_value = @globals_db[name].value_type_check(value)
184
+ @globals_db[name].value = set_value
185
+ end
186
+
187
+ #override parameter should only be called by Params module methods.
188
+ def Params.override_param(name, value)
189
+ existing_param = @globals_db[name]
190
+ if existing_param.nil?
191
+ raise("Parameter:'#{name}' has not been defined and can not be overridden. " \
177
192
  "It should first be defined through Param module methods:" \
178
- "Params.string, Params.integer, Params.float or Params.boolean.")
179
- end
180
- if value.nil?
181
- existing_param.value = nil
182
- elsif existing_param.type.eql?('String')
183
- existing_param.value = value.to_s
193
+ "Params.string, Params.path, Params.integer, Params.float or Params.boolean.")
194
+ end
195
+ if value.nil?
196
+ existing_param.value = nil
197
+ elsif existing_param.type.eql?('String')
198
+ existing_param.value = value.to_s
199
+ elsif existing_param.type.eql?('Path')
200
+ existing_param.value = File.expand_path(value.to_s)
201
+ elsif existing_param.type.eql?('Complex')
202
+ if value.class.eql?(Hash) || value.class.eql?(Array)
203
+ existing_param.value = value
184
204
  else
185
- set_value = existing_param.value_type_check(value)
186
- existing_param.value = set_value
205
+ existing_param.value = YAML::load(StringIO.new(value.to_s))
187
206
  end
207
+ else
208
+ set_value = existing_param.value_type_check(value)
209
+ existing_param.value = set_value
188
210
  end
189
-
190
- # Define new global parameter of type Integer.
191
- def Params.integer(name, value, description)
192
- raise_error_if_param_exists(name)
193
- @globals_db[name] = Param.new(name, value, 'Integer', description)
194
- end
195
-
196
- # Define new global parameter of type Float.
197
- def Params.float(name, value, description)
198
- raise_error_if_param_exists(name)
199
- @globals_db[name] = Param.new(name, value, 'Float', description)
200
- end
201
-
202
- # Define new global parameter of type String.
203
- def Params.string(name, value, description)
204
- raise_error_if_param_exists(name)
205
- @globals_db[name] = Param.new(name, value, 'String', description)
206
- end
207
-
208
- # Define new global parameter of type Boolean.
209
- def Params.boolean(name, value, description)
210
- raise_error_if_param_exists(name)
211
- @globals_db[name] = Param.new(name, value, 'Boolean', description)
211
+ end
212
+
213
+ # Define new global parameter of type Integer.
214
+ def Params.integer(name, value, description)
215
+ raise_error_if_param_exists(name)
216
+ @globals_db[name] = Param.new(name, value, 'Integer', description)
217
+ end
218
+
219
+ # Define new global parameter of type Float.
220
+ def Params.float(name, value, description)
221
+ raise_error_if_param_exists(name)
222
+ @globals_db[name] = Param.new(name, value, 'Float', description)
223
+ end
224
+
225
+ # Define new global parameter of type String.
226
+ def Params.string(name, value, description)
227
+ raise_error_if_param_exists(name)
228
+ @globals_db[name] = Param.new(name, value, 'String', description)
229
+ end
230
+
231
+ # Define new global parameter of type path (the only difference with string is that the path expends '~' to
232
+ # full user directory).
233
+ def Params.path(name, value, description)
234
+ raise_error_if_param_exists(name)
235
+ @globals_db[name] = Param.new(name, File.expand_path(value), 'Path', description)
236
+ end
237
+
238
+ def Params.complex(name, value, description)
239
+ raise_error_if_param_exists(name)
240
+ @globals_db[name] = Param.new(name, value, 'Complex', description)
241
+ end
242
+
243
+ # Define new global parameter of type Boolean.
244
+ def Params.boolean(name, value, description)
245
+ raise_error_if_param_exists(name)
246
+ @globals_db[name] = Param.new(name, value, 'Boolean', description)
247
+ end
248
+
249
+ # Initializes the project parameters.
250
+ # Precedence is: Defined params, file and command line is highest.
251
+ def Params.init(args)
252
+ @init_debug_messages = []
253
+ results = parse_command_line_arguments(args)
254
+ if not results['conf_file'].nil?
255
+ Params['conf_file'] = File.expand_path(results['conf_file'])
212
256
  end
213
257
 
214
- # Initializes the project parameters.
215
- # Precedence is: Defined params, file and command line is highest.
216
- def Params.init(args)
217
- @init_debug_messages = []
218
- results = parse_command_line_arguments(args)
219
- if not results['conf_file'].nil?
220
- Params['conf_file'] = File.expand_path(results['conf_file'])
221
- end
222
-
223
- #load yml params if path is provided and exists
224
- if Params['conf_file'].nil?
225
- @init_debug_messages << 'Configuration file was not provided.' + \
258
+ #load yml params if path is provided and exists
259
+ if Params['conf_file'].nil?
260
+ @init_debug_messages << 'Configuration file was not provided.' + \
226
261
  'Skipping loading file parameters.'
262
+ else
263
+ if File.exist?(Params['conf_file'])
264
+ @init_debug_messages << "Loading parameters from configuration file:'#{Params['conf_file']}'"
265
+ if not read_yml_params(File.open(Params['conf_file'], 'r'))
266
+ @init_debug_messages << "Bad configuration file #{Params['conf_file']}."
267
+ end
227
268
  else
228
- if File.exist?(Params['conf_file'])
229
- @init_debug_messages << "Loading parameters from configuration file:'#{Params['conf_file']}'"
230
- read_yml_params(File.open(Params['conf_file'], 'r'))
231
- else
232
- @init_debug_messages << "Configuration file path:'#{Params['conf_file']}' does not exist. " + \
269
+ @init_debug_messages << "Configuration file path:'#{Params['conf_file']}' does not exist. " + \
233
270
  "Skipping loading file parameters."
234
- end
235
- end
236
-
237
- #override command line argument
238
- results.keys.each do |result_name|
239
- override_param(result_name, results[result_name])
240
271
  end
272
+ end
241
273
 
242
- print_global_parameters
243
-
244
- # Prints help and parameters if needed.
245
- puts @help_messages unless @help_messages.empty?
246
- puts @init_debug_messages if Params['print_params_to_stdout']
247
- exit unless @help_messages.empty?
274
+ #override command line argument
275
+ results.keys.each do |result_name|
276
+ override_param(result_name, results[result_name])
248
277
  end
249
278
 
250
- # Load yml params and override default values.
251
- # raise exception if a loaded yml param does not exist. or if types mismatch occurs.
252
- def Params.read_yml_params(yml_input_io)
253
- proj_params = YAML::load(yml_input_io)
254
- proj_params.keys.each do |param_name|
255
- override_param(param_name, proj_params[param_name])
279
+ print_global_parameters
280
+
281
+ # Prints help and parameters if needed.
282
+ if @show_help_and_exit
283
+ # Print parameters + description and exit.
284
+ puts "Full list of parameters:"
285
+ Params.each do |name, param|
286
+ puts "--#{name}, #{param.type}, default:#{param.value}\n\t#{param.desc}"
256
287
  end
288
+ exit
257
289
  end
258
-
259
- # Parse command line arguments
260
- def Params.parse_command_line_arguments(args)
261
- results = Hash.new # Hash to store parsing results.
262
- options = Hash.new # Hash of parsing options from Params.
263
-
264
- # Define options switch for parsing
265
- # Define List of options see example on
266
- # http://ruby.about.com/od/advancedruby/a/optionparser2.htm
267
- opts = OptionParser.new do |opts|
268
- @globals_db.values.each do |param|
269
- tmp_name_long = "--" + param.name + "=MANDATORY" # Define a command with single mandatory parameter
270
- tmp_value = "Default value:" + param.value.to_s # Description and Default value
271
-
272
- # Define type of the mandatory value
273
- # It can be integer, float or String(for all other types).
274
- case( param.type )
275
- when 'Integer' then value_type = Integer
276
- when 'Float' then value_type = Float
277
- else value_type = String
278
- end
279
- # Switches definition - according to what
280
- # was pre-defined in the Params
281
- opts.on(tmp_name_long, value_type, tmp_value) do |result|
282
- if result.to_s.upcase.eql? 'TRUE'
283
- results[param.name] = true
284
- elsif result.to_s.upcase.eql? 'FALSE'
285
- results[param.name] = false
286
- else
287
- results[param.name] = result
288
- end
289
- end
290
+ puts @init_debug_messages if Params['print_params_to_stdout']
291
+ end
292
+
293
+ # Load yml params and override default values.
294
+ # raise exception if a loaded yml param does not exist. or if types mismatch occurs.
295
+ def Params.read_yml_params(yml_input_io)
296
+ proj_params = YAML::load(yml_input_io)
297
+ return false unless proj_params.is_a?(Hash)
298
+ proj_params.keys.each do |param_name|
299
+ override_param(param_name, proj_params[param_name])
300
+ end
301
+ true
302
+ end
303
+
304
+ # Parse command line arguments
305
+ def Params.parse_command_line_arguments(args)
306
+ results = Hash.new # Hash to store parsing results.
307
+ options = Hash.new # Hash of parsing options from Params.
308
+
309
+ # Define options switch for parsing
310
+ # Define List of options see example on
311
+ # http://ruby.about.com/od/advancedruby/a/optionparser2.htm
312
+ opts = OptionParser.new do |opts|
313
+ @globals_db.values.each do |param|
314
+ tmp_name_long = "--#{param.name} #{param.name.upcase}" # Define a command with single mandatory parameter
315
+ tmp_value = param.desc + " Default value:" + param.value.to_s # Description and Default value
316
+
317
+ # Define type of the mandatory value
318
+ # It can be integer, float or String(for all other types).
319
+ case(param.type)
320
+ when 'Integer' then value_type = Integer
321
+ when 'Float' then value_type = Float
322
+ else value_type = String
290
323
  end
291
-
292
- # Define help command for available options
293
- # executing --help will printout all pre-defined switch options
294
- opts.on_tail("-h", "--help", "Show this message") do
295
- @help_messages << opts
324
+ # Switches definition - according to what
325
+ # was pre-defined in the Params
326
+ opts.on(tmp_name_long, value_type, tmp_value) do |result|
327
+ if result.to_s.upcase.eql? 'TRUE'
328
+ results[param.name] = true
329
+ elsif result.to_s.upcase.eql? 'FALSE'
330
+ results[param.name] = false
331
+ else
332
+ results[param.name] = result
333
+ end
296
334
  end
297
-
298
- opts.parse(args) # Parse command line
299
335
  end
300
- return results
301
- end # end of Parse function
302
-
303
- def Params.print_global_parameters
304
- @init_debug_messages << "\n"
305
- @init_debug_messages << 'Initialized global parameters:'
306
- @init_debug_messages << '---------------------------------'
307
- counter=0
308
- @globals_db.values.each do |param|
309
- counter += 1
310
- @init_debug_messages << "#{counter}: #{param.name}=#{param.value}"
336
+
337
+ # Define introduction text for help command
338
+ opts.banner =
339
+ "Usage: content_serve [options] or \n" +
340
+ " : backup_server [options] \n\n" +
341
+ "Description: This application for backuping files and folders\n" +
342
+ "There is two application: \n" +
343
+ "backup_server is server run on machine where files is backuped,\n" +
344
+ "content_server is application that run on machine from where files is copied.\n\n" +
345
+ "Before run applications:" +
346
+ "Before running backup_server and content server you need to prepare two configuration files\n" +
347
+ "Create configuration file for content server which should be located at ~/.bbfs/etc/file_monitoring.yml\n" +
348
+ "the content of the file is:
349
+ ------- begin of file_monitoring.yml --------
350
+ paths:
351
+ - path: ~/.bbfs/test_files # <=== replace with your local dir.
352
+ scan_period: 1
353
+ stable_state: 5
354
+ ------- end of file_monitoring.yml --------\n" +
355
+ "Create configuration file for backup server which should be located at \n" +
356
+ "~/.bbfs/etc/backup_file_monitoring.yml\n" +
357
+ "File content:
358
+ ------- begin of backup_file_monitoring.yml --------
359
+ paths:
360
+ - path: ~/.bbfs/backup_data # <=== replace with your local dir.
361
+ scan_period: 1
362
+ stable_state: 5
363
+ ------- end of backup_file_monitoring.yml --------\n\n" +
364
+ "Explanation about file_monitoring.yml and backup_file_monitoring.yml configuration files:
365
+
366
+ \"path:\" - say to program which folder to scan recursively in order to find new/changed files and folders.
367
+ \"scan_period:\" - how much time in seconds passed before two consecutive scans for files and directories.
368
+ \"stable_state:\" - how many scan_period passed until the file is considered stable.\n\n" +
369
+ "List of options:"
370
+
371
+
372
+ # Define help command for available options
373
+ # executing --help will printout all pre-defined switch options
374
+ opts.on_tail("-h", "--help", "Show this message") do
375
+ @show_help_and_exit = true
311
376
  end
312
- @init_debug_messages << '---------------------------------'
313
- end
314
377
 
315
- #Auxiliary method to retrieve the executable name
316
- def Params.executable_name
317
- /([a-zA-Z0-9\-_\.]+):\d+/ =~ caller[caller.size-1]
318
- return $1
378
+ opts.parse(args) # Parse command line
319
379
  end
320
- #define default params:
321
- # 1. configuration file
322
- Params.string('conf_file', nil, 'Configuration file path.')
323
- # 2. Print params to stdout
324
- Params.boolean('print_params_to_stdout', false, 'print_params_to_stdout or not during Params.init')
325
-
326
- private_class_method :print_global_parameters, :parse_command_line_arguments, \
327
- :raise_error_if_param_exists, :raise_error_if_param_does_not_exist, \
328
- :read_yml_params, :override_param, :executable_name
380
+ return results
381
+ end # end of Parse function
382
+
383
+ def Params.print_global_parameters
384
+ @init_debug_messages << "\n"
385
+ @init_debug_messages << 'Initialized global parameters:'
386
+ @init_debug_messages << '---------------------------------'
387
+ counter=0
388
+ @globals_db.values.each do |param|
389
+ counter += 1
390
+ @init_debug_messages << "#{counter}: #{param.name}=#{param.value}"
329
391
  end
392
+ @init_debug_messages << '---------------------------------'
393
+ end
394
+
395
+ def Params.to_simple_hash
396
+ @globals_db.map { |param|
397
+ param.value
398
+ }
399
+ end
400
+
401
+ #Auxiliary method to retrieve the executable name
402
+ def Params.executable_name
403
+ /([a-zA-Z0-9\-_\.]+):\d+/ =~ caller[caller.size-1]
404
+ return $1
405
+ end
406
+ #define default params:
407
+ # 1. configuration file
408
+ Params.string('conf_file', nil, 'Configuration file path.')
409
+ # 2. Print params to stdout
410
+ Params.boolean('print_params_to_stdout', false, 'print_params_to_stdout or not during Params.init')
411
+
412
+ private_class_method :print_global_parameters, :parse_command_line_arguments, \
413
+ :raise_error_if_param_exists, :raise_error_if_param_does_not_exist, \
414
+ :read_yml_params, :override_param, :executable_name
330
415
  end
331
416