objective_command 0.1.5.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 (40) hide show
  1. data/AUTHORS +5 -0
  2. data/ChangeLog +17 -0
  3. data/NEWS +3 -0
  4. data/README +2 -0
  5. data/Rakefile +8 -0
  6. data/SPEC.gemspec +15 -0
  7. data/SPEC.yml +43 -0
  8. data/bin/ocmd +32 -0
  9. data/lib/hookable.rb +284 -0
  10. data/lib/hooker.rb +47 -0
  11. data/lib/objective_command/all.rb +32 -0
  12. data/lib/objective_command/commands/command.rb +535 -0
  13. data/lib/objective_command/commands/factory.rb +69 -0
  14. data/lib/objective_command/commands/pipe.rb +121 -0
  15. data/lib/objective_command/commands/seq.rb +35 -0
  16. data/lib/objective_command/datas/composite.rb +55 -0
  17. data/lib/objective_command/datas/data.rb +175 -0
  18. data/lib/objective_command/datas/factory.rb +74 -0
  19. data/lib/objective_command/datas/pipe.rb +55 -0
  20. data/lib/objective_command/datas/temp.rb +24 -0
  21. data/lib/objective_command/datas.rb +11 -0
  22. data/lib/objective_command/helpers.rb +113 -0
  23. data/lib/objective_command/runners/exec.rb +46 -0
  24. data/lib/objective_command/runners/fork.rb +91 -0
  25. data/lib/objective_command/runners/mockable.rb +62 -0
  26. data/lib/objective_command/runners/no_run.rb +44 -0
  27. data/lib/objective_command/runners/popen.rb +49 -0
  28. data/lib/objective_command/runners/runner.rb +227 -0
  29. data/lib/objective_command/runners/system.rb +54 -0
  30. data/lib/objective_command/runners.rb +11 -0
  31. data/lib/objective_command/shell.rb +173 -0
  32. data/lib/objective_command/version_id.rb +10 -0
  33. data/lib/objective_command.rb +54 -0
  34. data/test/check-objective_command.yml +10 -0
  35. data/test/check-pkg-objective_command.yml +13 -0
  36. data/test/sanity/multiple-requires.yml +62 -0
  37. data/test/sanity/single-requires.yml +40 -0
  38. data/test/sanity-suite.yml +10 -0
  39. data/test/unit-suite.yml +14 -0
  40. metadata +97 -0
