tap 0.17.1 → 0.18.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.
- data/History +22 -0
- data/README +15 -14
- data/cmd/console.rb +1 -1
- data/cmd/manifest.rb +25 -5
- data/cmd/run.rb +60 -25
- data/doc/API +37 -38
- data/doc/Class Reference +36 -46
- data/doc/Examples/Workflow +1 -1
- data/lib/tap.rb +1 -1
- data/lib/tap/app.rb +15 -80
- data/lib/tap/app/node.rb +0 -14
- data/lib/tap/env.rb +55 -27
- data/lib/tap/env/manifest.rb +2 -2
- data/lib/tap/intern.rb +50 -0
- data/lib/tap/join.rb +12 -9
- data/lib/tap/middleware.rb +56 -0
- data/lib/tap/schema.rb +182 -14
- data/lib/tap/schema/utils.rb +5 -3
- data/lib/tap/task.rb +53 -130
- data/lib/tap/tasks/dump.rb +1 -1
- data/lib/tap/tasks/load.rb +8 -9
- data/lib/tap/templater.rb +203 -0
- data/lib/tap/{constants.rb → version.rb} +2 -2
- metadata +6 -5
- data/lib/tap/support/intern.rb +0 -53
- data/lib/tap/support/templater.rb +0 -207
    
        data/doc/Examples/Workflow
    CHANGED
    
    
    
        data/lib/tap.rb
    CHANGED
    
    
    
        data/lib/tap/app.rb
    CHANGED
    
    | @@ -4,7 +4,6 @@ require 'tap/app/node' | |
| 4 4 | 
             
            require 'tap/app/state'
         | 
| 5 5 | 
             
            require 'tap/app/stack'
         | 
| 6 6 | 
             
            require 'tap/app/queue'
         | 
| 7 | 
            -
            require 'tap/schema'
         | 
| 8 7 |  | 
| 9 8 | 
             
            module Tap
         | 
| 10 9 |  | 
| @@ -94,26 +93,6 @@ module Tap | |
| 94 93 | 
             
              # 
         | 
| 95 94 | 
             
              # Middleware can be nested with multiple calls to use.
         | 
| 96 95 | 
             
              #
         | 
| 97 | 
            -
              # === Dependencies
         | 
| 98 | 
            -
              #
         | 
| 99 | 
            -
              # Nodes allow the construction of dependency-based workflows.  A node only
         | 
| 100 | 
            -
              # executes after its dependencies have been resolved (ie executed).
         | 
| 101 | 
            -
              #
         | 
| 102 | 
            -
              #   runlist = []
         | 
| 103 | 
            -
              #   n0 = app.node { runlist << 0 }
         | 
| 104 | 
            -
              #   n1 = app.node { runlist << 1 }
         | 
| 105 | 
            -
              #
         | 
| 106 | 
            -
              #   n0.depends_on(n1)
         | 
| 107 | 
            -
              #   app.enq(n0)
         | 
| 108 | 
            -
              #
         | 
| 109 | 
            -
              #   app.run
         | 
| 110 | 
            -
              #   runlist                        # => [1, 0]
         | 
| 111 | 
            -
              #
         | 
| 112 | 
            -
              # Dependencies are resolved <em>every time</em> a node executes; individual
         | 
| 113 | 
            -
              # dependencies can implement single-execution if desired.  Dependencies are
         | 
| 114 | 
            -
              # not resolved with arguments, ie dependency nodes must be able to execute
         | 
| 115 | 
            -
              # without inputs.
         | 
| 116 | 
            -
              #
         | 
| 117 96 | 
             
              class App
         | 
| 118 97 | 
             
                class << self
         | 
| 119 98 | 
             
                  # Sets the current app instance
         | 
| @@ -148,8 +127,7 @@ module Tap | |
| 148 127 | 
             
                # The application queue
         | 
| 149 128 | 
             
                attr_reader :queue
         | 
| 150 129 |  | 
| 151 | 
            -
                # A cache of application-specific data. | 
| 152 | 
            -
                # instances of tasks.  Not recommended for casual use.
         | 
| 130 | 
            +
                # A cache of application-specific data.
         | 
| 153 131 | 
             
                attr_reader :cache
         | 
