bahuvrihi-tap 0.10.7 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/MIT-LICENSE +0 -2
  2. data/README +20 -31
  3. data/bin/rap +18 -8
  4. data/cgi/run.rb +47 -37
  5. data/cmd/console.rb +1 -1
  6. data/cmd/destroy.rb +3 -3
  7. data/cmd/generate.rb +3 -3
  8. data/cmd/manifest.rb +61 -53
  9. data/cmd/run.rb +1 -1
  10. data/doc/Class Reference +119 -110
  11. data/doc/Command Reference +76 -123
  12. data/doc/Syntax Reference +290 -0
  13. data/doc/Tutorial +307 -237
  14. data/lib/tap.rb +1 -12
  15. data/lib/tap/app.rb +46 -71
  16. data/lib/tap/constants.rb +1 -1
  17. data/lib/tap/declarations.rb +110 -100
  18. data/lib/tap/env.rb +141 -173
  19. data/lib/tap/exe.rb +5 -5
  20. data/lib/tap/file_task.rb +2 -2
  21. data/lib/tap/generator/base.rb +0 -4
  22. data/lib/tap/generator/destroy.rb +8 -12
  23. data/lib/tap/generator/generate.rb +19 -14
  24. data/lib/tap/generator/generators/command/command_generator.rb +1 -1
  25. data/lib/tap/generator/generators/config/config_generator.rb +3 -3
  26. data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
  27. data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
  28. data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
  29. data/lib/tap/generator/generators/root/root_generator.rb +12 -12
  30. data/lib/tap/generator/generators/root/templates/Rakefile +1 -2
  31. data/lib/tap/generator/generators/root/templates/tapfile +11 -8
  32. data/lib/tap/generator/generators/task/task_generator.rb +1 -3
  33. data/lib/tap/generator/generators/task/templates/test.erb +1 -3
  34. data/lib/tap/root.rb +4 -2
  35. data/lib/tap/support/aggregator.rb +16 -3
  36. data/lib/tap/support/assignments.rb +10 -9
  37. data/lib/tap/support/audit.rb +58 -62
  38. data/lib/tap/support/class_configuration.rb +32 -43
  39. data/lib/tap/support/combinator.rb +7 -7
  40. data/lib/tap/support/configurable.rb +13 -14
  41. data/lib/tap/support/configurable_class.rb +6 -30
  42. data/lib/tap/support/configuration.rb +36 -9
  43. data/lib/tap/support/constant.rb +75 -13
  44. data/lib/tap/support/constant_manifest.rb +115 -0
  45. data/lib/tap/support/dependencies.rb +27 -67
  46. data/lib/tap/support/dependency.rb +44 -0
  47. data/lib/tap/support/executable.rb +78 -109
  48. data/lib/tap/support/executable_queue.rb +1 -1
  49. data/lib/tap/support/gems.rb +6 -0
  50. data/lib/tap/support/gems/rack.rb +197 -84
  51. data/lib/tap/support/instance_configuration.rb +29 -3
  52. data/lib/tap/support/intern.rb +46 -0
  53. data/lib/tap/support/join.rb +67 -11
  54. data/lib/tap/support/joins.rb +2 -0
  55. data/lib/tap/support/joins/fork.rb +1 -0
  56. data/lib/tap/support/joins/merge.rb +3 -1
  57. data/lib/tap/support/joins/sequence.rb +2 -2
  58. data/lib/tap/support/joins/switch.rb +3 -1
  59. data/lib/tap/support/joins/sync_merge.rb +6 -0
  60. data/lib/tap/support/lazy_attributes.rb +16 -1
  61. data/lib/tap/support/lazydoc.rb +21 -21
  62. data/lib/tap/support/lazydoc/comment.rb +59 -55
  63. data/lib/tap/support/lazydoc/definition.rb +36 -0
  64. data/lib/tap/support/lazydoc/document.rb +37 -13
  65. data/lib/tap/support/manifest.rb +120 -131
  66. data/lib/tap/support/minimap.rb +90 -0
  67. data/lib/tap/support/node.rb +4 -6
  68. data/lib/tap/support/parser.rb +63 -6
  69. data/lib/tap/support/schema.rb +11 -2
  70. data/lib/tap/support/shell_utils.rb +3 -5
  71. data/lib/tap/support/string_ext.rb +60 -0
  72. data/lib/tap/support/tdoc.rb +2 -2
  73. data/lib/tap/support/templater.rb +29 -15
  74. data/lib/tap/support/validation.rb +22 -11
  75. data/lib/tap/task.rb +155 -156
  76. data/lib/tap/tasks/load.rb +95 -8
  77. data/lib/tap/test/extensions.rb +2 -1
  78. data/lib/tap/test/script_tester.rb +7 -1
  79. data/template/index.erb +39 -32
  80. metadata +13 -13
  81. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
  82. data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
  83. data/lib/tap/patches/rake/testtask.rb +0 -57
  84. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
  85. data/lib/tap/patches/ruby19/parsedate.rb +0 -16
  86. data/lib/tap/spec.rb +0 -42
  87. data/lib/tap/spec/adapter.rb +0 -25
  88. data/lib/tap/spec/inheritable_class_test_root.rb +0 -9
  89. data/lib/tap/support/constant_utils.rb +0 -127
  90. data/lib/tap/support/summary.rb +0 -30
