tap 0.12.4 → 0.17.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 (102) hide show
  1. data/History +34 -0
  2. data/README +62 -41
  3. data/bin/tap +36 -40
  4. data/cmd/console.rb +14 -6
  5. data/cmd/manifest.rb +62 -58
  6. data/cmd/run.rb +49 -31
  7. data/doc/API +84 -0
  8. data/doc/Class Reference +83 -115
  9. data/doc/Examples/Command Line +36 -0
  10. data/doc/Examples/Workflow +40 -0
  11. data/lib/tap/app.rb +293 -214
  12. data/lib/tap/app/node.rb +43 -0
  13. data/lib/tap/app/queue.rb +77 -0
  14. data/lib/tap/app/stack.rb +16 -0
  15. data/lib/tap/app/state.rb +22 -0
  16. data/lib/tap/constants.rb +2 -2
  17. data/lib/tap/env.rb +400 -314
  18. data/lib/tap/env/constant.rb +227 -0
  19. data/lib/tap/env/gems.rb +63 -0
  20. data/lib/tap/env/manifest.rb +89 -0
  21. data/lib/tap/env/minimap.rb +292 -0
  22. data/lib/tap/{support → env}/string_ext.rb +2 -2
  23. data/lib/tap/exe.rb +113 -125
  24. data/lib/tap/join.rb +175 -0
  25. data/lib/tap/joins.rb +9 -0
  26. data/lib/tap/joins/switch.rb +44 -0
  27. data/lib/tap/joins/sync.rb +99 -0
  28. data/lib/tap/root.rb +100 -491
  29. data/lib/tap/root/utils.rb +220 -0
  30. data/lib/tap/{support → root}/versions.rb +31 -29
  31. data/lib/tap/schema.rb +248 -0
  32. data/lib/tap/schema/parser.rb +413 -0
  33. data/lib/tap/schema/utils.rb +82 -0
  34. data/lib/tap/support/intern.rb +19 -6
  35. data/lib/tap/support/templater.rb +8 -3
  36. data/lib/tap/task.rb +175 -171
  37. data/lib/tap/tasks/dump.rb +58 -0
  38. data/lib/tap/tasks/load.rb +62 -0
  39. metadata +30 -73
  40. data/cmd/destroy.rb +0 -27
  41. data/cmd/generate.rb +0 -27
  42. data/doc/Command Reference +0 -105
  43. data/doc/Syntax Reference +0 -234
  44. data/doc/Tutorial +0 -348
  45. data/lib/tap/dump.rb +0 -142
  46. data/lib/tap/file_task.rb +0 -384
  47. data/lib/tap/generator/arguments.rb +0 -13
  48. data/lib/tap/generator/base.rb +0 -176
  49. data/lib/tap/generator/destroy.rb +0 -60
  50. data/lib/tap/generator/generate.rb +0 -93
  51. data/lib/tap/generator/generators/command/command_generator.rb +0 -21
  52. data/lib/tap/generator/generators/command/templates/command.erb +0 -32
  53. data/lib/tap/generator/generators/config/config_generator.rb +0 -98
  54. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -37
  55. data/lib/tap/generator/generators/generator/templates/task.erb +0 -27
  56. data/lib/tap/generator/generators/generator/templates/test.erb +0 -26
  57. data/lib/tap/generator/generators/root/root_generator.rb +0 -84
  58. data/lib/tap/generator/generators/root/templates/MIT-LICENSE +0 -22
  59. data/lib/tap/generator/generators/root/templates/README +0 -14
  60. data/lib/tap/generator/generators/root/templates/Rakefile +0 -84
  61. data/lib/tap/generator/generators/root/templates/Rapfile +0 -11
  62. data/lib/tap/generator/generators/root/templates/gemspec +0 -27
  63. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -3
  64. data/lib/tap/generator/generators/task/task_generator.rb +0 -25
  65. data/lib/tap/generator/generators/task/templates/task.erb +0 -14
  66. data/lib/tap/generator/generators/task/templates/test.erb +0 -19
  67. data/lib/tap/generator/manifest.rb +0 -20
  68. data/lib/tap/generator/preview.rb +0 -69
  69. data/lib/tap/load.rb +0 -64
  70. data/lib/tap/spec.rb +0 -41
  71. data/lib/tap/support/aggregator.rb +0 -65
  72. data/lib/tap/support/audit.rb +0 -333
  73. data/lib/tap/support/constant.rb +0 -143
  74. data/lib/tap/support/constant_manifest.rb +0 -126
  75. data/lib/tap/support/dependencies.rb +0 -54
  76. data/lib/tap/support/dependency.rb +0 -44
  77. data/lib/tap/support/executable.rb +0 -198
  78. data/lib/tap/support/executable_queue.rb +0 -125
  79. data/lib/tap/support/gems.rb +0 -43
  80. data/lib/tap/support/join.rb +0 -144
  81. data/lib/tap/support/joins.rb +0 -12
  82. data/lib/tap/support/joins/switch.rb +0 -27
  83. data/lib/tap/support/joins/sync_merge.rb +0 -38
  84. data/lib/tap/support/manifest.rb +0 -171
  85. data/lib/tap/support/minimap.rb +0 -90
  86. data/lib/tap/support/node.rb +0 -176
  87. data/lib/tap/support/parser.rb +0 -450
  88. data/lib/tap/support/schema.rb +0 -385
  89. data/lib/tap/support/shell_utils.rb +0 -67
  90. data/lib/tap/test.rb +0 -77
  91. data/lib/tap/test/assertions.rb +0 -38
  92. data/lib/tap/test/env_vars.rb +0 -29
  93. data/lib/tap/test/extensions.rb +0 -73
  94. data/lib/tap/test/file_test.rb +0 -362
  95. data/lib/tap/test/file_test_class.rb +0 -15
  96. data/lib/tap/test/regexp_escape.rb +0 -87
  97. data/lib/tap/test/script_test.rb +0 -46
  98. data/lib/tap/test/script_tester.rb +0 -115
  99. data/lib/tap/test/subset_test.rb +0 -260
  100. data/lib/tap/test/subset_test_class.rb +0 -99
  101. data/lib/tap/test/tap_test.rb +0 -109
  102. data/lib/tap/test/utils.rb +0 -231
