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
data/bin/rap CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # usage: rap taskname {options} [args]
3
3
 
4
- require "#{File.dirname(__FILE__)}/../lib/tap.rb"
4
+ $:.unshift "#{File.dirname(__FILE__)}/../lib"
5
+ require 'tap/declarations'
5
6
 
6
7
  # setup the environment
7
8
  begin
@@ -11,9 +12,9 @@ begin
11
12
  env = Tap::Exe.instantiate
12
13
 
13
14
  # add the DEFAULT_TASK_FILE if it exists
14
- task_file = File.expand_path('tapfile.rb')
15
+ task_file = File.expand_path('Tapfile')
15
16
  if File.exists?(task_file)
16
- env.requires.unshift(task_file)
17
+ env.loads.unshift(task_file)
17
18
  env.manifest(:tasks).search_paths << [Dir.pwd, task_file]
18
19
  end
19
20
 
@@ -68,7 +69,11 @@ begin
68
69
  puts Tap::Support::Lazydoc.usage(__FILE__)
69
70
  puts
70
71
  puts "=== tap tasks ==="
71
- puts env.summarize(:tasks) {|const| const.document[const.name]['manifest'] }
72
+ str = env.summarize(:tasks) do |const|
73
+ const.document.resolve
74
+ const.document[const.name]['manifest'].subject
75
+ end
76
+ puts str
72
77
  puts
73
78
  puts "=== rake tasks ==="
74
79
  Tap::Tasks::Rake.new.enq('-T')
@@ -79,7 +84,10 @@ begin
79
84
  puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
80
85
  exit
81
86
  else
82
- queues = env.build(ARGV) {|args| Tap::Tasks::Rake }
87
+ queues = env.build(ARGV) do |args|
88
+ warn "warning: implict rake for [#{args.join(' ')}]"
89
+ Tap::Tasks::Rake
90
+ end
83
91
  ARGV.clear
84
92
 
85
93
  if queues.empty?
data/lib/tap.rb CHANGED
@@ -14,10 +14,6 @@ require 'tap/constants'
14
14
  require 'tap/exe'
15
15
  require 'tap/task'
16
16
  require 'tap/file_task'
17
- require 'tap/workflow'
18
-
19
- require 'tap/support/declarations'
20
- Tap.extend Tap::Support::Declarations
21
17
 
22
18
  # Apply platform-specific patches
23
19
  # case RUBY_PLATFORM
data/lib/tap/app.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'logger'
2
2
  require 'tap/support/aggregator'
3
+ require 'tap/support/dependencies'
3
4
  require 'tap/support/executable_queue'
4
5
 
5
6
  module Tap
@@ -77,8 +78,8 @@ module Tap
77
78
  #
78
79
  # t1 = Task.new {|task, input| input += 1 }
79
80
  # t2 = Task.new {|task, input| input += 10 }
80
- # Task.batch(t1, t2) # => [t1, t2]
81
81
  #
82
+ # t1.batch_with(t2)
82
83
  # t1.enq 0
83
84
  #
84
85
  # app.run
@@ -191,6 +192,8 @@ module Tap
191
192
  # methods that have no <tt>on_complete</tt> block
192
193
  attr_reader :aggregator
193
194
 
195
+ attr_reader :dependencies
196
+
194
197
  config :debug, false, &c.flag # Flag debugging
195
198
  config :force, false, &c.flag # Force execution at checkpoints
196
199
  config :quiet, false, &c.flag # Suppress logging
@@ -222,6 +225,7 @@ module Tap
222
225
  @state = State::READY
223
226
  @queue = Support::ExecutableQueue.new
224
227
  @aggregator = Support::Aggregator.new
228
+ @dependencies = Support::Dependencies.new
225
229
 
226
230
  initialize_config(config)
227
231
  self.logger = logger
@@ -270,9 +274,7 @@ module Tap
270
274
  # aggregator unless an on_complete block is set. Returns the audited
271
275
  # result.
272
276
  def execute(m, inputs)
273
- _result = m._execute(*inputs)
274
- aggregator.store(_result) unless m.on_complete_block
275
- _result
277
+ m._execute(*inputs)
276
278
  end
277
279
 