@@ -0,0 +1,115 @@
1
+ require 'tap/support/manifest'
2
+ require 'tap/support/constant'
3
+
4
+ module Tap
5
+ module Support
6
+
7
+ # ConstantManifest builds a manifest of Constant entries using Lazydoc.
8
+ # The idea is that Lazydoc can find files with resouces of a specific type
9
+ # (ex tasks) and Constant can reference those resouces and load them as
10
+ # necessary. ConstantManifest registers paths so that they may be lazily
11
+ # scanned when searching for a specific resource.
12
+ class ConstantManifest < Support::Manifest
13
+
14
+ # The attribute identifying resources in a file
15
+ attr_reader :const_attr
16
+
17
+ # Registered [root, [paths]] pairs that will be searched
18
+ # for the const_attr
19
+ attr_reader :search_paths
20
+
21
+ # The current index of search_paths
22
+ attr_reader :search_path_index
23
+
24
+ # The current index of paths
25
+ attr_reader :path_index
26
+
27
+ # Initializes a new ConstantManifest
28
+ def initialize(const_attr)
29
+ @const_attr = const_attr
30
+ @search_paths = []
31
+ @search_path_index = 0
32
+ @path_index = 0
33
+ super([])
34
+ end
35
+
36
+ # Registers the files matching pattern under dir. Returns self.
37
+ def register(dir, pattern)
38
+ search_paths << [dir, Dir.glob(File.join(dir, pattern)).select {|file| File.file?(file) }]
39
+ self
40
+ end
41
+
42
+ # Searches all paths for entries and adds them to self. Returns self.
43
+ def build
44
+ each {|entry| } unless built?
45
+ self
46
+ end
47
+
48
+ # True if there are no more paths to search
49
+ # (ie search_path_index == search_paths.length)
50
+ def built?
51
+ search_path_index == search_paths.length
52
+ end
53
+
54
+ # Sets search_path_index and path_index to zero and clears entries.
55
+ # Returns self.
56
+ def reset
57
+ # Support::Lazydoc[path].resolved = false
58
+ @entries.clear
59
+ @search_path_index = 0
60
+ @path_index = 0
61
+ super
62
+ end
63
+
64
+ # Yields each entry to the block. Unless built?, each lazily
65
+ # iterates over search_paths to look for new entries.
66
+ def each
67
+ entries.each do |entry|
68
+ yield(entry)
69
+ end
70
+
71
+ search_paths[search_path_index, search_paths.length - search_path_index].each do |(path_root, paths)|
72
+ paths[path_index, paths.length - path_index].each do |path|
73
+ new_entries = resolve(path_root, path) - entries
74
+ entries.concat(new_entries)
75
+
76
+ @path_index += 1
77
+ new_entries.each {|entry| yield(entry) }
78
+ end
79
+
80
+ @search_path_index += 1
81
+ @path_index = 0
82
+ end unless built?
83
+ end
84
+
85
+ protected
86
+
87
+ def minikey(const) # :nodoc:
88
+ const.path
89
+ end
90
+
91
+ # Scans path for constants having const_attr, and initializes Constant
92
+ # objects for each. If the document has no default_const_name set,
93
+ # resolve will set the default_const_name based on the relative
94
+ # filepath from path_root to path.
95
+ def resolve(path_root, path)
96
+ entries = []
97
+ if document = Lazydoc.scan_doc(path, const_attr)
98
+ if document.default_const_name.empty?
99
+ relative_path = Root.relative_filepath(path_root, path).chomp(File.extname(path))
100
+ document.default_const_name = relative_path.camelize
101
+ end
102
+
103
+ document.const_attrs.each_pair do |const_name, attrs|
104
+ if attrs.has_key?(const_attr)
105
+ entries << Constant.new(const_name, path)
106
+ end
107
+ end
108
+ end
109
+
110
+ entries
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -1,89 +1,49 @@
1
+ require 'tap/support/dependency'
2
+
1
3
  module Tap
