Class: Biopsy::Target

Inherits:
Object
  • Object
show all
Defined in:
lib/biopsy/target.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

pass calls to missing methods to the constructor iff the constructor’s class directly defines that method



147
148
149
150
151
152
153
154
# File 'lib/biopsy/target.rb', line 147

def method_missing(method, *args, &block)
  const_methods = @constructor.class.instance_methods(false)
  if const_methods.include? method
    return @constructor.send(method, *args, &block)
  else
    super
  end
end

Instance Attribute Details

#constructor_pathObject (readonly)

Returns the value of attribute constructor_path.



20
21
22
# File 'lib/biopsy/target.rb', line 20

def constructor_path
  @constructor_path
end

#nameObject

Returns the value of attribute name.



18
19
20
# File 'lib/biopsy/target.rb', line 18

def name
  @name
end

#optionsObject

Returns the value of attribute options.



16
17
18
# File 'lib/biopsy/target.rb', line 16

def options
  @options
end

#outputObject

Returns the value of attribute output.



17
18
19
# File 'lib/biopsy/target.rb', line 17

def output
  @output
end

#parametersObject

Returns the value of attribute parameters.



15
16
17
# File 'lib/biopsy/target.rb', line 15

def parameters
  @parameters
end

#shortnameObject

Returns the value of attribute shortname.



19
20
21
# File 'lib/biopsy/target.rb', line 19

def shortname
  @shortname
end

Instance Method Details

#check_constructor(name) ⇒ Object

Validate the constructor. True if valid, false otherwise.

Raises:



75
76
77
78
79
# File 'lib/biopsy/target.rb', line 75

def check_constructor name
  @constructor_path = self.locate_file name + '.rb'
  raise TargetLoadError.new("constructor path is not defined for this target") if @constructor_path.nil?
  self.valid_ruby? @constructor_path
end

#count_parameter_permutationsObject

return the total number of possible permutations of



141
142
143
# File 'lib/biopsy/target.rb', line 141

def count_parameter_permutations
  @parameters.each_pair.map{ |k, v| v }.reduce(1) { |n, arr| n * arr.size }
end

#generate_parameters(params) ⇒ Object

convert parameter specification to a hash of arrays and ranges



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/biopsy/target.rb', line 102

def generate_parameters params
  @parameters = {}
  @options = {}
  params.each_pair do |param, data|
    if data[:opt]
      # optimise this parameter
      if data[:values] 
        # definition has provided an array of values
        if !data[:values].is_a? Array
          raise TargetLoadError.new("'values' for parameter #{param} is not an array")
        end
        if data[:type] == 'integer'
          data[:values].each do |v|
            raise TypeLoadError.new("'values' for parameter #{param} expected integer") unless v.is_a? Integer
          end
        elsif data[:type] == 'string'
          data[:values].each do |v|
            raise TypeLoadError.new("'values' for parameter #{param} expected string") unless v.is_a? String
          end
        end
        @parameters[param] = data[:values]
      else
        # definition has specified a range
        min, max, step = data[:min], data[:max], data[:step]
        unless min && max
          raise TargetLoadError.new("min and max must be set for parameter #{param}") 
        end
        range = (min..max)
        range = range.step(step) if step
        @parameters[param] = range.to_a
      end
    else
      # present option to user
      @options[param] = data
    end
  end
end

#load_by_name(name) ⇒ Object

load target with name.

Raises:



23
24
25
26
27
28
29
30
31
32
# File 'lib/biopsy/target.rb', line 23

def load_by_name name
  path = self.locate_definition name
  raise TargetLoadError.new("Target definition file does not exist for #{name}") if path.nil?
  config = YAML::load_file(path)
  raise TargetLoadError.new("Target definition file #{path} is not valid YAML") if config.nil?
  config = config.deep_symbolize
  self.store_config config
  self.check_constructor name
  self.load_constructor
end

#load_constructorObject

Load constructor



82
83
84
85
86
87
# File 'lib/biopsy/target.rb', line 82

def load_constructor
  require @constructor_path 
  file_name = File.basename(@constructor_path, '.rb')
  constructor_name = file_name.camelize
  @constructor = Module.const_get(constructor_name).new
end

#locate_definition(name) ⇒ Object

given the name of a target, return the path to the definition YAML file. All :target_dirs defined in Settings are searched and the first matching YAML file is loaded.



37
38
39
# File 'lib/biopsy/target.rb', line 37

def locate_definition name
  self.locate_file(name + '.yml')
end

#locate_file(name) ⇒ Object

Locate a file with name in one of the target_dirs

Raises:



64
65
66
67
68
69
70
71
72
# File 'lib/biopsy/target.rb', line 64

def locate_file name
  Settings.instance.target_dir.each do |dir|
    Dir.chdir File.expand_path(dir) do
      return File.expand_path(name) if File.exists? name
    end
  end
  raise TargetLoadError.new("Couldn't find file #{name}")
  nil
end

#respond_to?(method, *args, &block) ⇒ Boolean

accurately report ability to respond to methods passed to constructor

Returns:

  • (Boolean)


158
159
160
161
162
163
164
165
# File 'lib/biopsy/target.rb', line 158

def respond_to?(method, *args, &block)
  const_methods = @constructor.class.instance_methods(false)
  if const_methods.include? method
    true
  else
    super
  end
end

#run(params) ⇒ Object

Run the constructor for the parameter set :params



90
91
92
# File 'lib/biopsy/target.rb', line 90

def run params
  @constructor.run params
end

#store_config(config) ⇒ Object

store the values in :config, checking they are valid

Raises:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/biopsy/target.rb', line 42

def store_config config
  required = Set.new([:name, :parameters, :output])
  missing = required - config.keys
  raise TargetLoadError.new("Required keys are missing from target definition: #{missing.to_a.join(",")}") unless missing.empty?
  config.each_pair do |param, data|
    case param
    when :name
      raise TargetLoadError.new('Target name must be a string') unless data.is_a? String
      @name = data
    when :shortname
      raise TargetLoadError.new('Target shortname must be a string') unless data.is_a? String
      @shortname = data
    when :parameters
      self.generate_parameters data
    when :output
      raise TargetLoadError.new('Target output must be a hash') unless data.is_a?(Hash)
      @output = data
    end
  end
end

#valid_ruby?(file) ⇒ Boolean

true if file is valid ruby

Returns:

  • (Boolean)


95
96
97
98
99
# File 'lib/biopsy/target.rb', line 95

def valid_ruby? file
  return false unless ::File.exists? file
  result = `ruby -c #{file} > /dev/null 2>&1`
  !result.size.zero?
end