rbbt-util 4.1.0 → 4.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/bin/run_workflow.rb CHANGED
@@ -92,12 +92,15 @@ if options[:server]
92
92
  require 'compass'
93
93
 
94
94
  Workflow.require_workflow workflow
95
- WorkflowREST.add_workflows Workflow.workflows.last
95
+ WorkflowREST.add_workflows *Workflow.workflows
96
96
 
97
97
  WorkflowREST.setup
98
98
 
99
99
  Sinatra::Application.port = options[:port] || 4567
100
100
  Sinatra::Application.run = true
101
+ if File.exists? workflow
102
+ Sinatra::Application.views = File.join(File.dirname(workflow), 'www/views')
103
+ end
101
104
 
102
105
  else
103
106
 
@@ -1,9 +1,12 @@
1
+ require 'rbbt/util/misc'
1
2
  require 'rbbt/util/chain_methods'
3
+
2
4
  require 'json'
3
5
  module Annotated
4
6
  attr_accessor :annotation_types
5
7
  attr_accessor :context
6
8
  attr_accessor :container
9
+ attr_accessor :container_index
7
10
 
8
11
  def self.extended(base)
9
12
  base.annotation_types ||= []
@@ -30,53 +33,83 @@ module Annotated
30
33
 
31
34
  def self.load(object, info)
32
35
  annotation_types = info[:annotation_types]
36
+ annotation_types = annotation_types.split("+") if String === annotation_types
37
+
33
38
  annotation_types.each do |mod|
34
39
  mod = Misc.string2const(mod) if String === mod
35
- mod.setup_info(object, info)
40
+ mod.setup(object, *info.values_at(*mod.all_annotations))
36
41
  end
37
42
 
38
43
  object
39
44
  end
40
45
 
41
46
  def tsv_values(*fields)
42
- fields = fields.flatten
43
- info = self.info
44
- values = []
45
- fields.each do |field|
46
- values << case
47
- when field == "JSON"
48
- info.to_json
49
- when field == "literal"
50
- self.gsub(/\n|\t/, ' ')
51
- when info.include?(field.to_sym)
52
- info.delete(field.to_sym)
53
- when self.respond_to?(field)
54
- self.send(field)
47
+ if Array === self and (not AnnotatedArray === self or self.double_array)
48
+ Misc.zip_fields(self.compact.collect{|e| e.tsv_values(fields)})
49
+ else
50
+ fields = fields.flatten
51
+ info = self.info
52
+ values = []
53
+
54
+ fields.each do |field|
55
+ values << case
56
+ when Proc === field
57
+ field.call(self)
58
+ when field == "JSON"
59
+ info.to_json
60
+ when field == "annotation_types"
61
+ annotation_types.collect{|t| t.to_s} * "+"
62
+ when field == "literal array"
63
+ (self * "|").gsub(/\n|\t/, ' ')
64
+ when field == "literal"
65
+ self.gsub(/\n|\t/, ' ')
66
+ when info.include?(field.to_sym)
67
+ info.delete(field.to_sym)
68
+ when self.respond_to?(field)
69
+ self.send(field)
70
+ end
55
71
  end
72
+
73
+ values
56
74
  end
57
- values
58
75
  end
59
76
 
60
77
  def self.load_tsv_values(id, values, *fields)
61
78
  fields = fields.flatten
62
79
  info = {}
63
80
  literal_pos = fields.index "literal"
81
+ literal_array_pos = fields.index "literal array"
64
82
 
65
- object = if literal_pos.nil?
66
- id
83
+ object = case
84
+ when literal_pos
85
+ values[literal_pos]
86
+ when literal_array_pos
87
+ values[literal_array_pos].split("|").extend AnnotatedArray
67
88
  else
68
- v = values[literal_pos]
69
- v = v.first if Array === v
70
- v
89
+ id.dup
71
90
  end
72
91
 
