tap 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. data/History +37 -30
  2. data/MIT-LICENSE +1 -1
  3. data/README +92 -44
  4. data/bin/tap +62 -75
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +6 -45
  13. data/lib/tap/app.rb +126 -500
  14. data/lib/tap/constants.rb +2 -29
  15. data/lib/tap/env.rb +555 -250
  16. data/lib/tap/file_task.rb +60 -103
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +16 -12
  21. data/lib/tap/generator/generators/command/templates/command.erb +13 -19
  22. data/lib/tap/generator/generators/config/config_generator.rb +18 -27
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +16 -11
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -2
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +24 -31
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +18 -22
  30. data/lib/tap/generator/generators/root/root_generator.rb +45 -31
  31. data/lib/tap/generator/generators/root/templates/Rakefile +64 -41
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +21 -28
  38. data/lib/tap/generator/generators/task/templates/task.erb +13 -23
  39. data/lib/tap/generator/generators/task/templates/test.erb +15 -18
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +0 -0
  42. data/lib/tap/patches/rake/testtask.rb +0 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +0 -0
  45. data/lib/tap/root.rb +260 -21
  46. data/lib/tap/support/aggregator.rb +11 -11
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +20 -18
  49. data/lib/tap/support/batchable.rb +21 -10
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +154 -239
  52. data/lib/tap/support/command_line.rb +97 -102
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +86 -65
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +30 -17
  61. data/lib/tap/support/executable_queue.rb +0 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +0 -0
  68. data/lib/tap/support/shell_utils.rb +33 -9
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +339 -134
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +0 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +0 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +409 -76
  75. data/lib/tap/support/versions.rb +5 -3
  76. data/lib/tap/task.rb +78 -174
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +3 -3
  80. data/lib/tap/test/env_vars.rb +2 -2
  81. data/lib/tap/test/file_methods.rb +19 -20
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +1 -1
  84. data/lib/tap/test/tap_methods.rb +28 -62
  85. data/lib/tap/workflow.rb +22 -39
  86. metadata +48 -179
  87. data/Basic Overview +0 -151
  88. data/Command Reference +0 -99
  89. data/Rakefile +0 -127
  90. data/Tutorial +0 -287
  91. data/lib/tap/cmd/console.rb +0 -31
  92. data/lib/tap/cmd/destroy.rb +0 -20
  93. data/lib/tap/cmd/generate.rb +0 -20
  94. data/lib/tap/cmd/run.rb +0 -151
  95. data/lib/tap/dump.rb +0 -57
  96. data/lib/tap/generator.rb +0 -91
  97. data/lib/tap/generator/generators/command/USAGE +0 -6
  98. data/lib/tap/generator/generators/config/USAGE +0 -21
  99. data/lib/tap/generator/generators/config/templates/config.erb +0 -1
  100. data/lib/tap/generator/generators/file_task/USAGE +0 -3
  101. data/lib/tap/generator/generators/file_task/templates/file.yml +0 -3
  102. data/lib/tap/generator/generators/generator/USAGE +0 -0
  103. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -21
  104. data/lib/tap/generator/generators/generator/templates/generator.erb +0 -32
  105. data/lib/tap/generator/generators/generator/templates/usage.erb +0 -1
  106. data/lib/tap/generator/generators/root/USAGE +0 -0
  107. data/lib/tap/generator/generators/root/templates/ReadMe.txt +0 -0
  108. data/lib/tap/generator/generators/root/templates/tap.yml +0 -80
  109. data/lib/tap/generator/generators/task/USAGE +0 -3
  110. data/lib/tap/generator/generators/workflow/USAGE +0 -0
  111. data/lib/tap/generator/generators/workflow/templates/task.erb +0 -16
  112. data/lib/tap/generator/generators/workflow/templates/test.erb +0 -7
  113. data/lib/tap/generator/generators/workflow/workflow_generator.rb +0 -6
  114. data/lib/tap/generator/options.rb +0 -26
  115. data/lib/tap/generator/usage.rb +0 -26
  116. data/lib/tap/support/batchable_methods.rb +0 -34
  117. data/lib/tap/support/command_line_methods.rb +0 -76
  118. data/lib/tap/support/configurable_methods.rb +0 -224
  119. data/lib/tap/support/logger.rb +0 -88
  120. data/lib/tap/support/rake.rb +0 -43
  121. data/lib/tap/support/tdoc/config_attr.rb +0 -362
  122. data/test/app/config/another/task.yml +0 -1
  123. data/test/app/config/batch.yml +0 -2
  124. data/test/app/config/empty.yml +0 -0
  125. data/test/app/config/erb.yml +0 -2
  126. data/test/app/config/some/task.yml +0 -1
  127. data/test/app/config/template.yml +0 -2
  128. data/test/app/config/version-0.1.yml +0 -1
  129. data/test/app/config/version.yml +0 -1
  130. data/test/app/lib/app_test_task.rb +0 -3
  131. data/test/app_test.rb +0 -1849
  132. data/test/env/test_configure/recurse_a.yml +0 -2
  133. data/test/env/test_configure/recurse_b.yml +0 -2
  134. data/test/env/test_configure/tap.yml +0 -23
  135. data/test/env/test_load_env_config/dir/tap.yml +0 -3
  136. data/test/env/test_load_env_config/recurse_a.yml +0 -2
  137. data/test/env/test_load_env_config/recurse_b.yml +0 -2
  138. data/test/env/test_load_env_config/tap.yml +0 -3
  139. data/test/env_test.rb +0 -198
  140. data/test/file_task/config/batch.yml +0 -2
  141. data/test/file_task/config/configured.yml +0 -1
  142. data/test/file_task/old_file_one.txt +0 -0
  143. data/test/file_task/old_file_two.txt +0 -0
  144. data/test/file_task_test.rb +0 -1291
  145. data/test/root/alt_lib/alt_module.rb +0 -4
  146. data/test/root/file.txt +0 -0
  147. data/test/root/glob/one.txt +0 -0
  148. data/test/root/glob/two.txt +0 -0
  149. data/test/root/lib/absolute_alt_filepath.rb +0 -2
  150. data/test/root/lib/alternative_filepath.rb +0 -2
  151. data/test/root/lib/another_module.rb +0 -2
  152. data/test/root/lib/nested/some_module.rb +0 -4
  153. data/test/root/lib/no_module_included.rb +0 -0
  154. data/test/root/lib/some/module.rb +0 -4
  155. data/test/root/lib/some_class.rb +0 -2
  156. data/test/root/lib/some_module.rb +0 -3
  157. data/test/root/load_path/load_path_module.rb +0 -2
  158. data/test/root/load_path/skip_module.rb +0 -2
  159. data/test/root/mtime/older.txt +0 -0
  160. data/test/root/unload/full_path.rb +0 -2
  161. data/test/root/unload/loaded_by_nested.rb +0 -2
  162. data/test/root/unload/nested/nested_load.rb +0 -6
  163. data/test/root/unload/nested/nested_with_ext.rb +0 -4
  164. data/test/root/unload/nested/relative_path.rb +0 -4
  165. data/test/root/unload/older.rb +0 -2
  166. data/test/root/unload/unload_base.rb +0 -9
  167. data/test/root/versions/another.yml +0 -0
  168. data/test/root/versions/file-0.1.2.yml +0 -0
  169. data/test/root/versions/file-0.1.yml +0 -0
  170. data/test/root/versions/file.yml +0 -0
  171. data/test/root_test.rb +0 -718
  172. data/test/support/aggregator_test.rb +0 -99
  173. data/test/support/audit_test.rb +0 -445
  174. data/test/support/batchable_test.rb +0 -74
  175. data/test/support/class_configuration_test.rb +0 -331
  176. data/test/support/command_line_test.rb +0 -58
  177. data/test/support/configurable/config/configured.yml +0 -2
  178. data/test/support/configurable_test.rb +0 -295
  179. data/test/support/executable_queue_test.rb +0 -103
  180. data/test/support/executable_test.rb +0 -38
  181. data/test/support/logger_test.rb +0 -31
  182. data/test/support/rake_test.rb +0 -37
  183. data/test/support/shell_utils_test.rb +0 -24
  184. data/test/support/tdoc_test.rb +0 -370
  185. data/test/support/validation_test.rb +0 -54
  186. data/test/support/versions_test.rb +0 -103
  187. data/test/tap_test_helper.rb +0 -57
  188. data/test/tap_test_suite.rb +0 -7
  189. data/test/task/config/batch.yml +0 -2
  190. data/test/task/config/batched.yml +0 -2
  191. data/test/task/config/configured.yml +0 -1
  192. data/test/task/config/example.yml +0 -1
  193. data/test/task_base_test.rb +0 -24
  194. data/test/task_syntax_test.rb +0 -300
  195. data/test/task_test.rb +0 -320
  196. data/test/test/env_vars_test.rb +0 -48
  197. data/test/test/file_methods/test_assert_files/expected/one.txt +0 -1
  198. data/test/test/file_methods/test_assert_files/expected/two.txt +0 -1
  199. data/test/test/file_methods/test_assert_files/input/one.txt +0 -1
  200. data/test/test/file_methods/test_assert_files/input/two.txt +0 -1
  201. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/one.txt +0 -1
  202. data/test/test/file_methods/test_assert_files_can_have_no_expected_files_if_specified/input/two.txt +0 -1
  203. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/one.txt +0 -1
  204. data/test/test/file_methods/test_assert_files_fails_for_different_content/expected/two.txt +0 -1
  205. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/one.txt +0 -1
  206. data/test/test/file_methods/test_assert_files_fails_for_different_content/input/two.txt +0 -1
  207. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/expected/one.txt +0 -1
  208. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/one.txt +0 -1
  209. data/test/test/file_methods/test_assert_files_fails_for_missing_expected_file/input/two.txt +0 -1
  210. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/one.txt +0 -1
  211. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/expected/two.txt +0 -1
  212. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/one.txt +0 -1
  213. data/test/test/file_methods/test_assert_files_fails_for_missing_output_file/input/two.txt +0 -1
  214. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/one.txt +0 -1
  215. data/test/test/file_methods/test_assert_files_fails_for_no_expected_files/input/two.txt +0 -1
  216. data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
  217. data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
  218. data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
  219. data/test/test/file_methods_doc/test_sub/expected/one.txt +0 -1
  220. data/test/test/file_methods_doc/test_sub/expected/two.txt +0 -1
  221. data/test/test/file_methods_doc/test_sub/input/one.txt +0 -1
  222. data/test/test/file_methods_doc/test_sub/input/two.txt +0 -1
  223. data/test/test/file_methods_doc_test.rb +0 -29
  224. data/test/test/file_methods_test.rb +0 -275
  225. data/test/test/subset_methods_test.rb +0 -171
  226. data/test/test/tap_methods/test_assert_files/expected/task/name/a.txt +0 -1
  227. data/test/test/tap_methods/test_assert_files/expected/task/name/b.txt +0 -1
  228. data/test/test/tap_methods/test_assert_files/input/a.txt +0 -1
  229. data/test/test/tap_methods/test_assert_files/input/b.txt +0 -1
  230. data/test/test/tap_methods_test.rb +0 -399
  231. data/test/workflow_test.rb +0 -120
  232. data/vendor/rails_generator.rb +0 -56
  233. data/vendor/rails_generator/base.rb +0 -263
  234. data/vendor/rails_generator/commands.rb +0 -581
  235. data/vendor/rails_generator/generated_attribute.rb +0 -42
  236. data/vendor/rails_generator/lookup.rb +0 -209
  237. data/vendor/rails_generator/manifest.rb +0 -53
  238. data/vendor/rails_generator/options.rb +0 -143
  239. data/vendor/rails_generator/scripts.rb +0 -83
  240. data/vendor/rails_generator/scripts/destroy.rb +0 -7
  241. data/vendor/rails_generator/scripts/generate.rb +0 -7
  242. data/vendor/rails_generator/scripts/update.rb +0 -12
  243. data/vendor/rails_generator/simple_logger.rb +0 -46
  244. data/vendor/rails_generator/spec.rb +0 -44
