eac_config 0.1.0

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
+ SHA256:
3
+ metadata.gz: 84f6dfb659545033cf9bd7ad9514ef8328ec32c13af6d3534c8cb884e716a3ee
4
+ data.tar.gz: a8fa8b10e98000122b2a9e479443d0975d55decf95a060474eaad7ecfa8f4dee
5
+ SHA512:
6
+ metadata.gz: 2d4c70a6acb8e033017a646ae5c1c1c3afe1b470fabcb194c8c8177fba8229d17abf13a504e58adf49983161a457a0d11b83ae1bc49a4917f80412672a9f518f
7
+ data.tar.gz: 383d7fb5e5812d1491dc73104c679b78b25c16b3e353591c3c37b2f467a3e1bd5f84de346bdb79c044a829dea0f7e32c898508dc1bd12bec42e290079efa74ca
data/lib/eac_config.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacConfig
6
+ require_sub __FILE__
7
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_config/entry_path'
4
+ require 'eac_ruby_utils/core_ext'
5
+
6
+ module EacConfig
7
+ class Entry
8
+ common_constructor :source_node, :path, :found, :value
9
+
10
+ def found?
11
+ found
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacConfig
6
+ class EntryPath
7
+ PART_SEPARATOR = '.'
8
+
9
+ class << self
10
+ def build_parts(source)
11
+ return validate_parts!(source.split(PART_SEPARATOR)) if source.is_a?(::String)
12
+ return validate_parts!(source.flat_map { |part| build_parts(part) }) if
13
+ source.is_a?(::Enumerable)
14
+
15
+ build_parts(source.to_s)
16
+ end
17
+
18
+ def validate_parts!(parts)
19
+ parts.assert_argument(::Enumerable, 'parts')
20
+ parts.each_with_index do |part, index|
21
+ raise ::ArgumentError, "Part #{index} of #{parts} is blank" if part.blank?
22
+ raise ::ArgumentError, "Part #{index} is not a string" unless part.is_a?(::String)
23
+ end
24
+ end
25
+ end
26
+
27
+ attr_reader :parts
28
+
29
+ def initialize(*parts)
30
+ @parts = self.class.build_parts(parts).freeze
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_config/entry'
4
+ require 'eac_config/paths_hash'
5
+
6
+ module EacConfig
7
+ class EntrySearch
8
+ enable_simple_cache
9
+ common_constructor :node, :path
10
+
11
+ private
12
+
13
+ # @return [EacConfig::Entry]
14
+ def result_uncached
15
+ if paths_hash.key?(to_paths_hash_key)
16
+ ::EacConfig::Entry.new(node, path, true, paths_hash.fetch(to_paths_hash_key))
17
+ else
18
+ ::EacConfig::Entry.new(nil, path, false, nil)
19
+ end
20
+ end
21
+
22
+ # @return [EacConfig::PathsHash]
23
+ def paths_hash_uncached
24
+ ::EacConfig::PathsHash.new(node.data)
25
+ end
26
+
27
+ def to_paths_hash_key
28
+ path.parts.join('.')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacConfig
6
+ class Manager
7
+ common_constructor :root_node
8
+
9
+ # @return [EacConfig::Entry]
10
+ def entry(*parts)
11
+ root_node.entry(*parts)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module EacConfig
6
+ class PathsHash
7
+ require_sub __FILE__
8
+
9
+ class << self
10
+ def parse_entry_key(entry_key)
11
+ r = entry_key.to_s.strip
12
+ raise ::EacConfig::PathsHash::EntryKeyError, 'Entry key cannot start or end with dot' if
13
+ r.start_with?('.') || r.end_with?('.')
14
+
15
+ r = r.split('.').map(&:strip)
16
+ if r.empty?
17
+ raise ::EacConfig::PathsHash::EntryKeyError, "Entry key \"#{entry_key}\" is empty"
18
+ end
19
+ return r.map(&:to_sym) unless r.any?(&:blank?)
20
+
21
+ raise ::EacConfig::PathsHash::EntryKeyError,
22
+ "Entry key \"#{entry_key}\" has at least one blank part"
23
+ end
24
+ end
25
+
26
+ attr_reader :root
27
+
28
+ def initialize(source_hash = {})
29
+ @root = Node.new(source_hash)
30
+ end
31
+
32
+ def [](entry_key)
33
+ root.read_entry(::EacConfig::PathsHash::PathSearch.parse_entry_key(entry_key))
34
+ end
35
+
36
+ def []=(entry_key, entry_value)
37
+ root.write_entry(
38
+ ::EacConfig::PathsHash::PathSearch.parse_entry_key(entry_key), entry_value
39
+ )
40
+ end
41
+
42
+ def fetch(entry_key)
43
+ root.fetch(::EacConfig::PathsHash::PathSearch.parse_entry_key(entry_key))
44
+ end
45
+
46
+ def key?(entry_key)
47
+ root.entry?(::EacConfig::PathsHash::PathSearch.parse_entry_key(entry_key))
48
+ end
49
+
50
+ delegate :to_h, to: :root
51
+
52
+ private
53
+
54
+ attr_reader :data
55
+ end
56
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacConfig
4
+ class PathsHash
5
+ class EntryKeyError < StandardError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'eac_config/paths_hash/entry_key_error'
5
+
6
+ module EacConfig
7
+ class PathsHash
8
+ class Node
9
+ PATH_SEARCH_UNENDED_ERROR_MESSAGE = 'Path search is not a Node and is not ended'
10
+
11
+ def initialize(source_hash)
12
+ source_hash.assert_argument(Hash, 'source_hash')
13
+ @data = source_hash.map { |k, v| [k.to_sym, v.is_a?(Hash) ? Node.new(v) : v] }.to_h
14
+ end
15
+
16
+ def entry?(path_search)
17
+ return false unless data.key?(path_search.cursor)
18
+ return true if path_search.ended?
19
+ return data.fetch(path_search.cursor).entry?(path_search.succeeding) if
20
+ data.fetch(path_search.cursor).is_a?(Node)
21
+
22
+ false # Paths continue and there is not available nodes
23
+ end
24
+
25
+ def fetch(path_search)
26
+ if data.key?(path_search.cursor)
27
+ node = data.fetch(path_search.cursor)
28
+ return (node.is_a?(Node) ? node.to_h : node) if path_search.ended?
29
+ return nil if node.blank?
30
+ return node.fetch(path_search.succeeding) if node.is_a?(Node)
31
+ end
32
+
33
+ path_search.raise_error(PATH_SEARCH_UNENDED_ERROR_MESSAGE)
34
+ end
35
+
36
+ def to_h
37
+ data.map { |k, v| [k, v.is_a?(Node) ? v.to_h : v] }.to_h
38
+ end
39
+
40
+ def read_entry(path_search)
41
+ node = data[path_search.cursor]
42
+ return (node.is_a?(Node) ? node.to_h : node) if path_search.ended?
43
+ return nil if node.blank?
44
+ return node.read_entry(path_search.succeeding) if node.is_a?(Node)
45
+
46
+ path_search.raise_error(PATH_SEARCH_UNENDED_ERROR_MESSAGE)
47
+ end
48
+
49
+ def write_entry(path_search, value)
50
+ if path_search.ended?
51
+ data[path_search.cursor] = value.is_a?(Hash) ? self.class.new(value) : value
52
+ else
53
+ assert_data_node(path_search.cursor).write_entry(path_search.succeeding, value)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ attr_reader :data
60
+
61
+ def assert_data_node(key)
62
+ data[key] = self.class.new({}) unless data[key].is_a?(Node)
63
+ data[key]
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacConfig
4
+ class PathsHash
5
+ class PathSearch
6
+ class << self
7
+ def parse_entry_key(string)
8
+ new(::EacConfig::PathsHash.parse_entry_key(string), [])
9
+ end
10
+ end
11
+
12
+ common_constructor :current, :previous do
13
+ self.current = current.assert_argument(Array, 'current').freeze
14
+ self.previous = previous.assert_argument(Array, 'previous')
15
+ raise ::EacConfig::PathsHash::EntryKeyError, 'Current is empty' if current.empty?
16
+ end
17
+
18
+ def cursor
19
+ current.first
20
+ end
21
+
22
+ def ended?
23
+ current.count <= 1
24
+ end
25
+
26
+ def raise_error(message)
27
+ raise ::EacConfig::PathsHash::EntryKeyError, "#{message} (#{self})"
28
+ end
29
+
30
+ def succeeding
31
+ self.class.new(current[1..-1], previous + [cursor])
32
+ end
33
+
34
+ def to_s
35
+ "#{self.class}[Current: #{current}, Previous: #{previous}]"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacConfig
4
+ module ReadableNode
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacConfig
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacConfig
4
+ module WriteableNode
5
+ end
6
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_config/entry'
4
+ require 'eac_config/entry_search'
5
+ require 'eac_config/readable_node'
6
+ require 'eac_config/writeable_node'
7
+ require 'eac_ruby_utils/core_ext'
8
+ require 'eac_ruby_utils/yaml'
9
+
10
+ module EacConfig
11
+ class YamlFileNode
12
+ include ::EacConfig::ReadableNode
13
+ include ::EacConfig::WriteableNode
14
+
15
+ common_constructor :path do
16
+ self.path = path.to_pathname
17
+ end
18
+
19
+ def data
20
+ @data ||= ::EacRubyUtils::Yaml.load_file(path)
21
+ end
22
+
23
+ def entry(*path)
24
+ ::EacConfig::EntrySearch.new(self, ::EacConfig::EntryPath.new(*path)).result
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eac_config
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Put here the authors
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: eac_ruby_utils
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.62'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.62'
27
+ - !ruby/object:Gem::Dependency
28
+ name: eac_ruby_gem_support
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/eac_config.rb
48
+ - lib/eac_config/entry.rb
49
+ - lib/eac_config/entry_path.rb
50
+ - lib/eac_config/entry_search.rb
51
+ - lib/eac_config/manager.rb
52
+ - lib/eac_config/paths_hash.rb
53
+ - lib/eac_config/paths_hash/entry_key_error.rb
54
+ - lib/eac_config/paths_hash/node.rb
55
+ - lib/eac_config/paths_hash/path_search.rb
56
+ - lib/eac_config/readable_node.rb
57
+ - lib/eac_config/version.rb
58
+ - lib/eac_config/writeable_node.rb
59
+ - lib/eac_config/yaml_file_node.rb
60
+ homepage:
61
+ licenses: []
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.0.9
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Put here de description.
82
+ test_files: []