omf_oml 0.9.7 → 0.9.8

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.
@@ -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