sadie 0.0.7 → 0.0.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.
data/CHANGELOG CHANGED
@@ -1 +1,3 @@
1
- Up to v0.0.6: getting it all working
1
+ [Up to v0.0.7] getting it all working
2
+
3
+ [0.0.8] abstracted primer types such that sadie can now use plugins. with two working plugins, IniFile and Resource, it is functionaly equivalent to v0.0.7. More to come.
data/Gemfile CHANGED
@@ -1,8 +1,4 @@
1
- source :rubygems
2
- source "http://rubyforge.org"
3
- source :rubyforge
4
- source "http://gems.rubyforge.org"
5
- gem "ini", "~> 0.1.1"
1
+ source 'http://rubygems.org'
6
2
 
7
- # Specify your gem's dependencies in sadie.gemspec
3
+ # Please see sadie.gemspec for dependency information.
8
4
  gemspec
@@ -0,0 +1,26 @@
1
+ # WARNING: THIS DOESN'T WORK YET!!!
2
+
3
+ Sadie::registerPrimerPlugin( { "match" => /\.dbi\.conx$/,
4
+ "accepts-block" => true } ) do |sadie, key_prefix, primer_file_filepath, block|
5
+
6
+ # build parameter hash
7
+ dbparams = Hash.new
8
+ inifile = Ini.new( primer_file_filepath )
9
+ inifile.each do | section, key_from_ini_file, value |
10
+ section.match(/^connection$/) \
11
+ or next
12
+ dbparams[key_from_ini_file] = value
13
+ end
14
+
15
+ # validate dbistr
16
+ dbparams.has_key( 'dbistr' ) \
17
+ or raise 'requried connection::dbistr was not defined'
18
+
19
+ # default user and pass to nil
20
+ user = dbparams.has_key('user') ? dbparams['user']: nil;
21
+ pass = dbparams.has_key('pass') ? dbparams['pass']: nil;
22
+
23
+ # call connect with block
24
+ require 'dbi'
25
+ DBI.connect( dbparams['dbistr'], user, pass, block )
26
+ end
@@ -0,0 +1,21 @@
1
+ Sadie::registerPrimerPlugin( { "match" => /\.ini$/,
2
+ "accepts-block" => false,
3
+ "prime-on-init" => true } ) do |sadie, key_prefix, primer_file_filepath|
4
+
5
+ require 'ini'
6
+
7
+ ini_file_basename = File.basename primer_file_filepath
8
+ ini_file_root = ini_file_basename.gsub( /\.ini$/, "" )
9
+
10
+ inifile = Ini.new( primer_file_filepath )
11
+ # puts "key_prefix: #{key_prefix}, primer_file_filepath: #{primer_file_filepath}"
12
+ inifile.each do | section, key_from_ini_file, value |
13
+
14
+ # compute key
15
+ # key_prefix = sadie.getCurrentPrimerKeyPrefix
16
+ key_to_set = key_prefix + "." + ini_file_root + "." +section + "." + key_from_ini_file
17
+ key_to_set = key_to_set.gsub( /^\.+/, "" )
18
+
19
+ sadie.set( key_to_set, value )
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ Sadie::registerPrimerPlugin( { "match" => /(\.res|\.res\.rb)$/,
2
+ "accepts-block" => true,
3
+ "prime-on-init" => false } ) do |sadie, key_prefix, primer_file_filepath, block|
4
+
5
+ load( primer_file_filepath )
6
+
7
+ end
@@ -0,0 +1,21 @@
1
+ # WARNING: THIS DOESN'T WORK YET!!!
2
+
3
+ Sadie::registerPrimerPlugin( { "match" => /\.sql$/,
4
+ "accepts-block" => true } ) do |sadie, key_prefix, primer_file_filepath, block|
5
+
6
+ # read query from file @filepath, ditch newlines
7
+ f = open( primer_file_filepath )
8
+ query = f.read
9
+ close( f )
10
+ query = query.gsub(/\n/,'')
11
+
12
+ # get the database and run query
13
+ db_key = key_prefix+".db.conx"
14
+ sadie.get( db_key ) do | dbh |
15
+
16
+ # run the query
17
+ dbh.select_all( query, block )
18
+
19
+ end
20
+ raise 'Sadie returned nil for key: #{db_key}'
21
+ end
data/lib/sadie/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # this file sets the version of the Sadie gem
3
3
 
4
4
  class Sadie
5
- VERSION = "0.0.7"
5
+ VERSION = "0.0.8"
6
6
  end
data/lib/sadie.rb CHANGED
@@ -9,7 +9,7 @@ Bundler.require(:default)
9
9
  # ==Description: Sadie
10
10
  # Sadie is a data framework intended to ease the pain of constructing, accessing, and
11
11
  # managing the resources required by large stores of inter-related data. It supports
12
- # sessions, lazy on-demand, one-time evaluation and file-based storage/retrieval
12
+ # sessions, lazy, on-demand, one-time evaluation and file-based storage/retrieval
13
13
  # operations for resource-heavy data.
14
14
  #
15
15
  # For simplicity, it supports simple, ini-style data
@@ -19,47 +19,95 @@ Bundler.require(:default)
19
19
 
20
20
  class Sadie
21
21
 