| 154 132 |  | 
| 155 133 | 
             
                # The default joins for nodes that have no joins set
         | 
| @@ -171,7 +149,6 @@ module Tap | |
| 171 149 | 
             
                  @stack = options[:stack] || Stack.new(self)
         | 
| 172 150 | 
             
                  @queue = options[:queue] || Queue.new
         | 
| 173 151 | 
             
                  @cache = options[:cache] || {}
         | 
| 174 | 
            -
                  @trace = []
         | 
| 175 152 | 
             
                  @default_joins = []
         | 
| 176 153 | 
             
                  on_complete(&block)
         | 
| 177 154 |  | 
| @@ -220,27 +197,24 @@ module Tap | |
| 220 197 |  | 
| 221 198 | 
             
                # Adds the specified middleware to the stack.
         | 
| 222 199 | 
             
                def use(middleware, *argv)
         | 
| 223 | 
            -
                   | 
| 200 | 
            +
                  synchronize do
         | 
| 201 | 
            +
                    @stack = middleware.new(@stack, *argv)
         | 
| 202 | 
            +
                  end
         | 
| 224 203 | 
             
                end
         | 
| 225 204 |  | 
| 226 | 
            -
                 | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
                  end
         | 
| 205 | 
            +
                # Returns an array of middlware in use by self.
         | 
| 206 | 
            +
                def middleware
         | 
| 207 | 
            +
                  middleware = []
         | 
| 230 208 |  | 
| 231 | 
            -
                   | 
| 232 | 
            -
                     | 
| 233 | 
            -
             | 
| 209 | 
            +
                  synchronize do
         | 
| 210 | 
            +
                    current = stack
         | 
| 211 | 
            +
                    until current.kind_of?(Stack)
         | 
| 212 | 
            +
                      middleware << current
         | 
| 213 | 
            +
                      current = current.stack
         | 
| 234 214 | 
             
                    end
         | 
| 235 215 | 
             
                  end
         | 
| 236 216 |  | 
| 237 | 
            -
                   | 
| 238 | 
            -
                  
         | 
| 239 | 
            -
                  if options[:clean]
         | 
| 240 | 
            -
                    reset
         | 
| 241 | 
            -
                  end
         | 
| 242 | 
            -
                  
         | 
| 243 | 
            -
                  schema.build!(self)
         | 
| 217 | 
            +
                  middleware
         | 
| 244 218 | 
             
                end
         | 
| 245 219 |  | 
| 246 220 | 
             
                # Clears the cache, the queue, and resets the stack so that no middleware
         | 
| @@ -257,36 +231,6 @@ module Tap | |
| 257 231 | 
             
                  end
         | 
| 258 232 | 
             
                end
         | 
| 259 233 |  | 
| 260 | 
            -
                # Dispatches each dependency of node.  A block can be given to do something
         | 
| 261 | 
            -
                # else with the nodes (ex: reset single-execution dependencies).  Resolve
         | 
| 262 | 
            -
                # will recursively yield dependencies if specified.
         | 
| 263 | 
            -
                #
         | 
| 264 | 
            -
                # Resolve raises an error for circular dependencies.
         | 
| 265 | 
            -
                def resolve(node, recursive=false, &block)
         | 
| 266 | 
            -
                  node.dependencies.each do |dependency|
         | 
| 267 | 
            -
                    if @trace.include?(dependency)
         | 
| 268 | 
            -
                      @trace.push dependency
         | 
| 269 | 
            -
                      raise DependencyError.new(@trace)
         | 
| 270 | 
            -
                    end
         | 
| 271 | 
            -
             | 
| 272 | 
            -
                    # mark the results at the index to prevent
         | 
| 273 | 
            -
                    # infinite loops with circular dependencies
         | 
| 274 | 
            -
                    @trace.push dependency
         | 
| 275 | 
            -
                    
         | 
| 276 | 
            -
                    if recursive
         | 
| 277 | 
            -
                      resolve(dependency, recursive, &block)
         | 
| 278 | 
            -
                    end
         | 
| 279 | 
            -
                    
         | 
| 280 | 
            -
                    if block_given?
         | 
| 281 | 
            -
                      yield(dependency)
         | 