2
4
  module Support
3
5
 
4
- # Dependable encapsulates the module-level methods facilitating
5
- # dependencies in Executable.
6
- class Dependencies
6
+ # Dependencies tracks Executable dependencies and results, and provides
7
+ # for thread-safe resolution of dependencies.
8
+ class Dependencies < Monitor
9
+
10
+ # Initializes a new Dependencies
7
11
  def initialize
8
- @registry = []
9
- @results = []
12
+ super
10
13
  @resolve_stack = []
11
14
  end
12
15
 
13
- # An array of registered [instance, argv] pairs.
14
- attr_reader :registry
15
-
16
- # An array of results matching the registry, produced
17
- # during dependency resolution by instance._execute(*argv).
18
- attr_reader :results
19
-
20
- # Clears all registered dependencies and results.
21
- def clear
22
- registry.clear
23
- results.clear
24
- @resolve_stack.clear
25
- end
26
-
27
- # Returns the index of the [instance, argv] pair in self,
28
- # or nil if the pair is not registered,
29
- def index(instance, argv=[])
30
- registry.each_with_index do |entry, index|
31
- return index if entry[0] == instance && entry[1] == argv
32
- end
33
- nil
34
- end
35
-
36
- # Registers an [instance, argv] pair with self and returns the index of
37
- # the pair in the registry; returns the index of a matching pair in the
38
- # registry if the instance and argv are already registered.
39
- def register(instance, argv=[])
40
- if existing = index(instance, argv)
41
- return existing
16
+ # Thread-safe registration of instance as a dependency. During
17
+ # registration, instance is extended with the Dependency module.
18
+ # Returns self.
19
+ def register(instance)
20
+ synchronize do
21
+ unless instance.kind_of?(Dependency)
22
+ instance.extend Dependency
23
+ end
42
24
  end
43
-
44
- registry << [instance, argv]
45
- registry.length - 1
25
+ self
46
26
  end
47
27
 
48
- # Resolves the instance-argv pairs at the specified indicies by calling
49
- # instance._execute(*argv). Results are collected in results; a pair is
50
- # only resolved if an existing result does not exist and an error is
51
- # raised if circular dependencies are detected. Returns self.
52
- def resolve(indicies)
53
- indicies.each do |index|
54
- next if resolved?(index)
55
-
56
- if @resolve_stack.include?(index)
28
+ # Thread-safe resolution of the instance. Resolve checks for
29
+ # circular dependencies, then yields control to the block,
30
+ # which is responsible for the actual resolution.
31
+ def resolve(instance)
32
+ synchronize do
33
+ if @resolve_stack.include?(instance)
57
34
  raise CircularDependencyError.new(@resolve_stack)