22
+ # ==method: Sadie::getSadieInstance
23
+ #
24
+ # returns a new Sadie instance. Options match those of Sadie's constructor method
25
+ def self.getSadieInstance( options )
26
+ Sadie.new(options)
27
+ end
28
+
29
+ # ==method: Sadie::setCurrentSadieInstance
30
+ #
31
+ # this is called just prior to calling a primer plugin to handle a primer to provide
32
+ # a current sadie instance for Sadie::getCurrentSadieInstance to return
33
+ def self.setCurrentSadieInstance ( instance )
34
+ @@current_sadie_instance = instance
35
+ end
36
+
37
+ # ==method: Sadie::setCurrentSadieInstance
38
+ #
39
+ # called by plugin handlers to get access to the current Sadie instance
40
+ def self.getCurrentSadieInstance
41
+ @@current_sadie_instance
42
+ end
43
+
44
+ # ==method: Sadie::Prime
45
+ #
46
+ # called my the .res files to register the keys the .res will prime for
47
+ #
48
+ # accepts as an argument a hash and a block. The hash must include the key:
49
+ # 'provides' and it must define an array
50
+ # of keys that the calling resource (.res) file will have provided after the block is
51
+ # evaluated
52
+ def self.prime ( primer_definition, &block )
53
+ current_sadie_instance = Sadie::getCurrentSadieInstance
54
+ current_sadie_instance.prime( primer_definition, &block )
55
+ end
56
+
57
+ # ==method: Sadie::registerPrimerPlugin
58
+ #
59
+ # this method is called in the .plugin.rb files to register new plugin types
60
+ #
61
+ def self.registerPrimerPlugin ( arghash, &block )
62
+ current_sadie_instance = Sadie::getCurrentSadieInstance
63
+ current_sadie_instance.registerPrimerPlugin( arghash, &block )
64
+ end
65
+
22
66
 
23
67
  # ==method: constructor
24
68
  # options can include any kay, value pairs but the following key values bear mention:
25
69
  # REQUIRED
26
70
  #
27
71
  # sadie.sessions_dirpath
28
- # or
29
- # sadie.session_id
30
- # or
31
- # sadie.session_filepath <- this is probably a bad call, use with caution
72
+ # or
73
+ # sadie.session_id
74
+ # or
75
+ # sadie.session_filepath <- this is probably a bad call, use with caution
32
76
  #
33
77
  # and
34
78
  #
35
- # sadie.primers_dirpath
79
+ # sadie.primers_dirpath
80
+ #
81
+ # and
82
+ # sadie.primer_plugins_dirpath
36
83
  def initialize( options )
37
84
 
38
- # start with blank slate short-term memory, primed and expensive flag hashes
39
- @shortterm = Hash.new
40
- @flag_expensive = Hash.new
41
- @flag_primed = Hash.new
42
- @flag_eachtimeprime = Hash.new
43
-
44
- # init class
45
- Sadie::_checkSanity
46
-
47
- # init mid_primer_initialization if not already done
48
- if ! defined? @@mid_primer_initialization
49
- @@mid_primer_initialization = false
50
- @@mid_primer_filepath = nil
51
- @@mid_primer_toplevel_primer_dirpath = nil
52
- end
85
+ # check instance sanity
86
+ _checkInstanceSanity
87
+ _checkClassSanity
53
88
 
54
89
  # internalize defaults to shortterm
55
90
  DEFAULTS.each do |key, value|
56
91
  _set( key, value )
57
92
  end
58
93
 
59
- # internalize supplied defaults
94
+ # internalize supplied defaults, postponing a set of sadie.primers_dirpath
95
+ # until the end if one is supplied. The reason for this is that the setter
96
+ # attempts to read the plugins and if the primer plugin dirpath has not
97
+ # yet been set, then it'll choke if it processes the wrong one first
98
+ delay_set_primers_dirpath = nil
99
+
100
+ # iterate over constructor args, but do primers_dirpath last since it
101
+ # causes a call to initializePrimers
60
102
  options.each do |key, value|
61
- set( key, value )
103
+ if ( key.eql? "sadie.primers_dirpath")
104
+ delay_set_primers_dirpath = value
105
+ else
106
+ set( key, value )
107
+ end
62
108
  end
109
+ defined? delay_set_primers_dirpath \
110
+ and set( "sadie.primers_dirpath", delay_set_primers_dirpath )
63
111
 
64
112
  # if a path to a session is given, init using session file
65
113
  if defined? options[:sadie.session_filepath] && options[:sadie.session_filepath].match(/^[^\s]+$/)
@@ -78,23 +126,7 @@ class Sadie
78
126
 
79
127
  end
80
128
 
81
- # ==method: Sadie::getSadieInstance
82
- #
83
- # returns a new Sadie instance. Options match those of Sadie's constructor method
84
- def self.getSadieInstance( options )
85
- Sadie.new(options)
86
- end
87
-
88
- # ==method: Sadie::Prime
89
- #
90
- # called my the .res files to register the keys the .res will prime for
91
- #
92
- # accepts as an argument a hash and a block. The hash must include the key:
93
- # 'provides' and it must define an array
94
- # of keys that the calling resource (.res) file will have provided after the block is
95
- # evaluated
96
- def self.Prime ( primer_definition )
97
-
129
+ def prime ( primer_definition, &block )
98
130
  # validate params
99
131
  defined? primer_definition \
100
132
  or raise "Prime called without parameters"
@@ -105,18 +137,17 @@ class Sadie
105
137
 
106
138
  # if initializing primers, just remember how to get back to the primer later,
107
139
  # otherwise, prime
108
- if Sadie::_midPrimerInit?
140
+ if midPrimerInit?
109
141
 
110
142
  # mid primer init, just memorize primer location
111
- Sadie::_memorizePrimerLocation( @@mid_primer_filepath, primer_definition["provides"] )
143
+ memorizePrimerLocation( @@mid_primer_filepath, primer_definition["provides"] )
112
144
  else
113
145
 
114
146
  # run code block with the current sadie instance
115
- current_sadie_instance = Sadie::_getCurrentSadieInstance
116
- yield( current_sadie_instance )
147
+ block.call( self )
117
148
 
118
149
  # loop thru all primer provides, ensuring each primed
119
- current_primer_filepath = Sadie::_getCurrentPrimerFilepath
150
+ current_primer_filepath = getCurrentPrimerFilepath
120
151
  primer_definition["provides"].each do | key |
121
152
 
122
153
  # skip blank lines
@@ -125,11 +156,77 @@ class Sadie
125
156
  #puts "Prime> providing: #{key}"