73
- fields.each_with_index do |field,i|
74
- if field == "JSON"
75
- JSON.parse(values[i]).each do |key, value|
76
- info[key.to_sym] = value
92
+ if Array === values
93
+ Misc.zip_fields(values).collect do |list|
94
+ fields.each_with_index do |field,i|
95
+ if field == "JSON"
96
+ JSON.parse(list[i]).each do |key, value|
97
+ info[key.to_sym] = value
98
+ end
99
+ else
100
+ info[field.to_sym] = list[i]
101
+ end
102
+ end
103
+ end
104
+ else
105
+ fields.each_with_index do |field,i|
106
+ if field == "JSON"
107
+ JSON.parse(values[i]).each do |key, value|
108
+ info[key.to_sym] = value
109
+ end
110
+ else
111
+ info[field.to_sym] = values[i]
77
112
  end
78
- else
79
- info[field.to_sym] = values[i]
80
113
  end
81
114
  end
82
115
 
@@ -84,44 +117,71 @@ module Annotated
84
117
  end
85
118
 
86
119
  def self.tsv(annotations, *fields)
120
+ return nil if annotations.nil?
87
121
  fields = case
88
122
  when ((fields.compact.empty?) and not annotations.empty?)
89
- fields = annotations.first.annotations
123
+ fields = AnnotatedArray === annotations ? annotations.annotations : annotations.first.annotations
90
124
  fields << :annotation_types
91
125
  when (fields == [:literal] and not annotations.empty?)
92
- fields = annotations.first.annotations
93
126
  fields << :literal
94
127
  when (fields == [:all] and not annotations.empty?)
95
- fields = [:annotation_types] + annotations.first.annotations
128
+ fields = [:annotation_types] + (Annotated === annotations ? annotations.annotations : annotations.first.annotations)
96
129
  fields << :literal
97
130
  else
98
131
  fields.flatten
99
132
  end
133
+
100
134
  fields = fields.collect{|f| f.to_s}
101
135
 
102
- tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list )
136
+ fields = fields.collect{|f| ((f == "literal" and AnnotatedArray === annotations) ? "literal array" : f)}
103
137
 
104
- annotations.each do |annotation|
105
- tsv[annotation.id] = annotation.tsv_values(fields)
138
+ case
139
+ when (Annotated === annotations and not annotations.double_array)
140
+ tsv = TSV.setup({}, :key_field => "Single", :fields => fields, :type => :list, :unnamed => true)
141
+ tsv[annotations.id] = annotations.tsv_values(*fields)
142
+ when Array === annotations
143
+ tsv = TSV.setup({}, :key_field => "ID", :fields => fields, :type => :list, :unnamed => true)
144
+ annotations.compact.each do |annotation|
145
+ tsv[annotation.id] = annotation.tsv_values(*fields)
146
+ end
147
+ else
148
+ raise "Annotations need to be an Array to create TSV"
106
149
  end
107
150
 
108
151
  tsv
109
152
  end
110
153
 
111
154
  def self.load_tsv(tsv)
112
- tsv.collect do |id, values|
113
- Annotated.load_tsv_values(id, values, tsv.fields)
155
+ tsv.with_unnamed do
156
+ annotated_entities = tsv.collect do |id, values|
157
+ Annotated.load_tsv_values(id, values, tsv.fields)
158
+ end
159
+
160
+ if tsv.key_field == "Single"
161
+ annotated_entities.first
162
+ else
163
+ annotated_entities[0].annotate annotated_entities unless annotated_entities.empty?
164
+ end
114
165
  end
115
166
  end
116
167
 
117
168
  def make_list
118
169
  new = [self]
119
170
  annotation_types.each do |mod|
120
- mod.setup(new, *info.values_at(*mod.annotations))
171
+ mod.setup(new, *info.values_at(*mod.all_annotations))
121
172
  end
122
173
  new.context = self.context
123
174
  new
124
175
  end
176
+
177
+ def annotate(object)
178
+ annotation_types.each do |mod|
179
+ mod.setup(object, *info.values_at(*mod.annotations))
180
+ end
181
+ object.context = self.context
182
+ object.container = self.container
183
+ object
184
+ end
125
185
  end
126
186
 
127
187
 
@@ -145,12 +205,12 @@ module Annotation
145
205
 
146
206
  def self.extended(object)
147
207
  self.send(:prev_annotation_extended, object)
