rbbt-util 5.1.0 → 5.2.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/LICENSE +1 -1
- data/README.rdoc +2 -2
- data/bin/rbbt +45 -0
- data/bin/rbbt_dangling_locks.rb +9 -0
- data/bin/rbbt_monitor.rb +12 -10
- data/bin/run_workflow.rb +80 -18
- data/lib/rbbt.rb +1 -1
- data/lib/rbbt/annotations.rb +1 -19
- data/lib/rbbt/annotations/annotated_array.rb +23 -0
- data/lib/rbbt/fix_width_table.rb +2 -2
- data/lib/rbbt/persist.rb +13 -5
- data/lib/rbbt/persist/tsv.rb +2 -0
- data/lib/rbbt/resource.rb +4 -4
- data/lib/rbbt/resource/path.rb +35 -10
- data/lib/rbbt/resource/util.rb +54 -47
- data/lib/rbbt/tsv.rb +17 -15
- data/lib/rbbt/tsv/accessor.rb +35 -37
- data/lib/rbbt/tsv/excel.rb +3 -1
- data/lib/rbbt/tsv/manipulate.rb +27 -4
- data/lib/rbbt/tsv/parser.rb +13 -7
- data/lib/rbbt/util/R.rb +11 -1
- data/lib/rbbt/util/misc.rb +182 -26
- data/lib/rbbt/util/named_array.rb +14 -7
- data/lib/rbbt/util/open.rb +2 -1
- data/lib/rbbt/util/tmpfile.rb +16 -1
- data/lib/rbbt/workflow.rb +63 -101
- data/lib/rbbt/workflow/accessor.rb +19 -9
- data/lib/rbbt/workflow/annotate.rb +33 -64
- data/lib/rbbt/workflow/definition.rb +71 -0
- data/lib/rbbt/workflow/soap.rb +15 -5
- data/lib/rbbt/workflow/step.rb +57 -8
- data/lib/rbbt/workflow/usage.rb +72 -0
- data/share/lib/R/util.R +12 -0
- data/share/rbbt_commands/conf/web_user/add +26 -0
- data/share/rbbt_commands/conf/web_user/list +9 -0
- data/share/rbbt_commands/conf/web_user/remove +18 -0
- data/share/rbbt_commands/workflow/remote/add +11 -0
- data/share/rbbt_commands/workflow/remote/list +9 -0
- data/share/rbbt_commands/workflow/remote/remove +9 -0
- data/share/rbbt_commands/workflow/task +181 -0
- data/test/rbbt/test_resource.rb +2 -1
- data/test/rbbt/test_workflow.rb +13 -0
- data/test/rbbt/tsv/test_manipulate.rb +18 -0
- data/test/rbbt/util/test_misc.rb +19 -39
- data/test/rbbt/util/test_tmpfile.rb +8 -0
- data/test/rbbt/workflow/test_soap.rb +2 -0
- metadata +31 -2
@@ -8,35 +8,42 @@ module NamedArray
|
|
8
8
|
attr_accessor :fields
|
9
9
|
attr_accessor :key
|
10
10
|
attr_accessor :entity_options
|
11
|
+
attr_accessor :entity_templates
|
11
12
|
|
12
|
-
def
|
13
|
+
def entity_templates
|
14
|
+
@entity_templates ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.setup(array, fields, key = nil, entity_options = nil, entity_templates = nil)
|
13
18
|
array.extend NamedArray unless NamedArray === array
|
14
19
|
array.fields = fields
|
15
20
|
array.key = key
|
16
|
-
array.entity_options = entity_options
|
21
|
+
array.entity_options = entity_options unless entity_options.nil?
|
22
|
+
array.entity_templates = entity_templates unless entity_templates.nil?
|
17
23
|
array
|
18
24
|
end
|
19
25
|
|
20
26
|
def prepare_entity(entity, field, options = {})
|
21
27
|
return entity if entity.nil?
|
22
28
|
return entity unless defined? Entity
|
23
|
-
|
24
|
-
|
29
|
+
template = entity_templates[field]
|
30
|
+
entity_templates ||= {}
|
31
|
+
if template
|
25
32
|
entity = template.annotate(entity.frozen? ? entity.dup : entity)
|
26
33
|
entity.extend AnnotatedArray if Array === entity
|
27
34
|
entity
|
28
35
|
else
|
29
|
-
if
|
36
|
+
if entity_templates.include? field
|
30
37
|
entity
|
31
38
|
else
|
32
39
|
template = Misc.prepare_entity("TEMPLATE", field, options)
|
33
40
|
if Annotated === template
|
34
|
-
|
41
|
+
entity_templates[field] = template
|
35
42
|
entity = template.annotate(entity.frozen? ? entity.dup : entity)
|
36
43
|
entity.extend AnnotatedArray if Array === entity
|
37
44
|
entity
|
38
45
|
else
|
39
|
-
|
46
|
+
entity_templates[field] = nil
|
40
47
|
entity
|
41
48
|
end
|
42
49
|
end
|
data/lib/rbbt/util/open.rb
CHANGED
@@ -180,6 +180,7 @@ module Open
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def self.open(url, options = {})
|
183
|
+
return url if IO === url
|
183
184
|
options = Misc.add_defaults options, :noz => false, :mode => 'r'
|
184
185
|
|
185
186
|
mode = Misc.process_options options, :mode
|
@@ -283,7 +284,7 @@ module Open
|
|
283
284
|
f.flock(File::LOCK_UN)
|
284
285
|
end
|
285
286
|
rescue Exception
|
286
|
-
FileUtils.
|
287
|
+
FileUtils.rm_rf file if File.exists? file
|
287
288
|
raise $!
|
288
289
|
end
|
289
290
|
content.close
|
data/lib/rbbt/util/tmpfile.rb
CHANGED
@@ -28,8 +28,11 @@ module TmpFile
|
|
28
28
|
File.join(TMPDIR, random_name(s,max))
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.with_file(content = nil, erase = true)
|
31
|
+
def self.with_file(content = nil, erase = true, options = {})
|
32
32
|
tmpfile = tmp_file
|
33
|
+
if options[:extension]
|
34
|
+
tmpfile += ".#{options[:extension]}"
|
35
|
+
end
|
33
36
|
|
34
37
|
File.open(tmpfile, 'w') do |f| f.write content end if content != nil
|
35
38
|
|
@@ -39,4 +42,16 @@ module TmpFile
|
|
39
42
|
|
40
43
|
result
|
41
44
|
end
|
45
|
+
|
46
|
+
def self.with_dir(erase = true, options = {})
|
47
|
+
tmpdir = tmp_file
|
48
|
+
|
49
|
+
FileUtils.mkdir_p tmpdir
|
50
|
+
|
51
|
+
result = yield(tmpdir)
|
52
|
+
|
53
|
+
FileUtils.rm_rf tmpdir if File.exists?(tmpdir) and erase
|
54
|
+
|
55
|
+
result
|
56
|
+
end
|
42
57
|
end
|
data/lib/rbbt/workflow.rb
CHANGED
@@ -1,14 +1,33 @@
|
|
1
|
+
require 'rbbt/workflow/definition'
|
1
2
|
require 'rbbt/workflow/task'
|
2
3
|
require 'rbbt/workflow/step'
|
3
|
-
require 'rbbt/workflow/annotate'
|
4
4
|
require 'rbbt/workflow/accessor'
|
5
5
|
|
6
6
|
module Workflow
|
7
|
+
def self.resolve_locals(inputs)
|
8
|
+
inputs.each do |name, value|
|
9
|
+
if value =~ /^local:(.*?):(.*)/ or
|
10
|
+
(Array === value and value.length == 1 and value.first =~ /^local:(.*?):(.*)/) or
|
11
|
+
(TSV === value and value.size == 1 and value.keys.first =~ /^local:(.*?):(.*)/)
|
12
|
+
task_name = $1
|
13
|
+
jobname = $2
|
14
|
+
value = load_id(File.join(task_name, jobname)).load
|
15
|
+
end
|
16
|
+
inputs[name] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#{{{ WORKFLOW MANAGEMENT
|
7
21
|
class << self
|
8
22
|
attr_accessor :workflows
|
9
23
|
end
|
10
24
|
self.workflows = []
|
11
25
|
|
26
|
+
def self.extended(base)
|
27
|
+
self.workflows << base
|
28
|
+
base.libdir = Path.caller_lib_dir.tap{|p| p.resource = base}
|
29
|
+
end
|
30
|
+
|
12
31
|
def self.require_remote_workflow(wf_name, url)
|
13
32
|
require 'rbbt/workflow/rest/client'
|
14
33
|
eval "Object::#{wf_name} = RbbtRestClient.new '#{ url }', '#{wf_name}'"
|
@@ -95,10 +114,10 @@ module Workflow
|
|
95
114
|
rescue Exception
|
96
115
|
Log.debug $!.message
|
97
116
|
Log.debug $!.backtrace.first
|
98
|
-
raise "Workflow not found: #{ wf_name }" if wf_name == Misc.
|
99
|
-
Log.debug "Trying with humanized: '#{Misc.
|
117
|
+
raise "Workflow not found: #{ wf_name }" if wf_name == Misc.snake_case(wf_name)
|
118
|
+
Log.debug "Trying with humanized: '#{Misc.snake_case wf_name}'"
|
100
119
|
begin
|
101
|
-
require_local_workflow(Misc.
|
120
|
+
require_local_workflow(Misc.snake_case(wf_name))
|
102
121
|
rescue Exception
|
103
122
|
Log.debug $!.message
|
104
123
|
raise "Workflow not found: #{ wf_name }"
|
@@ -106,121 +125,65 @@ module Workflow
|
|
106
125
|
end
|
107
126
|
end
|
108
127
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
attr_accessor :libdir, :workdir, :tasks, :task_dependencies, :task_description, :dependencies, :asynchronous_exports, :synchronous_exports, :exec_exports, :last_task
|
114
|
-
|
115
|
-
alias prev_workflow_extended extended if methods.include? "extended"
|
116
|
-
|
117
|
-
def extended(object)
|
118
|
-
self.send(:prev_workflow_extended, object) if methods.include? "prev_workflow_extended"
|
119
|
-
object.extend Workflow unless Workflow === object
|
120
|
-
|
121
|
-
object.tasks.merge! self.tasks
|
122
|
-
object.task_dependencies.merge! self.task_dependencies
|
123
|
-
end
|
124
|
-
|
125
|
-
def dependencies
|
126
|
-
i = @dependencies; @dependencies = []; i
|
127
|
-
end
|
128
|
-
|
129
|
-
def task_dependencies
|
130
|
-
IndiferentHash.setup(@task_dependencies || {})
|
131
|
-
end
|
132
|
-
|
133
|
-
def tasks
|
134
|
-
IndiferentHash.setup(@tasks || {})
|
135
|
-
end
|
136
|
-
end
|
128
|
+
attr_accessor :libdir, :workdir
|
129
|
+
attr_accessor :helpers, :tasks
|
130
|
+
attr_accessor :task_dependencies, :task_description, :last_task
|
131
|
+
attr_accessor :asynchronous_exports, :synchronous_exports, :exec_exports
|
137
132
|
|
138
|
-
|
139
|
-
base.workdir = Rbbt.var.jobs.find
|
140
|
-
else
|
141
|
-
base.workdir = Path.setup('var/jobs')
|
142
|
-
end
|
143
|
-
base.tasks = {}
|
144
|
-
base.dependencies = []
|
145
|
-
base.task_dependencies = {}
|
146
|
-
base.task_description = {}
|
147
|
-
base.asynchronous_exports = []
|
148
|
-
base.synchronous_exports = []
|
149
|
-
base.exec_exports = []
|
150
|
-
base.libdir = Path.caller_lib_dir
|
151
|
-
end
|
152
|
-
self.workflows << base
|
153
|
-
end
|
133
|
+
#{{{ ATTR DEFAULTS
|
154
134
|
|
155
|
-
|
135
|
+
def workdir
|
136
|
+
@workdir ||= if defined? Rbbt
|
137
|
+
Rbbt.var.jobs[self].find
|
138
|
+
else
|
139
|
+
Path.setup('var/jobs')
|
140
|
+
end
|
141
|
+
end
|
156
142
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
else
|
162
|
-
result_type = :marshal
|
163
|
-
end
|
143
|
+
def libdir
|
144
|
+
@libdir = Path.caller_lib_dir if @libdir.nil?
|
145
|
+
@libdir
|
146
|
+
end
|
164
147
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
result_type = result_type
|
170
|
-
annotations = {
|
171
|
-
:name => name,
|
172
|
-
:inputs => inputs,
|
173
|
-
:description => description,
|
174
|
-
:input_types => input_types,
|
175
|
-
:result_type => Array == result_type ? result_type.to_sym : result_type,
|
176
|
-
:input_defaults => input_defaults,
|
177
|
-
:input_descriptions => input_descriptions,
|
178
|
-
:input_options => input_options,
|
179
|
-
:result_description => result_description
|
180
|
-
}
|
181
|
-
|
182
|
-
task = Task.setup(annotations, &block)
|
148
|
+
def helpers
|
149
|
+
@helpers ||= {}
|
150
|
+
end
|
183
151
|
|
184
|
-
|
185
|
-
@tasks
|
186
|
-
@task_dependencies[name] = dependencies
|
152
|
+
def tasks
|
153
|
+
@tasks ||= {}
|
187
154
|
end
|
188
155
|
|
189
|
-
def
|
190
|
-
@
|
156
|
+
def task_dependencies
|
157
|
+
@task_dependencies ||= {}
|
191
158
|
end
|
192
159
|
|
193
|
-
def
|
194
|
-
@
|
160
|
+
def task_description
|
161
|
+
@task_description ||= {}
|
195
162
|
end
|
196
163
|
|
197
|
-
def
|
198
|
-
@
|
164
|
+
def asynchronous_exports
|
165
|
+
@asynchronous_exports ||= []
|
199
166
|
end
|
200
167
|
|
201
|
-
|
168
|
+
def synchronous_exports
|
169
|
+
@synchronous_exports ||= []
|
170
|
+
end
|
202
171
|
|
203
|
-
def
|
204
|
-
|
205
|
-
if value =~ /^local:(.*?):(.*)/ or
|
206
|
-
(Array === value and value.length == 1 and value.first =~ /^local:(.*?):(.*)/) or
|
207
|
-
(TSV === value and value.size == 1 and value.keys.first =~ /^local:(.*?):(.*)/)
|
208
|
-
task_name = $1
|
209
|
-
jobname = $2
|
210
|
-
value = load_id(File.join(task_name, jobname)).load
|
211
|
-
end
|
212
|
-
inputs[name] = value
|
213
|
-
end
|
172
|
+
def exec_exports
|
173
|
+
@exec_exports ||= []
|
214
174
|
end
|
215
175
|
|
176
|
+
# {{{ JOB MANAGEMENT
|
177
|
+
|
216
178
|
def job(taskname, jobname = nil, inputs = {})
|
179
|
+
taskname = taskname.to_sym
|
217
180
|
jobname = "Default" if jobname.nil? or jobname.empty?
|
218
181
|
task = tasks[taskname]
|
219
182
|
raise "Task not found: #{ taskname }" if task.nil?
|
220
183
|
|
221
184
|
IndiferentHash.setup(inputs)
|
222
185
|
|
223
|
-
resolve_locals(inputs)
|
186
|
+
Workflow.resolve_locals(inputs)
|
224
187
|
|
225
188
|
dependencies = real_dependencies(task, jobname, inputs, task_dependencies[taskname] || [])
|
226
189
|
|
@@ -230,9 +193,8 @@ module Workflow
|
|
230
193
|
|
231
194
|
step = Step.new step_path, task, input_values, dependencies
|
232
195
|
|
233
|
-
helpers
|
234
|
-
|
235
|
-
helpers.each do |name, block|
|
196
|
+
helpers.each do |name, block|
|
197
|
+
(class << step; self; end).instance_eval do
|
236
198
|
define_method name, &block
|
237
199
|
end
|
238
200
|
end
|
@@ -242,13 +204,13 @@ module Workflow
|
|
242
204
|
|
243
205
|
def load_step(path)
|
244
206
|
task = task_for path
|
245
|
-
Step.new path, tasks[task]
|
207
|
+
Step.new path, tasks[task.to_sym]
|
246
208
|
end
|
247
209
|
|
248
210
|
def load_id(id)
|
249
211
|
path = File.join(workdir, id)
|
250
212
|
task = task_for path
|
251
|
-
step = Step.new path, tasks[task]
|
213
|
+
step = Step.new path, tasks[task.to_sym]
|
252
214
|
if step.info.include? :dependencies
|
253
215
|
step.dependencies = step.info[:dependencies].collect do |task, job|
|
254
216
|
load_id(File.join(task.to_s, job))
|
@@ -11,6 +11,10 @@ class Step
|
|
11
11
|
name.sub(/(.*)_.*/, '\1')
|
12
12
|
end
|
13
13
|
|
14
|
+
def task_name
|
15
|
+
@task_name ||= task.name
|
16
|
+
end
|
17
|
+
|
14
18
|
# {{{ INFO
|
15
19
|
|
16
20
|
def info_file
|
@@ -71,8 +75,13 @@ class Step
|
|
71
75
|
end
|
72
76
|
|
73
77
|
def done?
|
74
|
-
|
75
|
-
|
78
|
+
path.exists?
|
79
|
+
end
|
80
|
+
|
81
|
+
def running?
|
82
|
+
return nil if not File.exists? info_file
|
83
|
+
return nil if info[:pid].nil?
|
84
|
+
return Misc.pid_exists? info[:pid]
|
76
85
|
end
|
77
86
|
|
78
87
|
def error?
|
@@ -166,6 +175,7 @@ module Workflow
|
|
166
175
|
end
|
167
176
|
|
168
177
|
def task_info(name)
|
178
|
+
name = name.to_sym
|
169
179
|
task = tasks[name]
|
170
180
|
description = task.description
|
171
181
|
result_description = task.result_description
|
@@ -187,7 +197,7 @@ module Workflow
|
|
187
197
|
end
|
188
198
|
|
189
199
|
|
190
|
-
dependencies =
|
200
|
+
dependencies = task_dependencies[name].select{|dep| String === dep or Symbol === dep}
|
191
201
|
{ :id => File.join(self.to_s, name.to_s),
|
192
202
|
:description => description,
|
193
203
|
:export => export,
|
@@ -213,23 +223,23 @@ module Workflow
|
|
213
223
|
end
|
214
224
|
|
215
225
|
def rec_inputs(taskname)
|
216
|
-
[taskname].concat(rec_dependencies(taskname)).inject([]){|acc, tn| acc.concat tasks[tn].inputs}
|
226
|
+
[taskname].concat(rec_dependencies(taskname)).inject([]){|acc, tn| acc.concat tasks[tn.to_sym].inputs}
|
217
227
|
end
|
218
228
|
|
219
229
|
def rec_input_defaults(taskname)
|
220
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn].input_defaults}
|
230
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_defaults}
|
221
231
|
end
|
222
232
|
|
223
233
|
def rec_input_types(taskname)
|
224
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn].input_types}
|
234
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_types}
|
225
235
|
end
|
226
236
|
|
227
237
|
def rec_input_descriptions(taskname)
|
228
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn].input_descriptions}
|
238
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_descriptions}
|
229
239
|
end
|
230
240
|
|
231
241
|
def rec_input_options(taskname)
|
232
|
-
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn].input_options}
|
242
|
+
[taskname].concat(rec_dependencies(taskname)).inject({}){|acc, tn| acc.merge tasks[tn.to_sym].input_options}
|
233
243
|
end
|
234
244
|
|
235
245
|
|
@@ -240,7 +250,7 @@ module Workflow
|
|
240
250
|
when Step === dependency
|
241
251
|
dependency
|
242
252
|
when Symbol === dependency
|
243
|
-
job
|
253
|
+
job(dependency, jobname, inputs)
|
244
254
|
when Proc === dependency
|
245
255
|
dependency.call jobname, inputs
|
246
256
|
end
|
@@ -1,79 +1,48 @@
|
|
1
1
|
module AnnotatedModule
|
2
|
-
def self.extended(base)
|
3
|
-
if not base.respond_to? :inputs
|
4
|
-
class << base
|
5
|
-
attr_accessor :description, :inputs, :input_types, :input_descriptions, :input_defaults, :input_options, :result_description, :helpers
|
6
2
|
|
7
|
-
|
8
|
-
|
3
|
+
def self.add_consummable_annotation(target, *annotations)
|
4
|
+
if annotations.length == 1 and Hash === annotations.first
|
5
|
+
annotations.first.each do |annotation, default|
|
6
|
+
target.send(:attr_accessor, annotation)
|
7
|
+
target.send(:define_method, "consume_#{annotation}") do
|
8
|
+
value = instance_variable_get("@#{annotation}") || default.dup
|
9
|
+
instance_variable_set("@#{annotation}", default.dup)
|
10
|
+
value
|
9
11
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def input_descriptions
|
20
|
-
i = @input_descriptions; @input_descriptions = {}; i
|
21
|
-
end
|
22
|
-
|
23
|
-
def input_defaults
|
24
|
-
i = @input_defaults; @input_defaults = {}; i
|
25
|
-
end
|
26
|
-
|
27
|
-
def input_options
|
28
|
-
i = @input_options; @input_options = {}; i
|
29
|
-
end
|
30
|
-
|
31
|
-
def description
|
32
|
-
i = @description; @description = ""; i
|
33
|
-
end
|
34
|
-
|
35
|
-
def result_description
|
36
|
-
i = @result_description; @result_description = nil; i
|
12
|
+
end
|
13
|
+
else
|
14
|
+
annotations.each do |annotation|
|
15
|
+
target.send(:attr_accessor, annotation)
|
16
|
+
target.send(:define_method, "consume_#{annotation}") do
|
17
|
+
value = instance_variable_get("@#{annotation}")
|
18
|
+
instance_variable_set("@#{annotation}", nil)
|
37
19
|
end
|
38
20
|
end
|
39
|
-
|
40
|
-
base.description = ""
|
41
|
-
base.inputs = []
|
42
|
-
base.input_types = {}
|
43
|
-
base.input_descriptions = {}
|
44
|
-
base.input_defaults = {}
|
45
|
-
base.input_options = {}
|
46
|
-
base.helpers = {}
|
47
|
-
|
48
21
|
end
|
49
22
|
end
|
50
23
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
def desc(description)
|
60
|
-
@description = description
|
61
|
-
end
|
62
|
-
|
63
|
-
def dep(*dependencies, &block)
|
64
|
-
dependencies << block if block_given?
|
65
|
-
@dependencies.concat dependencies
|
66
|
-
end
|
24
|
+
add_consummable_annotation(self,
|
25
|
+
:description => "",
|
26
|
+
:inputs => [],
|
27
|
+
:input_types => {},
|
28
|
+
:input_descriptions => {},
|
29
|
+
:input_defaults => {},
|
30
|
+
:input_options => {})
|
67
31
|
|
68
32
|
def input(name, type = nil, desc = nil, default = nil, options = nil)
|
69
33
|
name = name.to_sym
|
70
34
|
type = type.to_sym
|
71
|
-
|
72
|
-
@
|
35
|
+
|
36
|
+
@inputs = [] if @inputs.nil?
|
37
|
+
@input_types = {} if @input_types.nil?
|
38
|
+
@input_descriptions = {} if @input_descriptions.nil?
|
39
|
+
@input_defaults = {} if @input_defaults.nil?
|
40
|
+
@input_options = {} if @input_options.nil?
|
41
|
+
|
42
|
+
@inputs << name
|
43
|
+
@input_types[name] = type unless type.nil?
|
73
44
|
@input_descriptions[name] = desc unless desc.nil?
|
74
|
-
@input_defaults[name]
|
75
|
-
@input_options[name]
|
45
|
+
@input_defaults[name] = default unless default.nil?
|
46
|
+
@input_options[name] = options unless options.nil?
|
76
47
|
end
|
77
48
|
end
|
78
|
-
|
79
|
-
|