tap 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/History +12 -0
  2. data/MIT-LICENSE +0 -2
  3. data/README +23 -32
  4. data/bin/rap +116 -0
  5. data/bin/tap +6 -9
  6. data/cgi/run.rb +67 -0
  7. data/cmd/console.rb +1 -1
  8. data/cmd/destroy.rb +4 -4
  9. data/cmd/generate.rb +4 -4
  10. data/cmd/manifest.rb +61 -53
  11. data/cmd/run.rb +8 -75
  12. data/doc/Class Reference +130 -121
  13. data/doc/Command Reference +76 -124
  14. data/doc/Syntax Reference +290 -0
  15. data/doc/Tutorial +305 -237
  16. data/lib/tap/app.rb +140 -467
  17. data/lib/tap/constants.rb +2 -2
  18. data/lib/tap/declarations.rb +211 -0
  19. data/lib/tap/env.rb +171 -193
  20. data/lib/tap/exe.rb +100 -21
  21. data/lib/tap/file_task.rb +3 -3
  22. data/lib/tap/generator/base.rb +1 -1
  23. data/lib/tap/generator/destroy.rb +10 -10
  24. data/lib/tap/generator/generate.rb +29 -18
  25. data/lib/tap/generator/generators/command/command_generator.rb +2 -2
  26. data/lib/tap/generator/generators/command/templates/command.erb +2 -2
  27. data/lib/tap/generator/generators/config/config_generator.rb +3 -3
  28. data/lib/tap/generator/generators/config/templates/doc.erb +1 -1
  29. data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
  30. data/lib/tap/generator/generators/file_task/templates/task.erb +1 -1
  31. data/lib/tap/generator/generators/file_task/templates/test.erb +1 -1
  32. data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
  33. data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
  34. data/lib/tap/generator/generators/root/root_generator.rb +13 -13
  35. data/lib/tap/generator/generators/root/templates/README +0 -0
  36. data/lib/tap/generator/generators/root/templates/Rakefile +2 -2
  37. data/lib/tap/generator/generators/root/templates/gemspec +4 -5
  38. data/lib/tap/generator/generators/root/templates/tapfile +11 -8
  39. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  40. data/lib/tap/generator/generators/task/task_generator.rb +1 -3
  41. data/lib/tap/generator/generators/task/templates/test.erb +1 -3
  42. data/lib/tap/patches/optparse/summarize.rb +62 -0
  43. data/lib/tap/root.rb +41 -29
  44. data/lib/tap/support/aggregator.rb +16 -3
  45. data/lib/tap/support/assignments.rb +10 -9
  46. data/lib/tap/support/audit.rb +58 -64
  47. data/lib/tap/support/class_configuration.rb +33 -44
  48. data/lib/tap/support/combinator.rb +125 -0
  49. data/lib/tap/support/configurable.rb +13 -14
  50. data/lib/tap/support/configurable_class.rb +21 -43
  51. data/lib/tap/support/configuration.rb +55 -9
  52. data/lib/tap/support/constant.rb +87 -13
  53. data/lib/tap/support/constant_manifest.rb +116 -0
  54. data/lib/tap/support/dependencies.rb +54 -0
  55. data/lib/tap/support/dependency.rb +44 -0
  56. data/lib/tap/support/executable.rb +247 -32
  57. data/lib/tap/support/executable_queue.rb +1 -1
  58. data/lib/tap/support/gems/rake.rb +29 -8
  59. data/lib/tap/support/gems.rb +10 -30
  60. data/lib/tap/support/instance_configuration.rb +29 -3
  61. data/lib/tap/support/intern.rb +46 -0
  62. data/lib/tap/support/join.rb +143 -0
  63. data/lib/tap/support/joins/fork.rb +19 -0
  64. data/lib/tap/support/joins/merge.rb +22 -0
  65. data/lib/tap/support/joins/sequence.rb +21 -0
  66. data/lib/tap/support/joins/switch.rb +25 -0
  67. data/lib/tap/support/joins/sync_merge.rb +63 -0
  68. data/lib/tap/support/joins.rb +15 -0
  69. data/lib/tap/support/lazy_attributes.rb +17 -2
  70. data/lib/tap/support/lazydoc/comment.rb +503 -0
  71. data/lib/tap/support/lazydoc/config.rb +17 -0
  72. data/lib/tap/support/lazydoc/definition.rb +36 -0
  73. data/lib/tap/support/lazydoc/document.rb +152 -0
  74. data/lib/tap/support/lazydoc/method.rb +24 -0
  75. data/lib/tap/support/lazydoc.rb +269 -343
  76. data/lib/tap/support/manifest.rb +121 -103
  77. data/lib/tap/support/minimap.rb +90 -0
  78. data/lib/tap/support/node.rb +56 -0
  79. data/lib/tap/support/parser.rb +436 -0
  80. data/lib/tap/support/schema.rb +359 -0
  81. data/lib/tap/support/shell_utils.rb +3 -5
  82. data/lib/tap/support/string_ext.rb +60 -0
  83. data/lib/tap/support/tdoc.rb +7 -2
  84. data/lib/tap/support/templater.rb +30 -16
  85. data/lib/tap/support/validation.rb +77 -8
  86. data/lib/tap/task.rb +431 -143
  87. data/lib/tap/tasks/dump.rb +15 -10
  88. data/lib/tap/tasks/load.rb +112 -0
  89. data/lib/tap/tasks/rake.rb +4 -41
  90. data/lib/tap/test/assertions.rb +38 -0
  91. data/lib/tap/test/env_vars.rb +1 -1
  92. data/lib/tap/test/extensions.rb +79 -0
  93. data/lib/tap/test/file_test.rb +420 -0
  94. data/lib/tap/test/file_test_class.rb +12 -0
  95. data/lib/tap/test/regexp_escape.rb +87 -0
  96. data/lib/tap/test/script_test.rb +46 -0
  97. data/lib/tap/test/script_tester.rb +115 -0
  98. data/lib/tap/test/subset_test.rb +260 -0
  99. data/lib/tap/test/subset_test_class.rb +99 -0
  100. data/lib/tap/test/{tap_methods.rb → tap_test.rb} +45 -43
  101. data/lib/tap/test/utils.rb +231 -0
  102. data/lib/tap/test.rb +53 -26
  103. data/lib/tap.rb +3 -20
  104. metadata +50 -27
  105. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
  106. data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
  107. data/lib/tap/patches/rake/testtask.rb +0 -57
  108. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
  109. data/lib/tap/patches/ruby19/parsedate.rb +0 -16
  110. data/lib/tap/support/batchable.rb +0 -47
  111. data/lib/tap/support/batchable_class.rb +0 -107
  112. data/lib/tap/support/command_line.rb +0 -98
  113. data/lib/tap/support/comment.rb +0 -270
  114. data/lib/tap/support/constant_utils.rb +0 -127
  115. data/lib/tap/support/declarations.rb +0 -111
  116. data/lib/tap/support/framework.rb +0 -83
  117. data/lib/tap/support/framework_class.rb +0 -180
  118. data/lib/tap/support/run_error.rb +0 -39
  119. data/lib/tap/support/summary.rb +0 -30
  120. data/lib/tap/test/file_methods.rb +0 -377
  121. data/lib/tap/test/script_methods/script_test.rb +0 -98
  122. data/lib/tap/test/script_methods.rb +0 -107
  123. data/lib/tap/test/subset_methods.rb +0 -420
  124. data/lib/tap/workflow.rb +0 -200
