spreadsheet_agent 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|