omf_oml 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+
2
+ require 'csv'
3
+ require 'omf_oml'
4
+ require 'omf_oml/table'
5
+
6
+
7
+
8
+ module OMF::OML
9
+
10
+ # This class represents a table whose content is initially stored in a
11
+ # CSV file.
12
+ #
13
+ class OmlCsvTable < OmlTable
14
+
15
+ # @param opts
16
+ #
17
+ def self.create(tname, file_name, opts = {}, &on_before_row_added)
18
+ self.new(tname, file_name, opts, &on_before_row_added)
19
+ end
20
+
21
+ #
22
+ # tname - Name of table
23
+ # schema - OmlSchema or Array containing [name, type*] for every column in table
24
+ # Table adds a '__id__' column at the beginning which keeps track of the rows unique id
25
+ # @params opts
26
+ # @opts :max_size - keep table to that size by dropping older rows
27
+ # @opts :index - only keep the latest inserted row for a unique col value - messes with row order
28
+ # @opts :has_csv_header If true use first row in file as schema descriptor
29
+ # @opts :schema Schema associated with this table
30
+ #
31
+ def initialize(tname, file_name, opts = {}, &on_before_row_added)
32
+ unless File.readable?(file_name)
33
+ raise "Can't read CSV file '#{file_name}'"
34
+ end
35
+ csv_opts = {}
36
+ csv_opts[:headers] = (opts.delete(:has_csv_header) == true)
37
+ unless csv_opts[:headers]
38
+ raise "Current implementation only works with CSV files which inlcude a schema description in the first line"
39
+ end
40
+
41
+ encoding = opts.delete(:encoding)
42
+ mode = "rb"
43
+ mode << ":#{encoding}" if encoding
44
+ csv = CSV.open(file_name, mode, csv_opts)
45
+
46
+ unless schema = opts.delete(:schema)
47
+ unless csv_opts[:headers]
48
+ raise "No schema given and ':has_csv_header' not set to capture schema from file header"
49
+ end
50
+ first_row = csv.shift.fields # force reading the first row to have the header parsed
51
+ #csv.shift.each do |h, v| puts "#{h} => #{v.class}" end
52
+ schema = csv.headers.map do |c|
53
+ c = c.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?')
54
+ name, type = c.split(':')
55
+ [name, type || 'string']
56
+ end
57
+ end
58
+ super tname, schema, opts
59
+
60
+ if first_row # from getting the CSV header
61
+ first_row.insert(0, @row_id += 1) if @add_index
62
+ @rows = [@schema.cast_row(first_row)]
63
+ end
64
+
65
+ # This assumes that CSV reader is setup with proper schema converters
66
+ csv.each do |r|
67
+ # Convert any strange strings into a clean ruby string
68
+ row = r.fields.map do |e|
69
+ e ? e.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?') : nil
70
+ end
71
+ row.insert(0, @row_id += 1) if @add_index
72
+ @rows << @schema.cast_row(row)
73
+ end
74
+
75
+ end
76
+
77
+
78
+
79
+ end # class
80
+ end # module
@@ -1,5 +1,5 @@
1
1
 
2
- require 'omf_common/lobject'
2
+ require 'omf_base/lobject'
3
3
  require 'omf_oml'
4
4
 
5
5
  require 'omf_oml/oml_tuple'
@@ -10,7 +10,7 @@ module OMF::OML
10
10
  # be visualized. After creating the object, the @run@ method needs to be called to
11
11
  # start processing the stream.
12
12
  #
13
- class OmlEndpoint < OMF::Common::LObject
13
+ class OmlEndpoint < OMF::Base::LObject
14
14
 
15
15
  # Register a proc to be called when a new stream was
16
16
  # discovered on this endpoint.
@@ -77,7 +77,7 @@ module OMF::OML
77
77
  # and instance and then immediately calls the +run+ methods.
78
78
  #
79
79
  #