278
280
  # Sets state = State::READY unless the app is running. Returns self.
@@ -371,140 +373,6 @@ module Tap
371
373
  m = object._method(method_name)
372
374
  enq(m, *inputs)
373
375
  end
374
-
375
- # Sets a sequence workflow pattern for the tasks; each task will enque
376
- # the next task with it's results.
377
- #
378
- # Notes:
379
- # - Batched tasks will have the pattern set for each task in the batch
380
- # - The current audited results are yielded to the block, if given,
381
- # before the next task is enqued.
382
- # - Executables may provided as well as tasks.
383
- def sequence(tasks) # :yields: _result
384
- current_task = tasks.shift
385
- tasks.each do |next_task|
386
- # simply pass results from one task to the next.
387
- current_task.on_complete do |_result|
388
- yield(_result) if block_given?
389
- enq(next_task, _result)
390
- end
391
- current_task = next_task
392
- end
393
- end
394
-
395
- # Sets a fork workflow pattern for the source task; each target
396
- # will enque the results of source.
397
- #
398
- # Notes:
399
- # - Batched tasks will have the pattern set for each task in the batch
400
- # - The current audited results are yielded to the block, if given,
401
- # before the next task is enqued.
402
- # - Executables may provided as well as tasks.
403
- def fork(source, targets) # :yields: _result
404
- source.on_complete do |_result|
405
- targets.each do |target|
406
- yield(_result) if block_given?
407
- enq(target, _result)
408
- end
409
- end
410
- end
411
-
412
- # Sets a simple merge workflow pattern for the source tasks. Each source
413
- # enques target with it's result; no synchronization occurs, nor are
414
- # results grouped before being sent to the target.
415
- #
416
- # Notes:
417
- # - Batched tasks will have the pattern set for each task in the batch
418
- # - The current audited results are yielded to the block, if given,
419
- # before the next task is enqued.
420
- # - Executables may provided as well as tasks.
421
- def merge(target, sources) # :yields: _result
422
- sources.each do |source|
423
- # merging can use the existing audit trails... each distinct
424
- # input is getting sent to one place (the target)
425
- source.on_complete do |_result|
426
- yield(_result) if block_given?
427
- enq(target, _result)
428
- end
429
- end
430
- end
431
-
432
- # Sets a synchronized merge workflow for the source tasks. Results from
433
- # each source task are collected and enqued as a single group to the target.
434
- # The target is not enqued until all sources have completed. Raises an
435
- # error if a source returns twice before the target is enqued.
436
- #
437
- # Notes:
438
- # - Batched tasks will have the pattern set for each task in the batch
439
- # - The current audited results are yielded to the block, if given,
440
- # before the next task is enqued.
441
- # - Executables may provided as well as tasks.
442
- #
443
- #-- TODO: add notes on testing and the way results are received
444
- # (ie as a single object)
445
- def sync_merge(target, sources) # :yields: _result
446
- group = Array.new(sources.length, nil)
447
- sources.each_with_index do |source, index|
448
- batch_map = Hash.new(0)
449
- batch_length = if source.kind_of?(Support::Batchable)
450
- source.batch.each_with_index {|obj, i| batch_map[obj] = i }
451
- source.batch.length
452
- else
453
- 1
454
- end
455
-
456
- group[index] = Array.new(batch_length, nil)
457
-
458
- source.on_complete do |_result|
459
- batch_index = batch_map[_result._current_source]
460
-
461
- if group[index][batch_index] != nil
462
- raise "sync_merge collision... already got a result for #{_result._current_source}"
463
- end
464
-
465
- group[index][batch_index] = _result
466
-
467
- unless group.flatten.include?(nil)
468
- Support::Combinator.new(*group).each do |*combination|
469
- # merge the source audits
470
- _group_result = Support::Audit.merge(*combination)
471
-
472
- yield(_group_result) if block_given?
473
- target.enq(_group_result)
474
- end
475
-
476
- # reset the group array
477
- group.collect! {|i| nil }
478
- end
479
- end
480
- end
481
- end
482
-
483
- # Sets a choice workflow pattern for the source task. When the
484
- # source task completes, switch yields the audited result to the
485
- # block which then returns the index of the target to enque with
486
- # the results. No target will be enqued if the index is false or
487
- # nil; an error is raised if no target can be found for the
488
- # specified index.
489
- #
490
- # Notes:
491
- # - Batched tasks will have the pattern set for each task in the batch
492
- # - The current audited results are yielded to the block, if given,
493
- # before the next task is enqued.
494
- # - Executables may provided as well as tasks.
495
- def switch(source, targets) # :yields: _result
496
- source.on_complete do |_result|
497
- if index = yield(_result)
498
- unless target = targets[index]
499
- raise "no switch target for index: #{index}"
500
- end
501
-
502
- enq(target, _result)
503
- else
504
- aggregator.store(_result)
505
- end
506
- end
507
- end
508
376
 
