tap-tasks 0.5.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +4 -0
- data/MIT-LICENSE +1 -1
- data/README +2 -4
- data/lib/tap/tasks/console.rb +43 -0
- data/lib/tap/tasks/dump/csv.rb +15 -5
- data/lib/tap/tasks/dump/inspect.rb +2 -5
- data/lib/tap/tasks/dump/yaml.rb +1 -1
- data/lib/tap/tasks/error.rb +16 -0
- data/lib/tap/tasks/glob.rb +2 -2
- data/lib/tap/tasks/insert.rb +89 -0
- data/lib/tap/tasks/load/csv.rb +15 -4
- data/lib/tap/tasks/load/yaml.rb +1 -1
- data/lib/tap/tasks/null.rb +2 -3
- data/lib/tap/tasks/sleep.rb +17 -0
- data/lib/tap/tasks/stream/yaml.rb +1 -1
- data/lib/tap/tasks/version.rb +1 -1
- data/tap-tasks.gemspec +50 -0
- metadata +38 -21
- data/lib/tap/joins/gate.rb +0 -87
- data/lib/tap/middlewares/profiler.rb +0 -72
- data/lib/tap/tasks/stream.rb +0 -64
data/History
CHANGED
data/MIT-LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Copyright (c) 2009, Regents of the University of Colorado.
|
2
2
|
|
3
|
-
Copyright (c) 2009, Simon Chiang.
|
3
|
+
Copyright (c) 2009-2010, Simon Chiang.
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README
CHANGED
@@ -7,9 +7,7 @@ A set of standard Tap tasks.
|
|
7
7
|
== Description
|
8
8
|
|
9
9
|
A standard library of utility tasks, for example tasks to dump/load results as
|
10
|
-
{YAML}[http://www.yaml.org/]
|
11
|
-
is a part of the {Tap-Suite}[http://tap.rubyforge.org/tap-suite]. Check out
|
12
|
-
these links for documentation, development, and bug tracking.
|
10
|
+
{YAML}[http://www.yaml.org/] or CSV.
|
13
11
|
|
14
12
|
* Website[http://tap.rubyforge.org]
|
15
13
|
* Github[http://github.com/bahuvrihi/tap/tree/master]
|
@@ -19,7 +17,7 @@ these links for documentation, development, and bug tracking.
|
|
19
17
|
|
20
18
|
Usage is the same as for any tasks.
|
21
19
|
|
22
|
-
% tap
|
20
|
+
% tap load/yaml "{key: value}" -: inspect
|
23
21
|
{"key" => "value"}
|
24
22
|
|
25
23
|
== Installation
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
require 'tap/declarations'
|
3
|
+
require 'irb'
|
4
|
+
|
5
|
+
# http://www.ruby-forum.com/topic/182335
|
6
|
+
class IRB::Irb
|
7
|
+
alias initialize_orig initialize
|
8
|
+
def initialize(workspace = nil, *args)
|
9
|
+
default = IRB.conf[:DEFAULT_OBJECT]
|
10
|
+
workspace ||= IRB::WorkSpace.new(default) if default
|
11
|
+
initialize_orig(workspace, *args)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Tap
|
16
|
+
module Tasks
|
17
|
+
# :startdoc::task start an irb session
|
18
|
+
#
|
19
|
+
# Console allows interaction with tap via IRB. Starts an IRB sssion with
|
20
|
+
# the same context as a tapfile (a Tap::Declarations::Context). Only one
|
21
|
+
# console can be running at time.
|
22
|
+
#
|
23
|
+
class Console < Tap::Task
|
24
|
+
# Handles a bug in IRB that causes exit to throw :IRB_EXIT
|
25
|
+
# and consequentially make a warning message, even on a
|
26
|
+
# clean exit. This module resets exit to the original
|
27
|
+
# aliased method.
|
28
|
+
module CleanExit # :nodoc:
|
29
|
+
def exit(ret = 0)
|
30
|
+
__exit__(ret)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def process
|
35
|
+
raise "console already running" if IRB.conf[:DEFAULT_OBJECT]
|
36
|
+
IRB.conf[:DEFAULT_OBJECT] = Declarations::Context.new(app, "console")
|
37
|
+
IRB.start
|
38
|
+
IRB.conf[:DEFAULT_OBJECT] = nil
|
39
|
+
IRB.CurrentContext.extend CleanExit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/tap/tasks/dump/csv.rb
CHANGED
@@ -11,18 +11,28 @@ module Tap
|
|
11
11
|
# into a single line of csv, ie multiple dumps build the csv results.
|
12
12
|
# Non-array objects are converted to arrays using to_ary.
|
13
13
|
#
|
14
|
-
# % tap
|
14
|
+
# % tap load/yaml '["a", "b", "c"]' -: dump/csv
|
15
15
|
# a,b,c
|
16
16
|
#
|
17
17
|
class Csv < Dump
|
18
18
|
|
19
19
|
config :col_sep, ",", :short => :c, &c.string # The column separator (",")
|
20
|
-
config :row_sep,
|
20
|
+
config :row_sep, $/, :short => :r, &c.string # The row separator ("\n")
|
21
21
|
|
22
|
-
# Dumps the data to io as CSV. Data is converted to an array using
|
23
|
-
# to_ary.
|
24
22
|
def dump(data, io)
|
25
|
-
io <<
|
23
|
+
io << generate_line(data.to_ary)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
if RUBY_VERSION >= '1.9'
|
29
|
+
def generate_line(data)
|
30
|
+
CSV.generate_line(data, :col_sep => col_sep, :row_sep => row_sep)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
def generate_line(data)
|
34
|
+
CSV.generate_line(data, col_sep) + row_sep
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
@@ -10,15 +10,12 @@ module Tap
|
|
10
10
|
# method can be specified for inspection using the inspect_method
|
11
11
|
# config.
|
12
12
|
#
|
13
|
-
# % tap
|
13
|
+
# % tap load/yaml "{key: value}" -: inspect
|
14
14
|
# {"key"=>"value"}
|
15
15
|
#
|
16
|
-
# % tap run -- load string --: inspect -m length
|
17
|
-
# 6
|
18
|
-
#
|
19
16
|
class Inspect < Dump
|
20
17
|
|
21
|
-
config :inspect_method, 'inspect', :short => :m # The inspection method
|
18
|
+
config :inspect_method, 'inspect', :long => :method, :short => :m # The inspection method
|
22
19
|
|
23
20
|
# Dumps the object to io using obj.inspect
|
24
21
|
def dump(obj, io)
|
data/lib/tap/tasks/dump/yaml.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::task raises an error
|
6
|
+
#
|
7
|
+
# Error raises a Runtime error when called. The input specifies the
|
8
|
+
# error message.
|
9
|
+
#
|
10
|
+
class Error < Tap::Task
|
11
|
+
def process(msg=nil)
|
12
|
+
raise msg
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/tap/tasks/glob.rb
CHANGED
@@ -7,7 +7,7 @@ module Tap
|
|
7
7
|
# Globs the input patterns for matching patterns. Matching files are
|
8
8
|
# returned as an array.
|
9
9
|
#
|
10
|
-
# % tap
|
10
|
+
# % tap glob * -: dump/yaml
|
11
11
|
#
|
12
12
|
# A variety of filters are available as configurations.
|
13
13
|
#
|
@@ -20,7 +20,7 @@ module Tap
|
|
20
20
|
#
|
21
21
|
# To glob within the task and not the command line, quote the glob.
|
22
22
|
#
|
23
|
-
# % tap
|
23
|
+
# % tap glob '*' -: dump/yaml
|
24
24
|
#
|
25
25
|
class Glob < Tap::Task
|
26
26
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::task insert into an array
|
6
|
+
#
|
7
|
+
# Insert supports a common workflow pattern of inserting variable
|
8
|
+
# arguments into an otherwise static array.
|
9
|
+
#
|
10
|
+
# % tap load moon -: insert goodnight %0 -: inspect
|
11
|
+
# ["goodnight", "moon"]
|
12
|
+
#
|
13
|
+
# The percent serves as a placeholder identifying the index of the
|
14
|
+
# argument that will be inserted. Unlike most tasks, command-line
|
15
|
+
# arguments provided to insert define the insertion template rather than
|
16
|
+
# inputs (ie they cannot be enqued or executed with -- or -!) so typically
|
17
|
+
# inserts are used with joins or signals.
|
18
|
+
#
|
19
|
+
# % tap insert goodnight %0 -: inspect -/enq 0 moon
|
20
|
+
# ["goodnight", "moon"]
|
21
|
+
#
|
22
|
+
# Arguments can be used more than once, as indicated. The default value
|
23
|
+
# will be used if the argument value at the given index is nil.
|
24
|
+
#
|
25
|
+
# % tap load a -: insert %0 %0 %1 -: inspect
|
26
|
+
# ["a", "a", nil]
|
27
|
+
#
|
28
|
+
class Insert < Tap::Task
|
29
|
+
class << self
|
30
|
+
def parse(argv=ARGV, app=Tap::App.current)
|
31
|
+
super(argv, app, &nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse!(argv=ARGV, app=Tap::App.current)
|
35
|
+
super(argv, app, &nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
def build(spec={}, app=Tap::App.current)
|
39
|
+
new(spec['template'], spec['config'], app)
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_to_spec(parser, args)
|
43
|
+
template = args.dup
|
44
|
+
args.clear
|
45
|
+
|
46
|
+
{
|
47
|
+
'config' => parser.nested_config,
|
48
|
+
'template' => template
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
config :placeholder, '%', :short => :p, &c.string # argument placeholder
|
54
|
+
config :default, nil # default insert value
|
55
|
+
|
56
|
+
attr_reader :template
|
57
|
+
|
58
|
+
def initialize(template, config={}, app=Tap::App.current)
|
59
|
+
super(config, app)
|
60
|
+
@template = template
|
61
|
+
@map = {}
|
62
|
+
|
63
|
+
plength = placeholder.length
|
64
|
+
template.each_with_index do |arg, index|
|
65
|
+
if arg.index(placeholder) == 0
|
66
|
+
@map[index] = arg[plength, arg.length - plength].to_i
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def process(*args)
|
72
|
+
result = template.dup
|
73
|
+
|
74
|
+
@map.each_pair do |insert_idx, arg_idx|
|
75
|
+
value = args[arg_idx]
|
76
|
+
result[insert_idx] = value.nil? ? default : value
|
77
|
+
end
|
78
|
+
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_spec
|
83
|
+
spec = super
|
84
|
+
spec['template'] = template
|
85
|
+
spec
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/tap/tasks/load/csv.rb
CHANGED
@@ -10,7 +10,7 @@ module Tap
|
|
10
10
|
# Load CSV data as an array of arrays, selecting the specified rows and
|
11
11
|
# columns.
|
12
12
|
#
|
13
|
-
# % tap
|
13
|
+
# % tap load/csv 'a,b,c.d,e,f' --row-sep '.' -: inspect
|
14
14
|
# [["a", "b", "c"], ["d", "e", "f"]]
|
15
15
|
#
|
16
16
|
# Note this task is quite inefficient in that it will load all data
|
@@ -22,12 +22,12 @@ module Tap
|
|
22
22
|
config :columns, nil, :short => :C, &c.range_or_nil # Specify a range of columns
|
23
23
|
config :rows, nil, :short => :R, &c.range_or_nil # Specify a range of rows
|
24
24
|
|
25
|
-
config :col_sep,
|
26
|
-
config :row_sep,
|
25
|
+
config :col_sep, ',', :short => :c, &c.string_or_nil # The column separator (",")
|
26
|
+
config :row_sep, $/, :short => :r, &c.string_or_nil # The row separator ("\r\n" or "\n")
|
27
27
|
|
28
28
|
# Loads the io data as CSV, into an array of arrays.
|
29
29
|
def load(io)
|
30
|
-
data =
|
30
|
+
data = parse(io.read)
|
31
31
|
|
32
32
|
if rows
|
33
33
|
data = data[rows]
|
@@ -42,6 +42,17 @@ module Tap
|
|
42
42
|
data
|
43
43
|
end
|
44
44
|
|
45
|
+
private
|
46
|
+
|
47
|
+
if RUBY_VERSION >= '1.9'
|
48
|
+
def parse(str)
|
49
|
+
CSV.parse(str, :col_sep => col_sep, :row_sep => row_sep)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
def parse(str)
|
53
|
+
CSV.parse(str, col_sep, row_sep)
|
54
|
+
end
|
55
|
+
end
|
45
56
|
end
|
46
57
|
end
|
47
58
|
end
|
data/lib/tap/tasks/load/yaml.rb
CHANGED
data/lib/tap/tasks/null.rb
CHANGED
@@ -8,11 +8,10 @@ module Tap
|
|
8
8
|
# to Null go nowhere. Null does not accept joins and will not execute
|
9
9
|
# the default app joins.
|
10
10
|
#
|
11
|
-
# % tap
|
11
|
+
# % tap load/yaml '[1, 2, 3]' -: null
|
12
12
|
#
|
13
|
-
class Null < Tap::Task
|
13
|
+
class Null < Tap::Task
|
14
14
|
def process(*args)
|
15
|
-
nil
|
16
15
|
end
|
17
16
|
|
18
17
|
def joins
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'tap/task'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
module Tasks
|
5
|
+
# :startdoc::task sleep
|
6
|
+
#
|
7
|
+
# Sleeps for the specified duration.
|
8
|
+
class Sleep < Tap::Task
|
9
|
+
config :duration, 1, &c.numeric # sleep duration (ms)
|
10
|
+
|
11
|
+
def call(input)
|
12
|
+
sleep duration
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/tap/tasks/version.rb
CHANGED
data/tap-tasks.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
$:.unshift File.expand_path('../../tap/lib', __FILE__)
|
2
|
+
$:.unshift File.expand_path('../../tap-test/lib', __FILE__)
|
3
|
+
$:.unshift File.expand_path('../../tap-tasks/lib', __FILE__)
|
4
|
+
|
5
|
+
require 'tap/version'
|
6
|
+
require 'tap/test/version'
|
7
|
+
require 'tap/tasks/version'
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.name = 'tap-tasks'
|
11
|
+
s.version = Tap::Tasks::VERSION
|
12
|
+
s.author = 'Simon Chiang'
|
13
|
+
s.email = 'simon.a.chiang@gmail.com'
|
14
|
+
s.homepage = File.join(Tap::WEBSITE, 'tap-tasks')
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.summary = 'A set of standard Tap tasks'
|
17
|
+
s.require_path = 'lib'
|
18
|
+
s.rubyforge_project = 'tap'
|
19
|
+
s.add_dependency('tap', ">= #{Tap::VERSION}")
|
20
|
+
s.add_development_dependency('tap-test', ">= #{Tap::Test::VERSION}")
|
21
|
+
s.has_rdoc = true
|
22
|
+
s.rdoc_options.concat %W{--main README -S -N --title Tap-Tasks}
|
23
|
+
|
24
|
+
# list extra rdoc files here.
|
25
|
+
s.extra_rdoc_files = %W{
|
26
|
+
History
|
27
|
+
README
|
28
|
+
MIT-LICENSE
|
29
|
+
}
|
30
|
+
|
31
|
+
# list the files you want to include here. you can
|
32
|
+
# check this manifest using 'rap print_manifest'
|
33
|
+
s.files = %W{
|
34
|
+
lib/tap/tasks/insert.rb
|
35
|
+
lib/tap/tasks/console.rb
|
36
|
+
lib/tap/tasks/dump/csv.rb
|
37
|
+
lib/tap/tasks/dump/inspect.rb
|
38
|
+
lib/tap/tasks/dump/yaml.rb
|
39
|
+
lib/tap/tasks/error.rb
|
40
|
+
lib/tap/tasks/glob.rb
|
41
|
+
lib/tap/tasks/load/csv.rb
|
42
|
+
lib/tap/tasks/load/yaml.rb
|
43
|
+
lib/tap/tasks/null.rb
|
44
|
+
lib/tap/tasks/sleep.rb
|
45
|
+
lib/tap/tasks/stream/yaml.rb
|
46
|
+
lib/tap/tasks/version.rb
|
47
|
+
tap-tasks.gemspec
|
48
|
+
tap.yml
|
49
|
+
}
|
50
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tap-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 7
|
8
|
+
- 0
|
9
|
+
version: 0.7.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Simon Chiang
|
@@ -9,29 +14,37 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-05-02 00:00:00 -06:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: tap
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
version: 1.3.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: tap-test
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 6
|
44
|
+
- 0
|
45
|
+
version: 0.6.0
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
35
48
|
description:
|
36
49
|
email: simon.a.chiang@gmail.com
|
37
50
|
executables: []
|
@@ -43,24 +56,26 @@ extra_rdoc_files:
|
|
43
56
|
- README
|
44
57
|
- MIT-LICENSE
|
45
58
|
files:
|
46
|
-
- lib/tap/
|
47
|
-
- lib/tap/
|
59
|
+
- lib/tap/tasks/insert.rb
|
60
|
+
- lib/tap/tasks/console.rb
|
48
61
|
- lib/tap/tasks/dump/csv.rb
|
49
62
|
- lib/tap/tasks/dump/inspect.rb
|
50
63
|
- lib/tap/tasks/dump/yaml.rb
|
51
|
-
- lib/tap/tasks/
|
64
|
+
- lib/tap/tasks/error.rb
|
65
|
+
- lib/tap/tasks/glob.rb
|
52
66
|
- lib/tap/tasks/load/csv.rb
|
67
|
+
- lib/tap/tasks/load/yaml.rb
|
53
68
|
- lib/tap/tasks/null.rb
|
54
|
-
- lib/tap/tasks/
|
55
|
-
- lib/tap/tasks/stream.rb
|
69
|
+
- lib/tap/tasks/sleep.rb
|
56
70
|
- lib/tap/tasks/stream/yaml.rb
|
57
71
|
- lib/tap/tasks/version.rb
|
72
|
+
- tap-tasks.gemspec
|
58
73
|
- tap.yml
|
59
74
|
- History
|
60
75
|
- README
|
61
76
|
- MIT-LICENSE
|
62
77
|
has_rdoc: true
|
63
|
-
homepage: http://tap.rubyforge.org/tap-tasks
|
78
|
+
homepage: http://tap.rubyforge.org/tap-tasks
|
64
79
|
licenses: []
|
65
80
|
|
66
81
|
post_install_message:
|
@@ -77,18 +92,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
92
|
requirements:
|
78
93
|
- - ">="
|
79
94
|
- !ruby/object:Gem::Version
|
95
|
+
segments:
|
96
|
+
- 0
|
80
97
|
version: "0"
|
81
|
-
version:
|
82
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
99
|
requirements:
|
84
100
|
- - ">="
|
85
101
|
- !ruby/object:Gem::Version
|
102
|
+
segments:
|
103
|
+
- 0
|
86
104
|
version: "0"
|
87
|
-
version:
|
88
105
|
requirements: []
|
89
106
|
|
90
107
|
rubyforge_project: tap
|
91
|
-
rubygems_version: 1.3.
|
108
|
+
rubygems_version: 1.3.6
|
92
109
|
signing_key:
|
93
110
|
specification_version: 3
|
94
111
|
summary: A set of standard Tap tasks
|
data/lib/tap/joins/gate.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'tap/join'
|
2
|
-
|
3
|
-
module Tap
|
4
|
-
module Joins
|
5
|
-
|
6
|
-
# :startdoc::join collects results before the join
|
7
|
-
#
|
8
|
-
# Similar to a synchronized merge, but collects all results regardless of
|
9
|
-
# where they come from. Gates enque themselves when called as a join, and
|
10
|
-
# won't let results pass until they get run as a node.
|
11
|
-
#
|
12
|
-
# % tap run -- load a -- load b -- inspect --[0,1][2].gate
|
13
|
-
# ["a", "b"]
|
14
|
-
#
|
15
|
-
# Gates are useful in conjunction with iteration where a single task may
|
16
|
-
# feed multiple results to a single join; in this case a sync merge doesn't
|
17
|
-
# produce the desired behavior of collecting the results.
|
18
|
-
#
|
19
|
-
# % tap run -- load/yaml "[1, 2, 3]" --:i inspect --:.gate inspect
|
20
|
-
# 1
|
21
|
-
# 2
|
22
|
-
# 3
|
23
|
-
# [1, 2, 3]
|
24
|
-
#
|
25
|
-
# % tap run -- load/yaml "[1, 2, 3]" --:i inspect --:.sync inspect
|
26
|
-
# 1
|
27
|
-
# [1]
|
28
|
-
# 2
|
29
|
-
# [2]
|
30
|
-
# 3
|
31
|
-
# [3]
|
32
|
-
#
|
33
|
-
# When a limit is specified, the gate will collect results up to the limit
|
34
|
-
# and then pass the results. Any leftover results are still passed at the
|
35
|
-
# end.
|
36
|
-
#
|
37
|
-
# % tap run -- load/yaml "[1, 2, 3]" --:i inspect -- inspect --. gate 1 2 --limit 2
|
38
|
-
# 1
|
39
|
-
# 2
|
40
|
-
# [1, 2]
|
41
|
-
# 3
|
42
|
-
# [3]
|
43
|
-
#
|
44
|
-
class Gate < Join
|
45
|
-
|
46
|
-
# An array of results collected thusfar.
|
47
|
-
attr_reader :results
|
48
|
-
|
49
|
-
config :limit, nil, :short => :l, &c.integer_or_nil # Pass results after limit
|
50
|
-
|
51
|
-
def initialize(config={}, app=Tap::App.instance)
|
52
|
-
super
|
53
|
-
@results = nil
|
54
|
-
end
|
55
|
-
|
56
|
-
def call(result)
|
57
|
-
if @results
|
58
|
-
# Results are set, so self is already enqued and collecting
|
59
|
-
# results. If the input is the collection, then it's time
|
60
|
-
# to dispatch the results and reset. Otherwise, just
|
61
|
-
# collect the input and wait.
|
62
|
-
|
63
|
-
if result == @results
|
64
|
-
@results = nil
|
65
|
-
super(result)
|
66
|
-
else
|
67
|
-
@results << result
|
68
|
-
|
69
|
-
if limit && @results.length >= limit
|
70
|
-
super(@results.dup)
|
71
|
-
@results.clear
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
else
|
76
|
-
# No results are set, so this is a first call and self is
|
77
|
-
# not enqued. Setup the collection.
|
78
|
-
|
79
|
-
@results = [result]
|
80
|
-
app.enq(self, @results)
|
81
|
-
end
|
82
|
-
|
83
|
-
self
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
require 'tap/middleware'
|
2
|
-
|
3
|
-
module Tap
|
4
|
-
module Middlewares
|
5
|
-
|
6
|
-
# :startdoc::middleware profile the workflow execution time
|
7
|
-
#
|
8
|
-
#
|
9
|
-
class Profiler < Tap::Middleware
|
10
|
-
|
11
|
-
attr_reader :app_time
|
12
|
-
attr_reader :nodes
|
13
|
-
attr_reader :counts
|
14
|
-
|
15
|
-
def initialize(stack, config={})
|
16
|
-
super
|
17
|
-
reset
|
18
|
-
at_exit { app.quiet = false; app.log(:profile, "\n" + summary.join("\n")) }
|
19
|
-
end
|
20
|
-
|
21
|
-
def reset
|
22
|
-
@app_time = 0
|
23
|
-
@last = nil
|
24
|
-
@nodes = Hash.new(0)
|
25
|
-
@counts = Hash.new(0)
|
26
|
-
end
|
27
|
-
|
28
|
-
def total_time
|
29
|
-
nodes.values.inject(0) {|sum, elapsed| sum + elapsed }
|
30
|
-
end
|
31
|
-
|
32
|
-
def total_counts
|
33
|
-
counts.values.inject(0) {|sum, n| sum + n }
|
34
|
-
end
|
35
|
-
|
36
|
-
def call(node, inputs=[])
|
37
|
-
@app_time += Time.now - @last if @last
|
38
|
-
|
39
|
-
start = Time.now
|
40
|
-
result = super
|
41
|
-
elapsed = Time.now - start
|
42
|
-
|
43
|
-
nodes[node] += elapsed
|
44
|
-
counts[node] += 1
|
45
|
-
|
46
|
-
@last = Time.now
|
47
|
-
result
|
48
|
-
end
|
49
|
-
|
50
|
-
def summary
|
51
|
-
lines = []
|
52
|
-
lines << "App Time: #{app_time}s"
|
53
|
-
lines << "Node Time: #{total_time}s"
|
54
|
-
lines << "Nodes Run: #{total_counts}"
|
55
|
-
lines << "Breakdown:"
|
56
|
-
|
57
|
-
nodes_by_class = {}
|
58
|
-
nodes.each_key do |node|
|
59
|
-
(nodes_by_class[node.class.to_s] ||= []) << node
|
60
|
-
end
|
61
|
-
|
62
|
-
nodes_by_class.keys.sort.each do |node_class|
|
63
|
-
nodes_by_class[node_class].each do |node|
|
64
|
-
lines << "- #{node_class}: [#{nodes[node]}, #{counts[node]}]"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
lines
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
data/lib/tap/tasks/stream.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'tap/tasks/load'
|
2
|
-
|
3
|
-
module Tap
|
4
|
-
module Tasks
|
5
|
-
|
6
|
-
# Stream recurrently loads data from $stdin by requeing self until an
|
7
|
-
# end-of-file is reached. This behavior is useful for creating tasks
|
8
|
-
# that load a bit of data from an IO, send it into a workflow, and then
|
9
|
-
# repeat.
|
10
|
-
#
|
11
|
-
# The eof cutoff can be modified using complete? method. Streaming will
|
12
|
-
# stop when complete? returns true. For instance, this is a prompt task:
|
13
|
-
#
|
14
|
-
# class Prompt < Tap::Tasks::Stream
|
15
|
-
# config :exit_seq, "\n"
|
16
|
-
#
|
17
|
-
# def load(io)
|
18
|
-
# if io.eof?
|
19
|
-
# nil
|
20
|
-
# else
|
21
|
-
# io.readline
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# def complete?(io, line)
|
26
|
-
# line == nil || line == exit_seq
|
27
|
-
# end
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
class Stream < Load
|
31
|
-
|
32
|
-
# Loads data from io. Process will open the input io object, load
|
33
|
-
# a result, then check to see if the loading is complete (using the
|
34
|
-
# complete? method). Unless loading is complete, process will enque
|
35
|
-
# io to self. Process will close io when loading is complete, provided
|
36
|
-
# use_close or file is specified.
|
37
|
-
def process(io=$stdin)
|
38
|
-
io = open(io)
|
39
|
-
result = load(io)
|
40
|
-
|
41
|
-
if complete?(io, result)
|
42
|
-
if use_close || file
|
43
|
-
close(io)
|
44
|
-
end
|
45
|
-
else
|
46
|
-
reque(io)
|
47
|
-
end
|
48
|
-
|
49
|
-
result
|
50
|
-
end
|
51
|
-
|
52
|
-
# Returns true by default. Override in subclasses to allow recurrent
|
53
|
-
# loading (see process).
|
54
|
-
def complete?(io, last)
|
55
|
-
io.eof?
|
56
|
-
end
|
57
|
-
|
58
|
-
# Reques self with io to the top of the queue.
|
59
|
-
def reque(io)
|
60
|
-
app.queue.unshift(self, [io])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|