bahuvrihi-tap 0.10.6 → 0.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/bin/rap +13 -5
  2. data/lib/tap.rb +0 -4
  3. data/lib/tap/app.rb +10 -138
  4. data/lib/tap/constants.rb +1 -1
  5. data/lib/tap/declarations.rb +201 -0
  6. data/lib/tap/env.rb +10 -2
  7. data/lib/tap/exe.rb +2 -2
  8. data/lib/tap/generator/generators/root/templates/Rakefile +1 -0
  9. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
  10. data/lib/tap/spec.rb +38 -63
  11. data/lib/tap/spec/adapter.rb +8 -31
  12. data/lib/tap/spec/inheritable_class_test_root.rb +9 -0
  13. data/lib/tap/support/audit.rb +0 -2
  14. data/lib/tap/support/combinator.rb +83 -31
  15. data/lib/tap/support/configurable_class.rb +7 -7
  16. data/lib/tap/support/{dependable.rb → dependencies.rb} +9 -7
  17. data/lib/tap/support/executable.rb +226 -19
  18. data/lib/tap/support/gems/rake.rb +6 -3
  19. data/lib/tap/support/join.rb +87 -0
  20. data/lib/tap/support/joins.rb +13 -0
  21. data/lib/tap/support/joins/fork.rb +18 -0
  22. data/lib/tap/support/joins/merge.rb +20 -0
  23. data/lib/tap/support/joins/sequence.rb +21 -0
  24. data/lib/tap/support/joins/switch.rb +23 -0
  25. data/lib/tap/support/joins/sync_merge.rb +57 -0
  26. data/lib/tap/support/lazydoc/document.rb +10 -0
  27. data/lib/tap/support/node.rb +58 -0
  28. data/lib/tap/support/parser.rb +379 -0
  29. data/lib/tap/support/schema.rb +350 -0
  30. data/lib/tap/support/tdoc.rb +5 -0
  31. data/lib/tap/support/validation.rb +2 -0
  32. data/lib/tap/task.rb +26 -61
  33. data/lib/tap/test.rb +9 -82
  34. data/lib/tap/test/assertions.rb +38 -0
  35. data/lib/tap/test/extensions.rb +78 -0
  36. data/lib/tap/test/{file_methods.rb → file_test.rb} +64 -37
  37. data/lib/tap/test/{file_methods_class.rb → file_test_class.rb} +2 -2
  38. data/lib/tap/test/regexp_escape.rb +87 -0
  39. data/lib/tap/test/script_test.rb +46 -0
  40. data/lib/tap/test/script_tester.rb +109 -0
  41. data/lib/tap/test/{subset_methods.rb → subset_test.rb} +9 -9
  42. data/lib/tap/test/{subset_methods_class.rb → subset_test_class.rb} +22 -14
  43. data/lib/tap/test/{tap_methods.rb → tap_test.rb} +43 -6
  44. data/lib/tap/test/utils.rb +6 -3
  45. metadata +27 -24
  46. data/lib/tap/parser.rb +0 -619
  47. data/lib/tap/spec/file_methods.rb +0 -16
  48. data/lib/tap/spec/file_methods_class.rb +0 -13
  49. data/lib/tap/spec/subset_methods.rb +0 -14
  50. data/lib/tap/support/batchable.rb +0 -47
  51. data/lib/tap/support/batchable_class.rb +0 -107
  52. data/lib/tap/support/declarations.rb +0 -131
  53. data/lib/tap/support/lazydoc/declaration.rb +0 -20
  54. data/lib/tap/support/parsers/base.rb +0 -81
  55. data/lib/tap/support/parsers/server.rb +0 -113
  56. data/lib/tap/test/script_methods.rb +0 -75
  57. data/lib/tap/test/script_methods/regexp_escape.rb +0 -94
  58. data/lib/tap/test/script_methods/script_test.rb +0 -109
  59. data/lib/tap/workflow.rb +0 -161
