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.
- data/configfiles-example.rb +86 -0
- data/lib/configfiles.rb +108 -0
- 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
|
+
|
data/lib/configfiles.rb
ADDED
@@ -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
|
+
|