126
157
 
127
158
  # key primed or raise error
128
- current_sadie_instance.primed? key \
159
+ primed? key \
129
160
  or raise "primer definition file: #{current_primer_filepath} was supposed to define #{key}, but did not"
130
161
  end
131
162
  end
163
+
132
164
  end
165
+
166
+ def registerPrimerPlugin ( arghash, &block )
167
+ if midPluginInit?
168
+
169
+ # init mode, just store arghash info
170
+ accepts_block = arghash.has_key?( "accepts-block" ) && arghash["accepts-block"] ? true : false
171
+ prime_on_init = arghash.has_key?( "prime-on-init" ) && arghash["prime-on-init"] ? true : false
172
+ regPluginMatch( arghash["match"], @@mid_plugin_filepath, accepts_block, prime_on_init )
173
+
174
+ else
175
+
176
+ # prime mode
177
+ currentPrimerPluginPrimerOnInit? \
178
+ or setMidPrimerInit( @@current_primer_filepath )
179
+ key_prefix = getCurrentPrimerKeyPrefix
180
+ if currentPrimerPluginAcceptsBlock?
181
+
182
+ # call with block only if accepts block
183
+ yield( self, key_prefix, @@current_primer_filepath, block )
184
+
185
+ else
186
+
187
+ yield( self, key_prefix, @@current_primer_filepath )
188
+
189
+ end
190
+ currentPrimerPluginPrimerOnInit? \
191
+ or unsetMidPrimerInit
192
+
193
+ end
194
+ end
195
+
196
+
197
+
198
+ # # ==method: pathToKey
199
+ # #
200
+ # # returns a dot-separated version of the filepath such that
201
+ # # with parentify=1 returns dot path to directory file is in,
202
+ # # with parentify=2 returns dot path to directory above directory file is in, etc.
203
+ # def pathToKey( filepath, parentify=0 )
204
+ #
205
+ # # separate path into basename,dirname
206
+ # path_basename = File.basename( filepath )
207
+ # path_dirname = File.dirname( filepath )
208
+ #
209
+ # # create stack of dir components
210
+ # path_stack = Array.new
211
+ # temp_path_stack = path_dirname.split(/\//)
212
+ # temp_path_stack.each do |item|
213
+ # next if item.match(/^\s*$/)
214
+ # path_stack.push item
215
+ # end
216
+ #
217
+ # # lose the suffix on the basename
218
+ # root_path_basename = path_basename.gsub( /\.[^\.]*$/, "" )
219
+ # path_stack.push( root_path_basename )
220
+ # if parentify > 1
221
+ # parentify.times do |i|
222
+ # path_stack.pop
223
+ # end
224
+ # end
225
+ #
226
+ # path_stack.join( "," )
227
+ #
228
+ # end
229
+
133
230
 
134
231
  # ==method: get
135
232
  #
@@ -137,110 +234,70 @@ class Sadie
137
234
  # completely behind-the-scenes as directed by the resource (.res) files
138
235
  def get( k )
139
236
 
237
+
238
+ if ! isset?( k )
239
+ # prime if not yet primed
240
+ primed?( k ) or _prime( k )
241
+ end
242
+
243
+ return _recallExpensive( k ) if expensive?( k )
244
+
140
245
  # if it's already set, return known answer
141
- if _isset?( k )
246
+ if isset?( k )
142
247
 
143
248
  # _get the return value
144
249
  return_value = _get( k )
145
250
 
146
251
  # unset and unprime if destructOnGet?
147
- if destructOnGet?( k )
148
- # puts "destructing #{k}"
149
- unset( k )
150
- unprime( k )
151
- end
252
+ destroyOnGet?( k ) \
253
+ and destroy! k
152
254
 
153
255
  return return_value
154
256
  end
155
257
 
156
- # prime if not yet primed
157
- primed?( k ) \
158
- or _prime( k )
159
-
160
- # if not expensive, then return what's already known
161
- expensive?( k ) \
162
- and return _recallExpensive( k )
163
-
164
- # _get the return value
165
- return_value = _get( k )
166
-
167
- # unset and unprime if destructOnGet?
168
- if destructOnGet?( k )
169
- # puts "destructing #{k}"
170
- unset( k )
171
- unprime( k )
172
- end
173
-
174
- return return_value
175
258
  end
176
259
 
177
-
178
- # ==method: setCheap
260
+ # ==method: isset?
179
261
  #
180
- # the expensive setter. key, value pairs stored via this method are not kept in memory
181
- # but are stored to file and recalled as needed
182
- def setExpensive(k,v)
183
- expensive_filepath = _computeExpensiveFilepath( k )
184
- serialized_value = Marshal::dump( v )
185
- File.open(expensive_filepath, 'w') { |f|
186
- f.write( serialized_value )
187
- }
188
- _expensive( k, true )
189
- _primed( k, true )
262
+ # returns true if sadie has a value for the key
263
+ def isset?( key )
264
+ return @shortterm.has_key?( key )
190
265
  end
191
266
 
192
- # ==method: setDestructOnGet
267
+ # ==method: setDestroyOnGet
193
268
  #
194
269
  # key value will go away and key will be unprimed and unset after next get
195
270
  #
196
271
  # NOTE: this doesn't make sense with keys that were set via setExpensive
197
272
  # so it can be set, but nothing's going to happen differently
198
- def setDestructOnGet( key, turnon=true )
199
- # puts "setDestructOnGet( #{key}, #{turnon} )"
273
+ def setDestroyOnGet( key, turnon=true )
200
274
  if ( turnon )
201
- # puts "turning on destructOnGet for key: #{key}"
202
- @flag_eachtimeprime["#{key}"] = true
275
+ @flag_destroyonget["#{key}"] = true
203
276
  return true
204
277
  end