| 282 | 
            -
                    else
         | 
| 283 | 
            -
                      dispatch(dependency)
         | 
| 284 | 
            -
                    end
         | 
| 285 | 
            -
                    
         | 
| 286 | 
            -
                    @trace.pop
         | 
| 287 | 
            -
                  end
         | 
| 288 | 
            -
                end
         | 
| 289 | 
            -
                
         | 
| 290 234 | 
             
                # Dispatches node to the application stack with the inputs.
         | 
| 291 235 | 
             
                def execute(node, *inputs)
         | 
| 292 236 | 
             
                  dispatch(node, inputs)
         | 
| @@ -295,13 +239,11 @@ module Tap | |
| 295 239 | 
             
                # Dispatch sends the node into the application stack with the inputs.
         | 
| 296 240 | 
             
                # Dispatch does the following in order:
         | 
| 297 241 | 
             
                #
         | 
| 298 | 
            -
                # - resolve node dependencies using resolve_dependencies
         | 
| 299 242 | 
             
                # - call stack with the node and inputs
         | 
| 300 243 | 
             
                # - call the node joins, if set, or the default_joins with the results
         | 
| 301 244 | 
             
                #
         | 
| 302 245 | 
             
                # Dispatch returns the node result.
         | 
| 303 246 | 
             
                def dispatch(node, inputs=[])
         | 
| 304 | 
            -
                  resolve(node)
         | 
| 305 247 | 
             
                  result = stack.call(node, inputs)
         | 
| 306 248 |  | 
| 307 249 | 
             
                  joins = node.joins.empty? ? default_joins : node.joins
         | 
| @@ -430,8 +372,8 @@ module Tap | |
| 430 372 | 
             
                  target
         | 
| 431 373 | 
             
                end
         | 
| 432 374 |  | 
| 433 | 
            -
                # Sets the block to receive the  | 
| 434 | 
            -
                # (ie the block is set as default_join).
         | 
| 375 | 
            +
                # Sets the block to receive the result of nodes with no joins
         | 
| 376 | 
            +
                # (ie the block is set as a default_join).
         | 
| 435 377 | 
             
                def on_complete(&block) # :yields: _result
         | 
| 436 378 | 
             
                  self.default_joins << block if block
         | 
| 437 379 | 
             
                  self
         | 
| @@ -443,12 +385,5 @@ module Tap | |
| 443 385 | 
             
                # called on an running App.  They are handled by the run rescue code.
         | 
| 444 386 | 
             
                class TerminateError < RuntimeError
         | 
| 445 387 | 
             
                end
         | 
| 446 | 
            -
                
         | 
| 447 | 
            -
                # Raised when Tap::App#resolve detects a circular dependency.
         | 
| 448 | 
            -
                class DependencyError < StandardError
         | 
| 449 | 
            -
                  def initialize(trace)
         | 
| 450 | 
            -
                    super "circular dependency: [#{trace.join(', ')}]"
         | 
| 451 | 
            -
                  end
         | 
| 452 | 
            -
                end
         | 
| 453 388 | 
             
              end
         | 
| 454 389 | 
             
            end
         | 
    
        data/lib/tap/app/node.rb
    CHANGED
    
    | @@ -9,9 +9,6 @@ module Tap | |
| 9 9 | 
             
                  # The joins called when call completes
         | 
| 10 10 | 
             
                  attr_accessor :joins
         | 
| 11 11 |  | 
| 12 | 
            -
                  # An array of node dependencies
         | 
| 13 | 
            -
                  attr_reader :dependencies
         | 
| 14 | 
            -
                  
         | 
| 15 12 | 
             
                  # Interns a new node by extending the block with Node. 
         | 
| 16 13 | 
             
                  def self.intern(&block)
         | 
| 17 14 | 
             
                    block.extend self
         | 
| @@ -20,7 +17,6 @@ module Tap | |
| 20 17 | 
             
                  # Sets up required variables for extended objects.
         | 
| 21 18 | 
             
                  def self.extended(obj) # :nodoc:
         | 
| 22 19 | 
             
                    obj.instance_variable_set(:@joins, [])
         | 
| 23 | 
            -
                    obj.instance_variable_set(:@dependencies, [])
         | 
