scout-gear 7.3.0 → 8.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.vimproject +44 -16
- data/Rakefile +6 -1
- data/VERSION +1 -1
- data/bin/scout +21 -7
- data/doc/lib/scout/path.md +35 -0
- data/doc/lib/scout/workflow/task.md +13 -0
- data/lib/rbbt-scout.rb +1 -0
- data/lib/scout/cmd.rb +24 -25
- data/lib/scout/concurrent_stream.rb +59 -39
- data/lib/scout/config.rb +1 -1
- data/lib/scout/exceptions.rb +10 -0
- data/lib/scout/log/color.rb +15 -12
- data/lib/scout/log/progress/report.rb +8 -6
- data/lib/scout/log/progress/util.rb +61 -54
- data/lib/scout/log/progress.rb +1 -1
- data/lib/scout/log/trap.rb +107 -0
- data/lib/scout/log.rb +115 -52
- data/lib/scout/meta_extension.rb +47 -6
- data/lib/scout/misc/digest.rb +12 -3
- data/lib/scout/misc/format.rb +24 -7
- data/lib/scout/misc/insist.rb +1 -1
- data/lib/scout/misc/monitor.rb +22 -0
- data/lib/scout/misc/system.rb +58 -0
- data/lib/scout/named_array.rb +73 -3
- data/lib/scout/offsite/ssh.rb +171 -0
- data/lib/scout/offsite/step.rb +83 -0
- data/lib/scout/offsite/sync.rb +55 -0
- data/lib/scout/offsite.rb +3 -0
- data/lib/scout/open/lock/lockfile.rb +587 -0
- data/lib/scout/open/lock.rb +9 -2
- data/lib/scout/open/remote.rb +16 -1
- data/lib/scout/open/stream.rb +146 -83
- data/lib/scout/open/util.rb +22 -3
- data/lib/scout/open.rb +5 -4
- data/lib/scout/path/find.rb +24 -11
- data/lib/scout/path/util.rb +40 -0
- data/lib/scout/persist/serialize.rb +19 -6
- data/lib/scout/persist.rb +29 -13
- data/lib/scout/resource/path.rb +57 -0
- data/lib/scout/resource/produce.rb +0 -8
- data/lib/scout/resource/util.rb +12 -5
- data/lib/scout/tmpfile.rb +7 -8
- data/lib/scout/tsv/attach.rb +177 -0
- data/lib/scout/tsv/change_id.rb +40 -0
- data/lib/scout/tsv/dumper.rb +74 -46
- data/lib/scout/tsv/index.rb +85 -87
- data/lib/scout/tsv/open.rb +160 -85
- data/lib/scout/tsv/parser.rb +142 -80
- data/lib/scout/tsv/path.rb +1 -2
- data/lib/scout/tsv/persist/adapter.rb +15 -45
- data/lib/scout/tsv/persist/fix_width_table.rb +3 -0
- data/lib/scout/tsv/persist/tokyocabinet.rb +6 -1
- data/lib/scout/tsv/persist.rb +4 -0
- data/lib/scout/tsv/stream.rb +204 -0
- data/lib/scout/tsv/transformer.rb +152 -0
- data/lib/scout/tsv/traverse.rb +96 -92
- data/lib/scout/tsv/util/filter.rb +9 -0
- data/lib/scout/tsv/util/reorder.rb +81 -0
- data/lib/scout/tsv/util/select.rb +78 -33
- data/lib/scout/tsv/util/unzip.rb +86 -0
- data/lib/scout/tsv/util.rb +60 -11
- data/lib/scout/tsv.rb +34 -4
- data/lib/scout/work_queue/socket.rb +6 -1
- data/lib/scout/work_queue/worker.rb +5 -2
- data/lib/scout/work_queue.rb +51 -20
- data/lib/scout/workflow/definition.rb +23 -3
- data/lib/scout/workflow/deployment/orchestrator.rb +245 -0
- data/lib/scout/workflow/deployment.rb +1 -0
- data/lib/scout/workflow/step/dependencies.rb +56 -10
- data/lib/scout/workflow/step/file.rb +5 -0
- data/lib/scout/workflow/step/info.rb +40 -7
- data/lib/scout/workflow/step/load.rb +1 -1
- data/lib/scout/workflow/step/provenance.rb +9 -7
- data/lib/scout/workflow/step/status.rb +43 -0
- data/lib/scout/workflow/step.rb +160 -49
- data/lib/scout/workflow/task/dependencies.rb +114 -0
- data/lib/scout/workflow/task/inputs.rb +40 -32
- data/lib/scout/workflow/task.rb +38 -102
- data/lib/scout/workflow/usage.rb +48 -18
- data/lib/scout/workflow.rb +4 -2
- data/lib/scout-gear.rb +2 -0
- data/lib/scout.rb +6 -0
- data/scout-gear.gemspec +52 -23
- data/scout_commands/doc +37 -0
- data/scout_commands/find +1 -0
- data/scout_commands/offsite +30 -0
- data/scout_commands/update +29 -0
- data/scout_commands/workflow/info +15 -3
- data/scout_commands/workflow/install +102 -0
- data/scout_commands/workflow/task +57 -9
- data/test/scout/offsite/test_ssh.rb +15 -0
- data/test/scout/offsite/test_step.rb +33 -0
- data/test/scout/offsite/test_sync.rb +36 -0
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/open/test_stream.rb +60 -58
- data/test/scout/path/test_find.rb +10 -1
- data/test/scout/resource/test_path.rb +6 -0
- data/test/scout/resource/test_produce.rb +15 -0
- data/test/scout/test_meta_extension.rb +25 -0
- data/test/scout/test_named_array.rb +24 -0
- data/test/scout/test_persist.rb +9 -2
- data/test/scout/test_tsv.rb +229 -2
- data/test/scout/test_work_queue.rb +65 -41
- data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
- data/test/scout/tsv/test_attach.rb +227 -0
- data/test/scout/tsv/test_change_id.rb +98 -0
- data/test/scout/tsv/test_dumper.rb +1 -1
- data/test/scout/tsv/test_index.rb +49 -3
- data/test/scout/tsv/test_open.rb +160 -2
- data/test/scout/tsv/test_parser.rb +33 -2
- data/test/scout/tsv/test_persist.rb +2 -0
- data/test/scout/tsv/test_stream.rb +200 -0
- data/test/scout/tsv/test_transformer.rb +120 -0
- data/test/scout/tsv/test_traverse.rb +88 -3
- data/test/scout/tsv/test_util.rb +1 -0
- data/test/scout/tsv/util/test_reorder.rb +94 -0
- data/test/scout/tsv/util/test_select.rb +25 -11
- data/test/scout/tsv/util/test_unzip.rb +112 -0
- data/test/scout/work_queue/test_socket.rb +0 -1
- data/test/scout/workflow/deployment/test_orchestrator.rb +272 -0
- data/test/scout/workflow/step/test_dependencies.rb +68 -0
- data/test/scout/workflow/step/test_info.rb +18 -0
- data/test/scout/workflow/step/test_status.rb +30 -0
- data/test/scout/workflow/task/test_dependencies.rb +355 -0
- data/test/scout/workflow/task/test_inputs.rb +67 -14
- data/test/scout/workflow/test_definition.rb +18 -0
- data/test/scout/workflow/test_documentation.rb +24 -0
- data/test/scout/workflow/test_step.rb +112 -3
- data/test/scout/workflow/test_task.rb +0 -151
- data/test/scout/workflow/test_usage.rb +33 -6
- data/test/test_scout.rb +9 -0
- metadata +100 -8
- data/scout_commands/workflow/task_old +0 -706
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
|
+
|
7
|
+
options = SOPT.setup <<EOF
|
8
|
+
|
9
|
+
Description of the tool
|
10
|
+
|
11
|
+
$ #{$0} [<options>] <filename> [<other|->]*
|
12
|
+
|
13
|
+
Install a workflow, or a coma separated list of workflows, from its source. If
|
14
|
+
repo is not specified then 'http://github.com/Rbbt-Workflows/' will be used. If
|
15
|
+
the workflow is already installed it will be updated. If 'all' is specified
|
16
|
+
instead of a particular workflow, all installed workflows will be updated.
|
17
|
+
|
18
|
+
You can set the environment variable SCOUT_WORKFLOW_AUTOINSTALL=true to make
|
19
|
+
workflows install automatically as required.
|
20
|
+
|
21
|
+
-h--help Print this help
|
22
|
+
EOF
|
23
|
+
if options[:help]
|
24
|
+
if defined? scout_usage
|
25
|
+
scout_usage
|
26
|
+
else
|
27
|
+
puts SOPT.doc
|
28
|
+
end
|
29
|
+
exit 0
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
workflow = ARGV[0]
|
34
|
+
base_repo = ARGV[1]
|
35
|
+
|
36
|
+
raise "No workflow specified" if workflow.nil?
|
37
|
+
|
38
|
+
workflow_dir = Scout.etc.workflow_dir.exists? ? Path.setup(Scout.etc.workflow_dir.read.strip) : Scout.workflows.find(:user)
|
39
|
+
|
40
|
+
FileUtils.mkdir_p workflow_dir unless File.exist? workflow_dir
|
41
|
+
|
42
|
+
all_workflows = workflow_dir.find.glob("*/.git").collect{|d| File.basename(File.dirname(d))}
|
43
|
+
workflows = workflow == 'all' ? all_workflows : workflow.split(",")
|
44
|
+
|
45
|
+
Misc.in_dir(workflow_dir) do
|
46
|
+
workflows.each do |workflow|
|
47
|
+
case
|
48
|
+
when File.exist?(Misc.snake_case(workflow))
|
49
|
+
Log.info "Updating: " + workflow
|
50
|
+
Misc.in_dir(Misc.snake_case(workflow)) do
|
51
|
+
`git pull`
|
52
|
+
`git submodule init`
|
53
|
+
`git submodule update`
|
54
|
+
end
|
55
|
+
when File.exist?(workflow)
|
56
|
+
Misc.in_dir(workflow) do
|
57
|
+
Log.info "Updating: " + workflow
|
58
|
+
`git pull`
|
59
|
+
`git submodule init`
|
60
|
+
`git submodule update`
|
61
|
+
end
|
62
|
+
else
|
63
|
+
Log.info "Installing: " + workflow
|
64
|
+
|
65
|
+
if base_repo.nil?
|
66
|
+
repo_base_url = Rbbt.etc.workflow_repo.exists? ? Rbbt.etc.workflow_repo.read.strip : 'https://github.com/Rbbt-Workflows/'
|
67
|
+
else
|
68
|
+
repo_base_url = base_repo
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
if repo_base_url.include?(workflow) or repo_base_url.include?(Misc.snake_case(workflow))
|
73
|
+
repo = repo_base_url
|
74
|
+
else
|
75
|
+
begin
|
76
|
+
repo = File.join(repo_base_url, workflow + '.git')
|
77
|
+
CMD.cmd("wget '#{repo}' -O /dev/null").read
|
78
|
+
rescue
|
79
|
+
Log.debug "Workflow repo does not exist, trying snake_case: #{ repo }"
|
80
|
+
begin
|
81
|
+
repo = File.join(repo_base_url, Misc.snake_case(workflow) + '.git')
|
82
|
+
CMD.cmd("wget '#{repo}' -O /dev/null").read
|
83
|
+
rescue
|
84
|
+
raise "Workflow repo does not exist: #{ repo }"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
Log.warn "Cloning #{ repo }"
|
90
|
+
Misc.insist do
|
91
|
+
`git clone "#{repo}" #{ Misc.snake_case(workflow) }`
|
92
|
+
raise unless $?.success?
|
93
|
+
end
|
94
|
+
Log.warn "Initializing and updating submodules for #{repo}. You might be prompted for passwords."
|
95
|
+
Misc.in_dir(Misc.snake_case(workflow)) do
|
96
|
+
`git submodule init`
|
97
|
+
`git submodule update`
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
@@ -4,6 +4,11 @@ require 'scout'
|
|
4
4
|
|
5
5
|
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
6
6
|
|
7
|
+
ENV["SCOUT_NO_STREAM"] = "true" if ARGV.include? "--nostream"
|
8
|
+
ARGV.delete '--nostream'
|
9
|
+
ENV["SCOUT_UPDATE"] = "true" if ARGV.include? "--update"
|
10
|
+
ARGV.delete '--update'
|
11
|
+
|
7
12
|
options = SOPT.setup <<EOF
|
8
13
|
|
9
14
|
Run a workflow job
|
@@ -11,11 +16,16 @@ Run a workflow job
|
|
11
16
|
$ #{$0} [<options>] <workflow> <task>
|
12
17
|
|
13
18
|
-h--help Print this help
|
19
|
+
--nostream Disable job streaming
|
20
|
+
--update Update jobs with newer dependencies
|
14
21
|
-jn--job_name* Name to use as job identifier
|
22
|
+
-li--load_inputs* Directory with inputs files to load
|
15
23
|
-pf--print_filepath Print the file path
|
16
24
|
-prov--provenance Print the step provenance
|
17
25
|
-cl--clean Clean the last step
|
18
26
|
-rcl--recursive_clean Clean all steps
|
27
|
+
-ct--clean_task* Clean a particular task
|
28
|
+
-d--deploy* Deploy mode: serial, local, or SLURM (default 'serial')
|
19
29
|
EOF
|
20
30
|
|
21
31
|
workflow_name, task_name = ARGV
|
@@ -28,7 +38,11 @@ task = workflow.tasks[task_name.to_sym] if task_name
|
|
28
38
|
|
29
39
|
options[:help] = true if task.nil?
|
30
40
|
|
31
|
-
|
41
|
+
help, provenance, clean, recursive_clean, clean_task, load_inputs, jobname, print_filepath, deploy = IndiferentHash.process_options options,
|
42
|
+
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :job_name, :print_filepath, :deploy,
|
43
|
+
:deploy => 'serial'
|
44
|
+
|
45
|
+
if help
|
32
46
|
if defined? scout_usage
|
33
47
|
scout_usage
|
34
48
|
else
|
@@ -39,18 +53,52 @@ if options[:help]
|
|
39
53
|
exit 0
|
40
54
|
end
|
41
55
|
|
42
|
-
|
43
|
-
|
56
|
+
if load_inputs
|
57
|
+
job_inputs = workflow.tasks[task_name].load_inputs(load_inputs)
|
58
|
+
else
|
59
|
+
job_inputs = task.get_SOPT
|
60
|
+
end
|
44
61
|
|
45
|
-
job.
|
46
|
-
|
62
|
+
job = workflow.job(task_name, jobname, job_inputs)
|
63
|
+
|
64
|
+
job.recursive_clean if recursive_clean
|
65
|
+
job.clean if clean
|
66
|
+
|
67
|
+
if clean_task
|
68
|
+
ENV["SCOUT_UPDATE"] = 'true'
|
69
|
+
clean_task.split(",").each do |clean_task|
|
70
|
+
if clean_task.include? "#"
|
71
|
+
clean_workflow, clean_task = clean_task.split("#")
|
72
|
+
end
|
47
73
|
|
48
|
-
|
74
|
+
job.rec_dependencies.each do |dep|
|
75
|
+
next unless dep.task_name.to_s == clean_task.to_s
|
76
|
+
next unless clean_workflow.nil? || clean_workflow == dep.workflow.to_s
|
77
|
+
dep.clean
|
78
|
+
dep.set_info :status, :cleaned
|
79
|
+
end
|
80
|
+
|
81
|
+
job.clean if job.task_name.to_s == clean_task.to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if provenance
|
49
86
|
puts Step.prov_report(job)
|
50
87
|
else
|
51
|
-
|
52
|
-
|
53
|
-
|
88
|
+
case deploy
|
89
|
+
when "serial"
|
90
|
+
job.run(true)
|
91
|
+
when "local"
|
92
|
+
orchestrator = Workflow::Orchestrator.new 3, "cpus" => Misc.processors
|
93
|
+
orchestrator.process({}, job)
|
94
|
+
when "slurm"
|
95
|
+
SLURM.orchestrate(job)
|
96
|
+
else
|
97
|
+
OffsiteStep.setup(job, server: deploy, provided_inputs: job_inputs)
|
98
|
+
job.run
|
99
|
+
end unless job.done?
|
100
|
+
|
101
|
+
if print_filepath
|
54
102
|
job.join
|
55
103
|
path = job.path
|
56
104
|
path = path.find if Path === path
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
class TestSSH < Test::Unit::TestCase
|
5
|
+
def test_marshal
|
6
|
+
return unless SSHLine.reach?
|
7
|
+
|
8
|
+
assert TrueClass === SSHLine.rbbt(:default, 'true')
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_localhost
|
12
|
+
assert SSHLine.scout('localhost', 'true')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
class TestOffsiteStep < Test::Unit::TestCase
|
5
|
+
def test_offsite_task
|
6
|
+
workflow_code =<<-EOF
|
7
|
+
module TestWF
|
8
|
+
extend Workflow
|
9
|
+
|
10
|
+
input :string, :string, "String", "string"
|
11
|
+
task :string => :string do |string| string end
|
12
|
+
end
|
13
|
+
|
14
|
+
TestWF.directory = Path.setup("#{tmpdir.offsite.TestWF}")
|
15
|
+
EOF
|
16
|
+
|
17
|
+
TmpFile.with_file workflow_code, :extension => 'rb' do |wffile|
|
18
|
+
wf = Workflow.require_workflow wffile
|
19
|
+
|
20
|
+
job = wf.job(:string)
|
21
|
+
|
22
|
+
sss 0
|
23
|
+
off = OffsiteStep.setup job, server: 'localhost', workflow_name: wffile
|
24
|
+
|
25
|
+
refute off.done?
|
26
|
+
assert_equal 'string', off.run
|
27
|
+
|
28
|
+
assert off.done?
|
29
|
+
assert_equal 'string', off.run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
class TestSync < Test::Unit::TestCase
|
5
|
+
def test_sync
|
6
|
+
TmpFile.with_path do |tmpdir|
|
7
|
+
tmpdir = Scout.tmp.tmpdir_sync
|
8
|
+
tmpdir.dir1.foo.write("FOO")
|
9
|
+
tmpdir.dir1.bar.write("BAR")
|
10
|
+
|
11
|
+
TmpFile.with_path do |tmpdir2|
|
12
|
+
Misc.in_dir tmpdir2 do
|
13
|
+
SSHLine.sync([tmpdir.dir1], map: :current)
|
14
|
+
|
15
|
+
assert tmpdir2.glob("**/*").select{|f| f.include?('foo') }.any?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_sync_dir_map
|
22
|
+
TmpFile.with_path do |tmpdir|
|
23
|
+
tmpdir = Scout.tmp.tmpdir_sync
|
24
|
+
tmpdir.dir1.foo.write("FOO")
|
25
|
+
tmpdir.dir1.bar.write("BAR")
|
26
|
+
|
27
|
+
TmpFile.with_path do |tmpdir2|
|
28
|
+
SSHLine.sync([tmpdir.dir1], map: tmpdir2)
|
29
|
+
Misc.in_dir tmpdir2 do
|
30
|
+
assert tmpdir2.glob("**/*").select{|f| f.include?('foo') }.any?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
File without changes
|
@@ -334,63 +334,65 @@ row1 A B C
|
|
334
334
|
assert_equal %w(## ## ## #Row row1 row2 row3), sorted.read.split("\n").collect{|l| l.split(" ").first}
|
335
335
|
end
|
336
336
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
337
|
+
def test_collapse_stream
|
338
|
+
text=<<-EOF
|
339
|
+
row1 A B C
|
340
|
+
row1 a b c
|
341
|
+
row2 AA BB CC
|
342
|
+
row2 aa bb cc
|
343
|
+
EOF
|
344
|
+
|
345
|
+
s = StringIO.new text
|
346
|
+
stream = Open.collapse_stream(s, sep: " ")
|
347
|
+
txt = stream.read
|
348
|
+
assert_include txt, "A|a"
|
349
|
+
assert_include txt, "B|b"
|
350
|
+
assert_include txt, "C|c"
|
351
|
+
end
|
352
|
+
|
353
|
+
|
354
|
+
def test_collapse_sum
|
355
|
+
text=<<-EOF
|
356
|
+
row1 12
|
357
|
+
row1 4
|
358
|
+
row2 10
|
359
|
+
row2 6
|
360
|
+
EOF
|
361
|
+
|
362
|
+
s = StringIO.new text
|
363
|
+
stream = Open.collapse_stream(s, sep: " ") do |parts|
|
364
|
+
next nil if parts.empty?
|
365
|
+
parts.first.split("|").collect{|p| p.to_f}.inject(0){|acc,e| acc += e}.to_s
|
366
|
+
end
|
367
|
+
assert_include stream.read, "row1 16"
|
368
|
+
end
|
369
|
+
|
370
|
+
|
371
|
+
def test_collapse_stream_gap
|
372
|
+
text=<<-EOF
|
373
|
+
row2 AA BB
|
374
|
+
row2 aa bb cc
|
375
|
+
EOF
|
376
|
+
|
377
|
+
s = StringIO.new text
|
378
|
+
assert Open.collapse_stream(s, sep: " ").read =~ /\|cc$/
|
379
|
+
|
380
|
+
text=<<-EOF
|
381
|
+
row2 aa bb cc
|
382
|
+
row2 AA BB
|
383
|
+
EOF
|
384
|
+
|
385
|
+
s = StringIO.new text
|
386
|
+
assert Open.collapse_stream(s, sep: " ").read =~ /cc\|$/
|
387
|
+
|
388
|
+
text=<<-EOF
|
389
|
+
row2 AA BB
|
390
|
+
row2 aa bb cc
|
391
|
+
EOF
|
392
|
+
|
393
|
+
s = StringIO.new text
|
394
|
+
assert Open.collapse_stream(s, sep: " ").read =~ /\|cc$/
|
395
|
+
end
|
394
396
|
#
|
395
397
|
#
|
396
398
|
# def test_paste_stream
|
@@ -433,7 +435,7 @@ row1 A B C
|
|
433
435
|
# s = StringIO.new text
|
434
436
|
# sorted = Misc.sort_stream(s)
|
435
437
|
# assert_equal %w(## ## ## #Row row2 row3 row1), text.split("\n").collect{|l| l.split(" ").first}
|
436
|
-
# assert_equal %w(## ## ## #Row row1 row2 row3), sorted.read.split("\n").collect{|l| l.split(" ").first}
|
438
|
+
# assert_equal %w(## ## ## #Row row1 row2 row3), sorted.read.split("\n").collect{|l| l.split(" ").first}
|
437
439
|
# end
|
438
440
|
#
|
439
441
|
# def test_sort_long_stream
|
@@ -68,7 +68,6 @@ class TestPathFind < Test::Unit::TestCase
|
|
68
68
|
p = Path.setup("/tmp/foo/bar")
|
69
69
|
assert p.located?
|
70
70
|
assert_equal_path p, p.find
|
71
|
-
|
72
71
|
end
|
73
72
|
|
74
73
|
def test_custom
|
@@ -106,5 +105,15 @@ class TestPathFind < Test::Unit::TestCase
|
|
106
105
|
assert Open.exist?(tmpdir.somefile)
|
107
106
|
end
|
108
107
|
end
|
108
|
+
|
109
|
+
def test_with_extension
|
110
|
+
dir = tmpdir.directory[__method__]
|
111
|
+
list = %w(a b)
|
112
|
+
Misc.in_dir(dir) do
|
113
|
+
file = dir.foo
|
114
|
+
Open.write(file.set_extension('list'), list * "\n")
|
115
|
+
assert_equal list, file.list
|
116
|
+
end
|
117
|
+
end
|
109
118
|
end
|
110
119
|
|
@@ -59,4 +59,19 @@ end
|
|
59
59
|
assert_include File.open(TestResource.tmp.test.work.footest.bar.find).read, "OTHER"
|
60
60
|
assert_include File.open(TestResource.tmp.test.work.footest.foo_bar.find).read, "OTHER"
|
61
61
|
end
|
62
|
+
|
63
|
+
def test_produce_with_extension
|
64
|
+
dir = tmpdir.directory[__method__]
|
65
|
+
dir.pkgdir = Scout
|
66
|
+
list = %w(a b)
|
67
|
+
|
68
|
+
Scout.claim dir["foo.list"], :proc do
|
69
|
+
list
|
70
|
+
end
|
71
|
+
|
72
|
+
Misc.in_dir(dir) do
|
73
|
+
file = dir.foo
|
74
|
+
assert_equal list, file.list
|
75
|
+
end
|
76
|
+
end
|
62
77
|
end
|
@@ -8,6 +8,13 @@ class TestMetaExtension < Test::Unit::TestCase
|
|
8
8
|
extension_attr :code, :code2
|
9
9
|
end
|
10
10
|
|
11
|
+
module ExtensionClass2
|
12
|
+
extend MetaExtension
|
13
|
+
|
14
|
+
extension_attr :code3, :code4
|
15
|
+
end
|
16
|
+
|
17
|
+
|
11
18
|
def test_setup_annotate
|
12
19
|
str = "String"
|
13
20
|
ExtensionClass.setup(str, :code)
|
@@ -51,5 +58,23 @@ class TestMetaExtension < Test::Unit::TestCase
|
|
51
58
|
assert o.extension_attr_hash.include?(:code)
|
52
59
|
assert o.extension_attr_hash.include?(:code2)
|
53
60
|
end
|
61
|
+
|
62
|
+
def test_twice
|
63
|
+
str = "String"
|
64
|
+
|
65
|
+
ExtensionClass.setup(str, :code2 => :code)
|
66
|
+
assert_equal :code, str.code2
|
67
|
+
assert_include str.instance_variable_get(:@extension_attrs), :code
|
68
|
+
|
69
|
+
str.extend ExtensionClass2
|
70
|
+
str.code3 = :code_alt
|
71
|
+
assert_equal :code, str.code2
|
72
|
+
assert_equal :code_alt, str.code3
|
73
|
+
assert_include str.instance_variable_get(:@extension_attrs), :code
|
74
|
+
assert_include str.instance_variable_get(:@extension_attrs), :code3
|
75
|
+
|
76
|
+
assert_include str.extension_attr_hash, :code
|
77
|
+
assert_include str.extension_attr_hash, :code3
|
78
|
+
end
|
54
79
|
end
|
55
80
|
|
@@ -15,5 +15,29 @@ ValueB (Entity type)
|
|
15
15
|
assert_equal 1, NamedArray.identify_name(names, "ValueB")
|
16
16
|
assert_equal 1, NamedArray.identify_name(names, 1)
|
17
17
|
end
|
18
|
+
|
19
|
+
def test_missing_field
|
20
|
+
a = NamedArray.setup([1,2], [:a, :b])
|
21
|
+
assert_equal 1, a[:a]
|
22
|
+
assert_equal nil, a[:c]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_zip_fields
|
26
|
+
a = [%w(a b), %w(1 1)]
|
27
|
+
assert_equal [%w(a 1), %w(b 1)], NamedArray.zip_fields(a)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_add_zipped
|
31
|
+
a = [%w(a b), %w(1 1)]
|
32
|
+
NamedArray.add_zipped a, [%w(c), %w(1)]
|
33
|
+
NamedArray.add_zipped a, [%w(d), %w(1)]
|
34
|
+
assert_equal [%w(a b c d), %w(1 1 1 1)], a
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_method_missing
|
38
|
+
a = NamedArray.setup([1,2], [:a, :b])
|
39
|
+
assert_equal 1, a.a
|
40
|
+
assert_equal 2, a.b
|
41
|
+
end
|
18
42
|
end
|
19
43
|
|
data/test/scout/test_persist.rb
CHANGED
@@ -114,6 +114,7 @@ class TestPersist < Test::Unit::TestCase
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
117
|
+
|
117
118
|
if IO === io
|
118
119
|
Open.consume_stream(io, false)
|
119
120
|
else
|
@@ -137,8 +138,8 @@ class TestPersist < Test::Unit::TestCase
|
|
137
138
|
Open.write(output2, io)
|
138
139
|
end
|
139
140
|
end
|
140
|
-
Process.wait
|
141
|
-
Process.wait
|
141
|
+
Process.wait pid1
|
142
|
+
Process.wait pid2
|
142
143
|
|
143
144
|
assert File.exist?(output1) || File.exist?(output2)
|
144
145
|
[pid1, pid2].zip([output2, output1]).each do |pid, found|
|
@@ -156,6 +157,12 @@ class TestPersist < Test::Unit::TestCase
|
|
156
157
|
end
|
157
158
|
end
|
158
159
|
|
160
|
+
def test_path_prefix
|
161
|
+
Persist.persist('foo', :tsv, :prefix => "TSV") do |filename|
|
162
|
+
assert File.basename(filename).start_with? "TSV"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
159
166
|
def __test_speed
|
160
167
|
times = 100_000
|
161
168
|
TmpFile.with_file do |tmpfile|
|