80
- class OmlSession < OMF::Common::LObject # :nodoc
80
+ class OmlSession < OMF::Base::LObject # :nodoc
81
81
 
82
82
  # Return the value for the respective @key@ in the protocol header.
83
83
  #
@@ -1,7 +1,7 @@
1
1
  require 'monitor'
2
2
  require 'json'
3
3
  require 'set'
4
- require 'omf_common/lobject'
4
+ require 'omf_base/lobject'
5
5
  require 'omf_oml'
6
6
 
7
7
 
@@ -19,7 +19,7 @@ module OMF::OML
19
19
  # This class represents a network consisting of nodes and links with their respective
20
20
  # attributes.
21
21
  #
22
- class OmlNetwork < OMF::Common::LObject
22
+ class OmlNetwork < OMF::Base::LObject
23
23
  include MonitorMixin
24
24
 
25
25
  @@name2network = {}
@@ -310,7 +310,7 @@ module OMF::OML
310
310
 
311
311
  # This class represents an abstract network element and shouldn't be used directly.
312
312
  #
313
- class NetworkElement < OMF::Common::LObject
313
+ class NetworkElement < OMF::Base::LObject
314
314
 
315
315
  attr_reader :name
316
316
  attr_reader :el_id
@@ -449,7 +449,7 @@ end
449
449
 
450
450
  if $0 == __FILE__
451
451
  require 'json'
452
- include OMF::Common::OML
452
+ include OMF::Base::OML
453
453
 
454
454
  nw = OmlNetwork.new
455
455
 
@@ -1,12 +1,12 @@
1
1
 
2
- require 'omf_common/lobject'
2
+ require 'omf_base/lobject'
3
3
  require 'omf_oml'
4
4
 
5
5
  module OMF::OML
6
6
 
7
7
  # This class represents the schema of an OML measurement stream.
8
8
  #
9
- class OmlSchema < OMF::Common::LObject
9
+ class OmlSchema < OMF::Base::LObject
10
10
 
