gloo 3.4.1 → 3.6.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/lib/VERSION +1 -1
  4. data/lib/VERSION_NOTES +15 -0
  5. data/lib/gloo/app/args.rb +2 -2
  6. data/lib/gloo/app/engine.rb +21 -2
  7. data/lib/gloo/app/info.rb +0 -2
  8. data/lib/gloo/convert/converter.rb +1 -2
  9. data/lib/gloo/convert/string_to_integer.rb +2 -0
  10. data/lib/gloo/core/dictionary.rb +1 -1
  11. data/lib/gloo/core/event_manager.rb +19 -0
  12. data/lib/gloo/core/factory.rb +2 -2
  13. data/lib/gloo/core/gloo_system.rb +1 -1
  14. data/lib/gloo/core/here.rb +1 -1
  15. data/lib/gloo/core/obj.rb +61 -5
  16. data/lib/gloo/core/parser.rb +1 -1
  17. data/lib/gloo/core/pn.rb +1 -1
  18. data/lib/gloo/exec/dispatch.rb +19 -0
  19. data/lib/gloo/exec/runner.rb +1 -1
  20. data/lib/gloo/objs/basic/integer.rb +10 -1
  21. data/lib/gloo/objs/ctrl/each.rb +17 -184
  22. data/lib/gloo/objs/ctrl/each_child.rb +68 -0
  23. data/lib/gloo/objs/ctrl/each_file.rb +83 -0
  24. data/lib/gloo/objs/ctrl/each_line.rb +67 -0
  25. data/lib/gloo/objs/ctrl/each_repo.rb +84 -0
  26. data/lib/gloo/objs/ctrl/each_word.rb +67 -0
  27. data/lib/gloo/objs/data/mysql.rb +2 -2
  28. data/lib/gloo/objs/data/pg.rb +1 -1
  29. data/lib/gloo/objs/data/query.rb +54 -5
  30. data/lib/gloo/objs/data/query_result.rb +6 -1
  31. data/lib/gloo/objs/data/sqlite.rb +1 -1
  32. data/lib/gloo/objs/data/table.rb +2 -2
  33. data/lib/gloo/objs/ror/eval.rb +1 -1
  34. data/lib/gloo/objs/security/password.rb +5 -8
  35. data/lib/gloo/objs/system/file_handle.rb +39 -5
  36. data/lib/gloo/objs/web_svr/element.rb +2 -2
  37. data/lib/gloo/objs/web_svr/page.rb +16 -6
  38. data/lib/gloo/objs/web_svr/svr.rb +29 -13
  39. data/lib/gloo/persist/file_loader.rb +2 -2
  40. data/lib/gloo/persist/file_storage.rb +1 -1
  41. data/lib/gloo/persist/line_splitter.rb +1 -0
  42. data/lib/gloo/verbs/check.rb +54 -0
  43. data/lib/gloo/verbs/redirect.rb +34 -2
  44. data/lib/gloo/verbs/tell.rb +11 -36
  45. data/lib/gloo/web_svr/handler.rb +32 -5
  46. data/lib/gloo/web_svr/request.rb +11 -40
  47. data/lib/gloo/web_svr/request_params.rb +104 -0
  48. data/lib/gloo/web_svr/response.rb +25 -0
  49. data/lib/gloo/web_svr/response_code.rb +1 -1
  50. data/lib/gloo/web_svr/routing/router.rb +10 -2
  51. data/lib/gloo/web_svr/session.rb +18 -12
  52. metadata +10 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac56d6b0d2298092e23e0bf352b6b5c77bfbf0d231b060003a404bc8e313e269
4
- data.tar.gz: 9524d5e521c258dd5922c49c3c8dfcef2c52f57d0dff02306bfdb5ed3f1d0baa
3
+ metadata.gz: 6e79ebad69bd8325e6f1b09ecd7d32520e7f82d1e4181d74c31433e4ca159cda
4
+ data.tar.gz: 50cdd391fa4d96d0cb8897bf8b8fdb02b30aea567083343e5540b492399a9e93
5
5
  SHA512:
6
- metadata.gz: c6e81f7c12f73b7736c79be525c23a300b231fbb76884490ef1b0b87ff85f3e85533ef708edb4b1044d99e443b7fb0df3f39551dce69b6d6dd91a3d2692dc472
7
- data.tar.gz: 3c50b4ffba3590217bcd2641a190e196a472620321a5f23eeb07d8e5cf24d19ba81d675497143bf44ea4c389d308ae65446ceee8be50037e5dbbc26c13cfad8f
6
+ metadata.gz: 6712527d452fb8c73799f4e9829ffe58edb518aa6ed440e30fadb9211af0b899dce31453098f518b6310b693aec330d567b7ffb50713049c9abb3c27b7395eb8
7
+ data.tar.gz: ba4b513a0e8b587d7418d10a16cfed7ecd2df4a9ce85409cdd78c59a5d936b0714008bfd02baa8a66814be1855ece161d3a07a9b7b1f6e6783d1ef9cf5091835
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-3.2.5
1
+ 3.3.5
data/lib/VERSION CHANGED
@@ -1 +1 @@
1
- 3.4.1
1
+ 3.6.0
data/lib/VERSION_NOTES CHANGED
@@ -1,3 +1,18 @@
1
+ 3.6.0 - 2024.11.26
2
+ - Adds support for route parameters
3
+ - Updates iterators
4
+ - Clear results for SQL queries
5
+ - Bug fixes
6
+
7
+
8
+ 3.5.0 - 2024.10.18
9
+ - check obj for message alternate to tell
10
+ - new base object messages
11
+ - fixes issue with single row returned from query
12
+ - adds on_error event
13
+ - use aliases in pwd obj
14
+
15
+
1
16
  3.4.1 - 2024.09.23
2
17
  - Removes old, unused sound objects
3
18
  - Adds support for lib folder in gloo rather than in the project folder
data/lib/gloo/app/args.rb CHANGED
@@ -51,12 +51,12 @@ module Gloo
51
51
  return true unless app?
52
52
 
53
53
  if @app_path.nil?
54
- @engine.log.error "App Path required to run in App mode."
54
+ @engine.err "App Path required to run in App mode."
55
55
  return false
56
56
  end
57
57
 
58
58
  unless File.directory? @app_path
59
- @engine.log.error "'#{@app_path}' is not a valid directory."
59
+ @engine.err "'#{@app_path}' is not a valid directory."
60
60
  return false
61
61
  end
62
62
 
@@ -201,7 +201,7 @@ module Gloo
201
201
  begin
202
202
  @parser.run @last_cmd
203
203
  rescue => e
204
- err e.message
204
+ log_exception e
205
205
  end
206
206
  end
207
207
 
@@ -282,11 +282,30 @@ module Gloo
282
282
  # Report an error.
283
283
  # Write it to the log and set the heap error value.
284
284
  #
285
- def err( msg )
285
+ def err( msg, backtrace=nil )
286
286
  @log.error msg
287
287
  @heap.error.set_to msg
288
+
289
+ @event_manager.on_error( msg, backtrace)
288
290
  end
289
291
 
292
+ #
293
+ # Log an exception.
294
+ # This function does not log the full backtrace, but
295
+ # does write part of it to the log.
296
+ #
297
+ def log_exception ex
298
+ # Get the stack trace, and if needed truncate to fit.
299
+ msg_lines = ex.backtrace
300
+ if msg_lines.count > 27
301
+ msg_lines = msg_lines[0..13] + [ '... truncated ...' ] + msg_lines[-13..-1]
302
+ end
303
+ backtrace = msg_lines.join( "\n" )
304
+ @log.error backtrace
305
+
306
+ err( ex.message, backtrace)
307
+ end
308
+
290
309
  end
291
310
  end
292
311
  end
data/lib/gloo/app/info.rb CHANGED
@@ -4,8 +4,6 @@
4
4
  # Application information such as Version and public name.
5
5
  #
6
6
 
7
- # require 'gloo-lang'
8
-
9
7
  module Gloo
10
8
  module App
11
9
  class Info
@@ -30,8 +30,7 @@ module Gloo
30
30
  o = clazz.new
31
31
  return o.convert( value )