@@ -56,7 +56,9 @@ module Tap
56
56
  # deversion("path/to/file.txt") # => ["path/to/file.txt", nil]
57
57
  #
58
58
  def deversion(path)
59
- path =~ /^(.*)-(\d(\.?\d)*)(.*)?/ ? [$1 + $4, $2] : [path, nil]
59
+ extname = File.extname(path)
60
+ extname = '' if extname =~ /^\.\d+$/
61
+ path =~ /^(.*)-(\d(\.?\d)*)#{extname}$/ ? [$1 + extname, $2] : [path, nil]
60
62
  end
61
63
 
62
64
  # A <=> comparison for versions. compare_versions can take strings,
@@ -80,8 +82,8 @@ module Tap
80
82
 
81
83
  private
82
84
 
83
- # Converts an input argument (typically a string or an array)
84
- # to an array of integers. Splits version string on "."
85
+ # Converts an input argument (typically a string or an array)
86
+ # to an array of integers. Splits version string on "."
85
87
  def to_integer_array(arg)
86
88
  arr = case arg
87
89
  when Array then arg
data/lib/tap/task.rb CHANGED
@@ -1,10 +1,11 @@
1
+ require 'tap/support/framework'
2
+
1
3
  module Tap
2
- # = Overview
3
- #
4
+
4
5
  # Tasks are the basic organizational unit of Tap. Tasks provide