205
- @flag_eachtimeprime.has_key?( key ) \
206
- and @flag_eachtimeprime.delete( key )
278
+ @flag_destroyonget.has_key?( key ) \
279
+ and @flag_destroyonget.delete( key )
280
+ end
281
+
282
+ # ==method: destroy!
283
+ #
284
+ # remove the key from sadie
285
+ def destroy! ( key )
286
+ unset( key )
287
+ primed?( key ) and unprime( key )
207
288
  end
208
289
 
209
- # ==method: destructOnGet?
290
+ # ==method: destroyOnGet?
210
291
  #
211
292
  # returns true if the destructOnGet flag is set for the key
212
- def destructOnGet?( key )
213
- # print "destructOnGet?> key #{key} "
214
- @flag_eachtimeprime.has_key?( key ) \
293
+ def destroyOnGet?( key )
294
+ @flag_destroyonget.has_key?( key ) \
215
295
  or return _newline( false )
216
- # print " defined-in-eachtimeprime "
217
- @flag_eachtimeprime["#{key}"] \
296
+ @flag_destroyonget["#{key}"] \
218
297
  and return _newline( true )
219
- # print " defined-but-false "
220
298
  return _newline(false)
221
299
  end
222
300
 
223
- def _newline( rval=true )
224
- #puts
225
- return rval
226
- end
227
-
228
- # ==method: unset
229
- # unsets the value of k. Note that this does not unprime, so
230
- # get(key) will simply return nil. Run with unprime to have the
231
- # primer run again
232
- def unset( key )
233
- _unset( key )
234
- end
235
-
236
- # ==method: unprime
237
- # unprimes k. Note that this does not unset the value, so
238
- # get(key) will continue to return whatever it otherwise would have.
239
- # run unset as well to have the primer run again.
240
- def unprime( key )
241
- _primed( key, false )
242
- end
243
-
244
301
  # ==method: set
245
302
  # alias for setCheap(k,v)
246
303
  def set( k, v )
@@ -252,29 +309,67 @@ class Sadie
252
309
  # the cheap setter. key, value pairs stored via this method are kept in memory
253
310
  def setCheap( k, v )
254
311
 
312
+ # puts "setCheap( #{k}, #{v} )"
313
+
255
314
  # set it, mark not expensive and primed
256
315
  _set( k, v )
257
316
  _expensive( k, false )
258
- _primed( k, true )
259
317
 
260
318
  # if we've reset the primers dirpath, init the primers
261
319
  if k.eql?( "sadie.primers_dirpath" )
262
- Sadie::_setMidPrimerTopLevelPrimersDirpath( v )
263
- Sadie::_setCurrentSadieInstance( self )
264
- Sadie::_init_primers
320
+ initializePrimers
321
+ end
322
+
323
+ _primed( k, true )
324
+
325
+ # if we've reset the primers dirpath, init the primers
326
+ if k.eql?( "sadie.primers_dirpath" )
327
+ Sadie::setCurrentSadieInstance( self )
265
328
  end
266
329
 
267
330
  end
268
331
 
332
+ def cheap?( k )
333
+ ! expensive? ( k )
334
+ end
335
+
336
+ # ==method: setExpensive
337
+ #
338
+ # the expensive setter. key, value pairs stored via this method are not kept in memory
339
+ # but are stored to file and recalled as needed
340
+ def setExpensive(k,v)
341
+ expensive_filepath = _computeExpensiveFilepath( k )
342
+ serialized_value = Marshal::dump( v )
343
+ File.open(expensive_filepath, 'w') { |f|
344
+ f.write( serialized_value )
345
+ }
346
+ _expensive( k, true )
347
+ _primed( k, true )
348
+ end
349
+
350
+ # ==method: primed?
351
+ #
352
+ # INTERNAL: this method should only be called the the class method, Prime
353
+ #
354
+ def expensive?( k )
355
+ @flag_expensive.has_key?( k ) or return false;
356
+ @flag_expensive["#{k}"] \
357
+ and return true
358
+ return false
359
+ end
360
+
361
+
269
362
  # ==method: save
270
363
  #
271
364
  # serialize to session file
272
365
  def save
273
- session_filepath = File.expand_path( "session."+value, get( "sadie.sessions_dirpath" ) )
366
+ session_id = get("sadie.session_id")
367
+ session_filepath = File.expand_path( "session."+session_id, get( "sadie.sessions_dirpath" ) )
274
368
  serialized_value = Marshal::dump( [ @shortterm, @flag_primed, @flag_expensive ] )
275
369
  File.open(session_filepath, 'w') { |f|
276
370
  f.write( serialized_value )
277
- }
371
+ }
372
+ return session_id
278
373
  end
279
374
 
280
375
  # ==method: revert!
@@ -291,6 +386,18 @@ class Sadie
291
386
  _initializeWithSessionId( get( "sadie.session_id" ) )
292
387
  end
293
388
 
389
+
390
+
391
+ private
392
+
393
+ # ==method: unprime
394
+ # unprimes k. Note that this does not unset the value, so
395
+ # get(key) will continue to return whatever it otherwise would have.
396
+ # run unset as well to have the primer run again.
397
+ def unprime( key )
398
+ _primed( key, false )
399
+ end
400
+
294
401
  # ==method: primed?
295
402
  #
296
403
  # INTERNAL: this method should only be called the the class method, Prime
@@ -303,122 +410,297 @@ class Sadie
303
410
  return false
304
411
  end
305
412
 
306
- # ==method: primed?
307
- #
308
- # INTERNAL: this method should only be called the the class method, Prime
309
- #
310
- def expensive?( k )
311
- @flag_expensive.has_key?( k ) or return false;
312
- @flag_expensive["#{k}"] \
313
- and return true
314
- return false
413
+ # direct access getter for shortterm memory
414
+ def _get( key )
415
+ value = @shortterm["#{key}"]
416
+ return value
315
417
  end
316
418
 
317
419
 
318
420
 