148
- object.extend Annotated
149
- if not object.annotation_types.include? self
150
- object.annotation_types.concat self.inheritance
151
- object.annotation_types << self
152
- object.annotation_types.uniq!
153
- end
208
+ object.extend Annotated unless Annotated == object
209
+ if not object.annotation_types.include? self
210
+ object.annotation_types.concat self.inheritance
211
+ object.annotation_types << self
212
+ object.annotation_types.uniq!
213
+ end
154
214
  end
155
215
 
156
216
  def self.included(base)
@@ -166,7 +226,7 @@ module Annotation
166
226
  end
167
227
 
168
228
  def update_annotations
169
- @all_annotations = all_inheritance.inject([]){|acc,mod| acc.concat mod.annotations}.concat(@annotations)
229
+ @all_annotations = all_inheritance.inject([]){|acc,mod| acc.concat mod.all_annotations}.concat(@annotations)
170
230
  end
171
231
 
172
232
  def annotation(*values)
@@ -179,14 +239,14 @@ module Annotation
179
239
  end
180
240
 
181
241
  def setup_info(object, info)
182
- object.extend self
242
+ object.extend self unless self === object
183
243
  all_annotations.each do |annotation|
184
244
  object.send(annotation.to_s + '=', info[annotation])
185
245
  end
186
246
  end
187
247
 
188
248
  def setup(object, *values)
189
- object.extend self
249
+ object.extend self unless self === object
190
250
 
191
251
  inputs = Misc.positional2hash(all_annotations, *values)
192
252
  inputs.each do |name, value|
@@ -195,29 +255,47 @@ module Annotation
195
255
 
196
256
  object
197
257
  end
258
+
198
259
  end
199
260
 
200
261
  module AnnotatedArray
201
262
  extend ChainMethods
202
263
  self.chain_prefix = :annotated_array
203
264
 
265
+ def double_array
266
+ AnnotatedArray === self.first
267
+ end
268
+
269
+ def annotated_array_first
270
+ self[0]
271
+ end
272
+
273
+ def annotated_array_last
274
+ self[-1]
275
+ end
276
+
204
277
  def annotated_array_get_brackets(pos)
205
278
  value = annotated_array_clean_get_brackets(pos)
206
279
  annotation_types.each do |mod|
207
- mod.setup(value, *info.values_at(*mod.annotations))
280
+ mod.setup(value, *info.values_at(*mod.all_annotations))
208
281
  end
209
282
  value.context = self.context
210
283
  value.container = self
284
+ value.container_index = pos
211
285
  value
212
286
  end
213
287
 
214
288
  def annotated_array_each
289
+ i = 0
215
290
  annotated_array_clean_each do |value|
291
+ value = value.dup if value.frozen?
216
292
  annotation_types.each do |mod|
217
293
  mod.setup(value, info)
218
294
  end
219
295
  value.context = self.context
220
296
  value.container = self
297
+ value.container_index = i
298
+ i += 1
221
299
  yield value
222
300
  end
223
301
  end
@@ -237,7 +315,7 @@ module AnnotatedArray
237
315
  annotated_array_each do |value|
238
316
  res << value if yield(value)
239
317
  end
240
-
318
+
241
319
  annotation_types.each do |mod|
242
320
  mod.setup(res, *info.values_at(*mod.annotations))
243
321
  end
@@ -252,7 +330,7 @@ module AnnotatedArray
252
330
  annotated_array_each do |value|
253
331
  res << value unless yield(value)
254
332
  end
255
-
333
+
256
334
  annotation_types.each do |mod|
257
335
  mod.setup(res, *info.values_at(*mod.annotations))
258
336
  end
@@ -265,7 +343,7 @@ module AnnotatedArray
265
343
  def annotated_array_subset(list)
266
344
  value = (self & list)
267
345
  annotation_types.each do |mod|
268
- mod.setup(value, *info.values_at(*mod.annotations))
346
+ mod.setup(value, *info.values_at(*mod.all_annotations))
269
347
  end
270
348
  value.context = self.context
271
349
  value.container = self.container
@@ -282,6 +360,18 @@ module AnnotatedArray
282
360
  value
283
361
  end
284
362
 
363
+ def annotated_array_compact
364
+ value = self.annotated_array_clean_compact
365
+
366
+ annotation_types.each do |mod|
367
+ mod.setup(value, *info.values_at(*mod.annotations))
368
+ end
369
+
370
+ value.context = self.context
371
+ value.container = self.container
372
+ value
373
+ end
374
+
285
375
  def annotated_array_uniq