5
6
  # a standard backbone for creating the working parts of an application
6
7
  # by facilitating configuration, batched execution of methods, and
7
- # interaction with the command line.
8
+ # documentation.
8
9
  #
9
10
  # The functionality of Task is built from several base modules:
10
11
  # - Tap::Support::Batchable
@@ -80,190 +81,104 @@ module Tap
80
81
  # end
81
82
  #
82
83
  # t = ValidatingTask.new
83
- # t.string = 1 # => ValidationError
84
- # t.integer = 1.1 # => ValidationError
84
+ # t.string = 1 # !> ValidationError
85
+ # t.integer = 1.1 # !> ValidationError
85
86
  #
86
87
  # t.integer = "1"
87
88
  # t.integer == 1 # => true
88
89
  #
89
- # Tasks have a name that gets used as a relative filepath to find
90
- # associated files (for instance config_file). By default the task
91
- # name is based on the task class, such that Tap::Task corresponds
92
- # to 'tap/task'. Custom names can be provided when a task is
93
- # initialized, as can additional and/or overriding configurations.
90
+ # Tasks have a name that gets used in auditing, and as a relative
91
+ # filepath to find associated files (for instance config files).
92
+ # By default the task name is based on the task class, such that
93
+ # Tap::Task has the default name 'tap/task'. Configurations
94
+ # and custom names can be provided when a task is initialized.
94
95
  #