319
- private
320
-
321
-
322
- def _prime ( k )
323
- # puts "_prime( #{k} )"
324
- # fetch primers dirpath and validate the primer hash
325
- primer_dirpath = _get("sadie.primers_dirpath")
326
- @@primer_hash.has_key?(primer_dirpath) \
327
- or @@primer_hash[primer_dirpath] = Hash.new
421
+ def primerPluginRegistered?( filename )
328
422
 
329
- primers = @@primer_hash[primer_dirpath]
330
- primers.has_key?( k ) or return true
331
-
332
- if primer_filepath = primers[k]
333
- # puts "loading filepath: #{primer_filepath}"
334
- Sadie::_setCurrentPrimerFilepath(primer_filepath)
335
- Sadie::_setCurrentSadieInstance( self )
336
- load primer_filepath
423
+ @@primer_plugin_lookup.each do | plugin_array |
424
+ re, path,accepts_block = plugin_array
425
+ re.match( filename ) \
426
+ and return true
427
+ end
428
+ return false;
429
+ end
430
+
431
+ def primeWithPlugin( key_prefix, filepath )
432
+
433
+ # when this primes, the block run of registerPrimerPlugin needs
434
+ # to know whether or not it accepts block
435
+ @@primer_plugin_lookup.each do | plugin_array |
436
+
437
+ # we just need to match the basename
438
+ filename = File.basename( filepath )
439
+
440
+ regexp, plugin_filepath, accepts_block, prime_on_init = plugin_array
441
+
442
+ if regexp.match( filename )
443
+
444
+ currentPrimerPluginAcceptsBlock( accepts_block )
445
+ currentPrimerPluginPrimeOnInit( prime_on_init )
446
+
447
+ plugin_filename = File.basename( plugin_filepath )
448
+
449
+ load( plugin_filepath )
450
+
451
+ return
452
+ end
337
453
  end
338
- return true
339
-
340
454
  end
341
455
 
342
- def self._setCurrentPrimerFilepath ( filepath )
343
- @@current_primer_filepath = filepath
456
+ def currentPrimerPluginAcceptsBlock( accepts )
457
+ @@primer_plugin_accepts_block = accepts
344
458
  end
345
459
 
346
- def self._getCurrentPrimerFilepath
347
- @@current_primer_filepath
460
+ def currentPrimerPluginAcceptsBlock?
461
+ @@primer_plugin_accepts_block
348
462
  end
349
463
 
350
- def self._setCurrentSadieInstance ( instance )
351
- @@current_sadie_instance = instance
464
+ def currentPrimerPluginPrimeOnInit( prime_on_init )
465
+ @@primer_plugin_prime_on_init = prime_on_init
352
466
  end
353
467
 
354
- def self._getCurrentSadieInstance
355
- @@current_sadie_instance
468
+ def currentPrimerPluginPrimerOnInit?
469
+ @@primer_plugin_prime_on_init
470
+ end
471
+
472
+ def setMidPluginInit( filepath )
473
+ @@mid_plugin_initialization = true
474
+ @@mid_plugin_filepath = filepath
356
475
  end
357
476
 
477
+ def unsetMidPluginInit
478
+ @@mid_plugin_initialization = false
479
+ end
480
+
481
+ def midPluginInit?
482
+ @@mid_plugin_initialization
483
+ end
358
484
 
359
- def self._init_primers( key_prefix="", current_dirpath="" )
485
+ def regPluginMatch ( regexp, filepath, accepts_block, prime_on_init )
486
+ @@primer_plugin_lookup.push( [ regexp, filepath, accepts_block, prime_on_init ] )
487
+ end
488
+
489
+ def primerPluginsInitialized?
490
+ @@primer_plugins_initialized
491
+ end
492
+
493
+ # == initializePrimerPlugins
494
+ #
495
+ # register all the primer plugins
496
+ #
497
+ # called by initializePrimers so it's not necessary to call this separate from that
498
+ def initializePrimerPlugins
360
499
 
361
- # default to the top-level primers dirpath
362
- if current_dirpath.empty?
363
- sadie_instance = Sadie::_getCurrentSadieInstance
364
- current_dirpath = sadie_instance.get( "sadie.primers_dirpath" ) \
365
- or raise "sadie.primers_dirpath not set"
366
- end
500
+ plugins_dirpath = get( "sadie.primer_plugins_dirpath" ) \
501
+ or raise 'sadie.primer_plugins_dirpath not set'
367
502
 
503
+ puts "Initializing primer plugins..."
368
504
 
505
+ # load the plugins
506
+ Dir.foreach( plugins_dirpath ) do |filename|
507
+ next if ! filename.match( /\.plugin\.rb$/ )
508
+
509
+ filepath = File.expand_path( filename, plugins_dirpath )
369
510
 
370
- # loop thru each file in the directory, recurse into subdirs and
371
- # process known filetypes
511
+ puts "initializing primer plugin with file: #{filename}"
512
+
513
+ setMidPluginInit( filepath )
514
+ load( filepath )
515
+ unsetMidPluginInit
516
+ end
517
+ @@primer_plugins_initialized = true
518
+ end
519
+
520
+ def setMidPrimerInit ( filepath )
521
+ @@mid_primer_initialization = true
522
+ @@mid_primer_filepath = filepath
523
+ end
524
+
525
+ def unsetMidPrimerInit
526
+ @@mid_primer_initialization = false
527
+ end
528
+
529
+ def midPrimerInit?
530
+ @@mid_primer_initialization \
531
+ and return true;
532
+ return false;
533
+ end
534
+
535
+
536
+
537
+ def primersInitialized? ( toplevel_dirpath )
538
+ @@flag_primed.has_key?( toplevel_dirpath ) \
539
+ or return false;
540
+ return @@flag_primed[toplevel_dirpath]
541
+ end
542
+
543
+ def initializePrimers
544
+
545
+ Sadie::setCurrentSadieInstance( self )
546
+
547
+ # make sure primer plugins have been initialized
548
+ primerPluginsInitialized? \
549
+ or initializePrimerPlugins
550
+
551
+
552
+ primers_dirpath = get( "sadie.primers_dirpath" ) \
553
+ or raise "sadie.primers_dirpath not set"
554
+
555
+ return true if primersInitialized? primers_dirpath
556
+
557
+ puts "Initializing primers..."
558
+ initializePrimerDirectory( "", primers_dirpath )
559
+
560
+
561
+ @@flag_primed[primers_dirpath] = true
562
+ end
563
+
564
+ def initializePrimerDirectory( key_prefix, current_dirpath )
565
+ puts "initializing primer directory: #{current_dirpath}"
372
566
  Dir.foreach( current_dirpath ) do |filename|