32
32
  rescue => e
33
- @engine.log.error e.message
34
- @engine.heap.error.set_to e.message
33
+ @engine.log_exception e
35
34
  end
36
35
 
37
36
  return default
@@ -12,6 +12,8 @@ module Gloo
12
12
  # Convert the given string value to an integer.
13
13
  #
14
14
  def convert( value )
15
+ return nil if value.blank?
16
+
15
17
  return value.to_i
16
18
  end
17
19
 
@@ -190,7 +190,7 @@ module Gloo
190
190
  #
191
191
  def add_key( keyword )
192
192
  if @keywords.include?( keyword )
193
- # @engine.log.error "duplicate keyword '#{keyword}'"
193
+ # @engine.err "duplicate keyword '#{keyword}'"
194
194
  return
195
195
  end
196
196
 
@@ -72,6 +72,25 @@ module Gloo
72
72
  arr.each { |o| Gloo::Exec::Dispatch.message( @engine, 'run', o ) }
73
73
  end
74
74
 
75
+ #
76
+ # Run the on_error scripts in any open objects.
77
+ # For each on_error script found, look for the error_data container
78
+ # and set the error message and backtrace.
79
+ #
80
+ def on_error msg, backtrace
81
+ @engine.log.debug 'on_error event'
82
+ arr = Gloo::Core::ObjFinder.by_name( @engine, 'on_error' )
83
+ arr.each do |o|
84
+ data = o.parent.find_child 'error_data'
85
+ if data
86
+ data.find_child( 'message' ).set_value msg
87
+ data.find_child( 'backtrace' ).set_value backtrace
88
+ end
89
+
90
+ Gloo::Exec::Dispatch.message( @engine, 'run', o )
91
+ end
92
+ end
93
+
75
94
  end
76
95
  end
77
96
  end
@@ -164,7 +164,7 @@ module Gloo
164
164
  #
165
165
  def create_new( name, value, type, parent )
166
166
  unless parent
167
- @engine.log.error "Could not create object. Bad path: #{name}"
167
+ @engine.err "Could not create object. Bad path: #{name}"
168
168
  return nil
169
169
  end
170
170
 
@@ -202,7 +202,7 @@ module Gloo
202
202
  end
203
203
 
204
204
  unless t.can_create?
205
- @engine.log.error "'#{type_name}' cannot be created."
205
+ @engine.err "'#{type_name}' cannot be created."
206
206
  return nil
207
207
  end
208
208
 
@@ -138,7 +138,7 @@ module Gloo
138
138
  o = "msg_#{msg}"
139
139
  return self.public_send( o ) if self.respond_to? o
140
140
 
141
- @engine.log.error "Message #{msg} not implemented"
141
+ @engine.err "Message #{msg} not implemented"
142
142
  return false
143
143
  end
144
144
 
@@ -15,7 +15,7 @@ module Gloo
15
15
  # Does the pathname start with here reference?
16
16
  #
17
17
  def self.includes_here_ref?( elements )
18
- return elements.first.start_with?( HERE )
18
+ return elements.first&.start_with?( HERE )
19
19
  end
20
20
 
21
21
  #
data/lib/gloo/core/obj.rb CHANGED
@@ -137,6 +137,13 @@ module Gloo
137
137
  return self.value.to_s.strip.empty?
138
138
  end
139
139
 
140
+ #
141
+ # Value for a SQL query.
142
+ #
143
+ def sql_value
144
+ return self.value
145
+ end
146
+
140
147
  #
141
148
  # Is this an alias to another object?
142
149
  #
@@ -144,6 +151,13 @@ module Gloo
144
151
  return self.type_display == Gloo::Objs::Alias.typename
145
152
  end
146
153
 
154
+ #
155
+ # Is this a container object?
156
+ #
157
+ def is_container?
158
+ return self.type_display == Gloo::Objs::Container.typename
159
+ end
160
+
147
161
  #
148
162
  # Is this a function object?
149
163
  #
@@ -216,6 +230,30 @@ module Gloo
216
230
  return nil
217
231
  end
218
232
 