95
- # # [/path/to/app/config/example.yml]
96
- # # one: ONE
97
- #
98
- # t = ConfiguredTask.new "example", :three => 'three'
96
+ # t = ConfiguredTask.new({:one => 'ONE', :three => 'three'}, "example")
99
97
  # t.name # => "example"
100
- # t.app[:config] # => "/path/to/app/config"
101
- # t.config_file # => "/path/to/app/config/example.yml"
102
98
  # t.config # => {:one => 'ONE', :two => 'two', :three => 'three'}
103
99
  #
104
- # Tasks can be assembled into batches that enque and execute
105
- # collectively. Batched tasks are automatically generated when a
106
- # config_file specifies an array of configurations.
107
- #
108
- # # [/path/to/app/config/batch.yml]
109
- # # - one: ONE
110
- # # - one: ANOTHER ONE
111
- #
112
- # t = ConfiguredTask.new "batch"
113
- # t.batch.size # => 2
114
- # t1, t2 = t.batch
115
- #
116
- # t1.name # => "batch"
117
- # t1.config # => {:one => 'ONE', :two => 'two'}
118
- #
119
- # t2.name # => "batch"
120
- # t2.config # => {:one => 'ANOTHER ONE', :two => 'two'}
121
- #
122
100
  # === Batches
101
+ #
102
+ # Tasks can be assembled into batches that enque and execute collectively.
103
+ # Batched tasks are often alternatively-configured derivatives of one
104
+ # parent task, although they can be manually assembled using Task.batch.
123
105
  #
124
- # Tasks facilitate batch processing of inputs using batched tasks. Often
125
- # a batch consists of the the same task class instantiated with a variety
126
- # of configurations. Once batched, tasks enque together; when any one of
127
- # the tasks is enqued, the entire batch is enqued.
128
- #
129
- # runlist = []
130
- # t1 = Task.new {|task, input| runlist << input}
106
+ # app = Tap::App.instance
107
+ # t1 = Tap::Task.new(:key => 'one') do |task, input|
108
+ # input + task.config[:key]
109
+ # end
131
110
  # t1.batch # => [t1]