373
567
 
568
+ # skip the dit dirs
569
+ next if filename.eql?(".") || filename.eql?("..")
570
+
374
571
  filepath = File.expand_path( filename, current_dirpath )
375
572
 
376
- if File.directory?( filepath )
377
-
378
- # recurse
379
- filename.eql?(".") || filename.eql?("..") \
380
- or Sadie::_init_primers( key_prefix + "." + filename, filepath )
573
+ if File.directory? filepath
574
+ new_key_prefix = key_prefix + '.' + filename
575
+ new_key_prefix = new_key_prefix.gsub(/^\.+/,"")
576
+ initializePrimerDirectory( new_key_prefix, filepath )
381
577
  else
382
-
383
- # proc known filetypes
384
- if matches = filename.match( /^(.*)\.ini$/ )
385
- prefix = key_prefix + "." + matches[1]
386
- prefix.gsub( /^\.+/, "" )
387
-
388
- Sadie::_init_primers_proc_ini_file( prefix, filepath )
389
- elsif filename.match( /\.res$/ ) || filename.match( /\.res.rb$/ )
390
- Sadie::_init_primers_proc_res_file( filepath )
391
- end
578
+ initializePrimerFile( key_prefix, filepath )
392
579
  end
393
580
  end
394
581
  end
395
582
 
396
- def self._init_primers_proc_ini_file( key_prefix, filepath )
397
- inifile = Ini.new( filepath )
398
- inifile.each do | section, key_from_ini_file, value |
583
+ def initializePrimerFile( key_prefix, filepath )
584
+
585
+
586
+ basename = File.basename( filepath )
587
+ if primerPluginRegistered? basename
588
+ setCurrentPrimerFilepath filepath
399
589
 
400
- # compute key
401
- key_to_set = key_prefix + "." + section + "." + key_from_ini_file
402
- key_to_set = key_to_set.gsub( /^\.+/, "" )
403
- #puts "key_to_set: #{key_to_set}"
590
+ setCurrentPrimerKeyPrefix key_prefix
404
591
 
405
- # get sadie instance and set
406
- sadie_instance = Sadie::_getCurrentSadieInstance
407
- sadie_instance.set( key_to_set, value )
592
+ basename = File.basename( filepath )
593
+ primeWithPlugin( key_prefix, filepath )
594
+ end
595
+ end
596
+
597
+
598
+
599
+ def setCurrentPrimerKeyPrefix ( prefix )
600
+ @@current_primer_keyprefix = prefix
601
+ end
602
+
603
+ def getCurrentPrimerKeyPrefix
604
+ @@current_primer_keyprefix
605
+ end
606
+
607
+ def setCurrentPrimerFilepath ( filepath )
608
+ @@current_primer_filepath = filepath
609
+ end
610
+
611
+ def getCurrentPrimerFilepath
612
+ @@current_primer_filepath
613
+ end
614
+
615
+
616
+
617
+ # ==memorizePrimerLocation
618
+ #
619
+ # internal, ignore the man behind the curtain
620
+ def memorizePrimerLocation( filepath, primer_provides )
621
+
622
+ # validate primer hash
623
+ #primer_dirpath = @@mid_primer_toplevel_primer_dirpath
624
+ primer_dirpath = _get("sadie.primers_dirpath")
625
+ @@primer_hash.has_key?( primer_dirpath ) \
626
+ or @@primer_hash["#{primer_dirpath}"] = Hash.new
627
+
628
+ # interate over provides setting primer providers for each
629
+ primer_provides.each do | key |
630
+ setPrimerProvider( key, filepath )
408
631
  end
409
632
  end
410
633
 
411
- def self._init_primers_proc_res_file( filepath )
634
+
635
+ # ==setPrimerProvider
636
+ #
637
+ # internal, ignore the man behind the curtain
638
+ def setPrimerProvider( primer_name, primer_filepath )
639
+
640
+ primer_dirpath = _get( "sadie.primers_dirpath" )
641
+ @@primer_hash.has_key?( primer_dirpath ) \
642
+ or @@primer_hash[primer_dirpath] = Hash.new
643
+
644
+ @@primer_hash["#{primer_dirpath}"]["#{primer_name}"] = primer_filepath
645
+
646
+ end
647
+
648
+ def getPrimerProvider( key )
412
649
 
413
- # puts "Loading #{filepath}..."
650
+ # fetch primers dirpath and validate the primer hash
651
+ primer_dirpath = _get( "sadie.primers_dirpath" )
652
+ @@primer_hash.has_key?( primer_dirpath ) \
653
+ or @@primer_hash[primer_dirpath] = Hash.new
414
654
 
415
- # load the res file
416
- Sadie::_setMidPrimerInit( filepath )
417
- load( filepath )
418
- Sadie::_unsetMidPrimerInit
655
+ primers = @@primer_hash[primer_dirpath]
656
+ primers.has_key?( key ) \
657
+ or return nil # primer not defined
419
658
 
659
+ return primers[key]
420
660
  end
421
661
 