| 24 20 | 
             
                  end
         | 
| 25 21 |  | 
| 26 22 | 
             
                  # Sets the block as a join for self.
         | 
| @@ -28,16 +24,6 @@ module Tap | |
| 28 24 | 
             
                    self.joins << block if block
         | 
| 29 25 | 
             
                    self
         | 
| 30 26 | 
             
                  end
         | 
| 31 | 
            -
                  
         | 
| 32 | 
            -
                  # Adds the dependency to self.  Dependencies are resolved by an app
         | 
| 33 | 
            -
                  # during App#dispatch and must be valid nodes.
         | 
| 34 | 
            -
                  def depends_on(dependency)
         | 
| 35 | 
            -
                    raise "cannot depend on self" if dependency == self
         | 
| 36 | 
            -
                    unless dependencies.include?(dependency)
         | 
| 37 | 
            -
                      dependencies << dependency
         | 
| 38 | 
            -
                    end
         | 
| 39 | 
            -
                    self
         | 
| 40 | 
            -
                  end
         | 
| 41 27 | 
             
                end
         | 
| 42 28 | 
             
              end
         | 
| 43 29 | 
             
            end
         | 
    
        data/lib/tap/env.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'tap/root'
         | 
| 2 2 | 
             
            require 'tap/env/manifest'
         | 
| 3 | 
            -
            require 'tap/ | 
| 3 | 
            +
            require 'tap/templater'
         | 
| 4 4 | 
             
            autoload(:YAML, 'yaml')
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Tap
         | 
| @@ -65,7 +65,7 @@ module Tap | |
| 65 65 | 
             
                    end
         | 
| 66 66 | 
             
                  end
         | 
| 67 67 |  | 
| 68 | 
            -
                  def  | 
| 68 | 
            +
                  def scan_dir(load_path, pattern='**/*.rb')
         | 
| 69 69 | 
             
                    Dir.chdir(load_path) do 
         | 
| 70 70 | 
             
                      Dir.glob(pattern).each do |require_path|
         | 
| 71 71 | 
             
                        next unless File.file?(require_path)
         | 
| @@ -73,15 +73,9 @@ module Tap | |
| 73 73 | 
             
                        default_const_name = require_path.chomp('.rb').camelize
         | 
| 74 74 |  | 
| 75 75 | 
             
                        # note: the default const name has to be set here to allow for implicit
         | 
| 76 | 
            -
                        # constant attributes  | 
| 77 | 
            -
                        #  | 
| 78 | 
            -
                         | 
| 79 | 
            -
                        document = Lazydoc[require_path]
         | 
| 80 | 
            -
                        case document.default_const_name
         | 
| 81 | 
            -
                        when nil then document.default_const_name = default_const_name
         | 
| 82 | 
            -
                        when default_const_name
         | 
| 83 | 
            -
                        else raise "found a conflicting default const name"
         | 
| 84 | 
            -
                        end
         | 
| 76 | 
            +
                        # constant attributes. An error can arise if the same path is globed
         | 
| 77 | 
            +
                        # from two different dirs... no surefire solution.
         | 
| 78 | 
            +
                        Lazydoc[require_path].default_const_name = default_const_name
         | 
| 85 79 |  | 
| 86 80 | 
             
                        # scan for constants
         | 
| 87 81 | 
             
                        Lazydoc::Document.scan(File.read(require_path)) do |const_name, type, comment|
         | 
| @@ -100,6 +94,27 @@ module Tap | |
| 100 94 | 
             
                      end
         | 
| 101 95 | 
             
                    end
         | 
| 102 96 | 
             
                  end
         | 
| 97 | 
            +
                  
         | 
| 98 | 
            +
                  def scan(path, key='[a-z_]+')
         | 
| 99 | 
            +
                    Lazydoc::Document.scan(File.read(path), key) do |const_name, type, comment|
         | 
| 100 | 
            +
                      if const_name.empty?
         | 
| 101 | 
            +
                        unless const_name = Lazydoc[path].default_const_name
         | 
| 102 | 
            +
                          raise "could not determine a constant name for #{type} in: #{path.inspect}"
         | 
| 103 | 
            +
                        end
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                      
         | 