233
+ #
234
+ # Find a child, resolve any alias references.
235
+ # This returns the object, not the value.
236
+ #
237
+ def find_child_resolve_alias( name )
238
+ o = find_child name
239
+ return nil unless o
240
+
241
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
242
+ return o
243
+ end
244
+
245
+ #
246
+ # Find a child, resolve any alias references,
247
+ # and return the object's value.
248
+ #
249
+ def find_child_value( name )
250
+ o = find_child name
251
+ return nil unless o
252
+
253
+ o = Gloo::Objs::Alias.resolve_alias( @engine, o )
254
+ return o&.value
255
+ end
256
+
219
257
  #
220
258
  # Get the index of the child with the given name.
221
259
  #
@@ -264,7 +302,7 @@ module Gloo
264
302
  # Get a list of message names that this object receives.
265
303
  #
266
304
  def self.messages
267
- return %w[reload unload]
305
+ return %w[reload unload blank? contains?]
268
306
  end
269
307
 
270
308
  #
@@ -282,7 +320,7 @@ module Gloo
282
320
  @params = params
283
321
  return self.dispatch msg if self.can_receive_message? msg
284
322
 
285
- @engine.log.error "Object #{self.name} cannot receive message #{msg}"
323
+ @engine.err "Object #{self.name} cannot receive message #{msg}"
286
324
  return false
287
325
  end
288
326
 
@@ -295,7 +333,7 @@ module Gloo
295
333
  self.public_send( o )
296
334
  return true
297
335
  else
298
- @engine.log.error "Message #{msg} not implemented"
336
+ @engine.err "Message #{msg} not implemented"
299
337
  return false
300
338
  end
301
339
  end
@@ -305,7 +343,7 @@ module Gloo
305
343
  #
306
344
  def msg_unload
307
345
  if self.root?
308
- @engine.log.error 'Cannot unload the root object.'
346
+ @engine.err 'Cannot unload the root object.'
309
347
  return
310
348
  end
311
349
 
@@ -318,13 +356,31 @@ module Gloo
318
356
  #
319
357
  def msg_reload
320
358
  if self.root?
321
- @engine.log.error 'Cannot reload the root object.'
359
+ @engine.err 'Cannot reload the root object.'
322
360
  return
323
361
  end
324
362
 
325
363
  @engine.persist_man.reload self
326
364
  end
327
365
 
366
+ #
367
+ # Check to see if the value is blank.
368
+ #
369
+ def msg_blank?
370
+ val_blank = value.blank?
371
+ @engine.heap.it.set_to val_blank
372
+ return val_blank
373
+ end
374
+
375
+ #
376
+ # Check to see if there are children.
377
+ #
378
+ def msg_contains?
379
+ has_children = child_count.positive?
380
+ @engine.heap.it.set_to has_children
381
+ return has_children
382
+ end
383
+
328
384
 
329
385
  # ---------------------------------------------------------------------
330
386
  # Render
@@ -31,7 +31,7 @@ module Gloo
31
31
  verb = dic.find_verb( tokens.verb )
32
32
  return verb.new( @engine, tokens, params ) if verb
33
33
 
34
- @engine.log.error "Verb '#{tokens.verb}' was not found."
34
+ @engine.err "Verb '#{tokens.verb}' was not found."
35
35
  return nil
36
36
  end
37
37
 
data/lib/gloo/core/pn.rb CHANGED
@@ -150,7 +150,7 @@ module Gloo
150
150
  @elements[ 0..-2 ].each do |e|
151
151
  o = o.find_child( e )
152
152
  if o.nil?
153
- @engine.log.error "Object '#{e}' was not found."
153
+ @engine.err "Object '#{e}' was not found."
154
154
  return nil
155
155
  end
156
156
  end
@@ -12,10 +12,29 @@ module Gloo
12
12
  module Exec
13
13
  class Dispatch
14
14
 