509
377
  # Returns all aggregated, audited results for the specified tasks.
510
378
  # Results are joined into a single array. Arrays of tasks are
@@ -531,6 +399,10 @@ module Tap
531
399
  _results(tasks).collect {|_result| _result._current}
532
400
  end
533
401
 
402
+ def inspect
403
+ "#<#{self.class.to_s}:#{object_id} root: #{root} >"
404
+ end
405
+
534
406
  protected
535
407
 
536
408
  # A hook for handling unknown configurations in subclasses, called from
data/lib/tap/constants.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Tap
2
2
  MAJOR = 0
3
3
  MINOR = 10
4
- TINY = 6
4
+ TINY = 7
5
5
 
6
6
  VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
7
7
  WEBSITE="http://tap.rubyforge.org"
@@ -0,0 +1,201 @@
1
+ require "#{File.dirname(__FILE__)}/../tap"
2
+ autoload(:OpenStruct, 'ostruct')
3
+
4
+ module Tap
5
+ module Declarations
6
+ Lazydoc = Tap::Support::Lazydoc
7
+
8
+ module Lazydoc
9
+ class Declaration < Comment
10
+ def resolve(lines)
11
+ super
12
+
13
+ @subject = case
14
+ when content.empty? || content[0][0].to_s !~ /^::desc(.*)/ then ""
15
+ else
16
+ content[0].shift
17
+ $1.strip
18
+ end
19
+
20
+ self
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.set_declaration_base(base)
26
+ # TODO -- warn if base is Object -- conflict with Rake
27
+ declaration_base = base.to_s
28
+ declaration_base = "" if ["Object", "Tap"].include?(declaration_base)
29
+
30
+ base.instance_variable_set(:@tap_declaration_base, declaration_base.underscore)
31
+ end
32
+
33
+ def self.included(base)
34
+ set_declaration_base(base)
35
+ end
36
+
37
+ def self.extended(base)
38
+ set_declaration_base(base)
39
+ end
40
+
41
+ def tasc(*args, &block)
42
+ # in this scheme, arg_names will be empty
43
+ name, configs, dependencies, arg_names = resolve_args(args)
44
+ declare(Tap::Task, name, configs, dependencies, arg_names, &block)
45
+ end
46
+
47
+ def task(*args, &block)
48
+ name, configs, dependencies, arg_names = resolve_args(args)
49
+
50
+ task_class = declare(Tap::Task, name, configs, dependencies, arg_names) do |*inputs|
51
+ args = {}
52
+ arg_names.each do |arg_name|
53
+ break if inputs.empty?
54
+ args[arg_name] = inputs.shift
55
+ end
56
+
57
+ args = OpenStruct.new(args)
58
+ self.class::BLOCKS.each do |task_block|
59
+ case task_block.arity
60
+ when 0 then task_block.call()
61
+ when 1 then task_block.call(self)
62
+ else task_block.call(self, args)
63
+ end
64
+ end
65
+ end
66
+
67
+ unless task_class.const_defined?(:BLOCKS)
68
+ task_class.const_set(:BLOCKS, [])
69
+ end
70
+ task_class::BLOCKS << block unless block == nil
71
+
72
+ task_class.instance
73
+ end
74
+
75
+ protected
76
+
77
+ def config(key, value=nil, options={}, &block)
78
+ if options[:desc] == nil
79
+ caller[0] =~ Lazydoc::CALLER_REGEXP
80
+ options[:desc] = Lazydoc.register($1, $3.to_i - 1)
81
+ end
82
+
83
+ [:config, key, value, options, block]
84
+ end
85
+
86
+ def config_attr(key, value=nil, options={}, &block)
87
+ if options[:desc] == nil
88
+ caller[0] =~ Lazydoc::CALLER_REGEXP
89
+ options[:desc] = Lazydoc.register($1, $3.to_i - 1)
90
+ end
91
+
92
+ [:config_attr, key, value, options, block]
93
+ end
94
+
95
+ def c
96
+ Tap::Support::Validation
97
+ end
98
+
99
+ private
100
+
101
+ # Resolve the arguments for a task/rule. Returns a triplet of
102
+ # [task_name, configs, prerequisites, arg_name_list].
103
+ #
104
+ # From Rake 0.8.3
105
+ # Changes:
106
+ # - no :needs support for the trailing Hash (which is now config)
107
+ def resolve_args(args)
108
+ task_name = args.shift
109
+ arg_names = args
110
+ configs = {}
111
+ needs = []
112
+
113
+ if task_name.is_a?(Hash)
114
+ hash = task_name
115
+ task_name = hash.keys[0]
116
+ needs = hash[task_name]
117
+ end
118
+
119
+ if arg_names.last.is_a?(Hash)
120
+ configs = arg_names.pop
121
+ end
122
+
123
+ needs = needs.respond_to?(:to_ary) ? needs.to_ary : [needs]
124
+ needs = needs.compact.collect do |need|
125
+ dependency, argv = case need
126
+ when Array then need
127
+ else [need, []]
128
+ end
129
+
130
+ unless dependency.kind_of?(Class)
131
+ dependency = declare(Tap::Task, dependency)
132
+ end
133
+
134
+ if dependency.ancestors.include?(Tap::Task)
135
+ [File.basename(dependency.default_name), dependency, argv]
136
+ else
137
+ raise ArgumentError, "malformed dependency declaration: #{need}"
138
+ end
139
+ end
140
+
141
+ [task_name, configs, needs, arg_names]
142
+ end
143
+
144
+ def arity(block)
145
+ arity = block.arity
146
+
147
+ case
148
+ when arity > 0 then arity -= 1
149
+ when arity < 0 then arity += 1
150
+ end
151
+
152
+ arity
153
+ end
154
+
155
+ def declare(klass, name, configs={}, dependencies=[], arg_names=[], &block)
156
+ # nest the constant name
157
+ base = (self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base)
158
+ name = File.join(base, name.to_s)
159
+
160
+ # generate the subclass
161
+ subclass = klass.subclass(name, configs, dependencies, &block)
162
+
163
+ # register documentation
164
+ caller[1] =~ Lazydoc::CALLER_REGEXP
165
+ subclass.source_file = File.expand_path($1)
166
+ lazydoc = subclass.lazydoc(false)
167
+ lazydoc[subclass.to_s]['manifest'] = lazydoc.register($3.to_i - 1, Lazydoc::Declaration)
168
+
169
+ if arg_names.empty?
170
+ arity = block_given? ? arity(block) : -1
171
+ case
172
+ when arity > 0
173
+ arg_names = Array.new(arity, "INPUT")
174
+ when arity < 0
175
+ arg_names = Array.new(-1 * arity - 1, "INPUT")
176
+ arg_names << "INPUTS..."
177
+ end
178
+ end
179
+
180
+ comment = Lazydoc::Comment.new
181
+ comment.subject = arg_names.join(' ')
182
+ lazydoc[subclass.to_s]['args'] = comment
183
+
184
+ # update any dependencies in instance
185
+ subclass.dependencies.each do |dependency, args|
186
+ subclass.instance.depends_on(dependency.instance, *args)
187
+ end
188
+
189
+ dir = File.dirname(lazydoc.source_file)
190
+ manifest = Tap::Env.instance_for(dir).manifest(:tasks).build
191
+ const_name = subclass.to_s
192
+ unless manifest.entries.find {|lookup, const| const.name == const_name }
193
+ manifest.entries << [const_name.underscore, Tap::Support::Constant.new(const_name, lazydoc.source_file)]
194
+ end
195
+
196
+ subclass
197
+ end
198
+ end
199
+
200
+ extend Declarations
201
+ end