132
111
  #
133
- # t2 = t1.initialize_batch_obj
112
+ # t2 = t1.initialize_batch_obj(:key => 'two')
134
113
  # t1.batch # => [t1, t2]
135
114
  # t2.batch # => [t1, t2]
136
115
  #
137
- # t1.enq 1
138
- # t2.enq 2
139
- # t1.app.run
140
- #
141
- # runlist # => [1,1,2,2]
142
- #
143
- # Here runlist reflects that t1 and t2 were run in succession with the 1
144
- # input, and then the 2 input.
145
- #
146
- # === Non-Task Tasks
147
- #
148
- # The essential behavior of a Task is expressed in the Tap::Task::Base
149
- # module. Using this module, non-task classes can be made to behave like
150
- # tasks. An even more fundamental module, Tap::Executable, allows any
151
- # method to behave in this manner.
152
- #
153
- # Configurations are specific to Task but batches are not. Non-task
154
- # tasks can be batched. Executable methods cannot be batched.
155
- #
156
- # See Tap::Task::Base and Tap::Support::Executable for more details as
157
- # well as Tap::Support::Rake::Task, which makes Rake[http://rake.rubyforge.org/]
158
- # tasks behave like Tap tasks.
159
- class Task
160
-
161
- # Defines the essential behavior of a Task. Using this module,
162
- # non-task classes can be made to behave like tasks; ie they can
163
- # be enqued, batched, and incorporated into workflows.
164
- module Base
165
- include Support::Executable
166
-
167
- attr_reader :app
168
-
169
- # Initializes obj to behave like a Task. The input method will be
170
- # called when obj is run by Tap::App.
171
- def self.initialize(obj, method_name, app=App.instance)
172
- obj.extend Base
173
- obj.extend Support::Batchable
174
- obj.instance_variable_set(:@app, app)
175
- obj.instance_variable_set(:@batch, [])
176
- obj.instance_variable_set(:@multithread, false)
177
- obj.instance_variable_set(:@on_complete_block, nil)
178
- obj.instance_variable_set(:@_method_name, method_name)
179
- obj.initialize_batch_obj
180
- obj
181
- end
182
-
183
- # Enqueues self and self.batch to app with the inputs.
184
- # The number of inputs provided should match the number
185
- # of inputs specified by the arity of the _method_name method.
186
- def enq(*inputs)
187
- batch.each {|t| t.unbatched_enq(*inputs) }
188
- self
189
- end
190
-
191
- # Like enq, but only enques self and not self.batch.
192
- def unbatched_enq(*inputs)
193
- app.queue.enq(self, inputs)
194
- end
195
-
196
- alias :unbatched_on_complete :on_complete
197
-
198
- # Sets the on_complete_block for self and self.batch.
199
- # Use unbatched_on_complete to set the on_complete_block
200
- # for just self.
201
- def on_complete(override=false, &block)
202
- batch.each {|t| t.unbatched_on_complete(override, &block)}
203
- self
204
- end
205
-
206
- alias :unbatched_multithread= :multithread=
207
-
208
- # Sets the multithread for self and self.batch. Use
209
- # unbatched_multithread= to set multithread for just self.
210
- def multithread=(value)
211
- batch.each {|t| t.unbatched_multithread = value }
212
- self
213
- end
214
-
215
- # Raises a TerminateError if app.state == State::TERMINATE.
216
- # check_terminate may be called at any time to provide a
217
- # breakpoint in long-running processes.
218
- def check_terminate
219
- if app.state == App::State::TERMINATE
220
- raise App::TerminateError.new
221
- end
222
- end
223
- end
224
-
225
- include Base
226
- include Support::Configurable
227
- extend Support::CommandLineMethods
116
+ # t1.enq 't1_by_'
117
+ # t2.enq 't2_by_'
118
+ # app.run
119
+ #
120
+ # app.results(t1) # => ["t1_by_one", "t2_by_one"]
121
+ # app.results(t2) # => ["t1_by_two", "t2_by_two"]
122
+ #
123
+ # Here the results reflects that t1 and t2 were run in succession with the
124
+ # input to t1, and then the input to t2.
125
+ #
126
+ # === Subclassing
127
+ # Tasks can be subclassed normally, with one reminder related to batching.
128
+ #
129
+ # Batched tasks are generated by duplicating an existing instance, hence
130
+ # all instance variables will point to the same object in the batched
131
+ # and original task. At times (as with configurations), this is
132
+ # undesirable; the batched task should have it's own copy of an
133
+ # instance variable.
134
+ #
135
+ # In these cases, the <tt>initialize_copy</tt> should be overridden
136
+ # and should re-initialize the appropriate variables. Be sure to call
137
+ # super to invoke the default <tt>initialize_copy</tt>:
138
+ #
139
+ # class SubclassTask < Tap::Task
140
+ # attr_accessor :array
141
+ # def initialize(*args)
142
+ # @array = []
143
+ # super
144
+ # end
145
+ #
146
+ # def initialize_copy(orig)
147
+ # @array = orig.array.dup
148
+ # super
149
+ # end
150
+ # end
151
+ #
152
+ # t1 = SubclassTask.new
153
+ # t2 = t1.initialize_batch_obj
154
+ # t1.array == t2.array # => true
155
+ # t1.array.object_id == t2.array.object_id # => false
156
+ #
157
+ class Task
158
+ include Support::Executable
159
+ include Support::Framework
228
160
 
