bahuvrihi-tap 0.10.2 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- data/cgi/run.rb +36 -0
- data/cmd/run.rb +4 -3
- data/cmd/server.rb +36 -0
- data/lib/tap/app.rb +1 -1
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/env.rb +8 -2
- data/lib/tap/exe.rb +1 -57
- data/lib/tap/support/declarations.rb +73 -51
- data/lib/tap/support/executable.rb +81 -2
- data/lib/tap/support/gems/rack.rb +151 -0
- data/lib/tap/support/parsers/base.rb +81 -0
- data/lib/tap/support/parsers/command_line.rb +90 -0
- data/lib/tap/support/parsers/server.rb +83 -0
- data/lib/tap/task.rb +327 -7
- data/lib/tap/workflow.rb +9 -48
- data/template/404.erb +12 -0
- data/template/index.erb +41 -0
- data/vendor/url_encoded_pair_parser.rb +93 -0
- metadata +10 -4
- data/lib/tap/support/command_line/parser.rb +0 -121
- data/lib/tap/support/framework.rb +0 -83
- data/lib/tap/support/framework_class.rb +0 -182
data/cgi/run.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# ::summary
|
2
|
+
# runs a task
|
3
|
+
#
|
4
|
+
# ::description
|
5
|
+
#
|
6
|
+
############################
|
7
|
+
require 'cgi'
|
8
|
+
require "#{File.dirname(__FILE__)}/../vendor/url_encoded_pair_parser"
|
9
|
+
require "tap/support/server/parser"
|
10
|
+
|
11
|
+
cgi = CGI.new("html3") # add HTML generation methods
|
12
|
+
|
13
|
+
argh = UrlEncodedPairParser.new(cgi.params.to_a).result
|
14
|
+
queues = Tap::Env.instance.build Tap::Support::Server::Parser.new(argh)
|
15
|
+
|
16
|
+
cgi.out() do
|
17
|
+
cgi.html() do
|
18
|
+
cgi.head{ cgi.title{ "Tap::Run" } } +
|
19
|
+
cgi.body() do
|
20
|
+
cgi.pre do
|
21
|
+
if queues.empty?
|
22
|
+
|
23
|
+
"b;ah"
|
24
|
+
else
|
25
|
+
|
26
|
+
queues.each_with_index do |queue, i|
|
27
|
+
app.queue.concat(queue)
|
28
|
+
app.run
|
29
|
+
end
|
30
|
+
|
31
|
+
"Ran"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/cmd/run.rb
CHANGED
@@ -47,11 +47,12 @@ end.parse!(ARGV)
|
|
47
47
|
#
|
48
48
|
# handle options for each specified task
|
49
49
|
#
|
50
|
+
require 'tap/support/parsers/command_line'
|
50
51
|
|
51
|
-
|
52
|
+
queues = Tap::Support::Parsers::CommandLine.new(ARGV).build(env, app)
|
52
53
|
ARGV.clear
|
53
54
|
|
54
|
-
if
|
55
|
+
if queues.empty?
|
55
56
|
puts "no task specified"
|
56
57
|
exit
|
57
58
|
end
|
@@ -99,7 +100,7 @@ end
|
|
99
100
|
# enque tasks and run!
|
100
101
|
#
|
101
102
|
|
102
|
-
|
103
|
+
queues.each_with_index do |queue, i|
|
103
104
|
app.queue.concat(queue)
|
104
105
|
app.run
|
105
106
|
end
|
data/cmd/server.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# tap server {options}
|
2
|
+
#
|
3
|
+
# Initializes a tap server.
|
4
|
+
|
5
|
+
require 'tap'
|
6
|
+
require 'tap/support/gems/rack'
|
7
|
+
|
8
|
+
env = Tap::Env.instance
|
9
|
+
|
10
|
+
#
|
11
|
+
# handle options
|
12
|
+
#
|
13
|
+
options = {:Port => 8080}
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
|
16
|
+
opts.separator ""
|
17
|
+
opts.separator "options:"
|
18
|
+
|
19
|
+
opts.on("-h", "--help", "Show this message") do
|
20
|
+
opts.banner = Tap::Support::TDoc.usage(__FILE__)
|
21
|
+
puts opts
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-p", "--port PORT", Integer, "Specifies the port (default #{options[:Port]})") do |value|
|
26
|
+
options[:Port] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
end.parse!(ARGV)
|
30
|
+
|
31
|
+
#
|
32
|
+
# cgi dir and public dir can be set in tap.yml
|
33
|
+
#
|
34
|
+
|
35
|
+
env.extend Tap::Support::Gems::Rack
|
36
|
+
Rack::Handler::WEBrick.run(env, options)
|
data/lib/tap/app.rb
CHANGED
@@ -492,7 +492,7 @@ module Tap
|
|
492
492
|
# An Executable may provided instead of a task.
|
493
493
|
def enq(task, *inputs)
|
494
494
|
case task
|
495
|
-
when Tap::Task
|
495
|
+
when Tap::Task
|
496
496
|
raise "not assigned to enqueing app: #{task}" unless task.app == self
|
497
497
|
task.enq(*inputs)
|
498
498
|
when Support::Executable
|
data/lib/tap/constants.rb
CHANGED
data/lib/tap/env.rb
CHANGED
@@ -273,8 +273,7 @@ module Tap
|
|
273
273
|
@envs = []
|
274
274
|
@active = false
|
275
275
|
@manifests = {}
|
276
|
-
|
277
|
-
|
276
|
+
|
278
277
|
# initialize these for reset_env
|
279
278
|
@gems = []
|
280
279
|
@env_paths = []
|
@@ -553,6 +552,13 @@ module Tap
|
|
553
552
|
nil
|
554
553
|
end
|
555
554
|
|
555
|
+
def reset(name, &block)
|
556
|
+
each do |env|
|
557
|
+
env.manifests[name].each(&block)
|
558
|
+
env.manifests[name] = nil
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
556
562
|
def constantize(name, *patterns)
|
557
563
|
patterns.collect do |pattern|
|
558
564
|
case const = search(name, pattern)
|
data/lib/tap/exe.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
|
-
require 'tap/support/command_line/parser'
|
2
|
-
|
3
1
|
module Tap
|
4
2
|
class Exe < Env
|
5
|
-
|
6
|
-
|
3
|
+
|
7
4
|
class << self
|
8
5
|
def instantiate
|
9
6
|
app = Tap::App.instance
|
@@ -66,58 +63,5 @@ module Tap
|
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
69
|
-
|
70
|
-
def parse(argv=ARGV)
|
71
|
-
parser = Parser.new(argv)
|
72
|
-
targets = parser.targets
|
73
|
-
|
74
|
-
tasks = []
|
75
|
-
rounds = parser.rounds.collect do |round|
|
76
|
-
round.each do |argv|
|
77
|
-
unless td = Parser.shift_arg(argv)
|
78
|
-
# warn nil?
|
79
|
-
next
|
80
|
-
end
|
81
|
-
|
82
|
-
# attempt lookup the task class
|
83
|
-
const = search(:tasks, td) or raise ArgumentError, "unknown task: #{td}"
|
84
|
-
task_class = const.constantize or raise ArgumentError, "unknown task: #{td}"
|
85
|
-
|
86
|
-
# now let the class handle the argv
|
87
|
-
task, args = task_class.instantiate(argv, app)
|
88
|
-
|
89
|
-
if !targets.include?(tasks.length)
|
90
|
-
task.enq(*args)
|
91
|
-
elsif !args.empty?
|
92
|
-
raise ArgumentError, "workflow target receives argv: [#{argv.unshift(td).join(', ')}]"
|
93
|
-
end
|
94
|
-
|
95
|
-
tasks << task
|
96
|
-
end
|
97
|
-
|
98
|
-
app.queue.clear
|
99
|
-
end
|
100
|
-
rounds.delete_if {|round| round.empty? }
|
101
|
-
|
102
|
-
# build the workflow
|
103
|
-
|
104
|
-
parser.sequences.each do |sequence|
|
105
|
-
app.sequence(*sequence.collect {|s| tasks[s]})
|
106
|
-
end
|
107
|
-
|
108
|
-
parser.forks.each do |source, targets|
|
109
|
-
app.fork(tasks[source], *targets.collect {|t| tasks[t]})
|
110
|
-
end
|
111
|
-
|
112
|
-
parser.merges.each do |target, sources|
|
113
|
-
app.merge(tasks[target], *sources.collect {|s| tasks[s]})
|
114
|
-
end
|
115
|
-
|
116
|
-
parser.sync_merges.each do |target, sources|
|
117
|
-
app.sync_merge(tasks[target], *sources.collect {|s| tasks[s]})
|
118
|
-
end
|
119
|
-
|
120
|
-
rounds
|
121
|
-
end
|
122
66
|
end
|
123
67
|
end
|
@@ -16,56 +16,39 @@ module Tap
|
|
16
16
|
def self.extended(base)
|
17
17
|
set_declaration_base(base)
|
18
18
|
end
|
19
|
-
|
20
|
-
def tasc(name, configs={},
|
21
|
-
Tap::Task
|
22
|
-
end
|
23
|
-
|
24
|
-
def task(name, configs={}, options={}, &block)
|
25
|
-
options[:arity] = arity(block)
|
26
|
-
tasc(name, configs, options, &task_block(block)).new
|
27
|
-
end
|
28
|
-
|
29
|
-
def file_tasc(name, configs={}, options={}, &block)
|
30
|
-
Tap::FileTask.subclass(nest(name), configs, options, &block)
|
19
|
+
|
20
|
+
def tasc(name, configs={}, &block)
|
21
|
+
declare(Tap::Task, name, configs, &block)
|
31
22
|
end
|
32
23
|
|
33
|
-
def
|
34
|
-
|
35
|
-
file_tasc(nest(name), configs, options, &task_block(block)).new
|
24
|
+
def task(name, configs={}, &block)
|
25
|
+
mod_declare(Tap::Task, name, configs, &block)
|
36
26
|
end
|
37
27
|
|
38
|
-
def
|
39
|
-
Tap::
|
28
|
+
def file_tasc(name, configs={}, &block)
|
29
|
+
declare(Tap::FileTask, name, configs, &block)
|
40
30
|
end
|
41
31
|
|
42
|
-
def
|
43
|
-
|
44
|
-
worcflow(name, configs, options, &task_block(block)).new
|
32
|
+
def file_task(name, configs={}, &block)
|
33
|
+
mod_declare(Tap::FileTask, name, configs, &block)
|
45
34
|
end
|
46
|
-
|
35
|
+
|
47
36
|
protected
|
48
37
|
|
49
38
|
def config(key, value=nil, options={}, &block)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
break
|
55
|
-
end
|
56
|
-
end if options[:desc] == nil
|
39
|
+
if options[:desc] == nil
|
40
|
+
caller[0] =~ Lazydoc::CALLER_REGEXP
|
41
|
+
options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
|
42
|
+
end
|
57
43
|
|
58
44
|
[:config, key, value, options, block]
|
59
45
|
end
|
60
46
|
|
61
47
|
def config_attr(key, value=nil, options={}, &block)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
break
|
67
|
-
end
|
68
|
-
end if options[:desc] == nil
|
48
|
+
if options[:desc] == nil
|
49
|
+
caller[0] =~ Lazydoc::CALLER_REGEXP
|
50
|
+
options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
|
51
|
+
end
|
69
52
|
|
70
53
|
[:config_attr, key, value, options, block]
|
71
54
|
end
|
@@ -75,12 +58,6 @@ module Tap
|
|
75
58
|
end
|
76
59
|
|
77
60
|
private
|
78
|
-
|
79
|
-
def nest(name)
|
80
|
-
# use self if self is a Module or Class,
|
81
|
-
# or self.class if self is an instance.
|
82
|
-
File.join((self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base), name.to_s)
|
83
|
-
end
|
84
61
|
|
85
62
|
def arity(block)
|
86
63
|
arity = block.arity
|
@@ -92,20 +69,65 @@ module Tap
|
|
92
69
|
|
93
70
|
arity
|
94
71
|
end
|
95
|
-
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
72
|
+
|
73
|
+
def declare(klass, declaration, configs={}, options={}, &block)
|
74
|
+
# Extract name and dependencies from declaration
|
75
|
+
name, dependencies = case declaration
|
76
|
+
when Hash then declaration.to_a[0]
|
77
|
+
else [declaration, []]
|
78
|
+
end
|
79
|
+
|
80
|
+
unless dependencies.kind_of?(Array)
|
81
|
+
dependencies = [dependencies]
|
82
|
+
end
|
83
|
+
|
84
|
+
unless dependencies.empty?
|
85
|
+
dependencies.collect! do |dependency|
|
86
|
+
case dependency
|
87
|
+
when Array then dependency
|
88
|
+
when String, Symbol then [dependency, declare(Tap::Task, dependency)]
|
89
|
+
else
|
90
|
+
if dependency.kind_of?(Class) && dependency.ancestors.include?(Tap::Task)
|
91
|
+
[File.basename(dependency.default_name), dependency]
|
92
|
+
else
|
93
|
+
raise ArgumentError, "malformed dependency declaration: #{dependency}"
|
94
|
+
end
|
95
|
+
end
|
104
96
|
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Nest the constant name
|
100
|
+
base = (self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base)
|
101
|
+
name = File.join(base, name.to_s)
|
102
|
+
|
103
|
+
klass.subclass(name, configs, dependencies, options, &block)
|
104
|
+
end
|
105
|
+
|
106
|
+
def mod_declare(klass, declaration, configs={}, &block)
|
107
|
+
options = {}
|
108
|
+
options[:arity] = arity(block) if block_given?
|
105
109
|
|
106
|
-
|
110
|
+
subclass = declare(klass, declaration, configs, options)
|
111
|
+
|
112
|
+
if block_given?
|
113
|
+
mod = Module.new
|
114
|
+
mod.module_eval %Q{
|
115
|
+
ACTION = ObjectSpace._id2ref(#{block.object_id})
|
116
|
+
def process(*args)
|
117
|
+
results = super
|
118
|
+
case ACTION.arity
|
119
|
+
when 0 then ACTION.call
|
120
|
+
when 1 then ACTION.call(self)
|
121
|
+
else ACTION.call(self, *args)
|
122
|
+
end
|
123
|
+
results
|
124
|
+
end
|
125
|
+
}
|
126
|
+
subclass.send(:include, mod)
|
107
127
|
end
|
128
|
+
subclass.instance
|
108
129
|
end
|
130
|
+
|
109
131
|
end
|
110
132
|
end
|
111
133
|
end
|
@@ -2,6 +2,7 @@ require 'tap/support/audit'
|
|
2
2
|
|
3
3
|
module Tap
|
4
4
|
module Support
|
5
|
+
|
5
6
|
# Executable wraps methods to make them executable by App. Methods are
|
6
7
|
# wrapped by extending the object that receives them; the easiest way
|
7
8
|
# to make an object executable is to use Object#_method.
|
@@ -15,7 +16,9 @@ module Tap
|
|
15
16
|
|
16
17
|
# Stores the on complete block.
|
17
18
|
attr_reader :on_complete_block
|
18
|
-
|
19
|
+
|
20
|
+
attr_reader :dependencies
|
21
|
+
|
19
22
|
public
|
20
23
|
|
21
24
|
# Extends obj with Executable and sets up all required variables. The
|
@@ -25,9 +28,57 @@ module Tap
|
|
25
28
|
obj.instance_variable_set(:@_method_name, method_name)
|
26
29
|
obj.instance_variable_set(:@multithread, multithread)
|
27
30
|
obj.instance_variable_set(:@on_complete_block, on_complete_block)
|
31
|
+
obj.instance_variable_set(:@dependencies, [])
|
28
32
|
obj
|
29
33
|
end
|
30
|
-
|
34
|
+
|
35
|
+
def self.clear_dependencies
|
36
|
+
@registry = []
|
37
|
+
@results = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.registry
|
41
|
+
@registry
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.results
|
45
|
+
@results
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.index(instance, args)
|
49
|
+
@registry.each_with_index do |entry, index|
|
50
|
+
return index if entry[0] == instance && entry[1] == args
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.resolved?(index)
|
56
|
+
@results[index] != nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.resolve(indicies)
|
60
|
+
indicies.each do |index|
|
61
|
+
next if @results[index]
|
62
|
+
instance, inputs = @registry[index]
|
63
|
+
@results[index] = instance._execute(*inputs)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.reset(indicies)
|
68
|
+
indicies.each {|index| @results[index] = nil }
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.register(instance, args)
|
72
|
+
if existing = index(instance, args)
|
73
|
+
return existing
|
74
|
+
end
|
75
|
+
|
76
|
+
@registry << [instance, args]
|
77
|
+
@registry.length - 1
|
78
|
+
end
|
79
|
+
|
80
|
+
clear_dependencies
|
81
|
+
|
31
82
|
# Sets a block to receive the results of _execute. Raises an error
|
32
83
|
# if an on_complete block is already set. Override an existing
|
33
84
|
# on_complete block by specifying override = true.
|
@@ -40,6 +91,30 @@ module Tap
|
|
40
91
|
end
|
41
92
|
@on_complete_block = block
|
42
93
|
end
|
94
|
+
|
95
|
+
# Adds the dependency to self, making self dependent on the dependency.
|
96
|
+
# The dependency will be called with the input arguments during
|
97
|
+
# resolve_dependencies.
|
98
|
+
def depends_on(dependency, *inputs)
|
99
|
+
raise ArgumentError, "not an Executable: #{dependency}" unless dependency.kind_of?(Executable)
|
100
|
+
raise ArgumentError, "cannot depend on self" if dependency == self
|
101
|
+
|
102
|
+
index = Executable.register(dependency, inputs)
|
103
|
+
dependencies << index unless dependencies.include?(index)
|
104
|
+
index
|
105
|
+
end
|
106
|
+
|
107
|
+
# Resolves dependencies by calling dependency.resolve with
|
108
|
+
# the dependency arguments.
|
109
|
+
def resolve_dependencies
|
110
|
+
Executable.resolve(dependencies)
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
def reset_dependencies
|
115
|
+
Executable.reset(dependencies)
|
116
|
+
self
|
117
|
+
end
|
43
118
|
|
44
119
|
# Auditing method call. Executes _method_name for self, but audits
|
45
120
|
# the result. Sends the audited result to the on_complete_block if set.
|
@@ -51,7 +126,11 @@ module Tap
|
|
51
126
|
# a new audit using the input
|
52
127
|
# multiple inputs:: merges the inputs into a new Audit.
|
53
128
|
#
|
129
|
+
# Dependencies are resolved using resolve_dependencies before
|
130
|
+
# _method_name is executed.
|
54
131
|
def _execute(*inputs)
|
132
|
+
resolve_dependencies
|
133
|
+
|
55
134
|
audit = case inputs.length
|
56
135
|
when 0 then Audit.new
|
57
136
|
when 1
|