bahuvrihi-tap 0.10.6 → 0.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/bin/rap +13 -5
  2. data/lib/tap.rb +0 -4
  3. data/lib/tap/app.rb +10 -138
  4. data/lib/tap/constants.rb +1 -1
  5. data/lib/tap/declarations.rb +201 -0
  6. data/lib/tap/env.rb +10 -2
  7. data/lib/tap/exe.rb +2 -2
  8. data/lib/tap/generator/generators/root/templates/Rakefile +1 -0
  9. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  10. data/lib/tap/spec.rb +38 -63
  11. data/lib/tap/spec/adapter.rb +8 -31
  12. data/lib/tap/spec/inheritable_class_test_root.rb +9 -0
  13. data/lib/tap/support/audit.rb +0 -2
  14. data/lib/tap/support/combinator.rb +83 -31
  15. data/lib/tap/support/configurable_class.rb +7 -7
  16. data/lib/tap/support/{dependable.rb → dependencies.rb} +9 -7
  17. data/lib/tap/support/executable.rb +226 -19
  18. data/lib/tap/support/gems/rake.rb +6 -3
  19. data/lib/tap/support/join.rb +87 -0
  20. data/lib/tap/support/joins.rb +13 -0
  21. data/lib/tap/support/joins/fork.rb +18 -0
  22. data/lib/tap/support/joins/merge.rb +20 -0
  23. data/lib/tap/support/joins/sequence.rb +21 -0
  24. data/lib/tap/support/joins/switch.rb +23 -0
  25. data/lib/tap/support/joins/sync_merge.rb +57 -0
  26. data/lib/tap/support/lazydoc/document.rb +10 -0
  27. data/lib/tap/support/node.rb +58 -0
  28. data/lib/tap/support/parser.rb +379 -0
  29. data/lib/tap/support/schema.rb +350 -0
  30. data/lib/tap/support/tdoc.rb +5 -0
  31. data/lib/tap/support/validation.rb +2 -0
  32. data/lib/tap/task.rb +26 -61
  33. data/lib/tap/test.rb +9 -82
  34. data/lib/tap/test/assertions.rb +38 -0
  35. data/lib/tap/test/extensions.rb +78 -0
  36. data/lib/tap/test/{file_methods.rb → file_test.rb} +64 -37
  37. data/lib/tap/test/{file_methods_class.rb → file_test_class.rb} +2 -2
  38. data/lib/tap/test/regexp_escape.rb +87 -0
  39. data/lib/tap/test/script_test.rb +46 -0
  40. data/lib/tap/test/script_tester.rb +109 -0
  41. data/lib/tap/test/{subset_methods.rb → subset_test.rb} +9 -9
  42. data/lib/tap/test/{subset_methods_class.rb → subset_test_class.rb} +22 -14
  43. data/lib/tap/test/{tap_methods.rb → tap_test.rb} +43 -6
  44. data/lib/tap/test/utils.rb +6 -3
  45. metadata +27 -24
  46. data/lib/tap/parser.rb +0 -619
  47. data/lib/tap/spec/file_methods.rb +0 -16
  48. data/lib/tap/spec/file_methods_class.rb +0 -13
  49. data/lib/tap/spec/subset_methods.rb +0 -14
  50. data/lib/tap/support/batchable.rb +0 -47
  51. data/lib/tap/support/batchable_class.rb +0 -107
  52. data/lib/tap/support/declarations.rb +0 -131
  53. data/lib/tap/support/lazydoc/declaration.rb +0 -20
  54. data/lib/tap/support/parsers/base.rb +0 -81
  55. data/lib/tap/support/parsers/server.rb +0 -113
  56. data/lib/tap/test/script_methods.rb +0 -75
  57. data/lib/tap/test/script_methods/regexp_escape.rb +0 -94
  58. data/lib/tap/test/script_methods/script_test.rb +0 -109
  59. data/lib/tap/workflow.rb +0 -161