11
11
  CLASS2TYPE = {
12
12
  TrueClass => 'boolean',
@@ -4,7 +4,7 @@ require 'time'
4
4
  require 'logger'
5
5
  require 'sequel'
6
6
 
7
- require 'omf_common/lobject'
7
+ require 'omf_base/lobject'
8
8
  require 'omf_oml'
9
9
 
10
10
  # module OMF::OML
@@ -14,7 +14,7 @@ require 'omf_oml'
14
14
  module OMF::OML::Sequel
15
15
  module Server
16
16
 
17
- class Query < OMF::Common::LObject
17
+ class Query < OMF::Base::LObject
18
18
 
19
19
  def self.parse(xmls, repoFactory = RepositoryFactory.new, logger = Logger.new(STDOUT))
20
20
  if xmls.kind_of? String
@@ -222,7 +222,7 @@ module OMF::OML::Sequel
222
222
 
223
223
  end # Query
224
224
 
225
- class RepositoryFactory < OMF::Common::LObject
225
+ class RepositoryFactory < OMF::Base::LObject
226
226
 
227
227
  def initialize(opts = {})
228
228
  @opts = opts
@@ -1,52 +1,52 @@
1
1
 
2
- require 'omf_oml/tuple'
2
+ require 'omf_oml/oml_tuple'
3
3
  require 'omf_oml/table'
4
4
 
5
5
  module OMF::OML
6
-
7
6
 
8
-
7
+
8
+
9
9
  # Read the content of a table and feeds it out as a tuple store.
10
10
  # After creation of the object. The actual tuple feed is started
11
11
  # with a call to +run+.
12
12
  #
13
13
  class OmlSqlRow < OmlTuple
14
14
  attr_reader :row
15
-
16
- #
15
+
16
+ #
17
17
  # Create a representation of a row in a database. Can be used to fill a table.
18
18
  #
19
19
  # @param [String] sql_table_name - name of SQL table in respective SQL database
20
20
  # @param [OmlSchema] schema - the schema describing the tuple
21
- # @param [Sequel] db - Database
22
- # @param [Hash] opts:
21
+ # @param [Sequel::Dataset] query - Databasequery to execute
22
+ # @param [Hash] opts:
23
23
  # - offset: Ignore first +offset+ rows. If negative or zero serve +offset+ rows initially
24
24
  # - limit: Number of rows to fetch each time [1000]
25
- # - check_interval: Interval in seconds when to check for new data. If 0, only run once.
25
+ # - check_interval: Interval in seconds when to check for new data. If < 0, only run once.
26
26
  # - query_interval: Interval between consecutive queries when processing large result set.
27
27
  #
28
- def initialize(sql_table_name, schema, db, opts = {})
28
+ def initialize(sql_table_name, schema, query, opts = {})
29
29
  @sname = sql_table_name
30
30
  @schema = schema
31
31
  raise "Expected OmlSchema but got '#{schema.class}" unless schema.is_a? OmlSchema
32
- @db = db
33
-
32
+ @query = query
33
+
34
34
  unless @offset = opts[:offset]
35
35
  @offset = 0
36
36
  end
37
37
  @limit = opts[:limit]
38
38
  @limit = 1000 unless @limit
39
-
39
+
40
40
  @check_interval = opts[:check_interval]
41
- @check_interval = 0 unless @check_interval
41
+ @check_interval = -1 unless @check_interval
42
42
  @query_interval = opts[:query_interval]
43
-
43
+
44
44
  @on_new_vector_proc = {}
45
45
 
46
- super opts[:name] || sql_table_name, schema
46
+ super opts[:name] || sql_table_name, schema
47
47
  end
48
-
49
-
48
+
49
+
50
50
  # Return a specific element of the vector identified either
51
51
  # by it's name, or its col index
52
52
  #
@@ -56,18 +56,18 @@ module OMF::OML
56
56
  else
57
57
  unless @row.key? name_or_index
58
58
  raise "Unknown column name '#{name_or_index}'"
59
- end
59
+ end
60
60
  @row[name_or_index]
61
61
  end
62
62
  end
63
-
64
- # Return the elements of the row as an array using the
63
+
64
+ # Return the elements of the row as an array using the
65
65
  # associated schema or 'schema' if non-nil.
66
66
  #
67
67
  def to_a(schema = nil)
68
68
  a = (schema || @schema).hash_to_row(@row) # don't need type conversion as sequel is doing this for us
69
69
  end
70
-
70
+
71
71
  # Return an array including the values for the names elements
72
72
  # given as parameters.
73
73
  #
@@ -76,19 +76,19 @@ module OMF::OML
76
76
  col_names.collect do |n|
77
77
  unless @row.key? n
78
78
  raise "Unknown column name '#{n}'"
79
- end
79
+ end
80
80
  @row[n]
81
81
  end
82
82
  end
83
-
83
+
84
84
  def ts
85
85
  self[:oml_ts_server]
86
86
  end
87
-
87
+
88
88
  def seq_no
89
89
  self[:oml_seq]
90
- end
91
-
90
+ end
91
+
92
92
  # Register a proc to be called when a new tuple arrived
93
93
  # on this stream.
94
94
  #
@@ -149,14 +149,14 @@ module OMF::OML
149
149
  self.on_new_tuple(t) do |v|
150
150
  r = v.to_a(schema)
151
151
  #puts r.inspect
152
- t.add_row(r)
152
+ t.add_row(r)
153
153
  end
154
154
  t
155
155
  end
156
156
 
157
157
 
158
158
  protected
159
-
159
+
160
160
  def run(in_thread = true)
161
161
  return if @running
162
162
  if in_thread
@@ -172,16 +172,17 @@ module OMF::OML
172
172
  _run
173
173
  end
174
174
  end
175
-
175
+
176
176
  private
177
-
177
+
178
178
  def _run
179
179
  if @check_interval <= 0
180
- while _run_once; end
180
+ #while _run_once; end
181
+ _run_once
181
182
  else
182
183
  @running = true
183
184
  while (@running)
184
- begin
185
+ begin
185
186
  unless _run_once
186
187
  # All rows read, wait a bit for news to show up
187
188
  sleep @check_interval
@@ -190,22 +191,22 @@ module OMF::OML
190
191
  warn ex
191
192
  debug "\t", ex.backtrace.join("\n\t")
192
193
  end
193
- end
194
+ end
194
195
  end
195
196
  end
196
-
197
+
197
198
  # Run a query on database an serve all rows found one at a time.
198
199
  # Return true if there might be more rows in the database
199
200
  def _run_once
200
201
  row_cnt = 0
201
202
  t = table_name = @sname
202
203
  if (@offset < 0)
203
- cnt = @db[table_name.to_sym].count()
204
+ cnt = @query.count()
204
205
  @offset = cnt + @offset # @offset was negative here
205
206
  debug("Initial offset #{@offset} in '#{table_name}' with #{cnt} rows")
206
207
  @offset = 0 if @offset < 0
207
208
  end
208
- @db["SELECT _senders.name as oml_sender, #{t}.* FROM #{t} INNER JOIN _senders ON (_senders.id = #{t}.oml_sender_id) LIMIT #{@limit} OFFSET #{@offset};"].each do |r|
209
+ @query.limit(@limit, @offset).each do |r|
209
210
  @row = r
210
211
  @on_new_vector_proc.each_value do |proc|
211
212
  proc.call(self)
@@ -216,10 +217,10 @@ module OMF::OML
216
217
  debug "Read #{row_cnt} (total #{@offset}) rows from '#{@sname}'" if row_cnt > 0
217
218
  if more_to_read = row_cnt >= @limit # there could be more to read
218
219
  sleep @query_interval if @query_interval # don't hammer database
219
- end
220
- more_to_read
220
+ end
221
+ more_to_read
221
222
  end
222
-
223
+
223
224
  end # OmlSqlRow
224
225
 
225
226
 
@@ -227,8 +228,19 @@ end
227
228
 
228
229
  if $0 == __FILE__
229
230
 
231
+ OMF::Base::Loggable.init_log('sql_row_test')
232
+
233
+ require 'omf_oml/sql_source'
234
+ db_file = File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3')
235
+ ss = OMF::OML::OmlSqlSource.new('sqlite://' + File.absolute_path(db_file))
236
+
237
+ r = ss.create_stream('wimaxmonitor_wimaxstatus')
238
+ puts r
239
+
240
+ exit
241
+
230
242
  require 'omf_oml/table'
231
- ep = OMF::OML::OmlSqlSource.new('brooklynDemo.sq3')
243
+ ep = OMF::OML::OmlSqlSource.new(File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3'))
232
244
  ep.on_new_stream() do |s|
233
245
  puts ">>>>>>>>>>>> New stream #{s.stream_name}: #{s.names.join(', ')}"
234
246
  case s.stream_name
@@ -239,7 +251,7 @@ if $0 == __FILE__
239
251
  end
240
252
 
241
253
  s.on_new_vector() do |v|
242
- puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
254
+ puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
243
255
  end
244
256
  end
245
257
  ep.run()
@@ -1,7 +1,7 @@
1
1
 
2
2
  require 'sequel'
3
3
 
4
- require 'omf_common/lobject'
4
+ require 'omf_base/lobject'
5
5
  require 'omf_oml/endpoint'
6
6
  require 'omf_oml/tuple'
7
7
  require 'omf_oml/sql_row'
@@ -14,12 +14,12 @@ module OMF::OML
14
14
  # After creating the object, the @run@ method needs to be called to
15
15
  # start producing the streams.
16
16
  #
17
- class OmlSqlSource < OMF::Common::LObject
18
-
17
+ class OmlSqlSource < OMF::Base::LObject
18
+
19
19
  # Sequel adaptors sometimes don't return a :type identifier,
20
20
  # but always return the :db_type. This is a list of maps which may not work
21
21
  # for all adaptors
22
- #
22
+ #
23
23
  FALLBACK_MAPPING = {
24
24
  'UNSIGNED INTEGER' => :integer
25
25
  }
@@ -49,42 +49,44 @@ module OMF::OML
49
49
  @on_new_stream_procs.delete key
50
50
  end
51
51
  end
52
-
53
- # Return a table (more precisely an OmlTable instance) fed from
52
+
53
+ # Return a table (more precisely an OmlTable instance) fed from
54
54
  # the content of a table 'table_name' in this database.
55
55
  #
56
56
  # table_name - Name of table in the SQL database
57
- # opts -
58
- # :include_oml_internals - Include OML 'header' columns [true]
57
+ # opts -
59
58
  # :name - name used for returned OML Table [table_name]
60
59
  # All other options defined for OmlSqlRow#new
61
60
  #
62
61
  def create_table(table_name, opts = {})
63
62
  tn = opts.delete(:name) || table_name
64
63
  schema = _schema_for_table(table_name)
65
- r = OmlSqlRow.new(table_name, schema, @db, opts)
64
+ r = OmlSqlRow.new(table_name, schema, _def_query_for_table(table_name), opts)
66
65
  r.to_table(tn, opts)
67
66
  end
68
-
67
+
69
68
  # Call 'block' for every row in 'table_name' table.
70
69
  #
71
70
  # table_name - Name of table in the SQL database
72
- # opts -
73
- # :include_oml_internals[boolean] - Include OML 'header' columns [true]
71
+ # opts -
74
72
  # :schema[Schema] Schema to use for creating row
75
73
  # All other options defined for OmlSqlRow#new
74
+ # returns OmlSqlRow
76
75
  #
77
76
  def create_stream(table_name, opts = {}, &block)
78
77
  rschema = opts.delete(:schema)
79
78
  schema = _schema_for_table(table_name)
80
- r = OmlSqlRow.new(table_name, schema, @db, opts)
81
- ropts = {}
82
- ropts[:schema] = rschema if rschema
83
- r.to_stream(ropts, &block)
79
+ r = OmlSqlRow.new(table_name, schema, _def_query_for_table(table_name), opts)
80
+ if block
81
+ ropts = {}
82
+ ropts[:schema] = rschema if rschema
83
+ r.to_stream(ropts, &block)
84
+ end
85
+ r
84
86
  end
85
87
 
86
88
  #
87
- # Run a query on the database and return the result as an OmlTable. The provided schema
89
+ # Run a query on the database and return the result as an OmlTable. The provided schema
88
90
  # needs to describe the SQL queries result set. Unfortunately we can only do very little
89
91
  # sanity checks here
90
92
  #
@@ -96,6 +98,33 @@ module OMF::OML
96
98
  tbl
97
99
  end
98
100
 
101
+ #
102
+ # Run a query on the database and return the result as an OmlTable. The provided schema
103
+ # needs to describe the SQL queries result set. Unfortunately we can only do very little
104
+ # sanity checks here. The query will be defined in the provided block which is passed in
105
+ # the Sequel Database object and is expected to return a Sequel Dataset instance.
106
+ #
107
+ def query2(table_name, schema, &block)
108
+ tbl = OmlTable.create(table_name, schema)
109
+ q = block.call(@db)
110
+ unless q.is_a? Sequel::Dataset
111
+ raise "Expected a Sequel::Dataset object, but got '#{q.class}'"
112
+ end
113
+ q.each do |row|
114
+ tbl << tbl.schema.hash_to_row(row)
115
+ end
116
+ tbl
117
+ end
118
+
119
+ # Return a Sequel Dataset from 'table_name'. See Sequel documentation on
120
+ # what one can do with that.
121
+ #
122
+ # db_table_name Name of table in database
123
+ #
124
+ def dataset(db_table_name)
125
+ @db.from(db_table_name)
126
+ end
127
+
99
128
  # Start checking the database for tables and create a new stream
100
129
  # by calling the internal +report_new_table+ method.
101
130
  # If +check_every+ > 0 continue checking every +check_every+ seconds
@@ -130,11 +159,6 @@ module OMF::OML
130
159
  report_new_table(table_name) unless table_name.start_with?('_')
131
160
  end
132
161
  @tables
133
-
134
- # postgresql
135
- # SELECT tablename FROM pg_tables
136
- # WHERE tablename NOT LIKE �pg\\_%�
137
- # AND tablename NOT LIKE �sql\\_%�;
138
162
  end
139
163
 
140
164
 
@@ -158,7 +182,7 @@ module OMF::OML
158
182
  end
159
183
  table
160
184
  end
161
-
185
+
162
186
  def _schema_for_table(table_name)
163
187
  begin
164
188
  schema_descr = @db.schema(table_name).map do |col_name, cd|
@@ -173,30 +197,54 @@ module OMF::OML
173
197
  raise "Problems reading schema of table '#{table_name}'. Does it exist? (#{@db.tables})"
174
198
  end
175
199
  end
200
+
201
+ def _def_query_for_table(table_name)
202
+ t = table_name
203
+ @db["SELECT _senders.name as oml_sender, a.* FROM #{t} AS a INNER JOIN _senders ON (_senders.id = a.oml_sender_id);"]
204
+ end
176
205
  end
177
-
206
+
178
207
 
179
208
 
180
209
  end
181
210
 
182
211
  if $0 == __FILE__
212
+ OMF::Base::Loggable.init_log('sql_source_test')
183
213
 
184
214
  require 'omf_oml/table'
185
- ep = OMF::OML::OmlSqlSource.new('brooklynDemo.sq3')
186
- ep.on_new_stream() do |s|
187
- puts ">>>>>>>>>>>> New stream #{s.stream_name}: #{s.names.join(', ')}"
188
- case s.stream_name
189
- when 'wimaxmonitor_wimaxstatus'
190
- select = [:oml_ts_server, :sender_hostname, :frequency, :signal, :rssi, :cinr, :avg_tx_pw]
191
- when 'GPSlogger_gps_data'
192
- select = [:oml_ts_server, :oml_sender_id, :lat, :lon]
193
- end
215
+ db_file = File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3')
216
+ ep = OMF::OML::OmlSqlSource.new('sqlite://' + File.absolute_path(db_file), limit: 10)
217
+
218
+ def on_new_stream(ep)
219
+ ep.on_new_stream() do |s|
220
+ puts ">>>>>>>>>>>> New stream #{s.stream_name}: #{s.schema.names}"
221
+ case s.stream_name
222
+ when 'wimaxmonitor_wimaxstatus'
223
+ select = [:oml_ts_server, :sender_hostname, :frequency, :signal, :rssi, :cinr, :avg_tx_pwr]
224
+ when 'GPSlogger_gps_data'
225
+ select = [:oml_ts_server, :oml_sender_id, :lat, :lon]
226
+ end
194
227
 
195
- s.on_new_vector() do |v|
196
- puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
228
+ s.on_new_tuple() do |v|
229
+ begin
230
+ puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
231
+ rescue Exception => ex
232
+ puts "ERROR: #{ex}"
233
+ abort
234
+ end
235
+ end
197
236
  end
237
+ ep.run()
198
238
  end
199
- ep.run()
239
+
240
+ t = ep.query2('gps', [[:lat, :float], [:lon, :float]]) do |db|
241
+ db.from('GPSlogger_gps_data').select(:lat, :lon).limit(2)
242
+ end
243
+ puts t.rows.inspect
244
+ puts t.schema
245
+
246
+ # Raw query on database
247
+ puts ep.dataset('GPSlogger_gps_data').select(:lat, :lon).limit(2).all
200
248
 
201
249
  end
202
250
 
data/lib/omf_oml/table.rb CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  require 'monitor'
3
3
 
4
- require 'omf_common/lobject'
4
+ require 'omf_base/lobject'
5
5
  require 'omf_oml'
6
6
  require 'omf_oml/schema'
7
7
 
@@ -12,8 +12,11 @@ module OMF::OML
12
12
  # This class represents a database like table holding a sequence of OML measurements (rows) according
13
13
  # a common schema.
14
14
  #
15
- class OmlTable < OMF::Common::LObject
15
+ class OmlTable < OMF::Base::LObject
16
16
 
17
+ # @param opts
18
+ # @opts :index Creates an index table (all rows have distinct values at column 'index')
19
+ #
17
20
  def self.create(tname, schema, opts = {}, &on_before_row_added)
18
21
  if (index = opts.delete(:index))
19
22
  require 'omf_oml/indexed_table'
data/lib/omf_oml/tuple.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- require 'omf_common/lobject'
2
+ require 'omf_base/lobject'
3
3
  require 'omf_oml'
4
4
  require 'omf_oml/schema'
5
5
 
@@ -14,7 +14,7 @@ module OMF::OML
14
14
  # Use +OmlTuple+ if the schema is an OML one. +OmlTuple+ has additional convenience
15
15
  # methods.
16
16
  #
17
- class Tuple < OMF::Common::LObject
17
+ class Tuple < OMF::Base::LObject
18
18
 
19
19
  # Return a specific element of the tuple identified either
20
20
  # by it's name, or its col index
@@ -1,6 +1,6 @@
1
1
 
2
2
  module OMF
3
3
  module OML
4
- VERSION = '0.9.7'
4
+ VERSION = '0.9.8'
5
5
  end
6
6
  end
data/omf_oml.gemspec CHANGED
@@ -23,5 +23,6 @@ Gem::Specification.new do |s|
23
23
  # specify any dependencies here; for example:
24
24
  # s.add_development_dependency "minitest", "~> 2.11.3"
25
25
  #s.add_runtime_dependency "sqlite3", "~> 1.3.6"
26
+ s.add_runtime_dependency 'omf_base'
26
27
  s.add_runtime_dependency 'sequel', '~> 3.45'
27
28
  end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omf_oml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-31 00:00:00.000000000 Z
12
+ date: 2013-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omf_base
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: sequel
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -39,6 +55,7 @@ files:
39
55
  - Gemfile
40
56
  - Rakefile
41
57
  - lib/omf_oml.rb
58
+ - lib/omf_oml/csv_table.rb
42
59
  - lib/omf_oml/endpoint.rb
43
60
  - lib/omf_oml/indexed_table.rb
44
61
  - lib/omf_oml/network.rb
@@ -51,6 +68,7 @@ files:
51
68
  - lib/omf_oml/tuple.rb
52
69
  - lib/omf_oml/version.rb
53
70
  - omf_oml.gemspec
71
+ - test/data/brooklynDemo.sq3
54
72
  homepage: https://www.mytestbed.net
55
73
  licenses: []
56
74
  post_install_message:
@@ -71,9 +89,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
89
  version: '0'
72
90
  requirements: []
73
91
  rubyforge_project: omf_oml
74
- rubygems_version: 1.8.24
92
+ rubygems_version: 1.8.23
75
93
  signing_key:
76
94
  specification_version: 3
77
95
  summary: Glue between OMF and OML.
78
- test_files: []
79
- has_rdoc:
96
+ test_files:
97
+ - test/data/brooklynDemo.sq3