229
161
  attr_reader :task_block
230
162
 
231
- # Creates a new Task with the specified attributes.
232
- #
233
- # === Subclassing
234
- # Batched tasks are generated by duplicating an existing instance, hence
235
- # it is a good idea to set shared instance variables BEFORE calling super
236
- # in a subclass initialize method. Non-shared instance variables can be
237
- # set by overriding the initialize_batch_obj method:
238
- #
239
- # class SubclassTask < Tap::Task
240
- # attr_accessor :shared_variable, :instance_specific_variable
241
- #
242
- # def initialize(*args)
243
- # @shared_variable = Object.new
244
- # super
245
- # end
246
- #
247
- # def initialize_batch_obj(*args)
248
- # task = super
249
- # task.instance_specific_variable = Object.new
250
- # task
251
- # end
252
- # end
253
- #
254
- # t1 = SubclassTask.new
255
- # t2 = t1.initialize_batch_obj
256
- # t1.shared_variable == t2.shared_variable # => true
257
- # t1.instance_specific_variable == t2.instance_specific_variable # => false
258
- #
259
- def initialize(name=nil, config={}, app=App.instance, &task_block)
163
+ def initialize(config={}, name=nil, app=App.instance, &task_block)
164
+ super(config, name, app)
165
+
260
166
  @task_block = (task_block == nil ? default_task_block : task_block)
261
167
  @multithread = false
262
168
  @on_complete_block = nil
263
169
  @_method_name = :execute
264
- super(name, config, app)
265
170
  end
266
171
 
172
+ # Enqueues self and self.batch to app with the inputs.
173
+ # The number of inputs provided should match the number
174
+ # of inputs specified by the arity of the _method_name method.
175
+ def enq(*inputs)
176
+ app.queue.enq(self, inputs)
177
+ end
178
+
179
+ batch_function :enq, :multithread=
180
+ batch_function(:on_complete) {}
181
+
267
182
  # Executes self with the given inputs. Execute provides hooks for subclasses
268
183
  # to insert standard execution code: before_execute, on_execute_error,
269
184
  # and after_execute. Override any/all of these methods as needed.
@@ -321,17 +236,6 @@ module Tap
321
236
 
322
237
  task_block.call(*inputs)
323
238
  end
324
-
325
- # Logs the inputs to the application logger (via app.log)
326
- def log(action, msg="", level=Logger::INFO)
327
- # TODO - add a task identifier?
328
- app.log(action, msg, level)
329
- end
330
-
331
- # Returns self.name
332
- def to_s
333
- name
334
- end
335
239
 
336
240
  protected
337
241
 