@@ -0,0 +1,62 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners/mockable.rb 23187 2006-03-31T21:59:37.612710Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+
10
+ module Mockable
11
+
12
+ def make_mock log=[], &block
13
+ @log = log
14
+ @block = block
15
+
16
+ class << self
17
+ attr_accessor :log
18
+ attr_accessor :block
19
+
20
+ def exec ( aCommand, aData )
21
+ @block[aCommand, aData]
22
+ end
23
+
24
+ def display_command ( m )
25
+ @log << m
26
+ end
27
+ end # class << self
28
+
29
+ self
30
+ end
31
+
32
+ end # module Mockable
33
+
34
+ Runner.include Mockable
35
+
36
+ test_section __FILE__ do
37
+
38
+ class MockTest < Test::Unit::TestCase
39
+
40
+ def setup
41
+ assert_nothing_raised { @runner = System.new.make_mock }
42
+ end
43
+
44
+ def test_0_initialize
45
+ end
46
+
47
+ def test_simple
48
+ assert_nothing_raised do
49
+ @cmd = 'foo bar baz'.to_ocmd
50
+ @data = @runner.run(@cmd)
51
+ end
52
+ assert_kind_of(Datas::Data, @data)
53
+ assert_equal([@cmd], @runner.log)
54
+ end
55
+
56
+ end # class SystemTest
57
+
58
+ end
59
+
60
+ end # module Runners
61
+
62
+ end # module ObjectiveCommand
@@ -0,0 +1,44 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners/no_run.rb 23187 2006-03-31T21:59:37.612710Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+
10
+ # This very particular runner returns it's command instead of running it.
11
+ class NoRun < Runner
12
+ make Concrete
13
+
14
+ def run ( aCommand )
15
+ aCommand
16
+ end
17
+
18
+ end # class NoRun
19
+
20
+
21
+
22
+ test_section __FILE__ do
23
+
24
+ class NoRunTest < Test::Unit::TestCase
25
+
26
+ def setup
27
+ assert_nothing_raised { @runner = NoRun.new }
28
+ end
29
+
30
+ def test_0_initialize
31
+ end
32
+
33
+ def test_simple
34
+ cmd = 'sleep'.to_ocmd[10]
35
+ assert_kind_of Commands::Command, cmd.run(@runner)
36
+ end
37
+
38
+ end # class NoRunTest
39
+
40
+ end
41
+
42
+ end # module Runners
43
+
44
+ end # module ObjectiveCommand
@@ -0,0 +1,49 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners/popen.rb 23187 2006-03-31T21:59:37.612710Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+
10
+ class Popen < Fork
11
+ make Concrete
12
+
13
+ def initialize ( *a, &b )
14
+ super
15
+ @command_data_factory.command_data_class = Datas::Pipe
16
+ end
17
+
18
+ end # class Popen
19
+
20
+
21
+
22
+ test_section __FILE__ do
23
+
24
+ class PopenTest < Test::Unit::TestCase
25
+
26
+ def setup
27
+ assert_nothing_raised { @runner = Popen.new }
28
+ end
29
+
30
+ def test_0_initialize
31
+ end
32
+
33
+ # FIXME
34
+ def test_simple
35
+ # TempPath.new do |tmp|
36
+ # cmd = %Q[ruby -e "sleep 0.5
37
+ # File.open('#{tmp}', 'w') { |f| f.puts :foo }"]
38
+ # @runner.run(cmd.to_ocmd)
39
+ # assert(tmp.exist?)
40
+ # end
41
+ end
42
+
43
+ end # class PopenTest
44
+
45
+ end
46
+
47
+ end # module Runners
48
+
49
+ end # module ObjectiveCommand
@@ -0,0 +1,227 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners/runner.rb 29674 2006-09-12T21:05:16.387536Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+
10
+ class Runner
11
+
12
+ include Abstract
13
+ include Hookable
14
+ include Hooker
15
+
16
+
17
+ #
18
+ # Accessors
19
+ #
20
+
21
+ attr_accessor :command_data_factory
22
+
23
+
24
+ #
25
+ # Hooks declaration
26
+ #
27
+
28
+ hook_declare :display_command
29
+ hook_declare :data
30
+ hook_declare :fork
31
+ hook_declare :son
32
+ hook_declare :before_open
33
+ hook_declare :before_chdir
34
+ hook_declare :before_exec
35
+ hook_declare :exec
36
+ hook_declare :exception_raised_during_exec
37
+ hook_declare :waitpid
38
+ hook_declare :failure
39
+ hook_declare :abort
40
+ hook_declare :already_killed
41
+ hook_declare :kill
42
+ hook_declare :before_return
43
+
44
+
45
+ #
46
+ # Construction methods.
47
+ #
48
+
49
+ def initialize *opts
50
+ @command_data_factory = Datas::Factory.new
51
+ @open_mode = :w
52
+ hooker_subscribe self
53
+ apply_options(*opts)
54
+ end
55
+
56
+
57
+ def initialize_copy ( copy )
58
+ super
59
+ if defined? @hookers
60
+ @hookers = @hookers.dup
61
+ else
62
+ @hookers = []
63
+ end
64
+ end
65
+
66
+
67
+ #
68
+ # Methods.
69
+ #
70
+
71
+ def run ( aCommand )
72
+ unless aCommand.is_a? Commands::Command
73
+ raise ArgumentError, "Need a OCmd::Commands::Command not #{aCommand}"
74
+ end
75
+
76
+ hook_trigger :display_command, aCommand
77
+
78
+ data = @command_data_factory.create
79
+ begin
80
+ data.open_mode = @open_mode
81
+ data.input = aCommand.input unless aCommand.input.nil?
82
+ data.output = aCommand.output unless aCommand.output.nil?
83
+ data.error = aCommand.error unless aCommand.error.nil?
84
+ hook_trigger :data, aCommand, data
85
+
86
+ hook_trigger :fork, data do
87
+ begin
88
+ hook_trigger :son, aCommand, data
89
+ hook_trigger :before_open, data
90
+ aCommand = aCommand.instanciate_args
91
+ STDIN.reopen(data.input.to_io_for_ocmd) unless data.input.nil?
92
+ STDOUT.reopen(data.output.to_io_for_ocmd) unless data.output.nil?
93
+ STDERR.reopen(data.error.to_io_for_ocmd) unless data.error.nil?
94
+ STDOUT.flush
95
+ STDERR.flush
96
+
97
+ hook_trigger :before_chdir, data
98
+ Dir.chdir(aCommand.dir) unless aCommand.dir.nil?
99
+
100
+ hook_trigger :before_exec, aCommand, data
101
+ hook_trigger :exec, aCommand, data
102
+ rescue Exception => ex
103
+ hook_trigger :exception_raised_during_exec, ex
104
+ end
105
+ end
106
+
107
+ hook_trigger :waitpid, data
108
+ if data.status.nil? or not data.status.success?
109
+ hook_trigger :failure, aCommand, data
110
+ end
111
+
112
+ hook_trigger :before_return, aCommand, data
113
+ rescue Exception => ex
114
+ hook_trigger :abort, data
115
+ raise ex
116
+ end
117
+ data
118
+ end
119
+
120
+
121
+ def make_verbose
122
+ hooker_subscribe VerboseHooker.new
123
+ self
124
+ end
125
+
126
+
127
+ def make_debug
128
+ hooker_subscribe DebugHooker.new
129
+ self
130
+ end
131
+
132
+
133
+ def raise_on_failures
134
+ hooker_subscribe FailureHooker.new
135
+ self
136
+ end
137
+
138
+
139
+ @@running_options =
140
+ {
141
+ :verbose => :make_verbose,
142
+ :v => :make_verbose,
143
+ :raise => :raise_on_failures,
144
+ :r => :raise_on_failures,
145
+ :debug => :make_debug,
146
+ :d => :make_debug,
147
+ :mock => :make_mock,
148
+ :m => :make_mock,
149
+ }
150
+
151
+ def apply_options ( *options )
152
+ options.flatten.each do |k|
153
+ option = @@running_options[k]
154
+ if option.nil?
155
+ raise ArgumentError, "Bad runner option: #{k}"
156
+ else
157
+ send option
158
+ end
159
+ end
160
+ self
161
+ end
162
+
163
+ def fork data, &block
164
+ block.call
165
+ end
166
+
167
+ #
168
+ # Hookers
169
+ #
170
+
171
+ class DebugHooker
172
+ include Hooker
173
+
174
+ def log ( m, *a )
175
+ STDERR.puts
176
+ STDERR.puts "#{m}: #{a.inspect}"
177
+ end
178
+
179
+ hook_default_method :log
180
+
181
+ end # class DebugHooker
182
+
183
+
184
+ class VerboseHooker
185
+ include Hooker
186
+
187
+ def display_command ( m )
188
+ STDERR.puts "Running: #{m.to_a.join(' ')}"
189
+ end
190
+
191
+ end # class VerboseHooker
192
+
193
+
194
+ class FailureHooker
195
+ include Hooker
196
+
197
+ class Error < Exception
198
+ end
199
+
200
+ def failure ( aCommand, data )
201
+ raise Error, { 'reason' => 'Command failed',
202
+ 'command' => aCommand.to_s,
203
+ 'data' => data }.to_yaml
204
+ end
205
+
206
+ end # class FailureHooker
207
+
208
+
209
+ end # class Runner
210
+
211
+
212
+ test_section __FILE__ do
213
+
214
+ class RunnerTest < Test::Unit::TestCase
215
+
216
+ def test_abstract
217
+ if defined? RubyEx
218
+ assert_raise(TypeError) { Runner.new }
219
+ end
220
+ end
221
+
222
+ end # class RunnerTest
223
+ end
224
+
225
+ end # module Runners
226
+
227
+ end # module ObjectiveCommand
@@ -0,0 +1,54 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners/system.rb 23187 2006-03-31T21:59:37.612710Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+
10
+ class WaitpidHooker
11
+ include Hooker
12
+
13
+ def waitpid ( data )
14
+ data.waitpid
15
+ end
16
+ end
17
+
18
+
19
+ # This version wait to reach the end of the command before returns.
20
+ class System < Fork
21
+ make Concrete
22
+
23
+ hooker_subscribe WaitpidHooker.new
24
+
25
+ end # class System
26
+
27
+
28
+ test_section __FILE__ do
29
+
30
+ class SystemTest < Test::Unit::TestCase
31
+
32
+ def setup
33
+ assert_nothing_raised { @runner = System.new }
34
+ end
35
+
36
+ def test_0_initialize
37
+ end
38
+
39
+ def test_simple
40
+ TempPath.new do |tmp|
41
+ cmd = %Q[ruby -e "sleep 0.5
42
+ File.open('#{tmp}', 'w') { |f| f.puts :foo }"]
43
+ @runner.run(cmd.to_ocmd)
44
+ assert(tmp.exist?)
45
+ end
46
+ end
47
+
48
+ end # class SystemTest
49
+
50
+ end
51
+
52
+ end # module Runners
53
+
54
+ end # module ObjectiveCommand
@@ -0,0 +1,11 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/runners.rb 22684 2006-03-12T16:36:11.301558Z pouillar $
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Runners
9
+ end # module Runners
10
+
11
+ end # module ObjectiveCommand
@@ -0,0 +1,173 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id$
5
+
6
+ module ObjectiveCommand
7
+
8
+ module Shell
9
+
10
+ module MethodMissing
11
+
12
+ setup do
13
+ cattr_accessor :runner unless respond_to? :runner
14
+ cattr_accessor :shell_options unless respond_to? :shell_options
15
+ end
16
+
17
+ def method_missing meth, *args, &block
18
+ super if block
19
+ meth = meth.to_s
20
+ if meth =~ /^(.*)!$/
21
+ raise 'No runner' unless respond_to? :runner or runner.nil?
22
+ Object.send(:remove_const, :Commands) if defined? ::Commands
23
+ Commands::Command.new($1, *args).run(runner)
24
+ else
25
+ cmd = Commands::Command.new(meth, *args)
26
+ cmd.freeze if shell_options and shell_options[:frozen]
27
+ cmd
28
+ end
29
+ end
30
+
31
+ end # module MethodMissing
32
+
33
+ class Simple
34
+
35
+ include Shell::MethodMissing
36
+ attr_accessor :runner, :shell_options
37
+
38
+ def initialize runner=nil, options=nil, &block
39
+ @runner = runner || OCmd::Runners::System.new
40
+ @shell_options = options || {}
41
+ other_opts = @shell_options.keys - [:frozen]
42
+ @runner.apply_options other_opts
43
+ block.bind(self).call if block
44
+ end
45
+
46
+ end # class Simple
47
+
48
+ module Attribute
49
+
50
+ setup do |*args|
51
+ runner, options = args
52
+ mattr_accessor :ocmd_shell
53
+ self.ocmd_shell = Shell::Simple.new runner, options
54
+ end
55
+
56
+ def shell *args, &block
57
+ local_shell = ocmd_shell
58
+ unless args.empty?
59
+ runner = ocmd_shell.runner
60
+ options = {}
61
+ for arg in args.flatten do
62
+ case arg
63
+ when OCmd::Runners::Runner then runner = arg
64
+ when Hash then options.merge! arg
65
+ when Symbol then options[arg] = true
66
+ else raise ArgumentError, "Bad argument: #{arg}"
67
+ end
68
+ end
69
+ local_shell = Shell::Simple.new runner, options
70
+ end
71
+ if block
72
+ block.bind(local_shell).call
73
+ else
74
+ local_shell
75
+ end
76
+ end
77
+
78
+ def shell! *args, &block
79
+ raise ArgumentError, 'Block needed' if block.nil?
80
+ local_shell = shell(*args)
81
+ block.bind(local_shell).call.run local_shell.runner
82
+ end
83
+
84
+ end # module Attribute
85
+
86
+ end # module Shell
87
+
88
+
89
+ have Shell::Attribute
90
+ module_function :shell, :shell!
91
+
92
+
93
+ test_section __FILE__ do
94
+ OCmd::Runners::Mockable.import!
95
+
96
+ class ShellTest < Test::Unit::TestCase
97
+
98
+ class Foo
99
+ include OCmd::Shell::MethodMissing
100
+ def bar
101
+ cat
102
+ end
103
+ end
104
+ class Bar < Foo
105
+ attr_accessor :runner
106
+ def initialize runner
107
+ @runner = runner
108
+ end
109
+ def bar!
110
+ cat!
111
+ end
112
+ end
113
+ attr_reader :file1, :file2
114
+
115
+ def setup
116
+ @file1 = TempPath.new('file1').overwrite('contents1')
117
+ @file2 = TempPath.new('file2').overwrite('contents2')
118
+ @runner = OCmd::Runners::System.new.make_mock()
119
+ end
120
+
121
+ def assert_shell_cmd! ref, &block
122
+ my = block[]
123
+ assert_kind_of Datas::Data, my
124
+ assert_equal 1, @runner.log.size, 'bad runner log size'
125
+ assert_equal ref, @runner.log.first.to_a
126
+ @runner.log.shift
127
+ end
128
+
129
+ def test_simple_shell
130
+ ref = ['cat', file1.to_s, file2.to_s]
131
+ my = OCmd.shell.cat file1, file2
132
+ assert_equal ref, my.to_a
133
+ end
134
+
135
+ def test_simple_shell_env
136
+ ref = ['cat', file1.to_s, file2.to_s]
137
+ OCmd.shell do
138
+ my = cat file1, file2
139
+ assert_equal ref, my.to_a
140
+ end
141
+ end
142
+
143
+ def test_simple_shell_included
144
+ assert_equal ['cat'], Foo.new.bar.to_a
145
+ end
146
+
147
+ def test_with_run
148
+ ref = ['cat', file1.to_s, file2.to_s]
149
+ assert_shell_cmd!(ref) { OCmd.shell(@runner).cat! file1, file2 }
150
+ t = self
151
+ assert_shell_cmd!(ref) {OCmd.shell(@runner) { cat! t.file1, t.file2 }}
152
+ assert_shell_cmd!(['cat']) { Bar.new(@runner).bar! }
153
+ end
154
+
155
+ def test_with_run2
156
+ ref = ['cat', file1.to_s, file2.to_s]
157
+ t = self
158
+ assert_shell_cmd!(ref) {OCmd.shell!(@runner) { cat t.file1, t.file2 }}
159
+ end
160
+
161
+ def test_frozen_shell
162
+ ref = ['cat', file1.to_s, file2.to_s]
163
+ t = self
164
+ opts = [@runner, { :frozen => true }]
165
+ assert_shell_cmd!(ref) { OCmd.shell!(opts) { cat t.file1, t.file2 } }
166
+ assert_raise(TypeError) { OCmd.shell!(opts) { cat << 'foo' } }
167
+ end
168
+
169
+ end # class ShellTest
170
+
171
+ end
172
+
173
+ end # module ObjectiveCommand
@@ -0,0 +1,10 @@
1
+ # Copyright:: Copyright (c) 2006 Nicolas Pouillard. All rights reserved.
2
+ # Author:: Nicolas Pouillard <nicolas.pouillard@gmail.com>.
3
+ # License:: Gnu General Public License.
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/version_id.rb 53907 2007-01-13T18:40:33.521685Z ertai $
5
+
6
+ module ObjectiveCommand
7
+
8
+ VersionId = Version.parse("dev-ruby/objective_command-0.1")
9
+
10
+ end # module ObjectiveCommand
@@ -0,0 +1,54 @@
1
+ # Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
2
+ # Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
3
+ # License:: GNU General Public License (GPL).
4
+ # Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command.rb 53907 2007-01-13T18:40:33.521685Z ertai $
5
+
6
+ require 'pathname'
7
+
8
+ lib = Pathname.new(__FILE__).dirname
9
+ vendor = lib.parent + 'vendor'
10
+ unless defined? CoreEx
11
+ $CORE_EX_VENDORS ||= []
12
+ $CORE_EX_VENDORS << vendor
13
+ file = vendor + 'core_ex' + 'lib' + 'core_ex'
14
+ if file.exist?
15
+ require file.to_s
16
+ else
17
+ require 'rubygems' unless ENV['NO_GEM']
18
+ require_gem 'core_ex'
19
+ require 'core_ex'
20
+ end
21
+ end
22
+ lib.load_path!
23
+
24
+ unless defined? RubyEx
25
+ module Abstract
26
+ end
27
+ module Concrete
28
+ end
29
+ end
30
+
31
+ # Provides an object oriented way to manage, combine and run your commands.
32
+ #
33
+ # Example:
34
+ # require 'rubygems' ; require_gem 'objective_command' ; require 'objective_command'
35
+ # ls, wc, out = 'ls'.to_ocmd, 'wc'.to_ocmd, 'out'.to_path
36
+ #
37
+ # data = ls.system # other runners exist (exec, fork, sh...)
38
+ #
39
+ # p data.status
40
+ # puts data.output.read
41
+ #
42
+ # (ls > STDOUT).system
43
+ #
44
+ # cmd = ls['*.rb'] | wc['-l'] > out
45
+ # cmd.system
46
+ #
47
+ # puts out.read
48
+ module ObjectiveCommand
49
+ end # module ObjectiveCommand
50
+
51
+ OCmd = ObjectiveCommand unless defined? OCmd and OCmd == ObjectiveCommand
52
+ Hooker.import!
53
+ OCmd::Helpers.import!
54
+
@@ -0,0 +1,10 @@
1
+ ---
2
+
3
+ ObjectiveCommand Main Test Suite: !S::Iterate
4
+
5
+ over: !pathlist <<pwd>>/(*-suite.yml)
6
+ iter: [it_file, it_name]
7
+
8
+ test:
9
+ <<it_name>>: !S::Import
10
+ import: <<it_file>>