58
35
  end
59
-
36
+
60
37
  # mark the results at the index to prevent
61
38
  # infinite loops with circular dependencies
62
- @resolve_stack.push index
63
-
64
- instance, inputs = registry[index]
65
- results[index] = instance._execute(*inputs)
66
-
39
+ @resolve_stack.push instance
40
+ yield()
67
41
  @resolve_stack.pop
68
42
  end
69
43
  self
70
44
  end
71
45
 
72
- # Returns true if the results at the specified index are non-nil (note
73
- # that Dependable expects instance-argv pairs to resolve to an Audit;
74
- # the current value of the Audit may, of course, be nil).
75
- def resolved?(index)
76
- results[index] != nil
77
- end
78
-
79
- # Sets the results at specified indicies to nil so that their
80
- # instance-argv pairs will re-execute on resolve. Returns self.
81
- def reset(indicies)
82
- indicies.each {|index| results[index] = nil }
83
- self
84
- end
85
-
86
- # Raised when resolve detects circular dependencies.
46
+ # Raised when Dependencies#resolve detects a circular dependency.
87
47
  class CircularDependencyError < StandardError
88
48
  def initialize(resolve_stack)
89
49
  super "circular dependency: [#{resolve_stack.join(', ')}]"
@@ -0,0 +1,44 @@
1
+ module Tap
2
+ module Support
3
+
4
+ # Constrains an Executable to only _execute once, and provides several
5
+ # methods making the Executable behave like a Dependency.
6
+ module Dependency
7
+
8
+ # The audited result of self
9
+ attr_accessor :_result
10
+
11
+ def self.extended(base) # :nodoc:
12
+ base.instance_variable_set(:@_result, nil)
13
+ end
14
+
15
+ # Conditional _execute; only calls _method_name if
16
+ # resolved? is false (thus assuring self will only
17
+ # be executed once).
18
+ #
19
+ # Returns _result.
20
+ def _execute(*args)
21
+ app.dependencies.resolve(self) do
22
+ @_result = super
23
+ end unless resolved?
24
+ _result
25
+ end
26
+
27
+ # Alias for _execute().
28
+ def resolve
29
+ _execute
30
+ end
31
+
32
+ # True if _result is non-nil.
33
+ def resolved?
34
+ @_result != nil
35
+ end
36
+
37
+ # Resets the dependency by setting _result to nil.
38
+ def reset
39
+ @_result = nil
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -3,24 +3,22 @@ require 'tap/support/audit'
3
3
  module Tap
4
4
  module Support
5
5
 
6
- # Executable wraps methods to make them executable by App. Methods are
7
- # wrapped by extending the object that receives them; the easiest way
8
- # to make an object executable is to use Object#_method.
6
+ # Executable wraps objects to make them executable by App.
9
7
  module Executable
10
8
 
11
- # The Tap::App the Executable belongs to.
9
+ # The App receiving self during enq
12
10
  attr_reader :app
13
11
 
14
- # The method called when an Executable is executed via _execute
12
+ # The method called during _execute
15
13
  attr_reader :_method_name
16
14
 
17
- # Stores the on complete block
15
+ # The block called when _execute completes
18
16
  attr_reader :on_complete_block
19
17
 
20
- # An array of dependency indexes that will be resolved on _execute
18
+ # An array of dependency indicies that will be resolved on _execute
21
19
  attr_reader :dependencies
22
20
 
23
- # The batch for the Executable.
21
+ # The batch for self
24
22
  attr_reader :batch
25
23
 
26
24
  public
@@ -41,8 +39,8 @@ module Tap
41
39
 
42
40
  # Initializes a new batch object and adds the object to batch.