| 106 | 
            +
                      constant = Constant.new(const_name, path, comment)
         | 
| 107 | 
            +
                      yield(type, constant)
         | 
| 108 | 
            +
                      
         | 
| 109 | 
            +
                      ###############################################################
         | 
| 110 | 
            +
                      # [depreciated] manifest as a task key will be removed at 1.0
         | 
| 111 | 
            +
                      if type == 'manifest'
         | 
| 112 | 
            +
                        warn "depreciation: ::task should be used instead of ::manifest as a resource key (#{require_path})"
         | 
| 113 | 
            +
                        yield('task', constant)
         | 
| 114 | 
            +
                      end
         | 
| 115 | 
            +
                      ###############################################################
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                  end
         | 
| 103 118 | 
             
                end
         | 
| 104 119 | 
             
                self.instance = nil
         | 
| 105 120 |  | 
| @@ -441,9 +456,8 @@ module Tap | |
| 441 456 | 
             
                    load_paths.each do |load_path|
         | 
| 442 457 | 
             
                      next unless File.directory?(load_path)
         | 
| 443 458 |  | 
| 444 | 
            -
                      Env. | 
| 445 | 
            -
                         | 
| 446 | 
            -
                        entries << constant
         | 
| 459 | 
            +
                      Env.scan_dir(load_path) do |type, constant|
         | 
| 460 | 
            +
                        (registry[type.to_sym] ||= []) << constant
         | 
| 447 461 | 
             
                      end
         | 
| 448 462 | 
             
                    end
         | 
| 449 463 |  | 
| @@ -468,6 +482,15 @@ module Tap | |
| 468 482 | 
             
                  builders[type] = block
         | 
| 469 483 | 
             
                end
         | 
| 470 484 |  | 
| 485 | 
            +
                #--
         | 
| 486 | 
            +
                # Potential bug, constants can be added twice.
         | 
| 487 | 
            +
                def scan(path, key='[a-z_]+')
         | 
| 488 | 
            +
                  registry = self.registry
         | 
| 489 | 
            +
                  Env.scan(path, key) do |type, constant|
         | 
| 490 | 
            +
                    (registry[type.to_sym] ||= []) << constant
         | 
| 491 | 
            +
                  end
         | 
| 492 | 
            +
                end
         | 
| 493 | 
            +
                
         | 
| 471 494 | 
             
                def manifest(type) # :yields: env
         | 
| 472 495 | 
             
                  type = type.to_sym
         | 
| 473 496 |  | 
| @@ -488,9 +511,11 @@ module Tap | |
| 488 511 | 
             
                  registries.clear
         | 
| 489 512 | 
             
                end
         | 
| 490 513 |  | 
| 491 | 
            -
                 | 
| 492 | 
            -
                #  | 
| 493 | 
            -
                 | 
| 514 | 
            +
                # Searches across each for the first registered object minimatching key. A
         | 
| 515 | 
            +
                # single env can be specified by using a compound key like 'env_key:key'.
         | 
| 516 | 
            +
                #
         | 
| 517 | 
            +
                # Returns nil if no matching object is found.
         | 
| 518 | 
            +
                def seek(type, key, value_only=true)
         | 
| 494 519 | 
             
                  key =~ COMPOUND_KEY
         | 
| 495 520 | 
             
                  envs = if $2
         | 
| 496 521 | 
             
                    # compound key, match for env
         | 
| @@ -504,21 +529,24 @@ module Tap | |
| 504 529 | 
             
                  # traverse envs looking for the first
         | 
| 505 530 | 
             
                  # manifest entry matching key
         | 
| 506 531 | 
             
                  envs.each do |env|
         | 
| 507 | 
            -
                    if  | 