@@ -0,0 +1,290 @@
1
+ = Syntax Reference
2
+
3
+ Tap uses several domain-specific languages to declare tasks and workflows. This is a reference for:
4
+
5
+ * task declarations
6
+ * class definitions
7
+ * workflows
8
+
9
+ == Task Declarations
10
+
11
+ A task declaration:
12
+
13
+ # name:: the name of the task, either alone or as the
14
+ # key of a {key => dependencies} hash
15
+ # dependencies:: an array of task names (optional)
16
+ # arg_names:: an array of argument names (optional)
17
+ # configurations:: a hash of {key => default} pairs (optional)
18
+
19
+ task({<name> => [<dependencies...>]}, <arg_names...>, {<configs>}) do |task, args|
20
+ # arguments are available through args:
21
+ args.arg_name
22
+
23
+ # configurations are available through task
24
+ task.key
25
+ end
26
+
27
+ A namespace declaration:
28
+
29
+ namespace(<name>) { task ... }
30
+
31
+ Simple documentation:
32
+
33
+ desc "description"
34
+ task ...
35
+
36
+ Extended documentation:
37
+
38
+ # ::desc description
39
+ # Extended documentation may span multiple lines, and
40
+ # supports
41
+ #
42
+ # code indentation
43
+ # like this.
44
+ #
45
+ # Lines are justified and wrapped on the command line.
46
+ task ...
47
+
48
+ Pains were taken to make task declarations for rap work the similar to rake tasks. In both cases (noting that in general, beyond rap, task classes are not limited in these ways):
49
+
50
+ * tasks are singleton instances that may be extended across multiple declarations
51
+ * tasks do not pass inputs from one task to the next
52
+ * tasks only execute once
53
+
54
+ A few syntactical differences between rake and rap must to be noted, as they can cause errors if you try to migrate rake tasks to tap. Tap declarations.
55
+
56
+ ==== no needs
57
+
58
+ Tasks do not support :needs as a way to specify dependencies. For instance, this will declare a ':needs' configuration with the default value ':another', not a task which depends on another:
59
+
60
+ Tap.task :name, :needs => :another
61
+
62
+ ==== immediate namespace lookup
63
+
64
+ Within a namespace, task will look for a literal match to the dependency first. If it doesn't find one, it will declare it within the namespace; one way or the other the dependency is resolved immediately. Hence, in this example the nested task depends on the non-nested task.
65
+
66
+ task :outer { print 'non-nested' }
67
+ namespace :nest do
68
+ task :inner => :outer { puts 'was executed' }
69
+ task :outer { print 'nested' }
70
+ end
71
+
72
+ By contrast, rake waits to resolve dependencies and so will always use a match within a namespace in preference to a literal match. For these tasks rap and rake produce different results:
73
+
74
+ % rap nest/inner
75
+ non-nested was executed
76
+ % rake nest:inner
77
+ nested was executed
78
+
79
+ == Task Classes
80
+
81
+ This is a verbose prototype for Tap::Task subclasses:
82
+
83
+ # <ClassName>::manifest summary description
84
+ #
85
+ # Extended documentation...
86
+ #
87
+ class ClassName < Tap::Task
88
+
89
+ # Sets up a configuration and makes the 'key' and 'key=' accessors.
90
+ #
91
+ # This documentation appears in static config files, and in RDoc.
92
+ #
93
+ config :key, 'default value' do |value| # config summary
94
+ "the config is set to the return value"
95
+ end
96
+
97
+ # Subclasses BaseClass with the specified configs, using the block
98
+ # to override process.
99
+ #
100
+ # Also creates the methods 'name', 'name_config', 'name_config='.
101
+ # The first will access an instance-specific instance of the
102
+ # subclass, the other two are accessors for the instance configs.
103
+ #
104
+ # Primarily used in conjunction with workflow.
105
+ #
106
+ define :name, <BaseClass>, {<configs>} do |*args|
107
+ # this is the process block
108
+ end
109
+
110
+ # Causes each instance to depend on DependencyClass.instance.
111
+ #
112
+ # Also defines a reader 'name' which will access the results
113
+ # of the dependency.
114
+ depends_on :name, <DependencyClass>
115
+
116
+ def process(*args)
117
+ # the method defining what this task does
118
+ end
119
+
120
+ protected
121
+
122
+ def workflow
123
+ # a hook to setup joins between various tasks used
124
+ # by the current instance. workflow is called
125
+ # during initialize
126
+ end
127
+
128
+ def before_execute()
129
+ # a hook to execute code before process
130
+ # (only works in workflows)
131
+ end
132
+
133
+ def after_execute()
134
+ # a hook to execute code after process
135
+ # (only works in workflows)
136
+ end
137
+
138
+ def on_execute_error(err)
139
+ # a hook to handle errors during process
140
+ # (only works in workflows)
141
+ end
142
+ end
143
+
144
+ == Workflows
145
+
146
+ The tap workflow syntax is designed to specify an arbitrary number of tasks, inputs, configurations, and joins. The syntax works both as text and as YAML; 'tap run' and rap both use it to specify which tasks to execute. Basically, the syntax uses double-dash delimiters to separate task vectors and modified delimiters to specify joins for the tasks.
147
+
148
+ These both specify three tasks (x,y,z) joined in a sequence:
149
+
150
+ % rap x --: y --: z
151
+ % rap x -- y -- z --0:1:2
152
+
153
+ The modified delimiters use numbers to indicate which tasks participate in a join and punctuation to indicate the join type. In the first example, the numbers are implicitly added for the preceding and following task. A variety of joins are supported:
154
+
155
+ delimiter function syntax example meaning
156
+ -- delimiter a -- b -- c enques/configures tasks a, b, c
157
+ --* dependency --* a enques dependency instance
158
+ --+ round --+ a --++ b enques a to round one, b to round two
159
+ --+[] round shorthand +round[targets] --+2[0,1] enques (a,b) to round two
160
+
161
+ --: sequence source:target --0:1:2 sequence a, b, c
162
+ --[] fork source[targets...] --0[1,2] fork a to (b,c)
163
+ --{} merge target{sources...} --2{0,1} merge (a,b) to c
164
+ --() sync_merge target(sources...) --2(0,1) synchronize merge (a,b) to c
165
+
166
+ Inputs may be specified between delimiters:
167
+
168
+ % rap x alpha beta --: y gamma --: z delta
169
+
170
+ As may be configurations, in a variety of formats:
171
+
172
+ % rap x alpha beta -k --: y gamma --key value --: z delta --key=value
173
+
174
+ These are the corresponding task vectors:
175
+
176
+ ['x', 'alpha', 'beta', '-k']
177
+ ['y', 'gamma', '--key', 'value']
178
+ ['z', 'delta', '--key=value']
179
+
180
+ This is how it would look as YAML:
181
+
182
+ - - x
183
+ - alpha
184
+ - beta
185
+ - -k
186
+ - - y
187
+ - gamma
188
+ - key: value
189
+ - - z
190
+ - delta
191
+ - --key=value
192
+ - 0:1:2
193
+
194
+ The task vectors are converted into a task and an argument vector by first looking up a task class and then calling TaskClass.parse. The parse method returns a configured instance of the task and an argv to be executed by the task. Once the task are instantiated, instances are joined and enqued to Tap::App for execution (see Tap::Support::Schema#build).
195
+
196
+ ==== Class Lookup
197
+
198
+ Tap looks up classes via Tap::Env. Tap can find tasks from multiple environments; by adding in environments for gems, Tap can find tasks within a gem.
199
+
200
+ During lookup, classes are treated like filepaths which match from the basename up:
201
+
202
+ class lookup matched by
203
+ Sample::Task sample/task task, sample/task
204
+ A::Nested::Task a/nested/task task, nested/task, a/nested/task
205
+
206
+ In the event of a name conflict, the path of the environment may also be specified. It seems like this could get confusing, but the tap executable produces manifests that specify the minimal path required to uniquely identify a class. Fragments of the minimized paths will be resolved in order from top to bottom within the specified environment. For example:
207
+
208
+ % tap run -T
209
+ one:
210
+ sample/task # some sample task
211
+ another/task # another task
212
+ two:
213
+ sample/task # a conflicting sample task
214
+
215
+ Runs the 'one' sample/task:
216
+
217
+ % tap run -- sample/task
218
+ % tap run -- one:sample/task
219
+
220
+ Runs the 'two' sample/task:
221
+
222
+ % tap run -- two:sample/task
223
+
224
+ Runs the 'one' sample/task:
225
+
226
+ % tap run -- task
227
+
228
+ Runs the 'two' sample/task:
229
+
230
+ % tap run -- two:task
231
+
232
+ Runs another/task:
233
+
234
+ % tap run -- another/task
235
+ % tap run -- one:another/task
236
+
237
+ Notice that the full minimized path ('another/task') is required because simply using 'task' will be matched to sample/task. The order of tasks is obviously not alphabetical -- rather it corresponds to the order in which Tap::Env discovers the tasks.
238
+
239
+ ==== Dependencies (--*)
240
+
241
+ Normally each task vector specifies a new instance of a task. This specifies three instance of the 'a' task.
242
+
243
+ % rap -- a -- a -- a
244
+
245
+ When you want to specify a 'singleton' instance of a task, the instance specified by TaskClass.instance, use the dependency delimiter '--*'.
246
+
247
+ % rap --* a
248
+
249
+ The dependency instance will be configured and enqued with the arguments. Dependency instances will be executed first, even if they are specified at the end of a workflow, they cannot participate in workflows, and any single dependency may only be specified once in a workflow. These are equivalent:
250
+
251
+ % rap --* a -- b -- c
252
+ % rap b -- c --* a
253
+
254
+ While these raise errors:
255
+
256
+ % rap --* a --* a
257
+ % rap --* a --: b
258
+
259
+ ==== Rounds (--+)
260
+
261
+ The workflow syntax allows multiple execution rounds to be specified All tasks in a round are run to completion before the next round begins. Rounds are specified by adding '+' characters after the double-dash break.
262
+
263
+ % tap run -- round_one_task --+ round_two_task
264
+
265
+ Tasks may be added to rounds in any order and may use the shorthand for multiple tasks. These are equivalents:
266
+
267
+ % tap run -- a --+ b --+ c --++ d
268
+ % tap run --+ b --++ d -- a --+ c
269
+ % tap run -- a -- b -- c -- d --+1[1,2] --+2[3]
270
+
271
+ Rounds are particularly useful for dump tasks; add a dump task as a final round to capture all results from previous rounds:
272
+
273
+ % tap run -- task -- task --+ dump
274
+
275
+ ==== Notes for rap
276
+
277
+ Specifying tasks for rap is no different than 'tap run'. The only exception occurs when the task can't be found. Unknown tasks are implicitly run as a Tap::Tasks::Rake task, which causes the task to be run as if by rake. These are the same:
278
+
279
+ Run a rake task with inputs and an ENV config:
280
+
281
+ % rake task_name[1,2,3] key=value
282
+
283
+ Explicitly run a Tap::Tasks::Rake task using the same inputs:
284
+
285
+ % rap rake task_name[1,2,3] key=value
286
+
287
+ Implicitly run the Tap::Tasks::Rake task:
288
+
289
+ % rap task_name[1,2,3] key=value
290
+