662
+
663
+
664
+ def _primed ( k, is_primed )
665
+ defined? k \
666
+ or raise '_primed> reqd parameter, k, was undefined'
667
+ k.is_a?( String ) \
668
+ or raise '_primed> reqd parameter, k, was non-string'
669
+ if ( is_primed )
670
+ @flag_primed[k] = true
671
+ return true
672
+ end
673
+ @flag_primed.has_key?( k ) \
674
+ or return true
675
+ @flag_primed.delete( k )
676
+ end
677
+
678
+ def _prime ( k )
679
+
680
+ provider = getPrimerProvider( k ) \
681
+ or return true;
682
+
683
+ setCurrentPrimerFilepath(provider)
684
+ Sadie::setCurrentSadieInstance( self )
685
+ load provider
686
+ true
687
+
688
+ end
689
+
690
+
691
+ def _newline( rval=true )
692
+ #puts
693
+ return rval
694
+ end
695
+
696
+ # ==method: unset
697
+ # unsets the value of k. Note that this does not unprime, so
698
+ # get(key) will simply return nil. Run with unprime to have the
699
+ # primer run again
700
+ def unset( key )
701
+ _unset( key )
702
+ end
703
+
422
704
  def _recallExpensive( k )
423
705
  expensive_filepath = _computeExpensiveFilepath( k )
424
706
  File.exists? expensive_filepath \
@@ -434,14 +716,6 @@ class Sadie
434
716
  File.expand_path("session."+session_id+".exp."+k, _get( "sadie.sessions_dirpath" ) )
435
717
  end
436
718
 
437
- def _primed( k, isprimed )
438
- if isprimed
439
- @flag_primed["#{k}"] = true
440
- return
441
- end
442
- @flag_primed.delete( k )
443
- end
444
-
445
719
  def _expensive( k, isexpensive )
446
720
  if isexpensive
447
721
  @flag_expensive["#{k}"] = true
@@ -450,13 +724,6 @@ class Sadie
450
724
  @flag_expensive.delete( k )
451
725
  end
452
726
 
453
- # direct access getter for shortterm memory
454
- def _get( key )
455
- value = @shortterm["#{key}"]
456
- #puts "_get(#{key})> #{value}"
457
- return value
458
- end
459
-
460
727
  # direct access setter for shortterm memory
461
728
  def _set( key, value )
462
729
 
@@ -469,9 +736,6 @@ class Sadie
469
736
  and @shortterm.delete( key )
470
737
  end
471
738
 
472
- def _isset?( key )
473
- return @shortterm.has_key?( key )
474
- end
475
739
 
476
740
  # init given path to session file
477
741
  def _initializeWithSessionFilePath(session_filepath)
@@ -515,43 +779,49 @@ class Sadie
515
779
  return value
516
780
  end
517
781
 
518
- def self._setMidPrimerInit ( filepath )
519
- @@mid_primer_initialization = true
520
- @@mid_primer_filepath = filepath
521
- end
522
-
523
- def self._unsetMidPrimerInit
524
- @@mid_primer_initialization = false
525
- end
526
-
527
- def self._midPrimerInit?
528
- @@mid_primer_initialization
782
+ # ==method: checkInstanceSanity
783
+ #
784
+ # verifies that needed instance variables are defined
785
+ def _checkInstanceSanity
786
+ defined? @shortterm \
787
+ or @shortterm = Hash.new
788
+ defined? @flag_expensive \
789
+ or @flag_expensive = Hash.new
790
+ defined? @flag_destroyonget \
791
+ or @flag_destroyonget = Hash.new
792
+ defined? @flag_primed \
793
+ or @flag_primed = Hash.new
794
+
529
795
  end
530
796
 
531
- def self._memorizePrimerLocation( filepath, primer_provides )
532
- primer_dirpath = @@mid_primer_toplevel_primer_dirpath
533
- @@primer_hash.has_key?( primer_dirpath ) \
534
- or @@primer_hash["#{primer_dirpath}"] = Hash.new
535
- primer_provides.each do | key |
536
- Sadie::_setPrimerProvider( key, filepath )
797
+ # ==method: checkClassSanity
798
+ #
799
+ # verifies that needed class variables are defined
800
+ def _checkClassSanity
801
+ defined? @@flag_primed \
802
+ or @@flag_primed = Hash.new
803
+
804
+ # init primer plugin vars
805
+ if ( ! defined? @@primer_plugin_lookup )
806
+ @@mid_plugin_initialization = false
807
+ @@primer_plugin_lookup = Array.new
808
+ @@primer_plugins_initialized = false
537
809
  end
538
- end
539
-
540
- def self._setMidPrimerTopLevelPrimersDirpath( dirpath )
541
- @@mid_primer_toplevel_primer_dirpath = dirpath
542
- end
543
-
544
- def self._setPrimerProvider( primer_name, primer_filepath )
545
- primer_dirpath = @@mid_primer_toplevel_primer_dirpath
546
- @@primer_hash["#{primer_dirpath}"]["#{primer_name}"] = primer_filepath
547
- end
548
-
549
- def self._checkSanity
550
- if ! defined? @@primer_hash
551
- @@primer_hash = Hash.new
810
+
811
+ # init primer vars
812
+ defined? @@primer_hash \
813
+ or @@primer_hash = Hash.new
814
+ defined? @flag_primed \
815
+ or @flag_primed = Hash.new
816
+ if ! defined? @@mid_primer_initialization
817
+ @@mid_primer_initialization = false
818
+ @@mid_primer_filepath = nil
819
+ # @@mid_primer_toplevel_primer_dirpath = nil
552
820
  end
553
821
 
554
822
  end
823
+
824
+
555
825
  end
556
826
 
557
827
  require "sadie/version"
data/sadie.gemspec CHANGED
@@ -21,4 +21,7 @@ Gem::Specification.new do |s|
21
21
  # specify any dependencies here; for example:
22
22
  # s.add_development_dependency "rspec"
23
23
  # s.add_runtime_dependency "rest-client"