| 508 | 
            -
                      return [env,  | 
| 532 | 
            +
                    if value = env.manifest(type).minimatch(key)
         | 
| 533 | 
            +
                      return value_only ? value : [env, value]
         | 
| 509 534 | 
             
                    end
         | 
| 510 535 | 
             
                  end
         | 
| 511 536 |  | 
| 512 537 | 
             
                  nil
         | 
| 513 538 | 
             
                end
         | 
| 514 539 |  | 
| 515 | 
            -
                 | 
| 516 | 
            -
             | 
| 517 | 
            -
             | 
| 518 | 
            -
             | 
| 519 | 
            -
             | 
| 520 | 
            -
             | 
| 521 | 
            -
             | 
| 540 | 
            +
                def reverse_seek(type, key_only=true, &block)
         | 
| 541 | 
            +
                  each do |env|
         | 
| 542 | 
            +
                    manifest = env.manifest(type)
         | 
| 543 | 
            +
                    if value = manifest.find(&block)
         | 
| 544 | 
            +
                      key = manifest.minihash(true)[value]
         | 
| 545 | 
            +
                      return key_only ? key : "#{minihash(true)[env]}:#{key}"
         | 
| 546 | 
            +
                    end
         | 
| 547 | 
            +
                  end
         | 
| 548 | 
            +
                
         | 
| 549 | 
            +
                  nil
         | 
| 522 550 | 
             
                end
         | 
| 523 551 |  | 
| 524 552 | 
             
                # All templaters are yielded to the block before any are built.  This
         | 
| @@ -530,7 +558,7 @@ module Tap | |
| 530 558 |  | 
| 531 559 | 
             
                  env_keys = minihash(true)
         | 
| 532 560 | 
             
                  collect do |env|
         | 
| 533 | 
            -
                    templater =  | 
| 561 | 
            +
                    templater = Templater.new(template, :env => env, :env_key => env_keys[env])
         | 
| 534 562 | 
             
                    yield(templater, globals) if block_given? 
         | 
| 535 563 | 
             
                    templater
         | 
| 536 564 | 
             
                  end.collect! do |templater|
         | 
    
        data/lib/tap/env/manifest.rb
    CHANGED
    
    | @@ -43,8 +43,8 @@ module Tap | |
| 43 43 | 
             
                  # env can be specified by using a compound key like 'env_key:key'.
         | 
| 44 44 | 
             
                  #
         | 
| 45 45 | 
             
                  # Returns nil if no matching entry is found.
         | 
| 46 | 
            -
                  def seek(key)
         | 
| 47 | 
            -
                    env.seek(type, key)
         | 
| 46 | 
            +
                  def seek(key, value_only=true)
         | 
| 47 | 
            +
                    env.seek(type, key, value_only)
         | 
| 48 48 | 
             
                  end
         | 
| 49 49 |  | 
| 50 50 | 
             
                  def [](key)
         | 
    
        data/lib/tap/intern.rb
    ADDED
    
    | @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Tap
         | 
| 2 | 
            +
              # Generates an Intern module to override the specified method_name.  Intern
         | 
| 3 | 
            +
              # modules are useful to override a tiny bit of functionality without having
         | 
| 4 | 
            +
              # to generate a full subclass.
         | 
| 5 | 
            +
              #
         | 
| 6 | 
            +
              # An Intern module:
         | 
| 7 | 
            +
              #
         | 
| 8 | 
            +
              # - adds an accessor for <method_name>_block
         | 
| 9 | 
            +
              # - overrides <method_name> to call the block, prepending self to
         | 
| 10 | 
            +
              #   the input arguments
         | 
| 11 | 
            +
              #
         | 
| 12 | 
            +
              # For example:
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              #   array = [1,2,3].extend Intern(:last)
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              #   array.last             # => 3
         | 
| 17 | 
            +
              #   array.last_block = lambda {|arr| arr.first }
         | 
| 18 | 
            +
              #   array.last             # => 3
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              def self.Intern(method_name)
         | 
| 21 | 
            +
                mod = INTERN_MODULES[method_name.to_sym]
         | 
| 22 | 
            +
                return mod unless mod == nil
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                mod = INTERN_MODULES[method_name.to_sym] = Module.new
         | 
| 25 | 
            +
                mod.module_eval %Q{
         | 
| 26 | 
            +
                attr_accessor :#{method_name}_block
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def #{method_name}(*inputs)
         | 
| 29 | 
            +
                  return super unless #{method_name}_block
         | 
| 30 | 
            +
                  inputs.unshift(self)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  arity = #{method_name}_block.arity
         | 
| 33 | 
            +
                  n = inputs.length
         | 
| 34 | 
            +
                  unless n == arity || (arity < 0 && (-1-n) <= arity) 
         | 
| 35 | 
            +
                    raise ArgumentError.new("wrong number of arguments (\#{n} for \#{arity})")
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  #{method_name}_block.call(*inputs)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                }
         | 
| 41 | 
            +
                mod
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
              
         | 
| 44 | 
            +
              # An array of already-declared intern modules,
         | 
| 45 | 
            +
              # keyed by method_name.
         | 
| 46 | 
            +
              INTERN_MODULES = {}
         | 
| 47 | 
            +
              
         | 
| 48 | 
            +
              # An Intern module for :process.
         | 
| 49 | 
            +
              Intern = Tap::Intern(:process)
         | 
| 50 | 
            +
            end
         | 
    
        data/lib/tap/join.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require 'tap/app'
         | 
| 2 | 
            -
            require 'tap/ | 
| 2 | 
            +
            require 'tap/intern'
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Tap
         | 
| 5 5 | 
             
              class App
         | 
| @@ -9,7 +9,7 @@ module Tap | |
| 9 9 | 
             
                end
         | 
| 10 10 | 
             
              end
         | 
| 11 11 |  | 
| 12 | 
            -
              # :startdoc::join  | 
| 12 | 
            +
              # :startdoc::join an unsyncrhonized, multi-way join
         | 
| 13 13 | 
             
              #
         | 
| 14 14 | 
             
              # Join defines an unsynchronized, multi-way join where n inputs send their
         | 
| 15 15 | 
             
              # results to m outputs.  Flags can augment how the results are passed, in
         | 
| @@ -25,10 +25,7 @@ module Tap | |
| 25 25 | 
             
                    super
         | 
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 | 
            -
                  # Parses the argv into an  | 
| 29 | 
            -
                  # inputs and outputs implicitly define the inputs and output for the
         | 
| 30 | 
            -
                  # instance.  By default parse parses an argh then calls instantiate,
         | 
| 31 | 
            -
                  # but there is no requirement that this occurs in subclasses.
         | 
| 28 | 
            +
                  # Parses the argv into an instance of self.
         | 
| 32 29 | 
             
                  def parse(argv=ARGV, app=Tap::App.instance)
         | 
| 33 30 | 
             
                    parse!(argv.dup, app)
         | 
| 34 31 | 
             
                  end
         | 
| @@ -47,8 +44,7 @@ module Tap | |
| 47 44 | 
             
                    }, app)
         | 
