evt-settings 0.2.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a822d919bc5c170700be5d1868528ce23963e9e
4
+ data.tar.gz: 76092c54a183f451291916f3463da61e3b43400f
5
+ SHA512:
6
+ metadata.gz: bdffc312827641c6cc382e7a04a4ec053fd844b3337bf3e8d4d428486c01d33c2e287e5e0169232aff7bf64e97895d803202cb2845ff199a287250c03a2f1c0e
7
+ data.tar.gz: ccafb6216d297b0898c11c572baf606e590d8a23c80b3c2cdbf08e833734ddc7eebbd6137ad45e8c7d349dc033cc9977c2094a1c76f214ca48342bfc719de791
@@ -0,0 +1,11 @@
1
+ class Settings
2
+ def self.activate(target_class=nil)
3
+ target_class ||= Object
4
+
5
+ macro_module = Settings::Setting::Macro
6
+
7
+ return if target_class.is_a? macro_module
8
+
9
+ target_class.extend(macro_module)
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ class Settings
2
+ class DataSource
3
+ module Build
4
+ def self.call(input=nil)
5
+ data_source_type = type(input)
6
+ data_source_type.build(input)
7
+ end
8
+ class << self; alias :! :call; end # TODO: Remove deprecated actuator [Kelsey, Thu Oct 08 2015]
9
+
10
+ def self.type(input=nil)
11
+ return Settings::DataSource::Hash if input.is_a?(::Hash)
12
+ return Settings::DataSource::File if input.is_a?(String) || input.nil?
13
+
14
+ raise Settings::Error, "Input is not supported: #{input}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ class Settings
2
+ class DataSource
3
+ include Log::Dependency
4
+
5
+ attr_reader :source
6
+
7
+ def initialize(source)
8
+ @source = source
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,119 @@
1
+ class Settings
2
+ class DataSource
3
+ class File < DataSource
4
+ def self.build(source=nil)
5
+ canonical = canonical(source)
6
+ validate(canonical)
7
+
8
+ new(canonical)
9
+ end
10
+
11
+ def self.canonical(source)
12
+ logger.trace { "Canonizing the file source (#{source})" }
13
+
14
+ canonize(source).tap do |instance|
15
+ logger.debug { "Canonized the file source (#{source})" }
16
+ end
17
+ end
18
+
19
+ def self.canonize(source)
20
+ return default_filepath if source.nil?
21
+ return source if full_path?(source)
22
+
23
+ dirpath = nil
24
+ filepath = nil
25
+
26
+ if file?(source)
27
+ dirpath = Pathname.new(Directory::Defaults.pathname)
28
+ else
29
+ filepath = Pathname.new(Defaults.filename)
30
+ end
31
+
32
+ dirpath ||= Pathname.new(source)
33
+ filepath ||= Pathname.new(source)
34
+
35
+ pathname(filepath, dirpath)
36
+ end
37
+
38
+ def self.default_filepath
39
+ dirpath = Pathname.new(Directory::Defaults.pathname)
40
+ filepath = Pathname.new(Defaults.filename)
41
+
42
+ pathname(filepath, dirpath)
43
+ end
44
+
45
+ def self.pathname(filepath, dirpath)
46
+ (dirpath + filepath).to_s
47
+ end
48
+
49
+ def self.full_path?(source)
50
+ file?(source) && dir?(source)
51
+ end
52
+
53
+ def self.file?(filepath)
54
+ ::File.extname(filepath) != ""
55
+ end
56
+
57
+ def self.dir?(dirpath)
58
+ ::File.dirname(dirpath) != "."
59
+ end
60
+
61
+ def self.validate(pathname)
62
+ logger.trace { "Validating the pathname (#{pathname})" }
63
+
64
+ pathname = Pathname.new(pathname)
65
+
66
+ unless pathname.file?
67
+ msg = "Settings cannot be read from #{pathname}. The file doesn't exist."
68
+ logger.error { msg }
69
+ raise Settings::Error, msg
70
+ end
71
+
72
+ logger.trace { "Validated the pathname (#{pathname})" }
73
+ end
74
+
75
+ def self.logger
76
+ @logger ||= Log.get(self)
77
+ end
78
+
79
+ def get_data
80
+ logger.trace { "Reading file: #{source}" }
81
+ file = ::File.open(source)
82
+ data = JSON.load(file).tap do
83
+ logger.debug { "Read file: #{source}" }
84
+ end
85
+
86
+ data = Casing::Underscore.(data)
87
+
88
+ hash_data_source = Hash.build data
89
+ hash_data_source.get_data
90
+ end
91
+
92
+ module Defaults
93
+ def self.logger
94
+ @logger ||= Log.get(self)
95
+ end
96
+
97
+ def self.filename
98
+ default_file = 'settings.json'
99
+ logger.debug { "Using the default settings file name (#{default_file})" }
100
+ default_file
101
+ end
102
+ end
103
+
104
+ module Directory
105
+ module Defaults
106
+ def self.logger
107
+ @logger ||= Log.get(self)
108
+ end
109
+
110
+ def self.pathname
111
+ default_dir = Dir.pwd
112
+ logger.debug { "Using the working directory default settings directory (#{default_dir})" }
113
+ default_dir
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,20 @@
1
+ class Settings
2
+ class DataSource
3
+ class Hash < DataSource
4
+ def self.logger
5
+ @logger ||= Log.get(self)
6
+ end
7
+
8
+ def self.build(source)
9
+ new(source)
10
+ end
11
+
12
+ def get_data
13
+ logger.trace { "Converting the raw source data to Confstruct" }
14
+ Confstruct::Configuration.new(source).tap do |instance|
15
+ logger.debug { "Converted the raw source data to Confstruct" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ class Settings
2
+ class Log < ::Log
3
+ def tag!(tags)
4
+ tags << :settings
5
+ tags << :library
6
+ tags << :verbose
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,38 @@
1
+ class Settings
2
+ class Registry
3
+ def data
4
+ @data ||= {}
5
+ end
6
+ attr_writer :data
7
+
8
+ def register(cls, attribute)
9
+ unless setting?(cls, attribute)
10
+ registered?(cls) ? @data[cls].push(attribute) : @data[cls] = [attribute]
11
+ end
12
+
13
+ data[cls]
14
+ end
15
+
16
+ def setting?(cls, attribute)
17
+ registered?(cls) ? data[cls].include?(attribute) : false
18
+ end
19
+
20
+ def registered?(cls)
21
+ !!data[cls]
22
+ end
23
+
24
+ class << self
25
+ def instance
26
+ @instance ||= new
27
+ end
28
+
29
+ def register(cls, attribute)
30
+ instance.register(cls, attribute)
31
+ end
32
+
33
+ def setting?(cls, attribute)
34
+ instance.setting?(cls, attribute)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,108 @@
1
+ class Settings
2
+ module Setting
3
+ module Assignment
4
+ extend self
5
+
6
+ def logger
7
+ @logger ||= Log.get(self)
8
+ end
9
+
10
+ def assign(receiver, attribute, value, strict=false)
11
+ settable = assure_settable(receiver, attribute, strict)
12
+ if settable
13
+ assign_value(receiver, attribute, value)
14
+ end
15
+
16
+ receiver
17
+ end
18
+
19
+ def assign_value(receiver, attribute, value)
20
+ logger.trace { "Assigning to #{attribute}" }
21
+ receiver.public_send("#{attribute}=", value).tap do
22
+ logger.debug { "Assigned to #{attribute}" }
23
+ logger.debug(tag: :data) { "#{attribute}: #{value}" }
24
+ end
25
+ end
26
+
27
+ def setting?(receiver, attribute)
28
+ receiver_class = receiver.class
29
+ Settings::Registry.instance.setting? receiver_class, attribute
30
+ end
31
+
32
+ def assignable?(receiver, attribute)
33
+ receiver.respond_to? setter_name(attribute)
34
+ end
35
+
36
+ def setter_name(attribute)
37
+ :"#{attribute.to_s}=" unless attribute.to_s.end_with? '='
38
+ end
39
+
40
+ def digest(receiver, attribute, strict)
41
+ content = []
42
+ content << "Attribute: #{attribute}" if attribute
43
+ content << "Receiver: #{receiver}"
44
+ strict = "<not set>" if strict.nil?
45
+ content << "Strict: #{strict}"
46
+ content.join ', '
47
+ end
48
+
49
+ module Object
50
+ extend Assignment
51
+
52
+ def logger
53
+ @logger ||= Log.get(self)
54
+ end
55
+
56
+ def self.assure_settable(receiver, attribute, strict=true)
57
+ logger.trace { "Approving attribute (#{digest(receiver, attribute, strict)})" }
58
+
59
+ if strict
60
+ setting = setting?(receiver, attribute)
61
+ unless setting
62
+ logger.warn { "Can't set \"#{attribute}\". It isn't a setting of #{receiver}." }
63
+ return false
64
+ end
65
+ end
66
+
67
+ assignable = assignable? receiver, attribute
68
+ unless assignable
69
+ logger.warn { "Can't set \"#{attribute}\". It isn't assignable to #{receiver}." }
70
+ return false
71
+ end
72
+
73
+ logger.debug { "\"#{attribute}\" can be set" }
74
+ true
75
+ end
76
+ end
77
+
78
+ module Attribute
79
+ extend Assignment
80
+
81
+ def logger
82
+ @logger ||= Log.get(self)
83
+ end
84
+
85
+ def self.assure_settable(receiver, attribute, strict=true)
86
+ if strict
87
+ setting = setting? receiver, attribute
88
+ unless setting
89
+ msg = "Can't set \"#{attribute}\". It isn't a setting of #{receiver}."
90
+ logger.error { msg }
91
+ raise msg
92
+ end
93
+ end
94
+
95
+ assignable = assignable? receiver, attribute
96
+ unless assignable
97
+ msg = "Can't set \"#{attribute}\". It isn't assignable to #{receiver}."
98
+ logger.error { msg }
99
+ raise msg
100
+ end
101
+
102
+ logger.debug { "\"#{attribute}\" can be set" }
103
+ true
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,16 @@
1
+ class Settings
2
+ module Setting
3
+ module Macro
4
+ def setting_macro(attribute)
5
+ logger = Log.get(self)
6
+
7
+ logger.trace { "Defining setting attribute: #{attribute}" }
8
+ Attribute::Define.(self, attribute, :accessor)
9
+ Settings::Registry.register(self, attribute).tap do
10
+ logger.debug { "Defined setting attribute: #{attribute}" }
11
+ end
12
+ end
13
+ alias :setting :setting_macro
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,143 @@
1
+ class Settings
2
+ class Error < RuntimeError; end
3
+
4
+ include Log::Dependency
5
+
6
+ attr_reader :data
7
+ attr_reader :pathname
8
+
9
+ def initialize(data, pathname=nil)
10
+ @data = data
11
+ @pathname = pathname
12
+ end
13
+
14
+ def self.logger
15
+ @logger ||= Log.get(self)
16
+ end
17
+
18
+ def self.build(source=nil)
19
+ source ||= implementer_source
20
+
21
+ data_source = DataSource::Build.(source)
22
+
23
+ data = data_source.get_data
24
+
25
+ instance = new data
26
+
27
+ instance
28
+ end
29
+
30
+ def self.implementer_source
31
+ logger.trace { "Getting data source from the implementer" }
32
+
33
+ unless self.respond_to? :data_source
34
+ logger.trace { "Implementer doesn't provide a data_source" }
35
+ return nil
36
+ end
37
+
38
+ self.data_source.tap do |data_source|
39
+ logger.trace { "Got data source from the implementer (#{data_source})" }
40
+ end
41
+ end
42
+
43
+ def override(override_data)
44
+ logger.trace { "Overriding settings data" }
45
+ res = data.push!(override_data)
46
+ logger.debug { "Overrode settings data" }
47
+ logger.debug(tag: :data) { "Override data #{override_data}" }
48
+ res
49
+ end
50
+
51
+ def reset
52
+ logger.trace { "Resetting overridden settings data" }
53
+ res = data.pop!
54
+ logger.debug { "Reset overridden settings data" }
55
+ res
56
+ end
57
+
58
+ def set(receiver, *namespace, attribute: nil, strict: true)
59
+ logger.trace { "Setting #{receiver} (#{digest(namespace, attribute, strict)})" }
60
+ unless attribute.nil?
61
+ value = set_attribute(receiver, attribute, namespace, strict)
62
+ else
63
+ receiver = set_object(receiver, namespace, strict)
64
+ end
65
+ value || receiver
66
+ end
67
+
68
+ def set_attribute(receiver, attribute, namespace, strict)
69
+ logger.trace { "Setting #{receiver} attribute (#{digest(namespace, attribute, strict)})" }
70
+
71
+ attribute = attribute.to_s if attribute.is_a? Symbol
72
+
73
+ attribute_namespace = namespace.dup
74
+ attribute_namespace << attribute
75
+
76
+ value = get(attribute_namespace)
77
+
78
+ if value.nil?
79
+ msg = "#{attribute_namespace} not found in the data"
80
+ logger.error { msg }
81
+ raise Settings::Error, msg
82
+ end
83
+
84
+ Settings::Setting::Assignment::Attribute.assign(receiver, attribute.to_sym, value, strict)
85
+
86
+ log_value = value
87
+ log_value = log_value.to_h if log_value.respond_to? :to_h
88
+
89
+ logger.debug { "Set #{receiver} #{attribute} to #{log_value}" }
90
+
91
+ value
92
+ end
93
+
94
+ def set_object(receiver, namespace, strict)
95
+ logger.trace { "Setting #{receiver} object (#{digest(namespace, nil, strict)})" }
96
+
97
+ data = get(namespace)
98
+
99
+ if data.nil?
100
+ msg = "#{namespace} not found in the data"
101
+ logger.error { msg }
102
+ raise Settings::Error, msg
103
+ end
104
+
105
+ data.each do |attribute, value|
106
+ Settings::Setting::Assignment::Object.assign(receiver, attribute.to_sym, value, strict)
107
+ end
108
+
109
+ logger.debug { "Set #{receiver} object (#{digest(namespace, nil, strict)})" }
110
+
111
+ receiver
112
+ end
113
+
114
+ def assign_value(receiver, attribute, value, strict=false)
115
+ Settings::Setting::Assignment.assign(receiver, attribute, value, strict)
116
+ end
117
+
118
+ def get(*namespace)
119
+ namespace.flatten!
120
+ logger.trace { "Getting #{namespace}" }
121
+
122
+ string_keys = namespace.map { |n| n.is_a?(String) ? n : n.to_s }
123
+
124
+ value = string_keys.inject(data) {|memo, k| memo ? memo[k] : nil }
125
+
126
+ log_data = value
127
+ log_data = log_data.to_h if log_data.respond_to? :to_h
128
+
129
+ logger.debug { "Got #{namespace}" }
130
+ logger.debug(tag: :data) { "#{namespace}: #{log_data}" }
131
+
132
+ value
133
+ end
134
+
135
+ def digest(namespace, attribute, strict)
136
+ content = []
137
+ content << "Namespace: #{namespace.join ', '}" unless namespace.empty?
138
+ content << "Attribute: #{attribute}" if attribute
139
+ strict = "<not set>" if strict.nil?
140
+ content << "Strict: #{strict}"
141
+ content.join ', '
142
+ end
143
+ end
data/lib/settings.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'pathname'
2
+ require 'json'
3
+
4
+ require 'log'
5
+ require 'casing'
6
+ require 'attribute'
7
+ require 'dependency'; Dependency.activate
8
+ require 'confstruct'
9
+
10
+ require 'settings/log'
11
+ require 'settings/data_source/data_source'
12
+ require 'settings/data_source/hash'
13
+ require 'settings/data_source/file'
14
+ require 'settings/data_source/build'
15
+ require 'settings/registry'
16
+ require 'settings/settings'
17
+ require 'settings/activate'
18
+ require 'settings/setting/assignment'
19
+ require 'settings/setting/macro'
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evt-settings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0.3
5
+ platform: ruby
6
+ authors:
7
+ - The Eventide Project
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: evt-log
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: evt-casing
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: confstruct
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ntl-test_bench
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: " "
70
+ email: opensource@eventide-project.org
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/settings.rb
76
+ - lib/settings/activate.rb
77
+ - lib/settings/data_source/build.rb
78
+ - lib/settings/data_source/data_source.rb
79
+ - lib/settings/data_source/file.rb
80
+ - lib/settings/data_source/hash.rb
81
+ - lib/settings/log.rb
82
+ - lib/settings/registry.rb
83
+ - lib/settings/setting/assignment.rb
84
+ - lib/settings/setting/macro.rb
85
+ - lib/settings/settings.rb
86
+ homepage: https://github.com/eventide-project/settings
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 2.3.3
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.5.2
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Settings data access and assignment
110
+ test_files: []