15
+ OBJ_NOT_FOUND_ERR = 'Object was not found: '.freeze
16
+
17
+ #
18
+ # Send a message to an object of a given name (and path).
19
+ # Once the object is found, the message is dispatched.
20
+ #
21
+ def self.send_message( engine, msg, to_obj_pn, params = nil )
22
+ pn = Gloo::Core::Pn.new( engine, to_obj_pn )
23
+ target_obj = pn.resolve
24
+
25
+ unless target_obj
26
+ engine.err "#{OBJ_NOT_FOUND_ERR} #{to_obj_pn}"
27
+ return
28
+ end
29
+ Gloo::Exec::Dispatch.message( engine, msg, target_obj, params )
30
+ end
31
+
15
32
  #
16
33
  # Dispatch the given message to the given object.
17
34
  #
18
35
  def self.message( engine, msg, to_obj, params = nil )
36
+ return unless to_obj
37
+
19
38
  engine.log.debug "Dispatch message #{msg} to #{to_obj.name}"
20
39
  a = Gloo::Exec::Action.new msg, to_obj, params
21
40
  Gloo::Exec::Dispatch.action( engine, a )
@@ -36,7 +36,7 @@ module Gloo
36
36
  if o
37
37
  o.send_message 'run'
38
38
  else
39
- engine.log.error "Could not send message to object. Bad path: #{path_name}"
39
+ engine.err "Could not send message to object. Bad path: #{path_name}"
40
40
  end
41
41
  end
42
42
 
@@ -38,7 +38,16 @@ module Gloo
38
38
  self.value = new_value.to_i
39
39
  end
40
40
 
41
-
41
+ #
42
+ # Value for a SQL query.
43
+ #
44
+ def sql_value
45
+ return nil if self.value.blank?
46
+
47
+ return self.value
48
+ end
49
+
50
+
42
51
  # ---------------------------------------------------------------------
43
52
  # Messages
44
53
  # ---------------------------------------------------------------------
@@ -3,6 +3,7 @@
3
3
  #
4
4
  # A looping construct...do something for each whatever in something.
5
5
  # This object has several possible uses:
6
+ # - each child in a container
6
7
  # - each word in a string
7
8
  # - each line in a string
8
9
  # - each file in a directory
@@ -15,13 +16,9 @@ module Gloo
15
16
 
16
17
  KEYWORD = 'each'.freeze
17
18
  KEYWORD_SHORT = 'each'.freeze
18
- CHILD = 'child'.freeze
19
19
  WORD = 'word'.freeze
20
- LINE = 'line'.freeze
21
- FILE = 'file'.freeze
22
- REPO = 'repo'.freeze
23
- IN = 'IN'.freeze
24
20
  DO = 'do'.freeze
21
+ IN = 'IN'.freeze
25
22
 
26
23
  #
27
24
  # The name of the object type.
@@ -42,8 +39,7 @@ module Gloo
42
39
  # Returns nil if there is none.
43
40
  #
44
41
  def in_value
45
- o = find_child IN
46
- return o ? o.value : nil
42
+ return find_child_value IN
47
43
  end
48
44
 
49
45
  #
@@ -56,6 +52,7 @@ module Gloo
56
52
  Gloo::Exec::Dispatch.message( @engine, 'run', o )
57
53
  end
58
54
 
55
+
59
56
  # ---------------------------------------------------------------------
60
57
  # Children
61
58
  # ---------------------------------------------------------------------
@@ -81,6 +78,7 @@ module Gloo
81
78
  fac.create_script DO, '', self
82
79
  end
83
80
 
81
+
84
82
  # ---------------------------------------------------------------------
85
83
  # Messages
86
84
  # ---------------------------------------------------------------------
@@ -94,186 +92,21 @@ module Gloo
94
92
 
95
93
  # Run the system command.
96
94
  def msg_run
97
- if each_child?
98
- run_each_child
99
- elsif each_word?
100
- run_each_word
101
- elsif each_line?
102
- run_each_line
103
- elsif each_repo?
104
- run_each_repo
95
+ if EachChild.use_for?( self )
96
+ EachChild.new( @engine, self ).run
97
+ elsif EachWord.use_for?( self )
98
+ EachWord.new( @engine, self ).run
99
+ elsif EachLine.use_for?( self )
100
+ EachLine.new( @engine, self ).run
101
+ elsif EachFile.use_for?( self )
102
+ EachFile.new( @engine, self ).run
103
+ elsif EachRepo.use_for?( self )
104
+ EachRepo.new( @engine, self ).run
105
+ else
106
+ @engine.err "Not set up to run each for that target."
105
107
  end
