key_tree 0.5.2 → 0.8.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/.github/workflows/ruby.yml +37 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -4
- data/CHANGELOG.md +222 -0
- data/Gemfile +4 -8
- data/README.md +6 -1
- data/Rakefile +2 -0
- data/bin/console +5 -4
- data/bin/setup +0 -1
- data/key_tree.gemspec +20 -7
- data/lib/key_tree.rb +70 -70
- data/lib/key_tree/forest.rb +58 -26
- data/lib/key_tree/loader.rb +19 -16
- data/lib/key_tree/loader/nil.rb +2 -0
- data/lib/key_tree/meta_data.rb +3 -1
- data/lib/key_tree/path.rb +32 -40
- data/lib/key_tree/refine/deep_hash.rb +157 -0
- data/lib/key_tree/refinements.rb +40 -0
- data/lib/key_tree/tree.rb +101 -74
- data/lib/key_tree/version.rb +8 -4
- data/ruby-keytree.sublime-project +8 -0
- metadata +110 -21
- data/.travis.yml +0 -5
- data/RELEASE_NOTES.md +0 -97
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KeyTree
|
4
|
+
# KeyTree refinements to core classes
|
5
|
+
module Refinements
|
6
|
+
refine Array do
|
7
|
+
def to_key_forest
|
8
|
+
Forest[*map(&:to_key_wood)]
|
9
|
+
end
|
10
|
+
alias_method :to_key_wood, :to_key_forest
|
11
|
+
|
12
|
+
def to_key_path
|
13
|
+
Path.new(self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
refine Hash do
|
18
|
+
def to_key_tree
|
19
|
+
Tree[self]
|
20
|
+
end
|
21
|
+
alias_method :to_key_wood, :to_key_tree
|
22
|
+
end
|
23
|
+
|
24
|
+
refine String do
|
25
|
+
def to_key_path
|
26
|
+
split('.').to_key_path
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
refine Symbol do
|
31
|
+
def to_key_path
|
32
|
+
to_s.to_key_path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
require_relative 'forest'
|
39
|
+
require_relative 'path'
|
40
|
+
require_relative 'tree'
|
data/lib/key_tree/tree.rb
CHANGED
@@ -1,118 +1,145 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require_relative 'meta_data'
|
5
|
+
require_relative 'path'
|
6
|
+
require_relative 'refinements'
|
7
|
+
require_relative 'refine/deep_hash'
|
8
|
+
|
9
|
+
module KeyTree # rubocop:disable Style/Documentation
|
10
|
+
using Refinements
|
11
|
+
using Refine::DeepHash
|
3
12
|
|
4
|
-
module KeyTree
|
5
13
|
# A tree of key-value lookup tables (hashes)
|
6
|
-
class Tree
|
14
|
+
class Tree
|
7
15
|
include MetaData
|
16
|
+
extend Forwardable
|
8
17
|
#
|
9
18
|
# KeyTree::Tree.new(+hash+)
|
10
19
|
#
|
11
20
|
# Initialize a new KeyTree from nested Hash:es
|
12
21
|
#
|
13
22
|
def self.[](hash = {})
|
14
|
-
|
15
|
-
hash.each do |key, value|
|
16
|
-
keytree[key] = value
|
17
|
-
end
|
18
|
-
keytree
|
23
|
+
new(hash)
|
19
24
|
end
|
20
25
|
|
21
|
-
def
|
22
|
-
|
26
|
+
def initialize(hash = {}, default = nil, &default_proc)
|
27
|
+
@hash = hash.to_h.deep_key_pathify
|
28
|
+
@default = default
|
29
|
+
@default_proc = default_proc
|
23
30
|
end
|
24
31
|
|
25
|
-
|
26
|
-
super(Path[key_or_path], *args, &missing_key)
|
27
|
-
end
|
32
|
+
attr_reader :default, :default_proc
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
34
|
+
alias to_key_tree itself
|
35
|
+
alias to_key_wood itself
|
32
36
|
|
33
|
-
|
34
|
-
|
37
|
+
delegate %i[empty? to_h to_json] => :@hash
|
38
|
+
|
39
|
+
# Convert a Tree to YAML, with string keys
|
40
|
+
#
|
41
|
+
# :call-seq:
|
42
|
+
# to_yaml => String
|
43
|
+
def to_yaml
|
44
|
+
to_h.deep_transform_keys(&:to_s).to_yaml
|
45
|
+
end
|
35
46
|
|
36
|
-
|
47
|
+
def [](key_path)
|
48
|
+
fetch(key_path) do
|
49
|
+
next default if default_proc.nil?
|
37
50
|
|
38
|
-
|
39
|
-
when Hash
|
40
|
-
new_value.each { |suffix, value| self[path + suffix] = value }
|
41
|
-
else
|
42
|
-
super(path, new_value)
|
51
|
+
default_proc.call(self, key_path)
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
46
|
-
def
|
47
|
-
|
55
|
+
def fetch(key_path, *args, &key_missing)
|
56
|
+
@hash.deep_fetch(key_path.to_key_path, *args, &key_missing)
|
48
57
|
end
|
49
58
|
|
50
|
-
def
|
51
|
-
|
52
|
-
default_proc.yield(self, Path[key_or_path])
|
53
|
-
true
|
54
|
-
rescue KeyError
|
55
|
-
false
|
59
|
+
def store(key_path, new_value)
|
60
|
+
@hash.deep_store(key_path.to_key_path, new_value)
|
56
61
|
end
|
57
62
|
|
58
|
-
def
|
59
|
-
|
63
|
+
def store!(key_path, new_value)
|
64
|
+
store(key_path, new_value)
|
65
|
+
rescue KeyError
|
66
|
+
delete!(key_path)
|
67
|
+
retry
|
60
68
|
end
|
69
|
+
alias []= store!
|
61
70
|
|
62
|
-
def
|
63
|
-
|
71
|
+
def delete(key_path)
|
72
|
+
@hash.deep_delete(key_path.to_key_path)
|
64
73
|
end
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
delete_if { |key, _| other.conflict?(key) }
|
72
|
-
super
|
75
|
+
def delete!(key_path)
|
76
|
+
delete(key_path)
|
77
|
+
rescue KeyError
|
78
|
+
key_path = key_path[0..-2]
|
79
|
+
retry
|
73
80
|
end
|
74
|
-
alias << merge!
|
75
81
|
|
76
|
-
def
|
77
|
-
|
82
|
+
def values_at(*key_paths)
|
83
|
+
key_paths.map { |key_path| self[key_path] }
|
78
84
|
end
|
79
|
-
alias + merge
|
80
85
|
|
81
|
-
#
|
82
|
-
|
83
|
-
|
86
|
+
# Return all maximal key paths in a tree
|
87
|
+
#
|
88
|
+
# :call-seq:
|
89
|
+
# keys => Array of KeyTree::Path
|
90
|
+
def keys
|
91
|
+
@hash.deep.each_with_object([]) do |(key_path, value), result|
|
92
|
+
result << key_path.to_key_path unless value.is_a?(Hash)
|
93
|
+
end
|
84
94
|
end
|
95
|
+
alias key_paths keys
|
85
96
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
to_hash_tree(**kwargs)
|
97
|
+
def include?(key_path)
|
98
|
+
fetch(key_path)
|
99
|
+
true
|
100
|
+
rescue KeyError
|
101
|
+
false
|
92
102
|
end
|
103
|
+
alias key? include?
|
104
|
+
alias has_key? include?
|
105
|
+
alias key_path? include?
|
106
|
+
alias has_key_path? include?
|
107
|
+
|
108
|
+
def prefix?(key_path)
|
109
|
+
key_path.to_key_path.reduce(@hash) do |subtree, key|
|
110
|
+
return false unless subtree.is_a?(Hash)
|
111
|
+
return false unless subtree.key?(key)
|
93
112
|
|
94
|
-
|
95
|
-
|
96
|
-
|
113
|
+
subtree[key]
|
114
|
+
end
|
115
|
+
true
|
97
116
|
end
|
117
|
+
alias has_prefix? prefix?
|
98
118
|
|
99
|
-
|
100
|
-
|
101
|
-
to_hash_tree(string_keys: true).to_yaml
|
119
|
+
def value?(needle)
|
120
|
+
@hash.deep.lazy.any? { |(_, straw)| straw == needle }
|
102
121
|
end
|
122
|
+
alias has_value? value?
|
103
123
|
|
104
|
-
|
124
|
+
# Merge values from +other+ tree into self
|
125
|
+
#
|
126
|
+
# :call-seq:
|
127
|
+
# merge!(other) => self
|
128
|
+
# merge!(other) { |key, lhs, rhs| } => self
|
129
|
+
def merge!(other, &block)
|
130
|
+
@hash.deep_merge!(other.to_h, &block)
|
131
|
+
self
|
132
|
+
end
|
133
|
+
alias << merge!
|
105
134
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
next first_value if first_key.nil? || first_key.empty?
|
114
|
-
to_hash_tree(next_level)
|
115
|
-
end
|
135
|
+
# Return a new tree by merging values from +other+ tree
|
136
|
+
#
|
137
|
+
# :call-seq:
|
138
|
+
# merge(other) => Tree
|
139
|
+
# merge(other) { |key, lhs, rhs| } => Tree
|
140
|
+
def merge(other, &block)
|
141
|
+
@hash.deep_merge(other.to_h, &block).to_key_tree
|
116
142
|
end
|
143
|
+
alias + merge
|
117
144
|
end
|
118
145
|
end
|
data/lib/key_tree/version.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module KeyTree
|
4
|
-
|
5
|
-
|
3
|
+
module KeyTree # rubocop:disable Style/Documentation
|
4
|
+
begin
|
5
|
+
require 'git-version-bump'
|
6
|
+
VERSION = GVB.version.freeze
|
7
|
+
rescue LoadError
|
8
|
+
VERSION = '0.0.0.UNDEF'
|
9
|
+
end
|
6
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: key_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Calle Englund
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git-version-bump
|
@@ -16,86 +16,170 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.17.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.17.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: codecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.5.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.14.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.14.0
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: rake
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
44
72
|
requirements:
|
45
73
|
- - "~>"
|
46
74
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
75
|
+
version: '13.0'
|
48
76
|
type: :development
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
82
|
+
version: '13.0'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: rspec
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
58
86
|
requirements:
|
59
87
|
- - "~>"
|
60
88
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
89
|
+
version: '3.10'
|
62
90
|
type: :development
|
63
91
|
prerelease: false
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
65
93
|
requirements:
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
96
|
+
version: '3.10'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: rubocop
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
103
|
+
version: '1.15'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.15'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.5.1
|
76
118
|
type: :development
|
77
119
|
prerelease: false
|
78
120
|
version_requirements: !ruby/object:Gem::Requirement
|
79
121
|
requirements:
|
80
122
|
- - "~>"
|
81
123
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
83
|
-
|
124
|
+
version: 0.5.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '2.3'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '2.3'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: ruby-prof
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.4'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.4'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.21.0
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.21.0
|
167
|
+
description:
|
84
168
|
email:
|
85
169
|
- calle@discord.bofh.se
|
86
170
|
executables: []
|
87
171
|
extensions: []
|
88
172
|
extra_rdoc_files: []
|
89
173
|
files:
|
174
|
+
- ".github/workflows/ruby.yml"
|
90
175
|
- ".gitignore"
|
91
176
|
- ".rspec"
|
92
177
|
- ".rubocop.yml"
|
93
|
-
-
|
178
|
+
- CHANGELOG.md
|
94
179
|
- CODE_OF_CONDUCT.md
|
95
180
|
- Gemfile
|
96
181
|
- LICENSE.txt
|
97
182
|
- README.md
|
98
|
-
- RELEASE_NOTES.md
|
99
183
|
- Rakefile
|
100
184
|
- bin/console
|
101
185
|
- bin/setup
|
@@ -106,13 +190,16 @@ files:
|
|
106
190
|
- lib/key_tree/loader/nil.rb
|
107
191
|
- lib/key_tree/meta_data.rb
|
108
192
|
- lib/key_tree/path.rb
|
193
|
+
- lib/key_tree/refine/deep_hash.rb
|
194
|
+
- lib/key_tree/refinements.rb
|
109
195
|
- lib/key_tree/tree.rb
|
110
196
|
- lib/key_tree/version.rb
|
197
|
+
- ruby-keytree.sublime-project
|
111
198
|
homepage: https://github.com/notcalle/ruby-keytree
|
112
199
|
licenses:
|
113
200
|
- MIT
|
114
201
|
metadata: {}
|
115
|
-
post_install_message:
|
202
|
+
post_install_message:
|
116
203
|
rdoc_options: []
|
117
204
|
require_paths:
|
118
205
|
- lib
|
@@ -120,16 +207,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
207
|
requirements:
|
121
208
|
- - ">="
|
122
209
|
- !ruby/object:Gem::Version
|
123
|
-
version: '
|
210
|
+
version: '2.6'
|
211
|
+
- - "<"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '4.0'
|
124
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
215
|
requirements:
|
126
216
|
- - ">="
|
127
217
|
- !ruby/object:Gem::Version
|
128
218
|
version: '0'
|
129
219
|
requirements: []
|
130
|
-
|
131
|
-
|
132
|
-
signing_key:
|
220
|
+
rubygems_version: 3.2.15
|
221
|
+
signing_key:
|
133
222
|
specification_version: 4
|
134
223
|
summary: Manage trees of keys
|
135
224
|
test_files: []
|