24
+
25
+ s.add_runtime_dependency "ini"
26
+
24
27
  end
@@ -8,7 +8,8 @@ class TestSadieToplevel < Test::Unit::TestCase
8
8
  def test_simple
9
9
  Dir.mktmpdir("sadie_testdir") do | dir |
10
10
  sadie = Sadie::getSadieInstance( { "sadie.primers_dirpath" => "test/test_primers",
11
- "sadie.sessions_dirpath" => dir } )
11
+ "sadie.sessions_dirpath" => dir,
12
+ "sadie.primer_plugins_dirpath" => "lib/sadie/primer_plugins" } )
12
13
 
13
14
  # test top-level ini
14
15
  assert_equal( sadie.get( "toplevel.somegroup.somekey" ), "someval" )
@@ -8,7 +8,8 @@ class TestSadieTwoDeep < Test::Unit::TestCase
8
8
  def test_simple
9
9
  Dir.mktmpdir("sadie_testdir") do | dir |
10
10
  sadie = Sadie::getSadieInstance( { "sadie.primers_dirpath" => "test/test_primers",
11
- "sadie.sessions_dirpath" => dir } )
11
+ "sadie.sessions_dirpath" => dir,
12
+ "sadie.primer_plugins_dirpath" => "lib/sadie/primer_plugins" } )
12
13
 
13
14
  # test two-deep ini
14
15
  assert_equal( sadie.get( "two.deep.conf.section.thiskey" ), "thisval" )
@@ -0,0 +1 @@
1
+ *.kate-swp
@@ -1,6 +1,4 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( "provides" => %w{ onedeep.multiresult.oneprime
1
+ Sadie::prime( "provides" => %w{ onedeep.multiresult.oneprime
4
2
  onedeep.multiresult.twoprime } ) do |sadie|
5
3
  sadie.set( "onedeep.multiresult.oneprime", "primedthem" )
6
4
  sadie.set( "onedeep.multiresult.twoprime", "primedthem" )
@@ -1,11 +1,9 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( "provides" => %w{ toplevel_destructonget.oneprime
1
+ Sadie::prime( "provides" => %w{ toplevel_destructonget.oneprime
4
2
  toplevel_destructonget.twoprime } ) do |sadie|
5
3
  puts "running destructonget primer..."
6
4
  timeobj = Time.now
7
5
  timeinsecs = timeobj.to_f
8
6
  sadie.set( "toplevel_destructonget.oneprime", "primedthem - #{timeinsecs}" )
9
7
  sadie.set( "toplevel_destructonget.twoprime", "primedthem" )
10
- sadie.setDestructOnGet("toplevel_destructonget.oneprime")
8
+ sadie.setDestroyOnGet("toplevel_destructonget.oneprime")
11
9
  end
@@ -1,7 +1,5 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( "provides" => %w{ toplevel_double.oneprime
4
- toplevel_double.twoprime } ) do |sadie|
1
+ Sadie::prime( "provides" => %w{ toplevel_double.oneprime
2
+ toplevel_double.twoprime } ) do |sadie|
5
3
  sadie.set( "toplevel_double.oneprime", "primedthem" )
6
4
  sadie.set( "toplevel_double.twoprime", "primedthem" )
7
5
  end
@@ -1,5 +1,3 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( "provides" => %w{ toplevel_single.oneprime } ) do |sadie|
1
+ Sadie::prime( "provides" => %w{ toplevel_single.oneprime } ) do |sadie|
4
2
  sadie.set( "toplevel_single.oneprime", "primedit" )
5
3
  end
@@ -1,5 +1,3 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( "provides" => %w{ expensive.oneprime } ) do |sadie|
1
+ Sadie::prime( "provides" => %w{ expensive.oneprime } ) do |sadie|
4
2
  sadie.setExpensive( "expensive.oneprime", "primedit" )
5
3
  end
@@ -1,7 +1,8 @@
1
- require 'sadie'
2
-
3
- Sadie::Prime( { "provides" => %w{ two.deep.two_results.firstkey \
1
+ Sadie::prime( { "provides" => %w{ two.deep.two_results.firstkey \
4
2
  two.deep.two_results.secondkey } } ) do |sadie|
3
+
4
+ #puts "priming two_results.res"
5
+
5
6
  sadie.set( "two.deep.two_results.firstkey", "primedthem" )
6
7
  sadie.set( "two.deep.two_results.secondkey", "primedthem" )
7
8
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sadie
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Fred McDavid
@@ -15,9 +15,22 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-20 00:00:00 Z
19
- dependencies: []
20
-
18
+ date: 2012-01-24 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: ini
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
21
34
  description: Sadie is a data framework intended to ease the pain of managing related data.
22
35
  email:
23
36
  - fred@landmetrics.com
@@ -38,6 +51,10 @@ files:
38
51
  - lib/.gitignore
39
52
  - lib/sadie.rb
40
53
  - lib/sadie/defaults.rb
54
+ - lib/sadie/primer_plugins/DatabaseConnection.plugin.rb
55
+ - lib/sadie/primer_plugins/IniFile.plugin.rb
56
+ - lib/sadie/primer_plugins/Resource.plugin.rb
57
+ - lib/sadie/primer_plugins/SQLQuery.plugin.rb
41
58
  - lib/sadie/version.rb
42
59
  - rdoc/classes/Sadie.html
43
60
  - rdoc/created.rid
@@ -53,7 +70,7 @@ files:
53
70
  - sadie.gemspec
54
71
  - test/tc_sadie_toplevel.rb
55
72
  - test/tc_sadie_twodeep.rb
56
- - test/test_primers/.toplevel_double.res.rb.kate-swp
73
+ - test/test_primers/.gitignore
57
74
  - test/test_primers/onedeep/multiresult.res
58
75
  - test/test_primers/toplevel.ini
59
76
  - test/test_primers/toplevel_destructonget.res.rb