data/doc/Tutorial DELETED
@@ -1,348 +0,0 @@
1
- = Tap (Task Application)
2
-
3
- Tap is a framework for creating configurable, distributable tasks and workflows.
4
- Although scalable for complex workflows, at it simplest tap works like a
5
- supercharged rake. Using the rap executable, you can declare tasks using a
6
- syntax almost identical to rake, but with added support for configurations and
7
- documentation.
8
-
9
- Note: this tutorial spans several modules in the {Tap-Suite}[http://tap.rubyforge.org/tap-suite].
10
- Be sure to install both tap and rap (or the full suite) beforehand.
11
-
12
- % gem install tap-suite
13
-
14
- == Quickstart
15
-
16
- If you've used rake, tap will be easy to pick up. To get started, make a
17
- Rapfile with a simple task declaration:
18
-
19
- [Rapfile]
20
-
21
- # ::desc your basic goodnight moon task
22
- # Says goodnight with a configurable message.
23
- Rap.task(:goodnight, :obj, :message => 'goodnight') do |task, args|
24
- puts "#{task.message} #{args.obj}\n"
25
- end
26
-
27
- Now from the command line:
28
-
29
- % rap goodnight moon
30
- goodnight moon
31
-
32
- % rap goodnight world --message hello
33
- hello world
34
-
35
- % rap goodnight --help
36
- Goodnight -- your basic goodnight moon task
37
- --------------------------------------------------------------------------------
38
- Says goodnight with a configurable message.
39
- --------------------------------------------------------------------------------
40
- usage: rap goodnight OBJ
41
-
42
- configurations:
43
- --message MESSAGE
44
-
45
- options:
46
- -h, --help Print this help
47
- --name NAME Specify a name
48
- --use FILE Loads inputs from file
49
-
50
- Just like that you have a command-line application with inputs, configuration,
51
- and documentation.
52
-
53
- The declaration syntax is obviously similar to rake; configurations are new but
54
- the task-block style is the same, as are inputs. Other rake constructs are
55
- available. Here is a similar goodnight task using dependencies, rake-style.
56
-
57
- [Rapfile]
58
-
59
- # make the declarations available everywhere
60
- # (normally they're accessed via Tap, as above)
61
- include Rap::Declarations
62
-
63
- namespace :example do
64
- task(:say, :message) do |task, args|
65
- print(args.message || 'goodnight')
66
- end
67
-
68
- desc "your basic goodnight moon task"
69
- task({:goodnight => 'example:say'}, :obj) do |task, args|
70
- puts " #{args.obj}\n"
71
- end
72
- end
73
-
74
- And now from the command line:
75
-
76
- % rap goodnight moon
77
- goodnight moon
78
-
79
- % rap goodnight world --* say hello
80
- hello world
81
-
82
- Unlike rake, rap inputs are written out individually and tasks are delimited
83
- by a modified double-dash. Aside from that, you can see rap is basically a
84
- supercharged rake. Furthermore, rap runs rake. Directly substitute rap for
85
- rake on the command line and your tasks should run as normal (see the Rap
86
- {Syntax Reference}[http://tap.rubyforge.org/rap/files/doc/Syntax%20Reference.html]
87
- for more details).
88
-
89
- However, supercharging rake isn't the point of Tap. Declarations bridge the
90
- gap between rake and tap, but tap itself is a more general framework. To get
91
- at other features like imperative workflows, testing, and distribution, we
92
- have to go beyond rap and take a look at what declarations do.
93
-
94
- Spoiler: declarations make subclasses of Tap::Task.
95
-
96
- == Beyond Rap
97
-
98
- Going back to the first example, lets take a look at how a task declaration
99
- maps to a class definition:
100
-
101
- [Rapfile]
102
-
103
- # ::desc your basic goodnight moon task
104
- # Says goodnight with a configurable message.
105
- Rap.task(:goodnight, :obj, :message => 'goodnight') do
106
- puts "#{task.message} #{args.obj}\n"
107
- end
108
-
109
- Here is a corresponding class:
110
-
111
- # Goodnight::manifest your basic goodnight moon task
112
- # Says goodnight with a configurable message.
113
- class Goodnight < Tap::Task
114
- config :message, 'goodnight'
115
-
116
- def process(obj)
117
- "#{message} #{obj}"
118
- end
119
- end
120
-
121
- Simple enough; the name corresponds to the class, configurations (and
122
- dependencies, although they aren't show) are written out individually, and the
123
- block corresponds to process. There are a few differences, especially relating
124
- to process, but for the moment lets gloss over them and see how Goodnight works.
125
-
126
- goodnight = Goodnight.new
127
- goodnight.message # => 'goodnight'
128
- goodnight.process('moon') # => 'goodnight moon'
129
-
130
- hello = Goodnight.new(:message => 'hello')
131
- hello.message # => 'hello'
132
- hello.process('world') # => 'hello world'
133
-
134
- Totally straightforward. Goodnight stores the default configurations, each
135
- instance has accessors to the configurations, and the defaults may be overridden
136
- during initialization, or later. Class definitions allow validation/transformation
137
- blocks to be specified for configurations. These blocks process inputs (ex the
138
- string inputs from the command line), quite literally defining the writer for a
139
- configuration accessor. A set of standard blocks are available through +c+, an
140
- alias for the {Configurable::Validation}[http://tap.rubyforge.org/configurable/classes/Configurable/Validation.html]
141
- module.
142
-
143
- [lib/goodnight.rb]
144
-
145
- # Goodnight::manifest a fancy goodnight moon task
146
- # Says goodnight with a configurable message.
147
- class Goodnight < Tap::Task
148
- config :message, 'goodnight' # a goodnight message
149
- config :reverse, false, &c.switch # reverses the message
150
- config :n, 1, &c.integer # repeats message n times
151
-
152
- def process(*objects)
153
- print "#{reverse == true ? message.reverse : message} " * n
154
- puts objects.join(', ')
155
- puts
156
- end
157
- end
158
-
159
- A few examples show a validation block in action:
160
-
161
- goodnight = Goodnight.new
162
-
163
- goodnight.n = 10
164
- goodnight.n # => 10
165
-
166
- goodnight.n = "100"
167
- goodnight.n # => 100
168
-
169
- goodnight.n = "not an integer" # !> ValidationError
170
-
171
- Now from the command line:
172
-
173
- % rap goodnight moon
174
- goodnight moon
175
-
176
- % rap goodnight moon mittens "little toy boat"
177
- goodnight moon, mittens, little toy boat
178
-
179
- % rap goodnight world --message hello --reverse --n 3
180
- olleh olleh olleh world
181
-
182
- % rap goodnight --help
183
- Goodnight -- a fancy goodnight moon task
184
- --------------------------------------------------------------------------------
185
- Says goodnight with a configurable message.
186
- --------------------------------------------------------------------------------
187
- usage: rap goodnight OBJECTS...
188
-
189
- configurations:
190
- --message MESSAGE a goodnight message
191
- --[no-]reverse reverses the message
192
- --n N repeats message n times
193
-
194
- options:
195
- -h, --help Print this help
196
- --name NAME Specify a name
197
- --use FILE Loads inputs from file
198
-
199
- Take a quick look at the documentation. Class definitions map documentation
200
- and, in some cases, metadata to the command line; the configurations now have
201
- comments and reverse is a switch! Rich mapping allows tasks to act as an
202
- script interface, not unlike {OptionParser}[http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html]
203
- (check out the {Configurable}[http://tap.rubyforge.org/configurable/] gem and
204
- specifically {ConfigParser}[http://tap.rubyforge.org/configurable/classes/ConfigParser.html]
205
- for more details).
206
-
207
- This is a stand-alone goodnight script:
208
-
209
- [goodnight]
210
-
211
- #!/usr/bin/env ruby
212
-
213
- require 'rubygems'
214
- require 'tap'
215
-
216
- # Goodnight::manifest a goodnight moon script
217
- # Says goodnight with a configurable message.
218
- class Goodnight < Tap::Task
219
- config :message, 'goodnight'
220
-
221
- def process(obj)
222
- puts "#{message} #{obj}\n"
223
- end
224
- end
225
-
226
- instance, args = Goodnight.parse!(ARGV)
227
- instance.execute(*args)
228
-
229
- Now, from the command line:
230
-
231
- % ./goodnight moon
232
- goodnight moon
233
-
234
- % ./goodnight --help
235
- ...
236
-
237
- As simple as it is to take a task to the command line, it's nice to note that
238
- tasks may be subclassed, tested, and distributed as usual. No magic, just
239
- convenience.
240
-
241
- == Tap
242
-
243
- Tap comes with two executables, rap and tap. The tap executable is more
244
- verbose than rap for running tasks, but it is more configurable, scalable, and
245
- logically pure. Tap comes with a number of {commands}[link:/files/doc/Command%20Reference.html]
246
- but we'll focus on generate to make, test, and package a task library. Begin
247
- by creating a tap directory structure and a task:
248
-
249
- % tap generate root sample
250
- % cd sample
251
- % tap generate task goodnight
252
-
253
- Take a look at the task files and you find something like this:
254
-
255
- [lib/goodnight.rb]
256
-
257
- # Goodnight::manifest <replace with manifest summary>
258
- # <replace with command line description>
259
-
260
- # Goodnight Documentation
261
- class Goodnight < Tap::Task
262
-
263
- # <config file documentation>
264
- config :message, 'goodnight' # a sample config
265
-
266
- def process(name)
267
- log message, name
268
- "#{message} #{name}"
269
- end
270
- end
271
-
272
- [test/goodnight_test.rb]
273
-
274
- require File.join(File.dirname(__FILE__), 'tap_test_helper.rb')
275
- require 'goodnight'
276
-
277
- class GoodnightTest < Test::Unit::TestCase
278
- acts_as_tap_test
279
-
280
- def test_goodnight
281
- task = Goodnight.new :message => "goodnight"
282
-
283
- # a simple test
284
- assert_equal({:message => 'goodnight'}, task.config)
285
- assert_equal "goodnight moon", task.process("moon")
286
-
287
- # a more complex test
288
- task.enq("moon")
289
- app.run
290
-
291
- assert_equal ["goodnight moon"], app.results(task)
292
- assert_audit_equal [[nil, "moon"], [task, "goodnight moon"]], app._results(task)[0]
293
- end
294
- end
295
-
296
- Run the test:
297
-
298
- % rap test
299
-
300
- Run the task:
301
-
302
- % rap goodnight moon
303
- I[23:22:19] goodnight moon
304
-
305
- Ok, lets share it. Print the current gemspec manifest:
306
-
307
- % rap print_manifest
308
- true README
309
- Rakefile
310
- lib/goodnight.rb
311
- sample.gemspec
312
- true tap.yml
313
- test/goodnight_test.rb
314
- true test/tap_test_helper.rb
315
- true test/tap_test_suite.rb
316
-
317
- As you can see, this needs an update to include the task file. Open up
318
- sample.gemspec and fix the manifest.
319
-
320
- [sample.gemspec]
321
-
322
- Gem::Specification.new do |s|
323
- s.name = "sample"
324
- s.version = "0.0.1"
325
- s.platform = Gem::Platform::RUBY
326
- s.summary = "sample"
327
- s.require_path = "lib"
328
- s.add_dependency("tap")
329
- s.files = %W{
330
- lib/goodnight.rb
331
- tap.yml
332
- }
333
- end
334
-
335
- Now package the gem and install it (gem may require sudo):
336
-
337
- % rap gem
338
- % gem install pkg/sample-0.0.1.gem
339
-
340
- Now you can say goodnight anywhere, using 'tap run' or rap:
341
-
342
- % cd ~/Desktop
343
- % tap run -- goodnight moon
344
- goodnight moon
345
- % rap goodnight opus
346
- goodnight opus
347
-
348
- And that is that.
data/lib/tap/dump.rb DELETED
@@ -1,142 +0,0 @@
1
- module Tap
2
-
3
- # :startdoc::manifest the default dump task
4
- #
5
- # A dump task to output results. Unlike most tasks, dump does not enque
6
- # arguments from the command line; instead command line arguments are only
7
- # used to setup the dump. Specifically dump accepts a filepath.
8
- #
9
- # % tap run -- [task] --: dump FILEPATH
10
- #
11
- # Results that come to dump are appended to the file. Dump only accepts
12
- # one object at a time, so joins that produce an array need to iterate
13
- # outputs to dump:
14
- #
15
- # % tap run -- load hello -- load world "--2(0,1)i" dump
16
- #
17
- # Note that dump uses $stdout by default so you can pipe or redirect dumps
18
- # as normal.
19
- #
20
- # % tap run -- load hello --: dump | cat
21
- # hello
22
- #
23
- # % tap run -- load hello --: dump 1> results.txt
24
- # % cat results.txt
25
- # hello
26
- #
27
- # :startdoc::manifest-
28
- #
29
- # Dump serves as a baseclass for more complicated dump tasks. A YAML dump
30
- # task (see {tap-tasks}[http://tap.rubyforge.org/tap-tasks]) looks like this:
31
- #
32
- # class Yaml < Tap::Dump
33
- # def dump(obj, io)
34
- # YAML.dump(obj, io)
35
- # end
36
- # end
37
- #
38
- # === Implementation Notes
39
- #
40
- # Dump passes on the command line arguments to setup rather than process.
41
- # Moreover, process will always receive the audits passed to _execute, rather
42
- # than the audit values. This allows a user to provide setup arguments (such
43
- # as a dump path) on the command line, and provides dump the opportunity to
44
- # inspect audit trails within process.
45
- #
46
- class Dump < Tap::Task
47
- class << self
48
-
49
- # Same as an ordinary parse!, except the arguments normally reserved for
50
- # executing the task are used to call setup. The return will always be
51
- # an instance and an empty array.
52
- def parse!(argv=ARGV, app=Tap::App.instance)
53
- instance, args = super
54
- instance.setup(*args)
55
- [instance, []]
56
- end
57
- end
58
-
59
- lazy_attr :args, :setup
60
- lazy_register :setup, Lazydoc::Arguments
61
-
62
- config :date_format, '%Y-%m-%d %H:%M:%S' # The date format
63
- config :audit, false, &c.switch # Include the audit trails
64
- config :date, false, &c.switch # Include a date
65
-
66
- # The dump target, by default $stdout. Target may be a filepath,
67
- # in which case dumps append the file.
68
- attr_accessor :target
69
-
70
- def initialize(config={}, name=nil, app=App.instance)
71
- super(config, name, app)
72
- @target = $stdout
73
- end
74
-
75
- # Setup self with the input target. Setup receives arguments passed from
76
- # the command line, via parse!
77
- def setup(output=$stdout)
78
- @target = output
79
- self
80
- end
81
-
82
- # Overrides the standard _execute to send process the audits and not
83
- # the audit values. This allows process to inspect audit trails.
84
- def _execute(input)
85
- resolve_dependencies
86
-
87
- previous = input.kind_of?(Support::Audit) ? input : Support::Audit.new(nil, input)
88
- input = previous.value
89
-
90
- # this is the overridden part
91
- audit = Support::Audit.new(self, input, app.audit ? previous : nil)
92
- send(method_name, audit)
93
-
94
- if complete_block = on_complete_block || app.on_complete_block
95
- complete_block.call(audit)
96
- else
97
- app.aggregator.store(audit)
98
- end
99
-
100
- audit
101
- end
102
-
103
- # The default process prints dump headers as specified in the config,
104
- # then append the audit value to io.
105
- def process(_audit)
106
- open_io(target) do |io|
107
- if date
108
- io.puts "# date: #{Time.now.strftime(date_format)}"
109
- end
110
-
111
- if audit
112
- io.puts "# audit:"
113
- io.puts "# #{_audit.dump.gsub("\n", "\n# ")}"
114
- end
115
-
116
- dump(_audit.value, io)
117
- end
118
- end
119
-
120
- # Dumps the object to io, by default dump puts (not prints) obj.to_s.
121
- def dump(obj, io)
122
- io.puts obj.to_s
123
- end
124
-
125
- protected
126
-
127
- # helper to open and yield the io specified by target. open_io
128
- # ensures file targets are closed when the block returns.
129
- def open_io(io) # :nodoc:
130
- case io
131
- when IO, StringIO
132
- yield(io)
133
- when String
134
- dir = File.dirname(io)
135
- FileUtils.mkdir_p(dir) unless File.directory?(dir)
136
- File.open(io, 'a') {|file| yield(file) }
137
- else
138
- raise "cannot open io: #{target.inspect}"
139
- end
140
- end
141
- end
142
- end