laborantin 0.0.21 → 0.1.2
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/Rakefile +7 -1
- data/TODO +1 -1
- data/lib/laborantin.rb +1 -1
- data/lib/laborantin/core/analysis.rb +19 -80
- data/lib/laborantin/core/dependencies.rb +37 -0
- data/lib/laborantin/core/dependency_solver.rb +30 -0
- data/lib/laborantin/core/exports.rb +45 -0
- data/lib/laborantin/core/resolutions.rb +39 -0
- data/lib/laborantin/core/scenario.rb +37 -15
- data/lib/laborantin/core/selector.rb +68 -0
- data/lib/laborantin/core/table.rb +3 -3
- data/lib/laborantin/core/verifications.rb +48 -0
- data/lib/laborantin/runner/commands/analyze.rb +7 -1
- data/lib/laborantin/runner/commands/run.rb +3 -0
- metadata +13 -4
data/Rakefile
CHANGED
@@ -56,7 +56,13 @@ spec = Gem::Specification.new do |s|
|
|
56
56
|
'lib/laborantin/extra/commands/git.rb',
|
57
57
|
'lib/laborantin/extra/commands/git/check.rb',
|
58
58
|
'lib/laborantin/extra/commands/git/run.rb',
|
59
|
-
'lib/laborantin/extra/vectorial_product.rb'
|
59
|
+
'lib/laborantin/extra/vectorial_product.rb',
|
60
|
+
'lib/laborantin/core/selector.rb',
|
61
|
+
'lib/laborantin/core/dependencies.rb',
|
62
|
+
'lib/laborantin/core/verifications.rb',
|
63
|
+
'lib/laborantin/core/resolutions.rb',
|
64
|
+
'lib/laborantin/core/dependency_solver.rb',
|
65
|
+
'lib/laborantin/core/exports.rb',
|
60
66
|
]
|
61
67
|
|
62
68
|
s.require_path = 'lib'
|
data/TODO
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
*modularize logging
|
1
2
|
new data structure:
|
2
3
|
in config files (both env and scenarii):
|
3
4
|
reference every rundir
|
@@ -17,7 +18,6 @@ commands:
|
|
17
18
|
optimize (given a goal)
|
18
19
|
estimate (cost, duration,
|
19
20
|
whatever defined by the user, only total sum, products?)
|
20
|
-
infos (gives info about the running environment)
|
21
21
|
config dir:
|
22
22
|
extra libraries to require
|
23
23
|
general:
|
data/lib/laborantin.rb
CHANGED
@@ -25,6 +25,9 @@ autoload :ERB, 'erb'
|
|
25
25
|
|
26
26
|
require 'laborantin/core/describable'
|
27
27
|
require 'laborantin/core/multi_name'
|
28
|
+
require 'laborantin/core/selector'
|
29
|
+
require 'laborantin/core/dependencies'
|
30
|
+
require 'laborantin/core/exports'
|
28
31
|
|
29
32
|
module Laborantin
|
30
33
|
# An Analysis is a handy way to reload and filter the various scenarii that were
|
@@ -32,26 +35,14 @@ module Laborantin
|
|
32
35
|
class Analysis
|
33
36
|
extend Metaprog::Describable
|
34
37
|
extend Metaprog::MultiName
|
38
|
+
include Metaprog::Selector
|
39
|
+
include Metaprog::Dependencies
|
40
|
+
include Metaprog::Exports
|
35
41
|
|
36
42
|
class << self
|
37
|
-
# A hash with two items, this might change later but KISS for now.
|
38
|
-
attr_accessor :selectors
|
39
|
-
|
40
43
|
# An array
|
41
44
|
attr_accessor :analyses
|
42
45
|
|
43
|
-
# Add a selector to filter for the analysis only the runs that pass the selector.
|
44
|
-
# * sym objects (sym currently must be :environments or
|
45
|
-
# :scenarii).
|
46
|
-
# * ary is a set of classes, only runs of this classes will be loaded
|
47
|
-
# * if a block is passed, only the instances for which the block is
|
48
|
-
# evaluated as true will be selected (the block must take one parameter:
|
49
|
-
# the tested instance)
|
50
|
-
def select(sym, ary=[], &blk)
|
51
|
-
@selectors ||= {}
|
52
|
-
@selectors[sym] = {:klasses => ary, :blk => blk}
|
53
|
-
end
|
54
|
-
|
55
46
|
# Adds an analysis to this class.
|
56
47
|
# str is a description of the added analysis params is a hash of
|
57
48
|
# parameters for this analysis, specifically, the :type parameters allows
|
@@ -62,26 +53,6 @@ module Laborantin
|
|
62
53
|
@analyses << {:str => str, :params => params, :blk => blk}
|
63
54
|
end
|
64
55
|
|
65
|
-
def plot(title, args, &blk)
|
66
|
-
args ||= {}
|
67
|
-
hash = args.merge({:type => :plot})
|
68
|
-
analyze(title, hash, &blk)
|
69
|
-
end
|
70
|
-
|
71
|
-
def table(title, args, &blk)
|
72
|
-
args ||= {}
|
73
|
-
hash = args.merge({:type => :table})
|
74
|
-
analyze(title, hash, &blk)
|
75
|
-
end
|
76
|
-
|
77
|
-
def plots
|
78
|
-
analyses.select{|a| a[:params][:type] == :plots}
|
79
|
-
end
|
80
|
-
|
81
|
-
def tables
|
82
|
-
analyses.select{|a| a[:params][:type] == :tables}
|
83
|
-
end
|
84
|
-
|
85
56
|
@@all = []
|
86
57
|
|
87
58
|
def inherited(klass)
|
@@ -96,12 +67,6 @@ module Laborantin
|
|
96
67
|
end
|
97
68
|
end # << self
|
98
69
|
|
99
|
-
# An array of the Environments that could be loaded from the result directory.
|
100
|
-
attr_accessor :environments
|
101
|
-
|
102
|
-
# An array of the Scenarii that could be loaded from the result directory.
|
103
|
-
attr_reader :scenarii
|
104
|
-
|
105
70
|
# TODO : recode this, maybe as nothing to do here
|
106
71
|
def analyze
|
107
72
|
self.class.analyses.each do |a|
|
@@ -109,6 +74,7 @@ module Laborantin
|
|
109
74
|
instance_eval &a[:blk]
|
110
75
|
puts "done"
|
111
76
|
end
|
77
|
+
save_exports
|
112
78
|
end
|
113
79
|
|
114
80
|
# TODO: more flexible
|
@@ -146,54 +112,27 @@ module Laborantin
|
|
146
112
|
Table.new(name, struct, self.output_path(name))
|
147
113
|
end
|
148
114
|
|
149
|
-
|
150
|
-
|
151
|
-
# Just loads the environments and scenarii from the resultdir.
|
152
|
-
def initialize(*args, &blk)
|
153
|
-
load_from_results
|
154
|
-
set_instance_vars
|
115
|
+
def export_file(mode='r', &blk)
|
116
|
+
output('exports.yaml', mode, &blk)
|
155
117
|
end
|
156
118
|
|
157
|
-
|
158
|
-
|
159
|
-
load_environments
|
160
|
-
load_scenarii
|
119
|
+
def export_path
|
120
|
+
output_path('exports.yaml')
|
161
121
|
end
|
162
122
|
|
163
|
-
|
164
|
-
# * @plots
|
165
|
-
# * @tables
|
166
|
-
def set_instance_vars
|
167
|
-
@plots = self.class.plots.dup
|
168
|
-
@tables = self.class.tables.dup
|
169
|
-
end
|
123
|
+
attr_reader :command
|
170
124
|
|
171
|
-
#
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
envs = Laborantin::Environment.scan_resdir('results')
|
176
|
-
@environments = envs.select do |env|
|
177
|
-
select_instance?(env, self.class.selectors[:environments])
|
178
|
-
end
|
125
|
+
# Just loads the environments and scenarii from the resultdir.
|
126
|
+
def initialize(command = nil)
|
127
|
+
@command = command
|
128
|
+
load_prior_results
|
179
129
|
end
|
180
130
|
|
181
|
-
|
182
|
-
|
183
|
-
def load_scenarii
|
184
|
-
scii = @environments.map{|e| e.populate}.flatten
|
185
|
-
@scenarii = scii.select do |sc|
|
186
|
-
select_instance?(sc, self.class.selectors[:scenarii])
|
187
|
-
end
|
131
|
+
def runner
|
132
|
+
command.runner if command
|
188
133
|
end
|
189
134
|
|
190
|
-
|
191
|
-
# or Scenario) matches the selector.
|
192
|
-
def select_instance?(obj, selector)
|
193
|
-
blk = selector[:blk]
|
194
|
-
(selector[:klasses].any?{|k| obj.is_a? k} ) and
|
195
|
-
(blk ? blk.call(obj) : true)
|
196
|
-
end
|
135
|
+
private
|
197
136
|
|
198
137
|
# Nice way to iterate on @scenarii
|
199
138
|
def each_scenario
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'laborantin/core/verifications'
|
3
|
+
|
4
|
+
module Laborantin
|
5
|
+
module Metaprog
|
6
|
+
module Dependencies
|
7
|
+
class Dependency
|
8
|
+
include Metaprog::Describable
|
9
|
+
include Metaprog::Verifications
|
10
|
+
attr_reader :name
|
11
|
+
def initialize(name)
|
12
|
+
@name = name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(klass)
|
17
|
+
klass.extend ClassMethods
|
18
|
+
klass.dependencies = []
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
attr_accessor :dependencies
|
23
|
+
|
24
|
+
def dependencies
|
25
|
+
@dependencies ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def dependency(name,&blk)
|
29
|
+
dep = Dependency.new(name)
|
30
|
+
dep.instance_eval &blk
|
31
|
+
dependencies << dep
|
32
|
+
dep
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
# Poor man's dependency greedy and recursive algorithm raises an error after
|
4
|
+
# two consecutive calls with the same previoulsy_wrong dependencies list
|
5
|
+
# we rely on the implementer to not create dependency loops.
|
6
|
+
# The whole dependency design is extremely wasteful, but it works.
|
7
|
+
module DependencySolver
|
8
|
+
def resolve_dependencies(obj, previously_wrong=[])
|
9
|
+
valid, wrong = obj.class.dependencies.partition do |dep|
|
10
|
+
dep.valid?(obj)
|
11
|
+
end
|
12
|
+
|
13
|
+
if wrong.empty?
|
14
|
+
puts "all dependencies met"
|
15
|
+
else
|
16
|
+
puts "unmet dependencies: #{wrong.map(&:name).join(' ')}"
|
17
|
+
if previously_wrong == wrong
|
18
|
+
raise RuntimeError, "already tried resolving these dependencies"
|
19
|
+
else
|
20
|
+
wrong.each do |dep|
|
21
|
+
# Since iterating changes the status of the dependency, we may want to re-test if a dep is valid or not.
|
22
|
+
# the assumption is that resolving a dep costs more than testing if it's valid or not
|
23
|
+
dep.verifications.each{|v| v.resolve!(obj)} unless dep.valid?(obj)
|
24
|
+
end
|
25
|
+
resolve_dependencies(obj, wrong)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Laborantin
|
4
|
+
module Metaprog
|
5
|
+
module Exports
|
6
|
+
|
7
|
+
def save_exports
|
8
|
+
log "saving exports: #{exports}" if respond_to? :log
|
9
|
+
export_file('w') do |f|
|
10
|
+
f.puts YAML.dump(exports)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def load_exports
|
15
|
+
path = export_path
|
16
|
+
if File.file?(path)
|
17
|
+
YAML.load_file(path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def export_path
|
22
|
+
raise NotImplementedError, "should override"
|
23
|
+
end
|
24
|
+
|
25
|
+
def export_file
|
26
|
+
raise NotImplementedError, "should override"
|
27
|
+
end
|
28
|
+
|
29
|
+
def exports
|
30
|
+
@exports ||= load_exports || {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def export(name, mime='plain/text')
|
34
|
+
log "#{mime}: #{name}" if respond_to? :log
|
35
|
+
exports[name] ||= mime
|
36
|
+
end
|
37
|
+
|
38
|
+
def plots
|
39
|
+
hash = exports
|
40
|
+
hash.keys.select{|k| hash[k] =~ /^image/}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module Resolutions
|
5
|
+
module InstanceMethods
|
6
|
+
attr_accessor :resolutions
|
7
|
+
|
8
|
+
def resolutions
|
9
|
+
@resolutions ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def resolve(name=nil, &blk)
|
13
|
+
dep = Resolution.new(name, &blk)
|
14
|
+
resolutions << dep
|
15
|
+
dep
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve!(*ary)
|
19
|
+
resolutions.map{|r| r.resolve!(*ary)}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
include InstanceMethods
|
24
|
+
|
25
|
+
class Resolution
|
26
|
+
attr_reader :name, :block
|
27
|
+
def initialize(name, &blk)
|
28
|
+
@name = name
|
29
|
+
@block = blk
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve!(*ary)
|
33
|
+
raise RuntimeError, "no block to resolve #{self}" unless block
|
34
|
+
block.call(*ary)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -33,6 +33,9 @@ require 'laborantin/core/hookable'
|
|
33
33
|
require 'laborantin/core/configurable'
|
34
34
|
require 'laborantin/core/multi_name'
|
35
35
|
require 'laborantin/core/table'
|
36
|
+
require 'laborantin/core/selector'
|
37
|
+
require 'laborantin/core/dependencies'
|
38
|
+
require 'laborantin/core/exports'
|
36
39
|
|
37
40
|
module Laborantin
|
38
41
|
|
@@ -50,9 +53,12 @@ module Laborantin
|
|
50
53
|
class Scenario
|
51
54
|
include Metaprog::Datable
|
52
55
|
include Metaprog::Configurable
|
53
|
-
extend
|
54
|
-
extend
|
55
|
-
extend
|
56
|
+
extend Metaprog::Describable
|
57
|
+
extend Metaprog::Hookable
|
58
|
+
extend Metaprog::MultiName
|
59
|
+
include Metaprog::Selector
|
60
|
+
include Metaprog::Dependencies
|
61
|
+
include Metaprog::Exports
|
56
62
|
|
57
63
|
@@all = []
|
58
64
|
|
@@ -98,10 +104,11 @@ module Laborantin
|
|
98
104
|
|
99
105
|
# Prepares attributes' default values whenever a subclass is created.
|
100
106
|
def inherited(klass)
|
101
|
-
klass.parameters = ParameterHash.new
|
102
|
-
klass.description =
|
103
|
-
klass.products = []
|
104
|
-
klass.hooks = {:setup => [], :teardown => []}
|
107
|
+
klass.parameters = ParameterHash.new.replace(self.parameters || {})
|
108
|
+
klass.description = "#{self.description} (child of #{self})"
|
109
|
+
klass.products = self.products ? self.products.dup : []
|
110
|
+
klass.hooks = Hash.new.replace(self.hooks || {:setup => [], :teardown => []})
|
111
|
+
klass.selectors = Hash.new.replace(self.selectors || {})
|
105
112
|
@@all << klass
|
106
113
|
end
|
107
114
|
|
@@ -173,7 +180,12 @@ module Laborantin
|
|
173
180
|
# so wait one sec between several runs of same Scenario
|
174
181
|
#
|
175
182
|
def prepare!
|
176
|
-
log
|
183
|
+
log "Loading prior results:"
|
184
|
+
load_prior_results
|
185
|
+
log "Got #{scenarii.size} scenarios in #{environments.size} environments"
|
186
|
+
log "Description:"
|
187
|
+
log(self.class.description || 'no description', :info)
|
188
|
+
log "Parameters:"
|
177
189
|
log self.params.inspect, :info
|
178
190
|
log "Preparing directory #{rundir}"
|
179
191
|
FileUtils.mkdir_p(rundir) #TODO: ensure unicity
|
@@ -202,6 +214,7 @@ module Laborantin
|
|
202
214
|
end
|
203
215
|
log "Measurement finished"
|
204
216
|
call_hooks :teardown
|
217
|
+
save_exports
|
205
218
|
end
|
206
219
|
|
207
220
|
# For each product define with Scenario.produces, and in its order,
|
@@ -217,6 +230,7 @@ module Laborantin
|
|
217
230
|
end
|
218
231
|
end
|
219
232
|
end
|
233
|
+
save_exports
|
220
234
|
end
|
221
235
|
|
222
236
|
# Returns the absolute path to a product file (see File.join) If brutname
|
@@ -266,14 +280,12 @@ module Laborantin
|
|
266
280
|
Table.new(name, struct, self.product_path(name))
|
267
281
|
end
|
268
282
|
|
269
|
-
|
283
|
+
def export_file(mode='r', &blk)
|
284
|
+
product_file('exports.yaml', mode, true, &blk)
|
285
|
+
end
|
270
286
|
|
271
|
-
def
|
272
|
-
|
273
|
-
self.class.hooks[name].each do |sym|
|
274
|
-
log "(#{sym})"
|
275
|
-
send sym
|
276
|
-
end
|
287
|
+
def export_path
|
288
|
+
product_path('exports.yaml', true)
|
277
289
|
end
|
278
290
|
|
279
291
|
def log(*args)
|
@@ -287,5 +299,15 @@ module Laborantin
|
|
287
299
|
def runner
|
288
300
|
environment.runner
|
289
301
|
end
|
302
|
+
|
303
|
+
private
|
304
|
+
|
305
|
+
def call_hooks(name)
|
306
|
+
log "Calling #{name} hooks"
|
307
|
+
self.class.hooks[name].each do |sym|
|
308
|
+
log "(#{sym})"
|
309
|
+
send sym
|
310
|
+
end
|
311
|
+
end
|
290
312
|
end # class
|
291
313
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
module Laborantin
|
3
|
+
module Metaprog
|
4
|
+
module Selector
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
# A hash with two items, this might change later but KISS for now.
|
11
|
+
attr_accessor :selectors
|
12
|
+
|
13
|
+
# Add a selector to filter for the analysis only the runs that pass the selector.
|
14
|
+
# * sym objects (sym currently must be :environments or
|
15
|
+
# :scenarii).
|
16
|
+
# * ary is a set of classes, only runs of this classes will be loaded
|
17
|
+
# * if a block is passed, only the instances for which the block is
|
18
|
+
# evaluated as true will be selected (the block must take one parameter:
|
19
|
+
# the tested instance)
|
20
|
+
def select(sym, ary=[], &blk)
|
21
|
+
@selectors ||= {}
|
22
|
+
@selectors[sym] = {:klasses => ary, :blk => blk}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# An array of the Environments that could be loaded from the result directory.
|
27
|
+
attr_accessor :environments
|
28
|
+
|
29
|
+
# An array of the Scenarii that could be loaded from the result directory.
|
30
|
+
attr_reader :scenarii
|
31
|
+
|
32
|
+
# Load first the environments, then the scenarii.
|
33
|
+
def load_prior_results
|
34
|
+
load_environments
|
35
|
+
load_scenarii
|
36
|
+
end
|
37
|
+
|
38
|
+
# Will try to load environments and set the @environments variable to an
|
39
|
+
# array of all the Environment instance that match the :environments class
|
40
|
+
# selector (set with Analysis#select).
|
41
|
+
def load_environments
|
42
|
+
envs = Laborantin::Environment.scan_resdir('results')
|
43
|
+
@environments = envs.select do |env|
|
44
|
+
select_instance?(env, self.class.selectors[:environments])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Same as load_environments, but for Scenario instances and :scenarii
|
49
|
+
# selector.
|
50
|
+
def load_scenarii
|
51
|
+
scii = @environments.map{|e| e.populate}.flatten
|
52
|
+
@scenarii = scii.select do |sc|
|
53
|
+
select_instance?(sc, self.class.selectors[:scenarii])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Handy test to see if an object (that should be an instance of Environment
|
58
|
+
# or Scenario) matches the selector.
|
59
|
+
def select_instance?(obj, selector)
|
60
|
+
return true unless selector
|
61
|
+
blk = selector[:blk]
|
62
|
+
(selector[:klasses].any?{|k| obj.is_a? k} ) and
|
63
|
+
(blk ? blk.call(obj) : true)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -17,7 +17,7 @@ module Laborantin
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def header
|
20
|
-
@header || [comment, fields].flatten.join(separator)
|
20
|
+
@header || [comment, fields].flatten.join(separator).strip
|
21
21
|
end
|
22
22
|
|
23
23
|
class Filler < Proc
|
@@ -43,8 +43,8 @@ module Laborantin
|
|
43
43
|
end
|
44
44
|
line = strings.join(separator)
|
45
45
|
if check
|
46
|
-
if line.start_with?(comment)
|
47
|
-
raise ArgumentError, "line starting with comment\n#{line}"
|
46
|
+
if line.start_with?(comment) and (not comment.empty?)
|
47
|
+
raise ArgumentError, "line starting with comment\n#{line}"
|
48
48
|
end
|
49
49
|
expected = struct.members.size
|
50
50
|
got = line.split(separator).size
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'laborantin/core/resolutions'
|
2
|
+
|
3
|
+
module Laborantin
|
4
|
+
module Metaprog
|
5
|
+
module Verifications
|
6
|
+
module InstanceMethods
|
7
|
+
attr_accessor :verifications
|
8
|
+
|
9
|
+
def verifications
|
10
|
+
@verifications ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def verify(name, &blk)
|
14
|
+
dep = Verification.new(name)
|
15
|
+
dep.instance_eval &blk
|
16
|
+
verifications << dep
|
17
|
+
dep
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?(*ary)
|
21
|
+
verifications.inject(true){|b,verif| b && verif.correct?(*ary)}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
include InstanceMethods
|
26
|
+
|
27
|
+
class Verification
|
28
|
+
include Metaprog::Describable
|
29
|
+
include Metaprog::Resolutions
|
30
|
+
attr_reader :name, :block
|
31
|
+
def initialize(name)
|
32
|
+
@name = name
|
33
|
+
end
|
34
|
+
|
35
|
+
def check(&blk)
|
36
|
+
@block = blk
|
37
|
+
end
|
38
|
+
|
39
|
+
def correct?(*ary)
|
40
|
+
raise RuntimeError, "no block for verification #{self}" unless block
|
41
|
+
block.call(*ary) && valid?(*ary)
|
42
|
+
end
|
43
|
+
|
44
|
+
include InstanceMethods
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -21,9 +21,13 @@ Copyright (c) 2009, Lucas Di Cioccio
|
|
21
21
|
|
22
22
|
=end
|
23
23
|
|
24
|
+
require 'laborantin/core/dependency_solver'
|
25
|
+
|
24
26
|
module Laborantin
|
25
27
|
module Commands
|
26
28
|
class Analyze < Command
|
29
|
+
include DependencySolver
|
30
|
+
|
27
31
|
describe "Runs the analyses"
|
28
32
|
|
29
33
|
option(:analyses) do
|
@@ -50,7 +54,9 @@ module Laborantin
|
|
50
54
|
|
51
55
|
anae.each do |klass|
|
52
56
|
puts "Analyzing: #{klass.name}"
|
53
|
-
klass.new
|
57
|
+
analysis = klass.new(self)
|
58
|
+
resolve_dependencies(analysis)
|
59
|
+
analysis.analyze
|
54
60
|
end
|
55
61
|
end
|
56
62
|
end
|
@@ -22,12 +22,14 @@ Copyright (c) 2009, Lucas Di Cioccio
|
|
22
22
|
=end
|
23
23
|
|
24
24
|
require 'laborantin'
|
25
|
+
require 'laborantin/core/dependency_solver'
|
25
26
|
require 'logger'
|
26
27
|
require 'fileutils'
|
27
28
|
|
28
29
|
module Laborantin
|
29
30
|
module Commands
|
30
31
|
class Run < Command
|
32
|
+
include DependencySolver
|
31
33
|
describe 'Runs all set of scenarios and environments'
|
32
34
|
|
33
35
|
option(:scenarii) do
|
@@ -110,6 +112,7 @@ module Laborantin
|
|
110
112
|
|
111
113
|
sc = sklass.new(env, cfg)
|
112
114
|
sc.prepare!
|
115
|
+
resolve_dependencies(sc)
|
113
116
|
sc.perform!
|
114
117
|
sc.analyze! if opts[:analyze]
|
115
118
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: laborantin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Lucas Di Cioccio
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2011-
|
18
|
+
date: 2011-07-21 00:00:00 +02:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -68,6 +69,12 @@ files:
|
|
68
69
|
- lib/laborantin/extra/commands/git/check.rb
|
69
70
|
- lib/laborantin/extra/commands/git/run.rb
|
70
71
|
- lib/laborantin/extra/vectorial_product.rb
|
72
|
+
- lib/laborantin/core/selector.rb
|
73
|
+
- lib/laborantin/core/dependencies.rb
|
74
|
+
- lib/laborantin/core/verifications.rb
|
75
|
+
- lib/laborantin/core/resolutions.rb
|
76
|
+
- lib/laborantin/core/dependency_solver.rb
|
77
|
+
- lib/laborantin/core/exports.rb
|
71
78
|
has_rdoc: true
|
72
79
|
homepage: http://dicioccio.fr/laborantin
|
73
80
|
licenses: []
|
@@ -82,6 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
89
|
requirements:
|
83
90
|
- - ">="
|
84
91
|
- !ruby/object:Gem::Version
|
92
|
+
hash: 3
|
85
93
|
segments:
|
86
94
|
- 0
|
87
95
|
version: "0"
|
@@ -90,6 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
98
|
requirements:
|
91
99
|
- - ">="
|
92
100
|
- !ruby/object:Gem::Version
|
101
|
+
hash: 3
|
93
102
|
segments:
|
94
103
|
- 0
|
95
104
|
version: "0"
|