configfiles 0.0.1

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.
Files changed (3) hide show
  1. data/configfiles-example.rb +86 -0
  2. data/lib/configfiles.rb +108 -0
  3. metadata +63 -0
@@ -0,0 +1,86 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+
3
+ require 'pp'
4
+ require 'ipaddr'
5
+ require 'configfiles'
6
+
7
+ class MyConfig < ConfigFiles::Base
8
+
9
+ class MyException < Exception; end
10
+ class MyArgumentError < ArgumentError; end
11
+
12
+ # I find more rubystic defining a "conversion"
13
+ # rater than statically declaring classes ;)
14
+ parameter :par_integer, :to_i
15
+ parameter :par_str # no conversion needed
16
+ parameter :par_custom do |s|
17
+ s.length
18
+ end
19
+
20
+ # receive an Enumerator from Parser, and turn into another Enumerator
21
+ #
22
+ # NOTE: Enumerable#map_enum would be cool ;-)
23
+ #
24
+ # TODO: use facets Enumerable#defer? Mmm, let's try to depend
25
+ # just on the std lib if possible...
26
+ #
27
+ enumerator :iplist do |ipstr|
28
+ IPAddr.new(ipstr)
29
+ end
30
+
31
+ validate do |data|
32
+ raise MyArgumentError if data[:par_custom] > 100
33
+ raise MyException unless data[:par_str] =~ /\S+/
34
+ # or you may use standard exceptions....
35
+ true
36
+ end
37
+
38
+ end
39
+
40
+ class MyKeyValueParser
41
+
42
+ include ConfigFiles::Parser
43
+
44
+ def self.read(io, opt_h={})
45
+ h = {}
46
+ io.each_line do |line|
47
+ key_re = '[\w\d_\-\.]+'
48
+ value_re = '[\w\d_\-\.]+'
49
+ if line =~ /(#{key_re})\s*=\s*(#{value_re})/
50
+ h[$1.to_sym] = $2
51
+ end
52
+ end
53
+ return h
54
+ end
55
+ end
56
+
57
+
58
+ class MyListSlurper
59
+
60
+ include ConfigFiles::Parser
61
+
62
+ def self.read(io, opt_h={})
63
+ if block_given?
64
+ io.each_line do |line|
65
+ yield line.strip if line =~ /\S/
66
+ end
67
+ else
68
+ enum_for :read, io
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+
75
+
76
+ c = MyConfig.new
77
+
78
+ parse_result = MyKeyValueParser.read(File.open 'keyval.conf')
79
+
80
+ c.load parse_result
81
+
82
+ pp c
83
+
84
+
85
+
86
+
@@ -0,0 +1,108 @@
1
+ # Copyright 2010, Guido De Rosa <guido.derosa*vemarsas.it>
2
+ # License: same of Ruby
3
+
4
+
5
+
6
+ module ConfigFiles
7
+
8
+ VERSION = 0.0.1
9
+
10
+ module Parser
11
+ def self.read_file(path)
12
+ self.read File.open path
13
+ end
14
+ end
15
+
16
+ class Base
17
+
18
+ class ArgumentError < ::ArgumentError; end
19
+ class RuntimeError < ::RuntimeError; end
20
+
21
+ @@parameters ||= {}
22
+ @@options ||= {}
23
+
24
+ # examples:
25
+ # on :unknown_parameter, :fail | :accept | :ignore
26
+ # on :unknown_parameter, {|str| str.to_i}
27
+ #
28
+ def self.on(name, value=nil, &block)
29
+ if block
30
+ @@options[name] = block
31
+ elsif name == :unknown_parameter and value == :accept
32
+ @@options[name] = lambda {|x| x}
33
+ else
34
+ @@options[name] = value
35
+ end
36
+ end
37
+
38
+ def self.option(name)
39
+ @@options[name]
40
+ end
41
+
42
+ def self.parameter(name, converter=nil, &converter_block)
43
+ if converter
44
+ if converter_block
45
+ raise ArgumentError, 'you must either specify a symbol or a block'
46
+ else
47
+ converter_block = lambda {|x| x.method(converter).call}
48
+ end
49
+ else
50
+ converter_block ||= lambda {|x| x}
51
+ end
52
+ @@parameters[name] = {
53
+ :converter => converter_block
54
+ }
55
+ end
56
+
57
+ # A special kind of parameter, with a special kind of converter, which in turn
58
+ # converts an Enumerator of Strings into an Enumerator of custom objects.
59
+ # Working with Enumerators instead of
60
+ # Arrays is the right thing to do when you deal with very long list of
61
+ # names, IP adresses, URIs etc.
62
+ def self.enumerator(name, &block)
63
+ parameter name do |enum|
64
+ Enumerator.new do |yielder|
65
+ enum.each do |string|
66
+ yielder << block.call(string)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def self.validate(&block)
73
+ @@validate = block
74
+ end
75
+
76
+ attr_accessor :options, :data
77
+
78
+ def initialize
79
+ @options = @@options.dup
80
+ @data = {}
81
+ def @data.missing_method(id); @data[id]; end
82
+ end
83
+
84
+ def validate
85
+ @@validate.call(@data)
86
+ end
87
+
88
+ def load(h)
89
+ h.each_pair do |id, value|
90
+ if @@parameters[id][:converter]
91
+ @data[id] = @@parameters[id][:converter].call(value)
92
+ elsif @options[:unknown_parameter] == :fail
93
+ raise RuntimeError, "unknown parameter #{key}" # otherwise ignore
94
+ elsif @options[:unknown_parameter].respond_to? :call
95
+ block = @options[:unknown_parameter]
96
+ @data[id] = block.call value
97
+ end
98
+ end
99
+ validate
100
+ end
101
+
102
+ def flush
103
+ @data = {}
104
+ end
105
+
106
+ end
107
+
108
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: configfiles
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Guido De Rosa
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-08-03 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: "A simple library to specify the format of configuration files and the way to turn them into Ruby objects. Ruby1.9 centric. It supports lazy lists. No write support: it's strongly sugested to use ERB or other templating systems for that."
22
+ email: guido.derosa@vemarsas.it
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - configfiles-example.rb
31
+ - lib/configfiles.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/gderosa/configfiles
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.3.6
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: A simple library to specify the format of configuration files and the way to turn them into Ruby objects.
62
+ test_files: []
63
+