| 48 45 | 
             
                  end
         | 
| 49 46 |  | 
| 50 | 
            -
                  # Instantiates an instance of self | 
| 51 | 
            -
                  # outputs, instance].
         | 
| 47 | 
            +
                  # Instantiates an instance of self.
         | 
| 52 48 | 
             
                  def instantiate(argh, app=Tap::App.instance)
         | 
| 53 49 | 
             
                    new(argh[:config] || {}, app)
         | 
| 54 50 | 
             
                  end
         | 
| @@ -61,7 +57,7 @@ module Tap | |
| 61 57 | 
             
                  def intern(config={}, app=Tap::App.instance, &block) # :yields: join, result
         | 
| 62 58 | 
             
                    instance = new(config, app)
         | 
| 63 59 | 
             
                    if block_given?
         | 
| 64 | 
            -
                      instance.extend  | 
| 60 | 
            +
                      instance.extend Intern(:call)
         | 
| 65 61 | 
             
                      instance.call_block = block
         | 
| 66 62 | 
             
                    end
         | 
| 67 63 | 
             
                    instance
         | 
| @@ -151,6 +147,13 @@ module Tap | |
| 151 147 | 
             
                  end
         | 
| 152 148 | 
             
                end
         | 
| 153 149 |  | 
| 150 | 
            +
                def to_hash
         | 
| 151 | 
            +
                  {
         | 
| 152 | 
            +
                    :class => self.class,
         | 
| 153 | 
            +
                    :config => config.to_hash
         | 
| 154 | 
            +
                  }
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
                
         | 
| 154 157 | 
             
                protected
         | 
| 155 158 |  | 
| 156 159 | 
             
                # Dispatches the results to the node.
         |