spreadsheet_agent 0.0.1
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.
- data/lib/spreadsheet_agent.rb +418 -0
- data/lib/spreadsheet_agent/db.rb +55 -0
- data/lib/spreadsheet_agent/error.rb +12 -0
- data/lib/spreadsheet_agent/runner.rb +306 -0
- data/test/agent_bin/othergoal_agent.rb +17 -0
- data/test/agent_bin/testgoal_agent.rb +18 -0
- data/test/spreadsheet_agent_db_test.rb +13 -0
- data/test/spreadsheet_agent_runner_test.rb +468 -0
- data/test/spreadsheet_agent_test.rb +411 -0
- metadata +157 -0
@@ -0,0 +1,411 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'shoulda/context'
|
3
|
+
require 'spreadsheet_agent'
|
4
|
+
require 'google_drive'
|
5
|
+
require 'psych'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
class TC_SpreadsheetAgentTest < Test::Unit::TestCase
|
9
|
+
|
10
|
+
context 'Agent' do
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@config_file = File.expand_path(File.dirname( __FILE__ )) + '/../config/agent.conf.yml'
|
14
|
+
|
15
|
+
unless File.exists? @config_file
|
16
|
+
$stderr.puts "You must create a valid test Google Spreadsheet and a valid #{ @config_file } configuration file pointing to it to run the tests. See README.txt file for more information on how to run the tests."
|
17
|
+
exit(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
@testing_page_name = 'testing'
|
21
|
+
@keys = { 'testentry' => 'test', 'testpage' => @testing_page_name }
|
22
|
+
@testing_page = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
teardown do
|
26
|
+
unless @testing_page.nil?
|
27
|
+
@testing_page.max_rows = 1
|
28
|
+
colnum = 1
|
29
|
+
while colnum <= @testing_page.num_cols
|
30
|
+
@testing_page[1,colnum] = nil
|
31
|
+
colnum += 1
|
32
|
+
end
|
33
|
+
@testing_page.save
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'instantiated' do
|
38
|
+
|
39
|
+
should 'be a SpreadsheetAgent::Agent' do
|
40
|
+
google_agent = SpreadsheetAgent::Agent.new(
|
41
|
+
:agent_name => 'instantiate',
|
42
|
+
:page_name => @testing_page_name,
|
43
|
+
:keys => @keys,
|
44
|
+
:config_file => @config_file
|
45
|
+
)
|
46
|
+
assert_not_nil google_agent, 'google_agent is nil!'
|
47
|
+
assert_instance_of(SpreadsheetAgent::Agent, google_agent)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end #instantiated
|
52
|
+
|
53
|
+
context 'that is not ready' do
|
54
|
+
|
55
|
+
setup do
|
56
|
+
@agent_name = 'donotrun'
|
57
|
+
@google_agent = prepare_google_agent_for(@agent_name, false)
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'return true from process! but not run the supplied code' do
|
61
|
+
subroutine_ran = false
|
62
|
+
process_ran = @google_agent.process! do |entry|
|
63
|
+
# this should not run at all
|
64
|
+
subroutine_ran = true
|
65
|
+
true
|
66
|
+
end
|
67
|
+
assert process_ran, 'process! should return true'
|
68
|
+
assert !subroutine_ran, 'The subref should not have run at all'
|
69
|
+
entry = @google_agent.get_entry
|
70
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should still be empty"
|
71
|
+
end
|
72
|
+
|
73
|
+
end #that is not ready
|
74
|
+
|
75
|
+
context 'that is ready' do
|
76
|
+
|
77
|
+
setup do
|
78
|
+
@agent_name = 'readytorun'
|
79
|
+
@google_agent = prepare_google_agent_for(@agent_name, true)
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'return true from process!, run passing code, and complete the agent_name field' do
|
83
|
+
subroutine_ran = false
|
84
|
+
process_ran = @google_agent.process! do |entry|
|
85
|
+
subroutine_ran = true
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
assert process_ran, 'process should return true'
|
90
|
+
assert subroutine_ran, 'The subref should have run'
|
91
|
+
entry = @google_agent.get_entry
|
92
|
+
assert_equal "1", entry[@agent_name], "#{ @agent_name } field should have completed successfully"
|
93
|
+
end
|
94
|
+
|
95
|
+
should 'return true from process!, run failing code, and Fail the agent_name field' do
|
96
|
+
subroutine_ran = false
|
97
|
+
process_ran = @google_agent.process! do |entry|
|
98
|
+
subroutine_ran = true
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
102
|
+
assert process_ran, 'process should return true'
|
103
|
+
assert subroutine_ran, 'The subref should have run'
|
104
|
+
entry = @google_agent.get_entry
|
105
|
+
expected_field_value = ['F', Socket.gethostname].join(':')
|
106
|
+
assert_equal expected_field_value, entry[@agent_name], "#{ @agent_name } field should have failed with #{ expected_field_value}, was #{ entry[@agent_name] }"
|
107
|
+
end
|
108
|
+
|
109
|
+
should 'be able to update cell contents on success' do
|
110
|
+
updated_cell_name = 'updatevalue'
|
111
|
+
updated_cell_value = 'iamupdated';
|
112
|
+
add_header_to_page(updated_cell_name, @testing_page)
|
113
|
+
subroutine_ran = false
|
114
|
+
|
115
|
+
process_ran = @google_agent.process! do |entry|
|
116
|
+
subroutine_ran = true
|
117
|
+
[true, { updated_cell_name => updated_cell_value }]
|
118
|
+
end
|
119
|
+
|
120
|
+
assert process_ran, 'process should return true'
|
121
|
+
assert subroutine_ran, 'The subref should have run'
|
122
|
+
entry = @google_agent.get_entry
|
123
|
+
assert_equal "1", entry[@agent_name], "#{ @agent_name } field should have completed successfully"
|
124
|
+
assert_equal updated_cell_value, entry[updated_cell_name]
|
125
|
+
end
|
126
|
+
|
127
|
+
end #that is ready
|
128
|
+
|
129
|
+
context 'that requires a prerequisite' do
|
130
|
+
|
131
|
+
setup do
|
132
|
+
@agent_name = 'readyifprereq'
|
133
|
+
@prerequisite_cell_name = 'prerequisitecell'
|
134
|
+
@prerequisites = [ @prerequisite_cell_name ]
|
135
|
+
@google_agent = prepare_google_agent_for(@agent_name, true, nil, { :prerequisites => @prerequisites } )
|
136
|
+
add_header_to_page(@prerequisite_cell_name, @testing_page)
|
137
|
+
end
|
138
|
+
|
139
|
+
should 'set prerequisites on agent' do
|
140
|
+
assert_not_nil @google_agent.prerequisites
|
141
|
+
assert_equal @prerequisites.count, @google_agent.prerequisites.count
|
142
|
+
@prerequisites.each do |prereq|
|
143
|
+
assert @google_agent.prerequisites.include?(prereq), "#{ prereq } should be a prerequisite"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
should 'not run if prerequisite has not run' do
|
148
|
+
entry = @google_agent.get_entry
|
149
|
+
assert entry[@prerequisite_cell_name].empty?, "#{ @prerequisite_cell_name } is #{ entry[@prerequisite_cell_name] } but should be empty!"
|
150
|
+
|
151
|
+
subroutine_ran = false
|
152
|
+
process_ran = @google_agent.process! do |entry|
|
153
|
+
# this should not run at all
|
154
|
+
subroutine_ran = true
|
155
|
+
true
|
156
|
+
end
|
157
|
+
|
158
|
+
assert process_ran, 'process! should return true'
|
159
|
+
assert !subroutine_ran, 'The subref should not have run at all'
|
160
|
+
entry = @google_agent.get_entry
|
161
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should still be empty"
|
162
|
+
end
|
163
|
+
|
164
|
+
should 'not run if prerequisite has failed' do
|
165
|
+
failed_value = ['F', Socket.gethostname].join(':')
|
166
|
+
entry = @google_agent.get_entry
|
167
|
+
entry.update(@prerequisite_cell_name => failed_value)
|
168
|
+
@testing_page.save
|
169
|
+
|
170
|
+
subroutine_ran = false
|
171
|
+
process_ran = @google_agent.process! do |entry|
|
172
|
+
# this should not run at all
|
173
|
+
subroutine_ran = true
|
174
|
+
true
|
175
|
+
end
|
176
|
+
|
177
|
+
assert process_ran, 'process! should return true'
|
178
|
+
assert !subroutine_ran, 'The subref should not have run at all'
|
179
|
+
entry = @google_agent.get_entry
|
180
|
+
assert_equal failed_value, entry[@prerequisite_cell_name]
|
181
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should still be empty"
|
182
|
+
end
|
183
|
+
|
184
|
+
should 'run if prerequisite has run successfully' do
|
185
|
+
success_value = "1"
|
186
|
+
entry = @google_agent.get_entry
|
187
|
+
entry.update( @prerequisite_cell_name => success_value )
|
188
|
+
@testing_page.save
|
189
|
+
|
190
|
+
subroutine_ran = false
|
191
|
+
process_ran = @google_agent.process! do |entry|
|
192
|
+
subroutine_ran = true
|
193
|
+
true
|
194
|
+
end
|
195
|
+
|
196
|
+
assert process_ran, 'process! should return true'
|
197
|
+
assert subroutine_ran, 'The subref should have run'
|
198
|
+
entry = @google_agent.get_entry
|
199
|
+
assert_equal success_value, entry[@prerequisite_cell_name]
|
200
|
+
assert_equal "1", entry[@agent_name]
|
201
|
+
end
|
202
|
+
|
203
|
+
end #that requires a prerequisite
|
204
|
+
|
205
|
+
context 'max_selves' do
|
206
|
+
setup do
|
207
|
+
@agent_name = 'maxselftest'
|
208
|
+
@allowed_selves = 3
|
209
|
+
@google_agents = { }
|
210
|
+
row = 2
|
211
|
+
4.times do
|
212
|
+
@keys['testentry'] = "test#{ row }"
|
213
|
+
@google_agents[@keys['testentry']] = prepare_google_agent_for(@agent_name, true, row, { :max_selves => @allowed_selves } )
|
214
|
+
row += 1
|
215
|
+
end
|
216
|
+
@command = 'ruby -e ' + "'" + '$0 = "%s"; sleep 120;' + "'"
|
217
|
+
@command %= File.basename $0
|
218
|
+
end
|
219
|
+
|
220
|
+
should 'set max_selves on agent' do
|
221
|
+
row = 2
|
222
|
+
4.times do
|
223
|
+
assert_not_nil @google_agents["test#{ row }"].max_selves
|
224
|
+
assert_equal @allowed_selves, @google_agents["test#{ row }"].max_selves
|
225
|
+
row += 1
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
should 'not allow more than max_selves agents of the same name to run' do
|
230
|
+
row = 2
|
231
|
+
num_running = 0
|
232
|
+
@allowed_selves.times do
|
233
|
+
assert num_running < @google_agents[ "test#{ row }" ].max_selves, "#{ num_running } is greater than #{ @google_agents[ "test#{ row }" ].max_selves }!"
|
234
|
+
|
235
|
+
subroutine_ran = false
|
236
|
+
process_ran = @google_agents[ "test#{ row }" ].process! do |entry|
|
237
|
+
subroutine_ran = true
|
238
|
+
true
|
239
|
+
end
|
240
|
+
|
241
|
+
assert process_ran, 'process should return true'
|
242
|
+
assert subroutine_ran, 'The subref should have run'
|
243
|
+
entry = @google_agents[ "test#{ row }" ].get_entry
|
244
|
+
assert_equal "1", entry[@agent_name], "#{ @agent_name } field should have completed successfully"
|
245
|
+
|
246
|
+
system("#{ @command } &")
|
247
|
+
row += 1
|
248
|
+
num_running += 1
|
249
|
+
end
|
250
|
+
assert_equal num_running, @google_agents[ "test#{ row }" ].max_selves
|
251
|
+
|
252
|
+
subroutine_ran = false
|
253
|
+
process_ran = @google_agents[ "test#{ row }" ].process! do |entry|
|
254
|
+
subroutine_ran = true
|
255
|
+
true
|
256
|
+
end
|
257
|
+
|
258
|
+
assert process_ran, 'process should return true'
|
259
|
+
assert !subroutine_ran, 'The subref should not have run'
|
260
|
+
entry = @google_agents[ "test#{ row }" ].get_entry
|
261
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should still be empty"
|
262
|
+
end
|
263
|
+
|
264
|
+
end #max_selves
|
265
|
+
|
266
|
+
context 'conflicts_with' do
|
267
|
+
|
268
|
+
setup do
|
269
|
+
@agent_name = 'conflictswithtest'
|
270
|
+
@max_conflicters = 2
|
271
|
+
@conflicting_script = 'conflicting_agent.rb'
|
272
|
+
@conflicts_with = { @conflicting_script => @max_conflicters }
|
273
|
+
@google_agent = prepare_google_agent_for(@agent_name, true, nil, { :conflicts_with => @conflicts_with } )
|
274
|
+
@command = 'ruby -e ' + "'" + '$0 = "%s"; sleep 60;' + "'"
|
275
|
+
@command %= @conflicting_script
|
276
|
+
end
|
277
|
+
|
278
|
+
should 'set conflicts_with on agent' do
|
279
|
+
assert_not_nil @google_agent.conflicts_with
|
280
|
+
assert @google_agent.conflicts_with.has_key? @conflicting_script
|
281
|
+
assert_equal @max_conflicters, @google_agent.conflicts_with[@conflicting_script]
|
282
|
+
end
|
283
|
+
|
284
|
+
should 'only run if a sufficiently low number of conflicting scripts are running' do
|
285
|
+
num_running = 0
|
286
|
+
@max_conflicters.times do
|
287
|
+
system("#{ @command } &")
|
288
|
+
num_running += 1
|
289
|
+
|
290
|
+
subroutine_ran = false
|
291
|
+
process_ran = @google_agent.process! do |entry|
|
292
|
+
subroutine_ran = true
|
293
|
+
true
|
294
|
+
end
|
295
|
+
assert process_ran, 'process should return true'
|
296
|
+
entry = @google_agent.get_entry
|
297
|
+
|
298
|
+
if num_running < @google_agent.conflicts_with[@conflicting_script]
|
299
|
+
assert subroutine_ran, "The subref should have run on the #{ num_running }th time"
|
300
|
+
assert_equal "1", entry[@agent_name], "#{ @agent_name } field should have completed successfully"
|
301
|
+
else
|
302
|
+
assert !subroutine_ran, 'The subref should not have run'
|
303
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should still be empty, got #{ entry[@agent_name ] }"
|
304
|
+
end
|
305
|
+
|
306
|
+
@testing_page[2,4] = nil
|
307
|
+
@testing_page.save
|
308
|
+
end
|
309
|
+
assert_equal num_running, @google_agent.conflicts_with[@conflicting_script]
|
310
|
+
end
|
311
|
+
|
312
|
+
end #conflicts_with
|
313
|
+
|
314
|
+
context 'subsumes' do
|
315
|
+
setup do
|
316
|
+
@agent_name = 'subsumingagent'
|
317
|
+
@subsumed_cell_name = 'subsumedcell'
|
318
|
+
@subsumes = [ @subsumed_cell_name ]
|
319
|
+
@google_agent = prepare_google_agent_for(@agent_name, true, nil, { :subsumes => @subsumes } )
|
320
|
+
add_header_to_page(@subsumed_cell_name, @testing_page)
|
321
|
+
end
|
322
|
+
|
323
|
+
should 'set subsumes on agent' do
|
324
|
+
assert_not_nil @google_agent.subsumes
|
325
|
+
assert_equal @subsumes.count, @google_agent.subsumes.count
|
326
|
+
@subsumes.each do |subsumed|
|
327
|
+
assert @google_agent.subsumes.include?(subsumed), "#{ subsumed } should be a a subsumed field"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
should 'update subsumed cell if run completes successfully' do
|
332
|
+
entry = @google_agent.get_entry
|
333
|
+
assert entry[@agent_name].empty?, "#{ @agent_name } field should be empty"
|
334
|
+
assert entry[@subsumed_cell_name].empty?, "#{ @subsumed_cell_name } field should be empty"
|
335
|
+
|
336
|
+
success_value = "1"
|
337
|
+
subroutine_ran = false
|
338
|
+
process_ran = @google_agent.process! do |entry|
|
339
|
+
# this should not run at all
|
340
|
+
subroutine_ran = true
|
341
|
+
true
|
342
|
+
end
|
343
|
+
|
344
|
+
assert process_ran, 'process! should return true'
|
345
|
+
assert subroutine_ran, 'The subref should have run'
|
346
|
+
entry = @google_agent.get_entry
|
347
|
+
assert_equal success_value, entry[@agent_name]
|
348
|
+
assert_equal success_value, entry[@subsumed_cell_name]
|
349
|
+
end
|
350
|
+
|
351
|
+
end #subsumes
|
352
|
+
|
353
|
+
context 'config_file' do
|
354
|
+
|
355
|
+
setup do
|
356
|
+
@agent_name = 'configagent'
|
357
|
+
@test_config_file = File.expand_path( File.dirname(__FILE__) + '/../config/test.config.yml' )
|
358
|
+
end
|
359
|
+
|
360
|
+
should 'be overridable' do
|
361
|
+
assert File.exists?(@test_config_file), "#{ @test_config_file } does not exist!"
|
362
|
+
test_config = Psych.load_file(@test_config_file)
|
363
|
+
@google_agent = prepare_google_agent_for(@agent_name, true, nil, { :config_file => @test_config_file } )
|
364
|
+
assert_equal @test_config_file, @google_agent.config_file
|
365
|
+
test_config.keys.each do |tkey|
|
366
|
+
assert @google_agent.config.has_key? tkey
|
367
|
+
assert_equal test_config[tkey], @google_agent.config[tkey]
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
end #config_file
|
372
|
+
|
373
|
+
end #Agent
|
374
|
+
|
375
|
+
def prepare_google_agent_for(agent, ready, agent_row = nil, extra_params = nil)
|
376
|
+
init_params = {
|
377
|
+
:agent_name => agent,
|
378
|
+
:page_name => @testing_page_name,
|
379
|
+
:keys => @keys,
|
380
|
+
:debug => true,
|
381
|
+
:config_file => @config_file
|
382
|
+
}
|
383
|
+
unless extra_params.nil?
|
384
|
+
init_params.merge!(extra_params)
|
385
|
+
end
|
386
|
+
|
387
|
+
google_agent = SpreadsheetAgent::Agent.new(init_params)
|
388
|
+
@testing_page = google_agent.worksheet
|
389
|
+
|
390
|
+
colnum = 1
|
391
|
+
['testentry','testpage','ready', agent, 'complete'].each do |field|
|
392
|
+
@testing_page[1,colnum] = field
|
393
|
+
colnum += 1
|
394
|
+
end
|
395
|
+
if agent_row.nil?
|
396
|
+
agent_row = 2
|
397
|
+
end
|
398
|
+
|
399
|
+
@testing_page[agent_row,1] = @keys['testentry']
|
400
|
+
@testing_page[agent_row,2] = @keys['testpage']
|
401
|
+
@testing_page[agent_row,3] = "1" if ready
|
402
|
+
@testing_page.save
|
403
|
+
google_agent
|
404
|
+
end
|
405
|
+
|
406
|
+
def add_header_to_page(header, page)
|
407
|
+
page[1, page.num_cols + 1] = header
|
408
|
+
page.save
|
409
|
+
end
|
410
|
+
|
411
|
+
end #TC_SpreadsheetAgentTest
|
metadata
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spreadsheet_agent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Darin London
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: google_drive
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: capture_io
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.1'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.1'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mail
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.5'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.5'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: shoulda-context
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '1.1'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '1.1'
|
94
|
+
description: ! 'SpreadsheetAgent is a framework for creating distributed pipelines
|
95
|
+
across many
|
96
|
+
|
97
|
+
different servers. It is extensible, and flexible. It does not specify what goals
|
98
|
+
|
99
|
+
any pipeline should be working towards, or which goals are prerequisites for
|
100
|
+
|
101
|
+
other goals, but it does provide logic for easily defining these relationships
|
102
|
+
|
103
|
+
based on your own needs. It does this by providing a subsumption architecture,
|
104
|
+
|
105
|
+
whereby many small, highly focused agents are written to perform specific goals,
|
106
|
+
|
107
|
+
and also know what prerequisites and resources they require to perform them.
|
108
|
+
|
109
|
+
In addition, it is designed from the beginning to support the creation of simple
|
110
|
+
|
111
|
+
human-computational workflows.
|
112
|
+
|
113
|
+
'
|
114
|
+
email: darin.london@duke.edu
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- lib/spreadsheet_agent/db.rb
|
120
|
+
- lib/spreadsheet_agent/error.rb
|
121
|
+
- lib/spreadsheet_agent/runner.rb
|
122
|
+
- lib/spreadsheet_agent.rb
|
123
|
+
- test/agent_bin/othergoal_agent.rb
|
124
|
+
- test/agent_bin/testgoal_agent.rb
|
125
|
+
- test/spreadsheet_agent_db_test.rb
|
126
|
+
- test/spreadsheet_agent_runner_test.rb
|
127
|
+
- test/spreadsheet_agent_test.rb
|
128
|
+
homepage: http://rubygems.org/gems/spreadsheet_agent
|
129
|
+
licenses:
|
130
|
+
- MIT
|
131
|
+
post_install_message:
|
132
|
+
rdoc_options: []
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 1.8.24
|
150
|
+
signing_key:
|
151
|
+
specification_version: 3
|
152
|
+
summary: SpreadsheetAgent is a framework for creating distributed pipelines across
|
153
|
+
many different servers, each using the same google spreadsheet as a control panel.
|
154
|
+
test_files:
|
155
|
+
- test/spreadsheet_agent_db_test.rb
|
156
|
+
- test/spreadsheet_agent_runner_test.rb
|
157
|
+
- test/spreadsheet_agent_test.rb
|