evt-settings 0.2.0.3

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.
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: []