106
108
  end
107
109
 
108
- # ---------------------------------------------------------------------
109
- # Child Object
110
- # ---------------------------------------------------------------------
111
-
112
- #
113
- # Is it set up to run for each word?
114
- # If there is a child object by the name "word"
115
- # then we will loop for each word in the string.
116
- #
117
- def each_child?
118
- return true if contains_child? CHILD
119
-
120
- return false
121
- end
122
-
123
- #
124
- # Run for each word.
125
- #
126
- def run_each_child
127
- o = find_child IN
128
- return unless o
129
-
130
- o = Gloo::Objs::Alias.resolve_alias( @engine, o )
131
- o.children.each do |child|
132
- set_child child
133
- run_do
134
- end
135
- end
136
-
137
- #
138
- # Set the child alias.
139
- #
140
- def set_child( obj )
141
- o = find_child CHILD
142
- return unless o
143
-
144
- o.set_value obj.pn
145
- end
146
-
147
- # ---------------------------------------------------------------------
148
- # Word
149
- # ---------------------------------------------------------------------
150
-
151
- #
152
- # Is it set up to run for each word?
153
- # If there is a child object by the name "word"
154
- # then we will loop for each word in the string.
155
- #
156
- def each_word?
157
- return true if find_child WORD
158
-
159
- return false
160
- end
161
-
162
- #
163
- # Run for each word.
164
- #
165
- def run_each_word
166
- str = in_value
167
- return unless str
168
-
169
- str.split( ' ' ).each do |word|
170
- set_word word
171
- run_do
172
- end
173
- end
174
-
175
- #
176
- # Set the value of the word.
177
- #
178
- def set_word( word )
179
- o = find_child WORD
180
- return unless o
181
-
182
- o.set_value word
183
- end
184
-
185
- # ---------------------------------------------------------------------
186
- # Line
187
- # ---------------------------------------------------------------------
188
-
189
- #
190
- # Is it set up to run for each line?
191
- # If there is a child object by the name "line"
192
- # then we will loop for each line in the string.
193
- #
194
- def each_line?
195
- return true if find_child LINE
196
-
197
- return false
198
- end
199
-
200
- #
201
- # Run for each line.
202
- #
203
- def run_each_line
204
- str = in_value
205
- return unless str
206
-
207
- str.each_line do |line|
208
- set_line line
209
- run_do
210
- end
211
- end
212
-
213
- #
214
- # Set the value of the word.
215
- #
216
- def set_line( line )
217
- o = find_child LINE
218
- return unless o
219
-
220
- o.set_value line
221
- end
222
-
223
- # ---------------------------------------------------------------------
224
- # Git Repo
225
- # ---------------------------------------------------------------------
226
-
227
- #
228
- # Is it set up to run for each git repo?
229
- # If there is a child object by the name "repo"
230
- # then we will loop for each repo in the directory.
231
- #
232
- def each_repo?
233
- return true if find_child REPO
234
-
235
- return false
236
- end
237
-
238
- #
239
- # Find all git projects in a path.
240
- #
241
- def find_all_git_projects( path )
242
- path.children.collect do |f|
243
- if f.directory? && ( File.basename( f ) == '.git' )
244
- File.dirname( f )
245
- elsif f.directory?
246
- find_all_git_projects( f )
247
- end
248
- end.flatten.compact
249
- end
250
-
251
- #
252
- # Run for each line.
253
- #
254
- def run_each_repo
255
- path = in_value
256
- return unless path
257
-
258
- path = Pathname.new( path )
259
- repos = find_all_git_projects( path )
260
- repos.each do |o|
261
- set_repo o
262
- run_do
263
- end
264
- end
265
-
266
- #
267
- # Set the value of the repo.
268
- # This is a path to the repo.
269
- #
270
- def set_repo( path )
271
- o = find_child REPO
272
- return unless o
273
-
274
- o.set_value path
275
- end
276
-
277
110
  end
278
111
  end
279
112
  end