gloo-yaml 1.1 → 1.2
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/yaml_obj.rb +135 -30
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c52213b581759c71164627cd649a22d13702a526d695701f6abb7f6469b5bcd
|
|
4
|
+
data.tar.gz: 947b874647d5e232fd87c32d530fa9bff5d926877b12f3f2cfab50d0e63244ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87e99e16ef94698cbc6dd471538a31724c61002674063845ccb179b7d4a2f2d2b26e9c88f17ad39c1ce1d5d1af5b56d3412512942a521413d3272efdff0635c8
|
|
7
|
+
data.tar.gz: 6a8380687d34b2a2e76e5082acbe2c9294c89c2f7d22ac60922df96c72912e2cefbf5b1a67f0fefed01e810c2375ee6f891b27c683c7bbd644ad629c4654a8ca
|
data/lib/yaml_obj.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# loading and saving named fields via a container object.
|
|
6
6
|
#
|
|
7
7
|
require 'yaml'
|
|
8
|
+
require 'date'
|
|
8
9
|
|
|
9
10
|
class YamlObj < Gloo::Core::Obj
|
|
10
11
|
|
|
@@ -48,40 +49,68 @@ class YamlObj < Gloo::Core::Obj
|
|
|
48
49
|
# Load fields from the YAML file into a container.
|
|
49
50
|
# The param is a path to a container object whose children
|
|
50
51
|
# are matched by name to YAML keys.
|
|
52
|
+
# It is true when the file was loaded, false if it couldn't be.
|
|
51
53
|
#
|
|
52
54
|
def msg_load
|
|
53
|
-
|
|
55
|
+
container = param_container( 'load' )
|
|
56
|
+
return @engine.heap.it.set_to( false ) unless container
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
return unless
|
|
58
|
+
path = resolve_path
|
|
59
|
+
return @engine.heap.it.set_to( false ) unless path
|
|
57
60
|
|
|
58
|
-
data = read_yaml_file
|
|
59
|
-
return unless data
|
|
61
|
+
data = read_yaml_file( path )
|
|
62
|
+
return @engine.heap.it.set_to( false ) unless data
|
|
60
63
|
|
|
61
64
|
container.children.each do |child|
|
|
62
65
|
key = child.name
|
|
63
|
-
|
|
66
|
+
next unless data.key?( key )
|
|
67
|
+
|
|
68
|
+
# Nested data is planned for an upcoming release; until then a
|
|
69
|
+
# nested block or list is skipped, not loaded as Ruby's text for it.
|
|
70
|
+
if nested?( data[ key ] )
|
|
71
|
+
warn_nested( key )
|
|
72
|
+
next
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
child.set_value scalar_text( data[ key ] )
|
|
64
76
|
end
|
|
77
|
+
@engine.heap.it.set_to true
|
|
65
78
|
end
|
|
66
79
|
|
|
67
80
|
#
|
|
68
81
|
# Save fields from a container into the YAML file.
|
|
69
82
|
# The param is a path to a container object whose children
|
|
70
|
-
# are matched by name to YAML keys.
|
|
83
|
+
# are matched by name to YAML keys. Creates the file if it does
|
|
84
|
+
# not exist; keys without a matching child are kept.
|
|
71
85
|
#
|
|
72
86
|
def msg_save
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
container = resolve_container
|
|
87
|
+
container = param_container( 'save' )
|
|
76
88
|
return unless container
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
path = resolve_path
|
|
91
|
+
return unless path
|
|
92
|
+
|
|
93
|
+
data = {}
|
|
94
|
+
if File.exist?( path )
|
|
95
|
+
data = read_yaml_file( path )
|
|
96
|
+
# The file couldn't be read (reported); don't overwrite it.
|
|
97
|
+
return unless data
|
|
98
|
+
end
|
|
79
99
|
|
|
80
100
|
container.children.each do |child|
|
|
81
|
-
|
|
101
|
+
key = child.name
|
|
102
|
+
|
|
103
|
+
# Nested data is planned for an upcoming release; until then a
|
|
104
|
+
# nested block or list in the file is left as it is.
|
|
105
|
+
if nested?( data[ key ] )
|
|
106
|
+
warn_nested( key )
|
|
107
|
+
next
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
data[ key ] = child.value
|
|
82
111
|
end
|
|
83
112
|
|
|
84
|
-
|
|
113
|
+
file_op( 'write', path ) { File.write( path, data.to_yaml ) }
|
|
85
114
|
end
|
|
86
115
|
|
|
87
116
|
|
|
@@ -92,31 +121,101 @@ class YamlObj < Gloo::Core::Obj
|
|
|
92
121
|
private
|
|
93
122
|
|
|
94
123
|
#
|
|
95
|
-
# Resolve the container
|
|
124
|
+
# Resolve the container named by the first param. Reports a syntax
|
|
125
|
+
# error if there's no param, or an error if the container doesn't
|
|
126
|
+
# exist, and returns nil.
|
|
96
127
|
#
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
def param_container( msg )
|
|
129
|
+
unless @params&.token_count&.positive?
|
|
130
|
+
@engine.syntax_err "Missing the container to #{msg}! eg. tell #{name} to #{msg} (data)"
|
|
131
|
+
return nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
container = Gloo::Core::Pn.new( @engine, @params.first ).resolve
|
|
135
|
+
@engine.err Gloo::Core::NotFound.object( @params.first ) unless container
|
|
136
|
+
return container
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
#
|
|
140
|
+
# Get the expanded path of the YAML file (the object's value).
|
|
141
|
+
# Reports an error and returns nil if there's no path.
|
|
142
|
+
#
|
|
143
|
+
def resolve_path
|
|
144
|
+
if self.value.to_s.strip.empty?
|
|
145
|
+
@engine.err "yaml '#{name}' has no path; put a file path into #{name} first."
|
|
146
|
+
return nil
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
return File.expand_path( self.value )
|
|
100
150
|
end
|
|
101
151
|
|
|
102
152
|
#
|
|
103
|
-
# Read and parse the YAML file. Returns a hash, or nil
|
|
153
|
+
# Read and parse the YAML file. Returns a hash of its keys, or nil
|
|
154
|
+
# after reporting an error: a missing or unreadable file, invalid
|
|
155
|
+
# YAML, or YAML that isn't key: value pairs. Dates and times are
|
|
156
|
+
# allowed.
|
|
104
157
|
#
|
|
105
|
-
def read_yaml_file
|
|
106
|
-
path = File.expand_path( self.value )
|
|
158
|
+
def read_yaml_file( path )
|
|
107
159
|
unless File.exist?( path )
|
|
108
|
-
@engine.
|
|
160
|
+
@engine.err Gloo::Core::NotFound.file( path )
|
|
109
161
|
return nil
|
|
110
162
|
end
|
|
111
|
-
|
|
163
|
+
|
|
164
|
+
content = file_op( 'read', path ) { File.read( path ) }
|
|
165
|
+
return nil unless content
|
|
166
|
+
|
|
167
|
+
data = YAML.safe_load( content, permitted_classes: [ Date, Time ] ) || {}
|
|
168
|
+
return data if data.is_a?( Hash )
|
|
169
|
+
|
|
170
|
+
return yaml_err( path, 'it is not a list of key: value pairs' )
|
|
171
|
+
rescue Psych::SyntaxError => e
|
|
172
|
+
return yaml_err( path, e.problem )
|
|
173
|
+
rescue Psych::Exception => e
|
|
174
|
+
return yaml_err( path, e.message )
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# Report YAML that can't be used, and return nil.
|
|
179
|
+
#
|
|
180
|
+
def yaml_err( path, reason )
|
|
181
|
+
@engine.err "Couldn't read the YAML in '#{path}': #{reason}."
|
|
182
|
+
return nil
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
#
|
|
186
|
+
# Run a file operation, reporting a failure (eg. no permission, a
|
|
187
|
+
# missing folder) as an error. Returns nil if it failed.
|
|
188
|
+
#
|
|
189
|
+
def file_op( action, path )
|
|
190
|
+
return yield
|
|
191
|
+
rescue SystemCallError => e
|
|
192
|
+
@engine.err "Could not #{action} '#{path}': #{e.message}"
|
|
193
|
+
return nil
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
#
|
|
197
|
+
# Is the value a nested block or a list (not yet supported)?
|
|
198
|
+
#
|
|
199
|
+
def nested?( val )
|
|
200
|
+
return val.is_a?( Hash ) || val.is_a?( Array )
|
|
112
201
|
end
|
|
113
202
|
|
|
114
203
|
#
|
|
115
|
-
#
|
|
204
|
+
# Warn that a nested block or list was left unchanged.
|
|
116
205
|
#
|
|
117
|
-
def
|
|
118
|
-
|
|
119
|
-
|
|
206
|
+
def warn_nested( key )
|
|
207
|
+
@engine.warn "YAML key '#{key}' is a nested block or list, which isn't supported yet; it was left unchanged."
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
#
|
|
211
|
+
# The text for a simple YAML value. YAML reads a time with no zone
|
|
212
|
+
# as UTC, so times are shown in UTC rather than converted to local
|
|
213
|
+
# time (the same as gloo-md's md_doc).
|
|
214
|
+
#
|
|
215
|
+
def scalar_text( val )
|
|
216
|
+
return val.utc.strftime( '%Y-%m-%d %H:%M:%S UTC' ) if val.is_a?( Time )
|
|
217
|
+
|
|
218
|
+
return val.to_s
|
|
120
219
|
end
|
|
121
220
|
|
|
122
221
|
# ---------------------------------------------------------------------
|
|
@@ -134,11 +233,17 @@ class YamlObj < Gloo::Core::Obj
|
|
|
134
233
|
'file (as its own value) and supports loading and saving ' \
|
|
135
234
|
'named fields via a container object.',
|
|
136
235
|
:messages => [
|
|
137
|
-
'load ({container.path}) — Load fields from the YAML file into the given container. Children of the container are matched by name to YAML keys. A parameter is required.',
|
|
138
|
-
'save ({container.path}) — Save fields from the given container into the YAML file, matching container children by name to YAML keys. A parameter is required.'
|
|
236
|
+
'load ({container.path}) — Load fields from the YAML file into the given container. Children of the container are matched by name to YAML keys; dates and times load as text. A parameter is required. It is true when the file was loaded, false if it could not be.',
|
|
237
|
+
'save ({container.path}) — Save fields from the given container into the YAML file, matching container children by name to YAML keys. Creates the file if it does not exist; keys with no matching child are kept. A parameter is required.'
|
|
139
238
|
],
|
|
140
|
-
:notes => '
|
|
141
|
-
'
|
|
239
|
+
:notes => 'Errors: no container (a syntax error), a container ' \
|
|
240
|
+
'that does not exist, an empty path, a file that does not ' \
|
|
241
|
+
'exist or cannot be read or written, and YAML that is not ' \
|
|
242
|
+
'valid or is not key: value pairs. load puts false in it on ' \
|
|
243
|
+
'an error; save does not overwrite a file it could not read. ' \
|
|
244
|
+
'Nested blocks and lists are not supported yet (planned for ' \
|
|
245
|
+
'an upcoming release): load skips them with a warning, and ' \
|
|
246
|
+
'save leaves them in the file as they are.',
|
|
142
247
|
:examples => <<~EXAMPLES.strip
|
|
143
248
|
settings [can] :
|
|
144
249
|
path [yaml] : ~/.my_app/settings.yml
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gloo-yaml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.2'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Crane
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: gloo
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '7.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '7.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: bundler
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|