@@ -0,0 +1,56 @@
1
+ module Tap
2
+ module Tasks
3
+ # :startdoc::manifest the default dump task
4
+ #
5
+ # A dump task to print application results to a file or IO. The results are
6
+ # printed in a format allowing dumped results to be reloaded and used as
7
+ # inputs to other tasks. See Tap::Load for more details.
8
+ #
9
+ # Often dump is used as the final task in a round of tasks; if no filepath is
10
+ # specified, the results are printed to stdout.
11
+ #
12
+ # % tap run -- [your tasks] --+ dump FILEPATH
13
+ #
14
+ class Dump < Tap::FileTask
15
+
16
+ config :date_format, '%Y-%m-%d %H:%M:%S' # the date format
17
+ config :audit, true, &c.switch # include the audit trails
18
+ config :date, true, &c.switch # include a date
19
+
20
+ def process(target=$stdout)
21
+ case target
22
+ when IO then dump_to(target)
23
+ else
24
+ log_basename(:dump, target)
25
+ prepare(target)
26
+ File.open(target, "wb") {|file| dump_to(file) }
27
+ end
28
+ end
29
+
30
+ # Dumps the current results in app.aggregator to the io.
31
+ # The dump will include the result audits and a date,
32
+ # as specified in config.
33
+ def dump_to(io)
34
+ trails = []
35
+ results = {}
36
+ app.aggregator.to_hash.each_pair do |src, _results|
37
+ name = src.respond_to?(:name) ? src.name : ''
38
+
39
+ results["#{name} (#{src.object_id})"] = _results.collect {|_audit| _audit._current }
40
+ _results.each {|_audit| trails << _audit._to_s }
41
+ end
42
+
43
+ if audit
44
+ io.puts "# audit:"
45
+ trails.each {|trail| io.puts "# #{trail.gsub("\n", "\n# ")}"}
46
+ end
47
+
48
+ if date
49
+ io.puts "# date: #{Time.now.strftime(date_format)}"
50
+ end
51
+
52
+ YAML::dump(results, io)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,93 @@
1
+ require 'rake'
2
+
3
+ module Tap
4
+ module Tasks
5
+ # :startdoc::manifest run rake tasks
6
+ #
7
+ # Simply enques the specified rake task(s) for execution. Useful when a
8
+ # rake task needs to be executed within a workflow. For example these
9
+ # are equivalent:
10
+ #
11
+ # % tap run -- rake test
12
+ # % rake test
13
+ #
14
+ # The only exeception is in the use of the --help option. Use --rake-help
15
+ # to access the rake help, and --help to access this help.
16
+ #
17
+ class Rake < Tap::Task
18
+
19
+ # Modifies Rake::Application by adding a hook to the standard_exception_handling
20
+ # method. This allows more fine-grained use of Rake::Applications by Tap.
21
+ module Application
22
+ def enq_top_level(app)
23
+ # takes the place of rake.top_level
24
+ if options.show_tasks
25
+ display_tasks_and_comments
26
+ exit
27
+ elsif options.show_prereqs
28
+ display_prerequisites
29
+ exit
30
+ else
31
+ top_level_tasks.each do |task_string|
32
+ name, args = parse_task_string(task_string)
33
+ task = self[name]
34
+
35
+ unless task.kind_of?(Tap::Support::Executable)
36
+ Tap::Support::Executable.initialize(task, :invoke)
37
+ end
38
+
39
+ app.enq(task, *args)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ class << self
46
+
47
+ # Overrides Tap::Support::FrameworkClass#instantiate to do
48
+ # nothing so that all args get passed forward to rake.
49
+ def instantiate(argv, app=Tap::App.instance) # => instance, argv
50
+ if argv.include?('--help')
51
+ puts help
52
+ exit
53
+ end
54
+ [new({}, default_name, app), argv.collect {|arg| arg == '--rake-help' ? '--help' : arg}]
55
+ end
56
+ end
57
+
58
+ #--
59
+ # def on_complete(override=false, &block)
60
+ # @rake_tasks.each do |task|
61
+ # task.on_complete(override, &block)
62
+ # end
63
+ # end
64
+ #++
65
+
66
+ def enq(*argv)
67
+ rake = ::Rake.application
68
+ unless rake.kind_of?(Application)
69
+ rake.extend Application
70
+ end
71
+
72
+ # run as if from command line using argv
73
+ current_argv = ARGV.dup
74
+ begin
75
+ ARGV.clear
76
+ ARGV.concat(argv)
77
+
78
+ # now follow the same protocol as
79
+ # in run, handling options
80
+ rake.init
81
+ rake.load_rakefile
82
+ ensure
83
+ ARGV.clear
84
+ ARGV.concat(current_argv)
85
+ end
86
+
87
+ rake.enq_top_level(app)
88
+
89
+ nil
90
+ end
91
+ end
92
+ end
93
+ end