replacing rake
Simon Chiang
Biomolecular Structure
Data Analysis
[Rakefile]
desc “a simple goodnight task”
task :goodnight, :obj do |task, args|
puts “#{ENV[‘msg’] || ‘goodnight’} #{args.obj}”
end
% rake -T
% rake goodnight[moon]
% rake goodnight[world] msg=hello
Dependencies
x1 y
x2 y1 z
The nature of Rake
x1 y b c1
x2 y1 z a ? b1 c2
Rake, Rap, Tap
Rake Task
[Rakefile, rakefile, rakefile.rb]
desc “a simple goodnight task”
task :goodnight, :obj do |task, args|
puts “#{ENV[‘msg’] || ‘goodnight’} #{args.obj}”
end
% rake -T
% rake goodnight[moon]
% rake goodnight[world] msg=hello
Rap Task
[Rapfile, rapfile, rapfile.rb]
# ::desc a simple goodnight task
# Extended documentation for the goodnight task...
task :goodnight, :obj, :msg => ‘goodnight’ do |task,args|
puts “#{task.msg} #{args.obj}”
end
% rap -T
% rap goodnight moon
% rap goodnight world --msg hello
% rap goodnight --help
Command Line
Quite Compatible
require ‘tap’
include Tap::Declartions
namespace :name do
desc ‘one line description’
task({:name => [:deps]}, :inputs, {:key => ‘value’}) do
sh “...”
end
end
% rap say_hello
% rap say_goodbye
% rap -T
Rap is like a
supercharged Rake
Class vs Instance
• Rake makes instances
t = task :name
t.class # => Rake::Task
def process(obj)
puts “#{msg} #{obj}”
end
end
Anatomy of a Task
Class
Executable
Configurable
(Lazydoc)
Executable
• Wraps a method
• Adds workflowability c
b c1
a ? b1 c2
Process
% rap goodnight
% rap goodnight moon lamp “little toy boat”
% rap goodnight --help
Command Line
Configurable
class Goodnight < Tap::Task
config :key, ‘value’ do |input|
input.downcase
end
end
t = Goodnight.new
t.key # => ‘value’
t.key = ‘New Value’
t.config[:key] # => ‘new value’
Standard Blocks
class Goodnight < Tap::Task
config :message, ‘goodnight’
config :reverse, false, &c.switch
config :repeat, 1, &c.integer
def process
str = “#{message} moon”
str = str.reverse if reverse == true
repeat.times { puts str }
end
end
class SomeClass
extend Tap::Support::LazyAttributes
lazy_attr :key
end
SomeClass.source_file = __FILE__
SomeClass.key.value # => “this is the value”
SomeClass.key.to_s # => “Extended value...”
Lazydoc
[lib/goodnight.rb]
# ::manifest a fancy goodnight task
# Says goodnight to lots of objects.
class Goodnight < Tap::Task
config :message, ‘goodnight’ # a goodnight message
config :reverse, false, &c.switch # reverses output
config :repeat, 1, &c.integer # repeats output
end
Goodnight.manifest.value
# => “a fancy goodnight task”
Goodnight.manifest.to_s
# => “Says goodnight to lots of objects.”
Command Line
Off the command line
class Goodnight < Tap::Task
config :msg, ‘goodnight’
def process(obj)
“#{msg} #{obj}”
end
end
g = Goodnight.new
g.process(‘moon’) # => ‘goodnight moon’
g.msg = ‘hello’
g.process(‘world’) # => ‘hello world’
Testing
def process(obj)
super(reverse ? obj.reverse : obj)
end
end
result = g1.process(‘moon’)
g2.process(result) # => ‘yo yo moon’
Workflows
Executable
g._execute(‘moon’)
current # => ‘goodnight moon’
Executable
g = Goodnight.new
g.depends_on(dep)
g._execute
Aggregator
ExecutableQueue
Tap::App
Example
• Simple Trace task, adds name to str
class Trace < Tap::Task
def process(str)
str + name
end
end
t = Trace.new({}, ‘a’)
t.name # => ‘a’
t.process(‘’) # => ‘a’
t.process(‘xyz’) # => ‘xyza’
Standard Joins
a, b, b1, c, c1, c2 = %w{a b b. c c. c..}.map do |name|
Tracer.new({}, name)
end
a ? b1 c2
Enque and Run
# (could just do this)
# a.execute(‘’)
app = Tap::App.instance c
app.enq(a, ‘’)
app.run
app.results(c2) b c1
# => ["abcab.c..", "abc.c.."]
a ? b1 c2
Audit Trail
puts app._results(c2)[0]._to_s
# o-[] ""
# o-[a] "a" c
# o-[b] "ab"
# o-[c] "abc"
# o-[a] "abca"
# o-[b.] "abcab."
b c1
# o-[c..] "abcab.c.."
a ? b1 c2
Workflow Syntax
---
- [task, a, b, c, --key, value]
- [task, x, y, z, --key, value]
- 0:1
Delimiters
break meaning
-- enque next to round 0
--+ enque next to round 1
--++ enque next to round 2
--+3 enque next to round 3
# Another::manifest
class Another < Tap::Task explicitly named
end
calc
molecules:calc
molecules-0.1.0:calc.rb
RubyGems
require ‘rubygems’
require ‘tap’
def process(*objects)
puts “#{message} #{objects.join(‘,’)}”
end
end
Goodnight.execute(ARGV)
Wrapup
• A supercharged rake
• A framework for configurable,
distributable tasks and workflows
Dr. Kirk Hansen
Lauren Kiemele
Ashley Zurawel
Acknowledgements
Mom, Dad, Brother, Girlfriend
Thanks
tap.rubyforge.org