286
376
  value = self.annotated_array_clean_uniq
287
377
 
@@ -353,11 +443,6 @@ module AnnotatedArray
353
443
  value << e if method.shift
354
444
  end
355
445
 
356
- #annotation_types.each do |mod|
357
- # mod.setup(value, *info.values_at(*mod.annotations))
358
- #end
359
- #value.context = self.context
360
- #value.container = self.container
361
446
  value
362
447
  end
363
448
  end
data/lib/rbbt/persist.rb CHANGED
@@ -10,6 +10,8 @@ module Persist
10
10
  CACHEDIR="/tmp/tsv_persistent_cache"
11
11
  FileUtils.mkdir CACHEDIR unless File.exist? CACHEDIR
12
12
 
13
+ MEMORY = {}
14
+
13
15
  def self.cachedir=(cachedir)
14
16
  CACHEDIR.replace cachedir
15
17
  FileUtils.mkdir_p CACHEDIR unless File.exist? CACHEDIR
@@ -62,7 +64,11 @@ module Persist
62
64
  persistence_dir = Misc.process_options(persist_options, :dir) || CACHEDIR
63
65
 
64
66
  filename = perfile.gsub(/\s/,'_').gsub(/\//,'>')
65
- options_md5 = Misc.hash2md5 options
67
+ clean_options = options
68
+ clean_options.delete :unnamed
69
+ clean_options.delete "unnamed"
70
+
71
+ options_md5 = Misc.hash2md5 clean_options
66
72
  filename << ":" << options_md5 unless options_md5.empty?
67
73
 
68
74
  File.join(persistence_dir, filename)
@@ -75,6 +81,8 @@ module Persist
75
81
  nil
76
82
  when :boolean
77
83
  TRUE_STRINGS.include? Open.read(path).chomp.strip
84
+ when :annotations
85
+ Annotated.load_tsv TSV.open(path)
78
86
  when :tsv
79
87
  TSV.open(path)
80
88
  when :marshal_tsv
@@ -104,7 +112,7 @@ module Persist
104
112
 
105
113
  def self.save_file(path, type, content)
106
114
 
107
- return if (content.nil? and File.exists? path)
115
+ return if content.nil?
108
116
 
109
117
  case (type || "nil").to_sym
110
118
  when :nil
@@ -116,6 +124,8 @@ module Persist
116
124
  Open.write(path, content.file.read)
117
125
  when :tsv
118
126
  Open.write(path, content.to_s)
127
+ when :annotations
128
+ Open.write(path, Annotated.tsv(content, :all).to_s)
119
129
  when :string, :text
120
130
  Open.write(path, content)
121
131
  when :array
@@ -140,19 +150,27 @@ module Persist
140
150
  def self.persist(name, type = nil, persist_options = {})
141
151
  type ||= :marshal
142
152
  persist_options = Misc.add_defaults persist_options, :persist => true
153
+ other_options = Misc.process_options persist_options, :other
143
154
 
144
155
  if persist_options[:persist]
145
- path = persistence_path(name, persist_options)
146
- Misc.lock(path) do
147
- if is_persisted?(path, persist_options)
148
- Log.debug "Persist up-to-date: #{ path } - #{persist_options.inspect}"
149
- return load_file(path, type)
150
- else
151
- Log.debug "Persist create: #{ path } - #{persist_options.inspect}"
156
+ path = persistence_path(name, persist_options, other_options || {})
157
+
158
+ case type
159
+ when :memory
160
+ Persist::MEMORY[path] ||= yield
161
+ else
162
+ Misc.lock(path) do
163
+ if is_persisted?(path, persist_options)
164
+ Log.debug "Persist up-to-date: #{ path } - #{persist_options.inspect[0..100]}"
165
+ return nil if persist_options[:no_load]
166
+ return load_file(path, type)
167
+ else
168
+ Log.debug "Persist create: #{ path } - #{persist_options.inspect[0..100]}"
169
+ end
170
+ res = yield
171
+ save_file(path, type, res)
172
+ res
152
173
  end
153
- res = yield
154
- save_file(path, type, res)
155
- res
156
174
  end
157
175
  else
158
176
  yield