eac_ruby_utils 0.8.0 → 0.9.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 +4 -4
- data/lib/eac_ruby_utils.rb +2 -0
- data/lib/eac_ruby_utils/configs.rb +71 -0
- data/lib/eac_ruby_utils/console.rb +1 -0
- data/lib/eac_ruby_utils/console/configs.rb +69 -0
- data/lib/eac_ruby_utils/console/speaker.rb +11 -0
- data/lib/eac_ruby_utils/patches/object.rb +5 -0
- data/lib/eac_ruby_utils/patches/object/asserts.rb +10 -0
- data/lib/eac_ruby_utils/paths_hash.rb +92 -0
- data/lib/eac_ruby_utils/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9290fda1cce697dcfd049b6a8085af55f0ca059d64d183b7571a0f5cbfa9a820
|
4
|
+
data.tar.gz: 54679bb172f9c3a2dcac08d642fc0a23dec10142384dff4b6e7f4c72db21622b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0611daf87bdb28ca44827934496a9d546b5f9220a0807d80416b61a9b30b282333cbdd9d6699644c47924704d428f9e2a9f18eba4f1c3eab74dc0c432e6efc8
|
7
|
+
data.tar.gz: 4402ebebc43b4b862951a39c6213c5c13f2f86fc0784deadbf49a78408e36c3827e40c73e66552bb7313c6603421cb65c8cd3c24fbec8f391ee27048496d3692
|
data/lib/eac_ruby_utils.rb
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
module EacRubyUtils
|
4
4
|
require 'eac_ruby_utils/arguments_consumer'
|
5
|
+
require 'eac_ruby_utils/configs'
|
5
6
|
require 'eac_ruby_utils/console'
|
6
7
|
require 'eac_ruby_utils/contextualizable'
|
7
8
|
require 'eac_ruby_utils/envs'
|
8
9
|
require 'eac_ruby_utils/listable'
|
9
10
|
require 'eac_ruby_utils/options_consumer'
|
10
11
|
require 'eac_ruby_utils/patches'
|
12
|
+
require 'eac_ruby_utils/paths_hash'
|
11
13
|
require 'eac_ruby_utils/simple_cache'
|
12
14
|
require 'eac_ruby_utils/yaml'
|
13
15
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
require 'yaml'
|
5
|
+
require 'eac_ruby_utils/patches/hash/sym_keys_hash'
|
6
|
+
require 'eac_ruby_utils/paths_hash'
|
7
|
+
require 'eac_ruby_utils/simple_cache'
|
8
|
+
|
9
|
+
module EacRubyUtils
|
10
|
+
class Configs
|
11
|
+
include ::EacRubyUtils::SimpleCache
|
12
|
+
|
13
|
+
attr_reader :configs_key, :options
|
14
|
+
|
15
|
+
# Valid options: [:storage_path]
|
16
|
+
def initialize(configs_key, options = {})
|
17
|
+
@configs_key = configs_key
|
18
|
+
@options = options.to_sym_keys_hash.freeze
|
19
|
+
load
|
20
|
+
end
|
21
|
+
|
22
|
+
def save
|
23
|
+
::File.write(storage_path, data.to_h.to_yaml)
|
24
|
+
end
|
25
|
+
|
26
|
+
def load
|
27
|
+
self.data = ::EacRubyUtils::PathsHash.new(YAML.load_file(storage_path))
|
28
|
+
end
|
29
|
+
|
30
|
+
def []=(entry_key, entry_value)
|
31
|
+
write_entry(entry_key, entry_value)
|
32
|
+
end
|
33
|
+
|
34
|
+
def write_entry(entry_key, entry_value)
|
35
|
+
data[entry_key] = entry_value
|
36
|
+
save if autosave?
|
37
|
+
end
|
38
|
+
|
39
|
+
def [](entry_key)
|
40
|
+
read_entry(entry_key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_entry(entry_key)
|
44
|
+
data[entry_key]
|
45
|
+
end
|
46
|
+
|
47
|
+
def autosave?
|
48
|
+
options[:autosave] ? true : false
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_accessor :data
|
54
|
+
|
55
|
+
def storage_path_uncached
|
56
|
+
path = options[:storage_path] || default_storage_path
|
57
|
+
return path if ::File.exist?(path)
|
58
|
+
::FileUtils.mkdir_p(::File.dirname(path))
|
59
|
+
::File.write(path, {}.to_yaml)
|
60
|
+
path
|
61
|
+
end
|
62
|
+
|
63
|
+
def options_storage_path
|
64
|
+
options[:storage_path]
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_storage_path
|
68
|
+
::File.join(ENV['HOME'], '.config', configs_key, 'settings.yml')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'eac_ruby_utils/configs'
|
4
|
+
require 'eac_ruby_utils/console/speaker'
|
5
|
+
|
6
|
+
module EacRubyUtils
|
7
|
+
module Console
|
8
|
+
class Configs
|
9
|
+
include ::EacRubyUtils::Console::Speaker
|
10
|
+
|
11
|
+
STORE_PASSWORDS_KEY = 'core.store_passwords'
|
12
|
+
|
13
|
+
attr_reader :configs
|
14
|
+
|
15
|
+
def initialize(configs_key)
|
16
|
+
@configs = ::EacRubyUtils::Configs.new(configs_key, autosave: true)
|
17
|
+
end
|
18
|
+
|
19
|
+
def request_password(entry_key, options = {})
|
20
|
+
options = options.merge(noecho: true)
|
21
|
+
if store_passwords?
|
22
|
+
read_entry(entry_key, options)
|
23
|
+
else
|
24
|
+
looped_entry_value_from_input(entry_key, options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_entry(entry_key, options = {})
|
29
|
+
stored_value = configs.read_entry(entry_key)
|
30
|
+
return stored_value if stored_value
|
31
|
+
options[:before_input].call if options[:before_input].present?
|
32
|
+
entry_value = looped_entry_value_from_input(entry_key, options)
|
33
|
+
configs.write_entry(entry_key, entry_value)
|
34
|
+
entry_value
|
35
|
+
end
|
36
|
+
|
37
|
+
def store_passwords?
|
38
|
+
'yes' == read_entry(
|
39
|
+
STORE_PASSWORDS_KEY,
|
40
|
+
before_input: -> { store_password_banner },
|
41
|
+
validator: ->(entry_value) { %w[yes no].include?(entry_value) }
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def store_password_banner
|
48
|
+
infom 'Do you wanna to store passwords?'
|
49
|
+
infom "Warning: the passwords will be store in clear text in \"#{configs.storage_path}\""
|
50
|
+
infom 'Enter "yes" or "no"'
|
51
|
+
end
|
52
|
+
|
53
|
+
def looped_entry_value_from_input(entry_key, options)
|
54
|
+
loop do
|
55
|
+
entry_value = entry_value_from_input(entry_key, options)
|
56
|
+
next unless entry_value.present?
|
57
|
+
next if options[:validator] && !options[:validator].call(entry_value)
|
58
|
+
return entry_value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def entry_value_from_input(entry_key, options)
|
63
|
+
entry_value = request_input("Value for entry \"#{entry_key}\"", options)
|
64
|
+
warn('Entered value is blank') if entry_value.blank?
|
65
|
+
entry_value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -39,6 +39,17 @@ module EacRubyUtils
|
|
39
39
|
puts string.to_s.yellow
|
40
40
|
end
|
41
41
|
|
42
|
+
def request_input(question, options = {})
|
43
|
+
STDERR.write "#{question}: ".to_s.yellow
|
44
|
+
if options[:noecho]
|
45
|
+
r = STDIN.noecho(&:gets).chomp.strip
|
46
|
+
STDERR.write("\n")
|
47
|
+
r
|
48
|
+
else
|
49
|
+
gets.chomp.strip
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
42
53
|
def infov(*args)
|
43
54
|
r = []
|
44
55
|
args.each_with_index do |v, i|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Object
|
4
|
+
def assert_argument(klass, argument_name)
|
5
|
+
return if is_a?(klass)
|
6
|
+
raise ::ArgumentError,
|
7
|
+
"Argument \"#{argument_name}\" is not a #{klass}" \
|
8
|
+
"(Actual class: #{self.class}, actual value: #{self})"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object'
|
4
|
+
require 'eac_ruby_utils/patches/object/asserts'
|
5
|
+
|
6
|
+
module EacRubyUtils
|
7
|
+
class PathsHash
|
8
|
+
class << self
|
9
|
+
def parse_entry_key(entry_key)
|
10
|
+
r = entry_key.to_s.strip
|
11
|
+
raise EntryKeyError, 'Entry key cannot start or end with dot' if
|
12
|
+
r.start_with?('.') || r.end_with?('.')
|
13
|
+
r = r.split('.').map(&:strip)
|
14
|
+
raise EntryKeyError, "Entry key \"#{entry_key}\" is empty" if r.empty?
|
15
|
+
return r.map(&:to_sym) unless r.any?(&:blank?)
|
16
|
+
raise EntryKeyError, "Entry key \"#{entry_key}\" has at least one blank part"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :root
|
21
|
+
|
22
|
+
def initialize(source_hash = {})
|
23
|
+
@root = Node.new(source_hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](entry_key)
|
27
|
+
root.read_entry(self.class.parse_entry_key(entry_key), [])
|
28
|
+
end
|
29
|
+
|
30
|
+
def []=(entry_key, entry_value)
|
31
|
+
root.write_entry(self.class.parse_entry_key(entry_key), entry_value, [])
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
root.to_h
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :data
|
41
|
+
|
42
|
+
class EntryKeyError < StandardError
|
43
|
+
end
|
44
|
+
|
45
|
+
class Node
|
46
|
+
def initialize(source_hash)
|
47
|
+
source_hash.assert_argument(Hash, 'source_hash')
|
48
|
+
@data = source_hash.map { |k, v| [k.to_sym, v.is_a?(Hash) ? Node.new(v) : v] }.to_h
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_h
|
52
|
+
data.map { |k, v| [k, v.is_a?(Node) ? v.to_h : v] }.to_h
|
53
|
+
end
|
54
|
+
|
55
|
+
def read_entry(path, current)
|
56
|
+
validate_path(path, current)
|
57
|
+
node_key = path.shift
|
58
|
+
node = data[node_key]
|
59
|
+
return (node.is_a?(Node) ? node.to_h : node) if path.empty?
|
60
|
+
return nil if node.blank?
|
61
|
+
return node.read_entry(path, current + [node_key]) if node.is_a?(Node)
|
62
|
+
raise(EntryKeyError,
|
63
|
+
"Path #{current.join(',')} is not a Node and path continues (#{current + path})")
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_entry(path, value, current)
|
67
|
+
validate_path(path, current)
|
68
|
+
node_key = path.shift
|
69
|
+
write_entry_value(path, node_key, value, current)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def write_entry_value(path, node_key, value, current)
|
75
|
+
if path.empty?
|
76
|
+
data[node_key] = value.is_a?(Hash) ? Node.new(value) : value
|
77
|
+
else
|
78
|
+
data[node_key] = Node.new({}) unless data[node_key].is_a?(Node)
|
79
|
+
data[node_key].write_entry(path, value, current + [node_key])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_path(path, current)
|
84
|
+
path.assert_argument(Array, 'path')
|
85
|
+
current.assert_argument(Array, 'current')
|
86
|
+
raise EntryKeyError, 'Path is empty' if path.empty?
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :data
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eac_ruby_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Esquilo Azul Company
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -103,7 +103,9 @@ files:
|
|
103
103
|
- README.rdoc
|
104
104
|
- lib/eac_ruby_utils.rb
|
105
105
|
- lib/eac_ruby_utils/arguments_consumer.rb
|
106
|
+
- lib/eac_ruby_utils/configs.rb
|
106
107
|
- lib/eac_ruby_utils/console.rb
|
108
|
+
- lib/eac_ruby_utils/console/configs.rb
|
107
109
|
- lib/eac_ruby_utils/console/docopt_runner.rb
|
108
110
|
- lib/eac_ruby_utils/console/docopt_runner/_class_methods.rb
|
109
111
|
- lib/eac_ruby_utils/console/docopt_runner/_doc.rb
|
@@ -131,6 +133,9 @@ files:
|
|
131
133
|
- lib/eac_ruby_utils/patches/hash.rb
|
132
134
|
- lib/eac_ruby_utils/patches/hash/options_consumer.rb
|
133
135
|
- lib/eac_ruby_utils/patches/hash/sym_keys_hash.rb
|
136
|
+
- lib/eac_ruby_utils/patches/object.rb
|
137
|
+
- lib/eac_ruby_utils/patches/object/asserts.rb
|
138
|
+
- lib/eac_ruby_utils/paths_hash.rb
|
134
139
|
- lib/eac_ruby_utils/simple_cache.rb
|
135
140
|
- lib/eac_ruby_utils/version.rb
|
136
141
|
- lib/eac_ruby_utils/yaml.rb
|