43
41
  # The object will be a duplicate of self. (Note this method
44
- # can raise an error for objects that don't support dup, like
45
- # methods generated by Object#_method).
42
+ # can raise an error for objects that don't support dup,
43
+ # notably Method objects generated by Object#_method).
46
44
  def initialize_batch_obj
47
45
  obj = self.dup
48
46
 
@@ -55,12 +53,12 @@ module Tap
55
53
  end
56
54
 
57
55
  # Returns true if the batch size is greater than one
58
- # (the one being self).
56
+ # (the one is assumed to be self).
59
57
  def batched?
60
58
  batch.length > 1
61
59
  end
62
60
 
63
- # Returns the index of the self in batch.
61
+ # Returns the index of self in batch.
64
62
  def batch_index
65
63
  batch.index(self)
66
64
  end
@@ -125,9 +123,9 @@ module Tap
125
123
  self
126
124
  end
127
125
 
128
- # Enqueues self and self.batch to app with the inputs. The number
129
- # of inputs provided should match the number of inputs specified
130
- # by the arity of the _method_name method.
126
+ # Enqueues each member of batch (and implicitly self) to app with the
127
+ # inputs. The number of inputs provided should match the number of
128
+ # inputs for the _method_name method.
131
129
  def enq(*inputs)
132
130
  batch.each do |executable|
133
131
  executable.unbatched_enq(*inputs)
@@ -141,12 +139,13 @@ module Tap
141
139
  self
142
140
  end
143
141
 
144
- # Sets a block to receive the results of _execute. Raises an
145
- # error if an on_complete block is already set. Override an
146
- # existing on_complete block by specifying override = true.
142
+ # Sets a block to receive the results of _execute for each member of
143
+ # batch (and implicitly self). Raises an error if on_complete_block
144
+ # is already set within the batch. Override the existing
145
+ # on_complete_block by specifying override = true.
147
146
  #
148
- # Note the block recieves an audited result and not
149
- # the result itself (see Audit for more information).
147
+ # Note: the block recieves an audited result and not the result
148
+ # itself (see Audit for more information).
150
149
  def on_complete(override=false, &block) # :yields: _result
151
150
  batch.each do |executable|
152
151
  executable.unbatched_on_complete(override, &block)
@@ -154,7 +153,7 @@ module Tap
154
153
  self
155
154
  end
156
155
 
157
- # Like on_complete, but only sets on_complete_block for self.
156
+ # Like on_complete, but only sets the on_complete_block for self.
158
157
  def unbatched_on_complete(override=false, &block) # :yields: _result
159
158
  unless on_complete_block == nil || override
160
159
  raise "on_complete_block already set: #{self}"
@@ -163,127 +162,87 @@ module Tap
163
162
  self
164
163
  end
165
164
 
166
- # Sets a sequence workflow pattern for the tasks; each task will enque
167
- # the next task with it's results.
168
- #
169
- # Notes:
170
- # - Batched tasks will have the pattern set for each task in the batch
171
- # - The current audited results are yielded to the block, if given,
172
- # before the next task is enqued.
173
- # - Executables may provided as well as tasks.
165
+ # Sets a sequence workflow pattern for the tasks; each task
166
+ # enques the next task with it's results, starting with self.
167
+ # See Joins::Sequence.
174
168
  def sequence(*tasks, &block) # :yields: _result
175
169
  Joins::Sequence.join(self, tasks, &block)
176
170
  end
177
171
 
178
- # Sets a fork workflow pattern for the source task; each target
179
- # will enque the results of source.
180
- #
181
- # Notes:
182
- # - Batched tasks will have the pattern set for each task in the batch
183
- # - The current audited results are yielded to the block, if given,
184
- # before the next task is enqued.
185
- # - Executables may provided as well as tasks.
172
+ # Sets a fork workflow pattern for self; each target
173
+ # will enque the results of self. See Joins::Fork.
186
174
  def fork(*targets, &block) # :yields: _result