data/lib/tap/parser.rb DELETED
@@ -1,619 +0,0 @@
1
- autoload(:Shellwords, 'shellwords')
2
-
3
- module Tap
4
- class Parser
5
- module Utils
6
- module_function
7
-
8
- # Parses the input string as YAML, if the string matches the YAML document
9
- # specifier (ie it begins with "---\s*\n"). Otherwise returns the string.
10
- #
11
- # str = {'key' => 'value'}.to_yaml # => "--- \nkey: value\n"
12
- # Tap::Script.parse_yaml(str) # => {'key' => 'value'}
13
- # Tap::Script.parse_yaml("str") # => "str"
14
- def parse_yaml(str)
15
- str =~ /\A---\s*\n/ ? YAML.load(str) : str
16
- end
17
-
18
- # Shell quotes the input string by enclosing in quotes if
19
- # str has no quotes, or double quotes if str has no double
20
- # quotes. Returns the str if it has not whitespace, quotes
21
- # or double quotes.
22
- #
23
- # Raises an ArgumentError if str has both quotes and double
24
- # quotes.
25
- def shell_quote(str)
26
- return str unless str =~ /[\s'"]/
27
-
28
- quote = str.include?("'")
29
- double_quote = str.include?('"')
30
-
31
- case
32
- when !quote then "'#{str}'"
33
- when !double_quote then "\"#{str}\""
34
- else raise ArgumentError, "cannot shell quote: #{str}"
35
- end
36
- end
37
-
38
- # Defines a break regexp that matches a bracketed-pairs
39
- # break. The left and right brackets are specified as
40
- # inputs. After a match:
41
- #
42
- # $2:: The source string after the break.
43
- # (ex: '--[]' => '', '--1[]' => '1')
44
- # $3:: The target string, or nil.
45
- # (ex: '--[]' => '', '--1[1,2,3]' => '1,2,3')
46
- #
47
- def bracket_regexp(l, r)
48
- /\A(--)?(\d*)#{Regexp.escape(l)}([\d,]*)#{Regexp.escape(r)}\z/
49
- end
50
-
51
- # The escape begin argument
52
- ESCAPE_BEGIN = "-."
53
-
54
- # The escape end argument
55
- ESCAPE_END = ".-"
56
-
57
- # The parser end flag
58
- END_FLAG = "---"
59
-
60
- # Matches any breaking arg (ex: '--', '--+', '--1:2')
61
- BREAK = /\A--(\z|[\+\d\:\*\[\{\(])/
62
-
63
- # Matches the start of any workflow regex (ex: '+', '2', '[', '{')
64
- WORKFLOW = /\A[\+\d\:\*\[\{\(]/
65
-
66
- # Matches an execution-round break. After the match:
67
- #
68
- # $3:: The round string after the break, or nil.
69
- # (ex: '--' => nil, '--++' => '++', '--+1' => '+1')
70
- # $6:: The target string, or nil.
71
- # (ex: '--+' => nil, '--+[1,2,3]' => '1,2,3')
72
- #
73
- ROUND = /\A(--\z|(--)?(\+(\d*|\+*))(\[([\d,]*)\])?\z)/
74
-
75
- # Matches a sequence break. After the match:
76
- #
77
- # $2:: The sequence string after the break.
78
- # (ex: '--:' => ':', '--1:2' => '1:2', '--1:' => '1:', '--:2' => ':2')
79
- #
80
- SEQUENCE = /\A(--)?(\d*(:\d*)+)\z/
81
-
82
- # Matches an instance break. After the match:
83
- #
84
- # $2:: The index string after the break.
85
- # (ex: '--*' => '', '--*1' => '1')
86
- #
87
- INSTANCE = /\A(--)?\*(\d*)\z/
88
-
89
- # A break regexp using "[]"
90
- FORK = bracket_regexp("[", "]")
91
-
92
- # A break regexp using "{}"
93
- MERGE = bracket_regexp("{", "}")
94
-
95
- # A break regexp using "()"
96
- SYNC_MERGE = bracket_regexp("(", ")")
97
-
98
- # Parses an indicies str along commas, and collects the indicies
99
- # as integers. Ex:
100
- #
101
- # parse_indicies('') # => []
102
- # parse_indicies('1') # => [1]
103
- # parse_indicies('1,2,3') # => [1,2,3]
104
- #
105
- def parse_indicies(str, regexp=/,+/)
106
- indicies = []
107
- str.split(regexp).each do |n|
108
- indicies << n.to_i unless n.empty?
109
- end
110
- indicies
111
- end
112
-
113
- # Parses the match of a ROUND regexp into a round index
114
- # and an array of task indicies that should be added to the
115
- # round. The inputs correspond to $3 and $6 for the match.
116
- #
117
- # If $3 is nil, a round index of zero is assumed; if $6 is
118
- # nil, then indicies of [] are assumed.
119
- #
120
- # parse_round("+", "") # => [1, []]
121
- # parse_round("+2", "1,2,3") # => [2, [1,2,3]]
122
- # parse_round(nil, nil) # => [0, []]
123
- #
124
- def parse_round(three, six)
125
- index = case three
126
- when nil then 0
127
- when /\d/ then three[1, three.length-1].to_i
128
- else three.length
129
- end
130
- [index, six == nil ? [] : parse_indicies(six)]
131
- end
132
-
133
- # Parses the match of a SEQUENCE regexp into an array of task
134
- # indicies. The input corresponds to $2 for the match. The
135
- # current and next index are assumed if $2 starts and/or ends
136
- # with a semi-colon.
137
- #
138
- # parse_sequence("1:2:3") # => [1,2,3]
139
- # parse_sequence(":1:2:") # => [:current_index,1,2,:next_index]
140
- #
141
- def parse_sequence(two)
142
- seq = parse_indicies(two, /:+/)
143
- seq.unshift current_index if two[0] == ?:
144
- seq << next_index if two[-1] == ?:
145
- seq
146
- end
147
-
148
- # Parses the match of an INSTANCE regexp into an index.
149
- # The input corresponds to $2 for the match. The next
150
- # index is assumed if $2 is empty.
151
- #
152
- # parse_instance("1") # => 1
153
- # parse_instance("") # => :next_index
154
- #
155
- def parse_instance(two)
156
- two.empty? ? next_index : two.to_i
157
- end
158
-
159
- # Parses the match of an bracket_regexp into a [source_index,
160
- # target_indicies] array. The inputs corresponds to $2 and
161
- # $3 for the match. The current and next index are assumed
162
- # if $2 and/or $3 is empty.
163
- #
164
- # parse_bracket("1", "2,3") # => [1, [2,3]]
165
- # parse_bracket("", "") # => [:current_index, [:next_index]]
166
- # parse_bracket("1", "") # => [1, [:next_index]]
167
- # parse_bracket("", "2,3") # => [:current_index, [2,3]]
168
- #
169
- def parse_bracket(two, three)
170
- targets = parse_indicies(three)
171
- targets << next_index if targets.empty?
172
- [two.empty? ? current_index : two.to_i, targets]
173
- end
174
- end
175
-
176
- class << self
177
- def load(task_argv)
178
- task_argv = YAML.load(task_argv) if task_argv.kind_of?(String)
179
-
180
- tasks, argv = task_argv.partition {|obj| obj.kind_of?(Array) }
181
- parser = new
182
- parser.tasks.concat(tasks)
183
- parser.parse(argv)
184
- parser
185
- end
186
- end
187
-
188
- include Utils
189
-
190
- # An array of task declarations.
191
- attr_reader :tasks
192
-
193
- # An array of integers indicating which tasks
194
- # should be set as globals.
195
- attr_reader :globals
196
-
197
- # The internal rounds data; an array of integers mapping to tasks
198
- # by index. The integers signify the round the corresponding
199
- # task should be assigned to; a nil entry indicates the task
200
- # should not be enqued to a round.
201
- attr_reader :rounds_map
202
-
203
- # The internal workflow data; an array of [type, targets] pairs
204
- # mapping to tasks by index. The entries signify the workflow
205
- # type and targets assigned to the corresponding task.
206
- attr_reader :workflow_map
207
-
208
- def initialize(argv=nil)
209
- @tasks = []
210
- @globals = []
211
- @rounds_map = []
212
- @workflow_map = []
213
-
214
- case argv
215
- when String, Array
216
- parse(argv)
217
- end
218
- end
219
-
220
- # Iterates through the argv splitting out task and workflow definitions.
221
- # Task definitions are split out (with configurations) along round and/or
222
- # workflow break lines. Rounds and workflows are dynamically parsed;
223
- # tasks may be reassigned to different rounds or workflows by later
224
- # arguments.
225
- #
226
- # Parse is non-destructive to argv. If a string argv is provided, parse
227
- # splits it into an array using Shellwords.
228
- #
229
- # ==== Round Assignment
230
- # Tasks can be defined and set to a round using the following:
231
- #
232
- # break assigns task(s) to round
233
- # -- next 0
234
- # --+ next 1
235
- # --++ next 2
236
- # --+2 next 2
237
- # --+2[1,2,3] 1,2,3 2
238
- #
239
- # Here all task (except c) are parsed into round 0, then the
240
- # final argument reassigns e to round 3.
241
- #
242
- # p = Parser.new "a -- b --+ c -- d -- e --+3[4]"
243
- # p.rounds # => [[0,1,3],[2], nil, [4]]
244
- #
245
- # ==== Workflow Assignment
246
- # All simple workflow patterns except switch can be specified within
247
- # the parse syntax (switch is the exception because there is no good
248
- # way to define a block from an array).
249
- #
250
- # break pattern source(s) target(s)
251
- # --: sequence last next
252
- # --[] fork last next
253
- # --{} merge next last
254
- # --() sync_merge next last
255
- #
256
- # example meaning
257
- # --1:2 1.sequence(2)
258
- # --1:2:3 1.sequence(2,3)
259
- # --:2: last.sequence(2,next)
260
- # --[] last.fork(next)
261
- # --1{2,3,4} 1.merge(2,3,4)
262
- # --(2,3,4) last.sync_merge(2,3,4)
263
- #
264
- # Note how all of the bracketed styles behave similarly; they are
265
- # parsed with essentially the same code, only reversing the source
266
- # and target in the case of merges.
267
- #
268
- # Here a and b are sequenced inline. Task c is assigned to no
269
- # workflow until the final argument which sequenced b and c.
270
- #
271
- # p = Parser.new "a --: b -- c --1:2"
272
- # p.tasks # => [["a"], ["b"], ["c"]]
273
- # p.workflow(:sequence) # => [[0,1],[1,2]]
274
- #
275
- # ==== Globals
276
- # Global instances of task (used, for example, by dependencies) may
277
- # be assigned in the parse syntax as well. The break for a global
278
- # is '--*'.
279
- #
280
- # p = Parser.new "a -- b --* global_name --config for --global"
281
- # p.globals # => [2]
282
- #
283
- # ==== Escapes and End Flags
284
- # Breaks can be escaped by enclosing them in '-.' and '.-' delimiters;
285
- # any number of arguments may be enclosed within the escape. After the
286
- # end delimiter, breaks are active once again.
287
- #
288
- # p = Parser.new "a -- b -- c"
289
- # p.tasks # => [["a"], ["b"], ["c"]]
290
- #
291
- # p = Parser.new "a -. -- b .- -- c"
292
- # p.tasks # => [["a", "--", "b"], ["c"]]
293
- #
294
- # Parsing continues until the end of argv, or a an end flag '---' is
295
- # reached. The end flag may also be escaped.
296
- #
297
- # p = Parser.new "a -- b --- c"
298
- # p.tasks # => [["a"], ["b"]]
299
- #
300
- #--
301
- # === Examples
302
- # Parse two tasks, with inputs and configs at separate times. Both
303
- # are assigned to round 0.
304
- #
305
- # p = Parser.new
306
- # p.parse(["a", "b", "--config", "c"])
307
- # p.tasks
308
- # # => [
309
- # # ["a", "b", "--config", "c"]]
310
- #
311
- # p.parse(["x", "y", "z"])
312
- # p.tasks
313
- # # => [
314
- # # ["a", "b", "--config", "c"],
315
- # # ["x", "y", "z"]]
316
- #
317
- # p.rounds # => [[0,1]]
318
- #
319
- # Parse two simple tasks at the same time into different rounds.
320
- #
321
- # p = Parser.new ["a", "--+", "b"]
322
- # p.tasks # => [["a"], ["b"]]
323
- # p.rounds # => [[0], [1]]
324
- #
325
- # Rounds can be declared multiple ways:
326
- #
327
- # p = Parser.new ["--+", "a", "--", "b", "--", "c", "--", "d"]
328
- # p.tasks # => [["a"], ["b"], ["c"], ["d"]]
329
- # p.rounds # => [[1,2,3], [0]]
330
- #
331
- # p.parse ["+3[2,3]"]
332
- # p.rounds # => [[1], [0], nil, [2,3]]
333
- #
334
- # Note the rounds were re-assigned using the second parse. Very
335
- # similar things may be done with workflows (note also that this
336
- # example shows how parse splits a string input into an argv
337
- # using Shellwords):
338
- #
339
- # p = Parser.new "a --: b --: c --: d"
340
- # p.tasks # => [["a"], ["b"], ["c"], ["d"]]
341
- # p.workflow(:sequence) # => [[0,1],[1,2],[2,3]]
342
- #
343
- # p.parse "1[2,3]"
344
- # p.workflow(:sequence) # => [[0,1],[2,3]]
345
- # p.workflow(:fork) # => [[1,[2,3]]]
346
- #
347
- # p.parse "e --{2,3}"
348
- # p.tasks # => [["a"], ["b"], ["c"], ["d"], ["e"]]
349
- # p.workflow(:sequence) # => [[0,1]]
350
- # p.workflow(:fork) # => [[1,[2,3]]]
351
- # p.workflow(:merge) # => [[4,[2,3]]]
352
- #
353
- # Use escapes ('-.' and '.-') to bring breaks into a task array. Any
354
- # number of breaks/args may occur within an escape sequence; breaks
355
- # are re-activated after the stop-escape:
356
- #
357
- # p = Parser.new "a -. -- b -- .- c -- d"
358
- # p.tasks # => [["a", "--", "b", "--", "c"], ["d"]]
359
- #
360
- # Use the stop delimiter to stop parsing (the unparsed argv is
361
- # returned by parse):
362
- #
363
- # argv = ["a", "--", "b", "---", "args", "after", "stop"]
364
- # p = Parser.new
365
- # p.parse(argv) # => ["args", "after", "stop"]
366
- # p.tasks # => [["a"], ["b"]]
367
- #
368
- def parse(argv)
369
- parse!(argv.kind_of?(String) ? argv : argv.dup)
370
- end
371
-
372
- # Same as parse, but removes parsed args from argv.
373
- def parse!(argv)
374
- if argv.kind_of?(String)
375
- argv = Shellwords.shellwords(argv)
376
- end
377
-
378
- round_index = 0
379
- current = []
380
- escape = false
381
- while !argv.empty?
382
- arg = argv.shift
383
-
384
- # add escaped arguments
385
- if escape
386
- if arg == ESCAPE_END
387
- escape = false
388
- else
389
- current << arg
390
- end
391
-
392
- next
393
- end
394
-
395
- # begin escaping if necessary
396
- if arg == ESCAPE_BEGIN
397
- escape = true
398
- next
399
- end
400
-
401
- # break if the end flag is reached
402
- break if arg == END_FLAG
403
-
404
- # add all non-breaking args to the
405
- # current argv array. this should
406
- # include all lookups, inputs, and
407
- # configurations
408
- unless arg =~ BREAK || (current.empty? && arg =~ WORKFLOW)
409
- current << arg
410
- next
411
- end
412
-
413
- # unless the current argv is empty,
414
- # append and start a new argv
415
- unless current.empty?
416
- add_task(current, round_index)
417
- round_index = 0
418
- current = []
419
- end
420
-
421
- # determine the type of break, parse,
422
- # and add to the appropriate collection
423
- case arg
424
- when ROUND
425
- round_index, indicies = parse_round($3, $6)
426
- indicies.each {|index| rounds_map[index] = round_index }
427
- next
428
-
429
- when SEQUENCE
430
- indicies = parse_sequence($2)
431
- while indicies.length > 1
432
- set_workflow(:sequence, indicies.shift, indicies[0])
433
- end
434
-
435
- when INSTANCE then globals << parse_instance($2)
436
- when FORK then set_workflow(:fork, *parse_bracket($2, $3))
437
- when MERGE then set_reverse_workflow(:merge, *parse_bracket($2, $3))
438
- when SYNC_MERGE then set_reverse_workflow(:sync_merge, *parse_bracket($2, $3))
439
- else raise ArgumentError, "invalid break argument: #{arg}"
440
- end
441
-
442
- round_index = nil
443
- end
444
-
445
- unless current.empty?
446
- add_task(current, round_index)
447
- end
448
-
449
- argv
450
- end
451
-
452
- # Returns an array of [type, targets] objects; the index of
453
- # each entry corresponds to the task on which to build the
454
- # workflow.
455
- #
456
- # If a type is specified, the output is ordered differently;
457
- # The return is an array of [source, targets] for the
458
- # specified workflow type. In this case the order of the
459
- # returned array is meaningless.
460
- #
461
- def workflow(type=nil)
462
- # recollect reverse types
463
-
464
- workflows = []
465
- workflow_map.each_with_index do |entry, source|
466
- next if entry == nil
467
-
468
- workflows[source] = case entry[0]
469
- when :merge, :sync_merge
470
- workflow_type, target = entry
471
- (workflows[target] ||= [workflow_type, []])[1] << source
472
- nil
473
- else entry
474
- end
475
- end
476
-
477
- return workflows if type == nil
478
-
479
- declarations = []
480
- workflows.each_with_index do |(workflow_type, targets), source|
481
- declarations << [source, targets] if workflow_type == type
482
- end
483
-
484
- declarations
485
- end
486
-
487
- # Returns an array task indicies; the index of each entry
488
- # corresponds to the round the tasks should be assigned to.
489
- #
490
- def rounds
491
- collected_rounds = []
492
- @rounds_map.each_with_index do |round_index, index|
493
- (collected_rounds[round_index] ||= []) << index unless round_index == nil
494
- end
495
-
496
- collected_rounds.each {|round| round.uniq! unless round.nil? }
497
- end
498
-
499
- def to_s
500
- segments = tasks.collect do |argv|
501
- argv.collect {|arg| shell_quote(arg) }.join(' ')
502
- end
503
- each_round_str {|str| segments << str }
504
- each_workflow_str {|str| segments << str }
505
-
506
- segments.join(" -- ")
507
- end
508
-
509
- def dump
510
- segments = tasks.dup
511
- each_round_str {|str| segments << str }
512
- each_workflow_str {|str| segments << str }
513
-
514
- segments
515
- end
516
-
517
- def build(app)
518
- instances = []
519
-
520
- # instantiate and assign globals
521
- globals.each do |index|
522
- task, args = yield(tasks[index])
523
- task.class.instance = task
524
- instances[index] = [task, args]
525
- end
526
-
527
- # instantiate the remaining task classes
528
- tasks.each_with_index do |args, index|
529
- instances[index] ||= yield(args)
530
- end
531
-
532
- # build the workflow
533
- workflow.each_with_index do |(type, target_indicies), source_index|
534
- next if type == nil
535
-
536
- targets = if target_indicies.kind_of?(Array)
537
- target_indicies.collect {|i| instances[i][0] }
538
- else
539
- instances[target_indicies][0]
540
- end
541
-
542
- instances[source_index][0].send(type, *targets)
543
- end
544
-
545
- # build queues
546
- queues = rounds.collect do |round|
547
- round.each do |index|
548
- task, args = instances[index]
549
- instances[index] = nil
550
- task.enq(*args)
551
- end
552
-
553
- app.queue.clear
554
- end
555
- queues.delete_if {|queue| queue.empty? }
556
-
557
- # notify any args that will be overlooked
558
- instances.compact.each do |(instance, args)|
559
- next if args.empty?
560
- puts "ignoring args: #{instance} [#{args.join(' ')}]"
561
- end
562
-
563
- queues
564
- end
565
-
566
- protected
567
-
568
- # Returns the index of the next argv to be parsed.
569
- def next_index
570
- tasks.length
571
- end
572
-
573
- # Returns the index of the last argv parsed.
574
- def current_index
575
- tasks.length - 1
576
- end
577
-
578
- # Sets the targets to the source in workflow_map, tracking the
579
- # workflow type.
580
- def set_workflow(type, source, targets) # :nodoc
581
- workflow_map[source] = [type, targets]
582
- [*targets].each {|target| rounds_map[target] = nil }
583
- end
584
-
585
- # Sets a reverse workflow... ie the source is set to
586
- # each target index.
587
- def set_reverse_workflow(type, source, targets) # :nodoc
588
- targets.each {|target| set_workflow(type, target, source) }
589
- end
590
-
591
- def add_task(definition, round_index) # :nodoc
592
- tasks << definition
593
- rounds_map[current_index] = round_index
594
- end
595
-
596
- # Yields each round formatted as a string.
597
- def each_round_str # :nodoc
598
- rounds.each_with_index do |indicies, round_index|
599
- unless indicies == nil
600
- yield "+#{round_index}[#{indicies.join(',')}]"
601
- end
602
- end
603
- end
604
-
605
- # Yields each workflow element formatted as a string.
606
- def each_workflow_str # :nodoc
607
- workflow.each_with_index do |(type, targets), source|
608
- next if type == nil
609
-
610
- yield case type
611
- when :sequence then [source, *targets].join(":")
612
- when :fork then "#{source}[#{targets.join(',')}]"
613
- when :merge then "#{source}{#{targets.join(',')}}"
614
- when :sync_merge then "#{source}(#{targets.join(',')})"
615
- end
616
- end
617
- end
618
- end
619
- end