@@ -1,16 +0,0 @@
1
- require 'tap/spec/adapter'
2
- require 'tap/test/file_methods'
3
- require 'tap/spec/file_methods_class'
4
-
5
- module Tap
6
- module Spec
7
- module FileMethods
8
- def self.included(base)
9
- super
10
- base.send(:include, Tap::Spec::Adapter)
11
- base.send(:include, Tap::Test::FileMethods)
12
- base.extend Tap::Spec::FileMethodsClass
13
- end
14
- end
15
- end
16
- end
@@ -1,13 +0,0 @@
1
- module Tap
2
- module Spec
3
- module FileMethodsClass
4
- def trs
5
- @trs ||= (superclass.respond_to?(:trs) ? superclass.trs : nil)
6
- end
7
-
8
- def file_test_root
9
- super.chomp("_spec")
10
- end
11
- end
12
- end
13
- end
@@ -1,14 +0,0 @@
1
- require 'tap/spec/adapter'
2
- require 'tap/test/subset_methods'
3
-
4
- module Tap
5
- module Spec
6
- module SubsetMethods
7
- def self.included(base)
8
- super
9
- base.send(:include, Tap::Spec::Adapter)
10
- base.send(:include, Tap::Test::SubsetMethods)
11
- end
12
- end
13
- end
14
- end
@@ -1,47 +0,0 @@
1
- require 'tap/support/batchable_class'
2
-
3
- module Tap
4
- module Support
5
-
6
- # Batchable encapsulates the methods used to support batching
7
- # of tasks. Classes including Batchable should call <tt>super</tt>
8
- # during initialization to initialize batch, or they should
9
- # initialize batch themselves.
10
- #
11
- # See the 'Batches' section in the Tap::Task documentation for
12
- # details on how Batchable works in practice.
13
- module Batchable
14
-
15
- def self.included(mod)
16
- mod.extend Support::BatchableClass if mod.kind_of?(Class)
17
- end
18
-
19
- # The object batch.
20
- attr_reader :batch
21
-
22
- def initialize(batch=[])
23
- @batch = batch
24
- @batch << self
25
- end
26
-
27
- # Returns true if the batch size is greater than one
28
- # (the one being self).
29
- def batched?
30
- batch.length > 1
31
- end
32
-
33
- # Returns the index of the self in batch.
34
- def batch_index
35
- batch.index(self)
36
- end
37
-
38
- # Initializes a new batch object and adds the object to batch.
39
- # The object will be a duplicate of self.
40
- def initialize_batch_obj
41
- obj = self.dup
42
- batch << obj
43
- obj
44
- end
45
- end
46
- end
47
- end
@@ -1,107 +0,0 @@
1
- module Tap
2
- module Support
3
-
4
- # BatchableClass encapsulates class methods related to Batchable.
5
- module BatchableClass
6
-
7
- # Merges the batches for the specified objects. All objects
8
- # sharing the individual object batches will be affected, even
9
- # if they are not listed explicitly as an input.
10
- #
11
- # t1 = Tap::Task.new
12
- # t2 = Tap::Task.new
13
- # t3 = t2.initialize_batch_obj
14
- #
15
- # Tap::Task.batch(t1, t2)
16
- # t3.batch # => [t1,t2,t3]
17
- #
18
- # Returns the new batch.
19
- def batch(*batchables)
20
- merged = []
21
- batches = batchables.collect {|batchable| batchable.batch }.uniq
22
- batches.each do |batch|
23
- merged.concat(batch)
24
- batch.clear
25
- end
26
- merged.uniq!
27
- batches.each {|batch| batch.concat(merged) }
28
- merged
29
- end
30
-
31
- protected
32
-
33
- # Redefines the specified method(s) as batched methods. The existing method
34
- # is renamed as <tt>unbatched_method</tt> and <tt>method</tt> redefined to
35
- # call <tt>unbatched_method</tt> on each object in the batch.
36
- #
37
- # def process(one, two)
38
- # ...
39
- # end
40
- # batch_function(:process)
41
- #
42
- # Is equivalent to:
43
- #
44
- # def unbatched_process(one, two)
45
- # ...
46
- # end
47
- #
48
- # def process(one, two)
49
- # batch.each do |t|
50
- # t.unbatched_process(one, two)
51
- # end
52
- # self
53
- # end
54
- #
55
- # The batched method will accept/pass as many arguments as are defined for
56
- # the unbatched method. Splats are supported, and blocks are supported too
57
- # by passing a block to batch_function:
58
- #
59
- # def process(arg, *args, &block)
60
- # ...
61
- # end
62
- # batch_function(:process) {}
63
- #
64
- # Is equivalent to:
65
- #
66
- # def unbatched_process(arg, *args, &block)
67
- # ...
68
- # end
69
- #
70
- # def process(*args, &block)
71
- # batch.each do |t|
72
- # t.unbatched_process(*args, &block)
73
- # end
74
- # self
75
- # end
76
- #
77
- # Obviously there are limitations to batch_function, most notably batching
78
- # functions with default values. In these cases, batch functionality
79
- # must be implemented manually.
80
- def batch_function(*methods)
81
- methods.each do |method_name|
82
- unbatched_method = "unbatched_#{method_name}"
83
- if method_defined?(unbatched_method)
84
- raise "unbatched method already defined: #{unbatched_method}"
85
- end
86
-
87
- arity = instance_method(method_name).arity
88
- args = case
89
- when arity < 0 then "*args"
90
- else Array.new(arity) {|index| "arg#{index}" }.join(", ")
91
- end
92
- args += ", &block" if block_given?
93
-
94
- class_eval %Q{
95
- alias #{unbatched_method} #{method_name}
96
- def #{method_name}(#{args})
97
- batch.each do |t|
98
- t.#{unbatched_method}(#{args})
99
- end
100
- self
101
- end
102
- }
103
- end
104
- end
105
- end
106
- end
107
- end
@@ -1,131 +0,0 @@
1
- require 'tap/support/lazydoc/declaration'
2
-
3
- module Tap
4
- module Support
5
- module Declarations
6
- def self.set_declaration_base(base)
7
- # TODO -- warn if base is Object -- conflict with Rake
8
- declaration_base = base.to_s
9
- declaration_base = "" if ["Object", "Tap"].include?(declaration_base)
10
-
11
- base.instance_variable_set(:@tap_declaration_base, declaration_base.underscore)
12
- end
13
-
14
- def self.included(base)
15
- set_declaration_base(base)
16
- end
17
-
18
- def self.extended(base)
19
- set_declaration_base(base)
20
- end
21
-
22
- def tasc(name, configs={}, &block)
23
- declare(Tap::Task, name, configs, &block)
24
- end
25
-
26
- protected
27
-
28
- def config(key, value=nil, options={}, &block)
29
- if options[:desc] == nil
30
- caller[0] =~ Lazydoc::CALLER_REGEXP
31
- options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
32
- end
33
-
34
- [:config, key, value, options, block]
35
- end
36
-
37
- def config_attr(key, value=nil, options={}, &block)
38
- if options[:desc] == nil
39
- caller[0] =~ Lazydoc::CALLER_REGEXP
40
- options[:desc] = Support::Lazydoc.register($1, $3.to_i - 1)
41
- end
42
-
43
- [:config_attr, key, value, options, block]
44
- end
45
-
46
- def c
47
- Support::Validation
48
- end
49
-
50
- private
51
-
52
- def arity(block)
53
- arity = block.arity
54
-
55
- case
56
- when arity > 0 then arity -= 1
57
- when arity < 0 then arity += 1
58
- end
59
-
60
- arity
61
- end
62
-
63
- def parse(declaration)
64
- # Extract name and dependencies from declaration
65
- name, dependencies = case declaration
66
- when Hash then declaration.to_a[0]
67
- else [declaration, []]
68
- end
69
-
70
- unless dependencies.kind_of?(Array)
71
- raise ArgumentError, "dependencies should be specified as an array (was #{dependencies.class})"
72
- end
73
-
74
- unless dependencies.empty?
75
- dependencies.collect! do |entry|
76
- dependency, argv = case entry
77
- when Array then entry
78
- else [entry, []]
79
- end
80
-
81
- unless dependency.kind_of?(Class)
82
- dependency = declare(Tap::Task, dependency)
83
- end
84
-
85
- if dependency.ancestors.include?(Tap::Task)
86
- [File.basename(dependency.default_name), dependency, argv]
87
- else
88
- raise ArgumentError, "malformed dependency declaration: #{dependency}"
89
- end
90
- end
91
- end
92
-
93
- [name, dependencies]
94
- end
95
-
96
- def declare(klass, declaration, configs={}, options={}, &block)
97
- # parse the declaration
98
- name, dependencies = parse(declaration)
99
-
100
- # nest the constant name
101
- base = (self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base)
102
- name = File.join(base, name.to_s)
103
-
104
- # generate the subclass
105
- subclass = klass.subclass(name, configs, dependencies, options, &block)
106
-
107
- # register documentation
108
- caller[1] =~ Lazydoc::CALLER_REGEXP
109
- subclass.source_file = File.expand_path($1)
110
- lazydoc = subclass.lazydoc(false)
111
- lazydoc[subclass.to_s]['manifest'] = lazydoc.register($3.to_i - 1, Lazydoc::Declaration)
112
-
113
- arity = options[:arity] || (block_given? ? block.arity : -1)
114
- comment = Lazydoc::Comment.new
115
- comment.subject = case
116
- when arity > 0
117
- Array.new(arity, "INPUT").join(' ')
118
- when arity < 0
119
- array = Array.new(-1 * arity - 1, "INPUT")
120
- array << "INPUTS..."
121
- array.join(' ')
122
- else ""
123
- end
124
- lazydoc[subclass.to_s]['args'] ||= comment
125
-
126
- subclass
127
- end
128
-
129
- end
130
- end
131
- end
@@ -1,20 +0,0 @@
1
- module Tap
2
- module Support
3
- module Lazydoc
4
- class Declaration < Comment
5
- def resolve(lines)
6
- super
7
-
8
- @subject = case
9
- when content.empty? || content[0][0].to_s !~ /^::desc(.*)/ then ""
10
- else
11
- content[0].shift
12
- $1.strip
13
- end
14
-
15
- self
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,81 +0,0 @@
1
- module Tap
2
- module Support
3
- module Parsers
4
- class Base
5
- class << self
6
- # Parses the input string as YAML, if the string matches the YAML document
7
- # specifier (ie it begins with "---\s*\n"). Otherwise returns the string.
8
- #
9
- # str = {'key' => 'value'}.to_yaml # => "--- \nkey: value\n"
10
- # Tap::Script.parse_yaml(str) # => {'key' => 'value'}
11
- # Tap::Script.parse_yaml("str") # => "str"
12
- def parse_yaml(str)
13
- str =~ /\A---\s*\n/ ? YAML.load(str) : str
14
- end
15
- end
16
-
17
- attr_reader :argvs
18
- attr_reader :rounds
19
- attr_reader :sequences
20
- attr_reader :forks
21
- attr_reader :merges
22
- attr_reader :sync_merges
23
-
24
- def build(env, app)
25
- # attempt lookup and instantiate the task class
26
- task_declarations = argvs.collect do |argv|
27
- pattern = argv.shift
28
-
29
- const = env.search(:tasks, pattern) or raise ArgumentError, "unknown task: #{pattern}"
30
- task_class = const.constantize or raise ArgumentError, "unknown task: #{pattern}"
31
- task_class.instantiate(argv, app)
32
- end
33
-
34
- # remove tasks used by the workflow
35
- tasks = targets.collect do |index|
36
- task, args = task_declarations[index]
37
-
38
- unless args.empty?
39
- raise ArgumentError, "workflow target receives args: #{task} [#{args.join(', ')}]"
40
- end
41
-
42
- tasks[index] = nil
43
- task
44
- end
45
-
46
- # build the workflow
47
- [:sequence, :fork, :merge, :sync_merge].each do |type|
48
- send("#{type}s").each do |source, targets|
49
- source.send(type, *targets.collect {|t| tasks[t] })
50
- end
51
- end
52
-
53
- # build queues
54
- queues = rounds.collect do |round|
55
- round.each do |index|
56
- task, args = task_declarations[index]
57
- task.enq(*args) if task
58
- end
59
-
60
- app.queue.clear
61
- end
62
- queues.delete_if {|queue| queue.empty? }
63
-
64
- queues
65
- end
66
-
67
- protected
68
-
69
- def targets
70
- results = sequences.collect {|source, targets| targets } +
71
- forks.collect {|source, targets| targets } +
72
- merges.collect {|target, sources| target } +
73
- sync_merges.collect {|target, sources| target }
74
-
75
- results.flatten.uniq.sort
76
- end
77
-
78
- end
79
- end
80
- end
81
- end
@@ -1,113 +0,0 @@
1
- require 'tap/support/parsers/base'
2
-
3
- module Tap
4
- module Support
5
- module Parsers
6
-
7
- # rounds syntax
8
- # 0[tasc]=dump&0[config][key]=value&0[input][]=a&0[input][]=b&0[selected]
9
- # sequence[1]=1,2,3
10
- # fork[1]=2,3
11
- # round[0]=1,2,3
12
- # ....
13
-
14
- class Server < Base
15
-
16
- class << self
17
- def parse_argv(hash)
18
- raise ArgumentError, "no task specified" unless hash.has_key?('tasc')
19
-
20
- # parse task
21
- argv = [hash.delete('tasc')]
22
-
23
- # parse configs
24
- configs = hash.delete('config')
25
- configs = YAML.load(configs) if configs.kind_of?(String)
26
-
27
- case configs
28
- when Hash
29
- configs.each_pair do |key, value|
30
- argv << "--#{key}"
31
- argv << value
32
- end
33
- when nil
34
- else raise ArgumentError, "non-hash configs specified: #{configs}"
35
- end
36
-
37
- # parse inputs
38
- inputs = hash.delete('inputs')
39
- inputs = YAML.load(inputs) if inputs.kind_of?(String)
40
-
41
- case inputs
42
- when Array then argv.concat(inputs)
43
- when nil
44
- else raise ArgumentError, "non-array inputs specified: #{inputs}"
45
- end
46
-
47
- argv
48
- end
49
-
50
- def parse_pairs(values)
51
- [*values].collect do |value|
52
- case value
53
- when String then value.split(',').collect {|i| i.to_i }
54
- when Array then value
55
- else raise ArgumentError, "non-array inputs specified: #{value}"
56
- end
57
- end.collect do |split|
58
- next if split.empty?
59
- [split.shift, split]
60
- end.compact
61
- end
62
-
63
- def compact(argh)
64
- compact = {}
65
- argh.each_pair do |key, value|
66
- compact[key] = case value
67
- when Array
68
- value.length == 1 && value[0].kind_of?(String) ? value[0] : value
69
- when Hash
70
- compact(value)
71
- else
72
- value
73
- end
74
- end
75
- compact
76
- end
77
- end
78
-
79
- INDEX = /\A\d+\z/
80
-
81
- attr_reader :attributes
82
-
83
- def initialize(argh)
84
- @argvs = []
85
- @attributes = []
86
-
87
- argh.each_pair do |key, value|
88
- case key
89
- when INDEX
90
- argvs[key.to_i] = Server.parse_argv(value)
91
- attributes[key.to_i] = value
92
- when "workflow"
93
- hash = value.kind_of?(String) ? YAML.load(value) : value
94
- unless hash.kind_of?(Hash)
95
- raise ArgumentError, "non-hash workflow specified: #{value}"
96
- end
97
-
98
- hash.each_pair do |type, entries|
99
- instance_variable_set("@#{type}s", Server.parse_pairs(entries))
100
- end
101
- end
102
- end
103
-
104
- @rounds ||= []
105
- @sequences ||= []
106
- @forks ||= []
107
- @merges ||= []
108
- @sync_merges ||= []
109
- end
110
- end
111
- end
112
- end
113
- end