187
175
  Joins::Fork.join(self, targets, &block)
188
176
  end
189
177
 
190
- # Sets a simple merge workflow pattern for the source tasks. Each source
191
- # enques target with it's result; no synchronization occurs, nor are
192
- # results grouped before being sent to the target.
193
- #
194
- # Notes:
195
- # - Batched tasks will have the pattern set for each task in the batch
196
- # - The current audited results are yielded to the block, if given,
197
- # before the next task is enqued.
198
- # - Executables may provided as well as tasks.
178
+ # Sets a simple merge workflow pattern for the source tasks. Each
179
+ # source enques self with it's result; no synchronization occurs,
180
+ # nor are results grouped before being enqued. See Joins::Merge.
199
181
  def merge(*sources, &block) # :yields: _result
200
182
  Joins::Merge.join(self, sources, &block)
201
183
  end
202
184
 
203
- # Sets a synchronized merge workflow for the source tasks. Results from
204
- # each source task are collected and enqued as a single group to the target.
205
- # The target is not enqued until all sources have completed. Raises an
206
- # error if a source returns twice before the target is enqued.
207
- #
208
- # Notes:
209
- # - Batched tasks will have the pattern set for each task in the batch
210
- # - The current audited results are yielded to the block, if given,
211
- # before the next task is enqued.
212
- # - Executables may provided as well as tasks.
213
- #
214
- #-- TODO: add notes on testing and the way results are received
215
- # (ie as a single object)
216
- #
217
- # - note stacking with a sync merge is *somewhat* pointless;
218
- # it does not change the run order, but of course it does
219
- # allow other tasks to be interleaved.
185
+ # Sets a synchronized merge workflow for the source tasks. Results
186
+ # from each source are collected and enqued as a single group to
187
+ # self. The collective results are not enqued until all sources
188
+ # have completed. See Joins::SyncMerge.
220
189
  #
190
+ # Raises an error if a source returns twice before the target is enqued.
221
191
  def sync_merge(*sources, &block) # :yields: _result
222
192
  Joins::SyncMerge.join(self, sources, &block)
223
193
  end
224
194
 
225
- # Sets a choice workflow pattern for the source task. When the
226
- # source task completes, switch yields the audited result to the
227
- # block which then returns the index of the target to enque with
228
- # the results. No target will be enqued if the index is false or
229
- # nil; an error is raised if no target can be found for the
230
- # specified index.
231
- #
232
- # Notes:
233
- # - Batched tasks will have the pattern set for each task in the batch
234
- # - The current audited results are yielded to the block, if given,
235
- # before the next task is enqued.
236
- # - Executables may provided as well as tasks.
195
+ # Sets a switch workflow pattern for self. When _execute completes,
196
+ # switch yields the audited result to the block which should return
197
+ # the index of the target to enque with the results. No target will
198
+ # be enqued if the index is false or nil; an error is raised if no
199
+ # target can be found for the specified index. See Joins::Switch.
237
200
  def switch(*targets, &block) # :yields: _result
238
201
  Joins::Switch.join(self, targets, &block)
239
202
  end
240
203
 
241
- def unbatched_depends_on(dependency, *inputs)
242
- raise ArgumentError, "not an Executable: #{dependency}" unless dependency.kind_of?(Executable)
243
- raise ArgumentError, "cannot depend on self" if dependency == self
244
-
245
- index = app.dependencies.register(dependency, inputs)
246
- dependencies << index unless dependencies.include?(index)
247
- index
248
- end
249
-
250
- # Adds the dependency to self, making self dependent on the dependency.
251
- # The dependency will be resolved by calling dependency._execute with
252
- # the input arguments during resolve_dependencies.
253
- def depends_on(dependency, *inputs)
254
- index = unbatched_depends_on(dependency, *inputs)
204
+ # Adds the dependency to each member in batch (and implicitly self).
205
+ # The dependency will be resolved with the input arguments during
206
+ # _execute, using resolve_dependencies.
207
+ def depends_on(dependency)
255
208
  batch.each do |e|
