configural 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.
@@ -0,0 +1,41 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Configural - Easy configuration file management
6
+ #
7
+ # Copyright (c) 2011 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module Configural
32
+
33
+ autoload :App, 'configural/app'
34
+ autoload :User, 'configural/user'
35
+ autoload :Config, 'configural/config'
36
+ autoload :Data, 'configural/data'
37
+ autoload :Cache, 'configural/data'
38
+ autoload :Platform, 'configural/platform'
39
+ autoload :Autosave, 'configural/autosave'
40
+
41
+ end
@@ -0,0 +1,97 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Configural - Easy configuration file management
6
+ #
7
+ # Copyright (c) 2011 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module Configural
32
+
33
+ class App
34
+ attr_accessor :name, :path
35
+ attr_writer :config_path, :cache_path, :data_path
36
+ attr_reader :user
37
+
38
+ def initialize( name )
39
+ @name = name
40
+ @user = Configural::User.new(self)
41
+ end
42
+
43
+
44
+ def cache
45
+ @cache ||=
46
+ begin
47
+ unless @cache_path
48
+ raise 'you must set cache_path or path first'
49
+ end
50
+ Configural::Cache.new(self)
51
+ end
52
+ end
53
+
54
+ def cache_path
55
+ @cache_path || (@path and File.join(@path, 'cache'))
56
+ end
57
+
58
+
59
+ def config
60
+ @config ||=
61
+ begin
62
+ unless @config_path
63
+ raise 'you must set config_path or path first'
64
+ end
65
+ Configural::Config.new(self)
66
+ end
67
+ end
68
+
69
+ def config_path
70
+ @config_path || (@path and File.join(@path, 'config'))
71
+ end
72
+
73
+
74
+ def data
75
+ @data ||=
76
+ begin
77
+ unless @data_path
78
+ raise 'you must set data_path or path first'
79
+ end
80
+ Configural::Data.new(self)
81
+ end
82
+ end
83
+
84
+ def data_path
85
+ @data_path || (@path and File.join(@path, 'data'))
86
+ end
87
+
88
+
89
+ def save_all
90
+ @config.save_all if @config
91
+ @user.save_all if @user
92
+ self
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,100 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Configural - Easy configuration file management
6
+ #
7
+ # Copyright (c) 2011 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module Configural
32
+
33
+ class Autosave
34
+
35
+ def self.instance
36
+ @instance ||= new()
37
+ end
38
+
39
+ # Shorthand for Autosave.instance.register
40
+ def self.register(*args)
41
+ instance.register(*args)
42
+ end
43
+
44
+ # Shorthand for Autosave.instance.unregister
45
+ def self.unregister(*args)
46
+ instance.unregister(*args)
47
+ end
48
+
49
+
50
+ def initialize
51
+ @weakrefs = {}
52
+ @enabled = true
53
+ at_exit{ self.save_all }
54
+ end
55
+
56
+
57
+ def register(object, method=:save)
58
+ require 'weakref'
59
+ weakref = WeakRef.new(object)
60
+ @weakrefs[weakref] = method
61
+ self
62
+ end
63
+
64
+ def unregister(object)
65
+ @weakrefs.delete_if{ |k,v| k.__id__ == object.object_id }
66
+ self
67
+ end
68
+
69
+ def unregister_all
70
+ @weakrefs = {}
71
+ self
72
+ end
73
+
74
+
75
+ attr_reader :enabled
76
+ alias :enabled? :enabled
77
+
78
+ def enable
79
+ @enabled = true
80
+ self
81
+ end
82
+
83
+ def disable
84
+ @enabled = false
85
+ self
86
+ end
87
+
88
+
89
+ def save_all
90
+ return self unless @enabled
91
+ @weakrefs.each do |weakref, method|
92
+ if weakref.weakref_alive? and weakref.respond_to?(method)
93
+ weakref.send(method)
94
+ end
95
+ end
96
+ self
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,93 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Configural - Easy configuration file management
6
+ #
7
+ # Copyright (c) 2011 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module Configural
32
+
33
+ class Config
34
+
35
+ attr_accessor :owner, :options
36
+
37
+ def initialize( owner )
38
+ @owner = owner
39
+ @files = {}
40
+ @options = {
41
+ :default_format => 'yaml',
42
+ :lazy_loading => false,
43
+ }
44
+ end
45
+
46
+ def path
47
+ @owner.config_path
48
+ end
49
+
50
+ def [](name)
51
+ @files[name.to_s] ||= make_file(name.to_s)
52
+ end
53
+
54
+ def []=(name, value)
55
+ @files[name.to_s] = value
56
+ end
57
+
58
+ def save_all
59
+ @files.each_value{ |file| file.save }
60
+ self
61
+ end
62
+
63
+ private
64
+
65
+ def make_file(name)
66
+ if File.extname(name).empty?
67
+ # No file extension, so use the default format.
68
+ format = FileBase.get_format_by_name(@options[:default_format])
69
+ # Check all possible extensions, choose the first file that
70
+ # exists, or use the first file extension if no files exist.
71
+ paths = format.extnames.collect{ |extname|
72
+ File.join( self.path, name ) + extname
73
+ }
74
+ path = paths.find{ |p| File.exists?(p) } || paths.first
75
+ else
76
+ # Has a file extension, so try to find a matching format.
77
+ format = FileBase.get_format_by_extname(File.extname(name))
78
+ # Just use the name with already-specified extension.
79
+ path = File.join(self.path, name)
80
+ end
81
+ format.new( path, @options )
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+
89
+ require 'configural/config/file_base'
90
+ require 'configural/config/json_file'
91
+ require 'configural/config/plist_file'
92
+ require 'configural/config/sdl_file'
93
+ require 'configural/config/yaml_file'
@@ -0,0 +1,161 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Configural - Easy configuration file management
6
+ #
7
+ # Copyright (c) 2011 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module Configural
32
+
33
+ # Base class for abstracting configuration file access. You
34
+ # shouldn't use this class directly. Use one of the subclasses (e.g.
35
+ # YAMLFile) instead.
36
+ #
37
+ class Config::FileBase
38
+
39
+ def self.inherited(subclass)
40
+ @subclasses ||= []
41
+ @subclasses << subclass
42
+ end
43
+
44
+
45
+ def self.get_format_by_name( format )
46
+ @subclasses.reverse.find { |subclass|
47
+ subclass.format == format
48
+ } or raise "Unrecognized file format: #{format}"
49
+ end
50
+
51
+ def self.get_format_by_extname( extname )
52
+ @subclasses.reverse.find { |subclass|
53
+ subclass.extnames.include?(extname)
54
+ } or raise "Unrecognized file extension: #{extname}"
55
+ end
56
+
57
+
58
+ def self.format
59
+ raise 'Method not implemented for base class.'
60
+ end
61
+
62
+ def self.extnames
63
+ raise 'Method not implemented for base class.'
64
+ end
65
+
66
+
67
+ require 'enumerator'
68
+ include Enumerable
69
+
70
+ attr_reader :path
71
+
72
+ def initialize( path, options )
73
+ @path = path
74
+ @options = options
75
+ @data = {}
76
+ @loaded = false
77
+ load unless @options[:lazy_loading]
78
+ end
79
+
80
+
81
+ def clear
82
+ @data = {}
83
+ @loaded = true
84
+ self
85
+ end
86
+
87
+ def close
88
+ @data = {}
89
+ @loaded = false
90
+ self
91
+ end
92
+
93
+ def delete
94
+ File.rm(path, :force => true)
95
+ self
96
+ end
97
+
98
+ def exists?
99
+ File.exists?(path)
100
+ end
101
+ alias :exist? :exists?
102
+
103
+ def each(&block)
104
+ load unless @loaded
105
+ @data.each(&block)
106
+ end
107
+
108
+ def keys
109
+ load unless @loaded
110
+ @data.keys
111
+ end
112
+
113
+ def [](key)
114
+ load unless @loaded
115
+ @data[key.to_s]
116
+ end
117
+
118
+ def []=(key, value)
119
+ load unless @loaded
120
+ @data[key.to_s] = value
121
+ end
122
+
123
+ def to_hash
124
+ load unless @loaded
125
+ @data.dup
126
+ end
127
+
128
+ def load
129
+ load! unless @loaded
130
+ self
131
+ end
132
+
133
+ def load!
134
+ _load
135
+ @loaded = true
136
+ self
137
+ end
138
+
139
+ def save
140
+ _save unless not @loaded
141
+ self
142
+ end
143
+
144
+ def save!
145
+ _save
146
+ self
147
+ end
148
+
149
+ private
150
+
151
+ def _load
152
+ raise 'Method not implemented for base class.'
153
+ end
154
+
155
+ def _save
156
+ raise 'Method not implemented for base class.'
157
+ end
158
+
159
+ end
160
+
161
+ end