256
- e.dependencies << index unless e.dependencies.include?(index)
209
+ e.unbatched_depends_on(dependency)
257
210
  end
258
- index
211
+ self
259
212
  end
260
213
 
261
- # Resolves dependencies by calling dependency._execute with
262
- # the dependency arguments. (See Dependable#resolve).
214
+ # Like depends_on, but only adds the dependency to self.
215
+ def unbatched_depends_on(dependency)
216
+ raise ArgumentError, "cannot depend on self" if dependency == self
217
+
218
+ app.dependencies.register(dependency)
219
+ dependencies << dependency unless dependencies.include?(dependency)
220
+ self
221
+ end
222
+
223
+ # Resolves dependencies. (See Dependency#resolve).
263
224
  def resolve_dependencies
264
- app.dependencies.resolve(dependencies)
225
+ dependencies.each {|dependency| dependency.resolve }
265
226
  self
266
227
  end
267
228
 
268
- # Resets dependencies so they will be re-resolved on resolve_dependencies.
269
- # (See Dependable#reset).
229
+ # Resets dependencies so they will be re-resolved on
230
+ # resolve_dependencies. (See Dependency#reset).
270
231
  def reset_dependencies
271
- app.dependencies.reset(dependencies)
232
+ dependencies.each {|dependency| dependency.reset }
272
233
  self
273
234
  end
274
235
 
275
- # Auditing method call. Executes _method_name for self, but audits
276
- # the result. Sends the audited result to the on_complete_block if set.
236
+ # Auditing method call. Resolves dependencies, executes _method_name,
237
+ # and sends the audited result to the on_complete_block (if set).
277
238
  #
278
239
  # Audits are initialized in the follwing manner:
279
- # no inputs:: create a new, empty Audit. The first value of the audit
280
- # will be the result of call
281
- # one input:: forks the input if it is an audit, otherwise initializes
282
- # a new audit using the input
283
- # multiple inputs:: merges the inputs into a new Audit.
240
+ # no inputs:: Creates a new, empty Audit. The first value of the audit
241
+ # will be the result of call.
242
+ # one input:: Forks the input if it is an audit, otherwise initializes
243
+ # a new audit using the input.
244
+ # multiple inputs:: Merges the inputs into a new Audit.
284
245
  #
285
- # Dependencies are resolved using resolve_dependencies before
286
- # _method_name is executed.
287
246
  def _execute(*inputs)
288
247
  resolve_dependencies
289
248
 
@@ -317,6 +276,15 @@ module Tap
317
276
  audit
318
277
  end
319
278
 
279
+ # Raises a TerminateError if app.state == State::TERMINATE.
280
+ # check_terminate may be called at any time to provide a
281
+ # breakpoint in long-running processes.
282
+ def check_terminate
283
+ if app.state == App::State::TERMINATE
284
+ raise App::TerminateError.new
285
+ end
286
+ end
287
+
320
288
  def inspect
321
289
  "#<#{self.class.to_s}:#{object_id} _method: #{_method_name} batch_length: #{batch.length} app: #{app}>"
322
290
  end
@@ -341,10 +309,11 @@ end
341
309
  #
342
310
  class Object
343
311
 
344
- # Initializes a Tap::Support::Executable using the Method returned by
345
- # Object#method(method_name), setting the on_complete block as specified.
312
+ # Initializes a Tap::Support::Executable using the object returned by
313
+ # Object#method(method_name).
314
+ #
346
315
  # Returns nil if Object#method returns nil.
347
- def _method(method_name, app=Tap::App.instance) # :yields: _result
316
+ def _method(method_name, app=Tap::App.instance)
348
317
  return nil unless m = method(method_name)
349
318
  Tap::Support::Executable.initialize(m, :call, app)
350
319
  end