main 4.3.0 → 4.4.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/README CHANGED
@@ -450,6 +450,48 @@ SAMPLES
450
450
  "forty-two"
451
451
 
452
452
 
453
+ <========< samples/j.rb >========>
454
+
455
+ ~ > cat samples/j.rb
456
+
457
+ #!/usr/bin/env ruby
458
+
459
+ require 'open-uri'
460
+
461
+ require 'main'
462
+ require 'digest/sha2'
463
+
464
+ # you have access to a sequel/amalgalite/sqlite db for free
465
+ #
466
+
467
+ Main {
468
+ name :i_can_haz_db
469
+
470
+ db {
471
+ create_table(:mp3s) do
472
+ primary_key :id
473
+ String :url
474
+ String :sha
475
+ end unless table_exists?(:mp3s)
476
+ }
477
+
478
+ def run
479
+ url = 'http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3'
480
+ mp3 = open(url){|fd| fd.read}
481
+ sha = Digest::SHA2.hexdigest(mp3)
482
+
483
+ db[:mp3s].insert(:url => url, :sha => sha)
484
+ p db[:mp3s].all
485
+ p db
486
+ end
487
+ }
488
+
489
+ ~ > ruby samples/j.rb
490
+
491
+ [{:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>1}, {:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>2}]
492
+ #<Sequel::Amalgalite::Database: "amalgalite://Users/ahoward/.i_can_haz_db/db.sqlite">
493
+
494
+
453
495
 
454
496
  DOCS
455
497
  test/main.rb
@@ -457,6 +499,69 @@ DOCS
457
499
  API section below
458
500
 
459
501
  HISTORY
502
+ 4.4.0
503
+ - support for automatic sequel/sqlite/amalgalite dbs for persistent state
504
+ across invocations
505
+
506
+ Main {
507
+ db {
508
+ create_table :foo do
509
+ String key
510
+ String val
511
+ end unless table_exists? :foo
512
+ }
513
+
514
+ def run
515
+ db[:foo].create(:key => 'using', :val => 'amalgalite')
516
+ end
517
+ }
518
+
519
+ - support for automatic config files with auto populated template data
520
+
521
+ Main {
522
+ config :email => 'your.addy@gmail.com', :password => 'pa$$word'
523
+
524
+ def run
525
+ email = config[:email]
526
+ end
527
+ }
528
+
529
+ - new paramter types :pathname, :path, :slug, :input, and :output
530
+
531
+ - input/output parameters. can be filenames or '-' to supply
532
+ stdin/stdout respectively
533
+
534
+ Main {
535
+ input :i
536
+ output :o
537
+
538
+ def run
539
+ i = params[:i].value
540
+ o = params[:o].value
541
+
542
+ line = i.gets
543
+ o.puts line
544
+ end
545
+ }
546
+
547
+ - clean up warnings running with 'ruby -w'
548
+
549
+ - fix a failing test
550
+
551
+ - ability to ignore parameters in sub modes
552
+
553
+ Main {
554
+ argument :foo
555
+ argument :bar
556
+
557
+ def run
558
+ p param[:bar].value
559
+ end
560
+
561
+ mode :ignoring do
562
+ params[:foo].ignore!
563
+ end
564
+ }
460
565
  4.0.0
461
566
  - avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
462
567
  utilized for testing. this was done to make it simple to wrap
data/README.erb CHANGED
@@ -5,9 +5,9 @@ SYNOPSIS
5
5
  a class factory and dsl for generating command line programs real quick
6
6
 
7
7
  URI
8
+ http://github.com/ahoward/main
8
9
  http://codeforpeople.com/lib/ruby/
9
10
  http://rubyforge.org/projects/codeforpeople/
10
- http://github.com/ahoward/main
11
11
 
12
12
  INSTALL
13
13
  gem install main
@@ -26,6 +26,8 @@ DESCRIPTION
26
26
  - parsing user defined ARGV and ENV
27
27
  - zero requirements for understanding the obtuse apis of *any* command
28
28
  line option parsers
29
+ - built-in support for persistent state via sqlite/sequel/amalgalite
30
+ - built-in support for yaml config files
29
31
  - leather pants
30
32
 
31
33
  in short main.rb aims to drastically lower the barrier to writing uniform
@@ -186,6 +188,82 @@ DOCS
186
188
  API section below
187
189
 
188
190
  HISTORY
191
+ 4.4.0
192
+ - app storage under a dotdir. for example
193
+
194
+ Main {
195
+ name :foobar
196
+ }
197
+
198
+ will have a ~/.foobar/ directory available for storing db/config/etc.
199
+
200
+ - support for automatic sequel/sqlite/amalgalite dbs for persistent state
201
+ across invocations. the db is automatically created under the main
202
+ programs dotdir (~/.$appname/db.sqlite)
203
+
204
+ Main {
205
+ db {
206
+ create_table :foo do
207
+ String key
208
+ String val
209
+ end unless table_exists? :foo
210
+ }
211
+
212
+ def run
213
+ db[:foo].create(:key => 'using', :val => 'amalgalite')
214
+ end
215
+ }
216
+
217
+ - support for automatic config files with auto populated template data.
218
+ the first time the program is run the user's editor will be invoked on a
219
+ config file pre-populate with the same config. subsequent invocations
220
+ will use the user configured values. the config file is stored at
221
+ ~/.$appname/config.yml
222
+
223
+ Main {
224
+ config :email => 'your.addy@gmail.com', :password => 'pa$$word'
225
+
226
+ def run
227
+ email = config[:email]
228
+ end
229
+ }
230
+
231
+ - new paramter types :pathname, :path, :slug, :input, and :output
232
+
233
+ - input/output parameters. can be filenames or '-' to supply
234
+ stdin/stdout respectively
235
+
236
+ Main {
237
+ input :i
238
+ output :o
239
+
240
+ def run
241
+ i = params[:i].value
242
+ o = params[:o].value
243
+
244
+ line = i.gets
245
+ o.puts line
246
+ end
247
+ }
248
+
249
+ - clean up warnings running with 'ruby -w'
250
+
251
+ - fix a failing test
252
+
253
+ - ability to ignore parameters in sub modes
254
+
255
+ Main {
256
+ argument :foo
257
+ argument :bar
258
+
259
+ def run
260
+ p param[:bar].value
261
+ end
262
+
263
+ mode :ignoring do
264
+ params[:foo].ignore!
265
+ end
266
+ }
189
267
  4.0.0
190
268
  - avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
191
269
  utilized for testing. this was done to make it simple to wrap
data/TODO CHANGED
@@ -1,20 +1,18 @@
1
+ todo:
2
+ - examples of new features
3
+ - use map.rb
1
4
 
2
- * support pathname casts
3
- * support uri casts
4
- * support filename casts
5
- * support directory costs
6
- * support io cast '-' (:input, :output)
7
-
8
- * fix weird super bug jeremy found
9
-
10
- * figure out how to support '-' ??
11
-
12
- * clean up warnings under 'ruby -w'
13
- * error reporting weird for some errors
14
-
15
- ===============================================================================
16
- X calls to abort sometimes lead to STDERR prining twice ;-(
17
- X main's' with modes, but no run do not operate properly - add default run w/wrap_run!
18
- X usage fubar when extra chunks are set
19
- X usage of arguments is fubar when negative arities are used
20
- X add sanity checks at parameter contruction completion
5
+ done:
6
+ - clean up warnings under 'ruby -w'
7
+ - intput/output arguments
8
+ - support io cast '-' (:input, :output)
9
+ - slug casts
10
+ - support uri casts
11
+ - dotdir support (based on name)
12
+ - db support
13
+ - configuration/configfile file support
14
+ - calls to abort sometimes lead to STDERR prining twice ;-(
15
+ - main's' with modes, but no run do not operate properly - add default run w/wrap_run!
16
+ - usage fubar when extra chunks are set
17
+ - usage of arguments is fubar when negative arities are used
18
+ - add sanity checks at parameter contruction completion
data/a.rb CHANGED
@@ -1,6 +1,33 @@
1
1
  require 'main'
2
2
 
3
3
  Main {
4
- argument('zero_or_more'){ arity(-1) }
5
- run{ p params }
4
+
5
+ name :foobar
6
+
7
+ db {
8
+ create_table(:foo) do
9
+ primary_key :id
10
+ String :name
11
+ Float :price
12
+ end unless table_exists?(:foo)
13
+ }
14
+
15
+ config(
16
+ :email => 'your.addy@gmail.com',
17
+ :password => 'yourPa$$word'
18
+ )
19
+
20
+ io
21
+
22
+
23
+ def run
24
+ #p input.path
25
+ #p output.path
26
+ p params.map{|param| param.name}
27
+ output.puts(:foobar)
28
+ end
29
+
30
+ mode :foo do
31
+ params[:input].ignore!
32
+ end
6
33
  }
data/lib/main.rb CHANGED
@@ -2,7 +2,7 @@ module Main
2
2
  #
3
3
  # top level constants
4
4
  #
5
- Main::VERSION = '4.3.0' unless
5
+ Main::VERSION = '4.4.0' unless
6
6
  defined? Main::VERSION
7
7
  def self.version() Main::VERSION end
8
8
 
@@ -13,6 +13,7 @@ module Main
13
13
  Main::EXIT_SUCCESS = 0 unless defined? Main::EXIT_SUCCESS
14
14
  Main::EXIT_FAILURE = 1 unless defined? Main::EXIT_FAILURE
15
15
  Main::EXIT_WARN = 42 unless defined? Main::EXIT_WARN
16
+ Main::EXIT_WARNING = 42 unless defined? Main::EXIT_WARNING
16
17
  #
17
18
  # built-in
18
19
  #
data/lib/main/cast.rb CHANGED
@@ -25,7 +25,7 @@ module Main
25
25
  end
26
26
 
27
27
  cast :integer do |obj|
28
- Integer obj
28
+ Float(obj).to_i
29
29
  end
30
30
 
31
31
  cast :float do |obj|
@@ -45,7 +45,7 @@ module Main
45
45
  end
46
46
 
47
47
  cast :uri do |obj|
48
- require 'uri'
48
+ require 'uri' unless defined?(::URI)
49
49
  ::URI.parse obj.to_s
50
50
  end
51
51
 
@@ -55,10 +55,53 @@ module Main
55
55
  end
56
56
 
57
57
  cast :date do |obj|
58
- require 'date'
58
+ require 'date' unless defined?(::Date)
59
59
  ::Date.parse obj.to_s
60
60
  end
61
61
 
62
+ cast :pathname do |obj|
63
+ require 'pathname' unless defined?(::Pathname)
64
+ Pathname.new(obj.to_s)
65
+ end
66
+
67
+ cast :path do |obj|
68
+ File.expand_path(obj.to_s)
69
+ end
70
+
71
+ cast :input do |obj|
72
+ case obj.to_s
73
+ when '-'
74
+ io = STDIN.dup
75
+ io.fattr(:path){ '/dev/stdin' }
76
+ io
77
+ else
78
+ io = open(obj.to_s, 'r+')
79
+ at_exit{ io.close }
80
+ io
81
+ end
82
+ end
83
+
84
+ cast :output do |obj|
85
+ case obj.to_s
86
+ when '-'
87
+ io = STDOUT.dup
88
+ io.fattr(:path){ '/dev/stdout' }
89
+ io
90
+ else
91
+ io = open(obj.to_s, 'w+')
92
+ at_exit{ io.close }
93
+ io
94
+ end
95
+ end
96
+
97
+ cast :slug do |obj|
98
+ string = [obj].flatten.compact.join('-')
99
+ words = string.to_s.scan(%r/\w+/)
100
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
101
+ words.delete_if{|word| word.nil? or word.strip.empty?}
102
+ String(words.join('-').downcase)
103
+ end
104
+
62
105
  cast :list do |*objs|
63
106
  [*objs].flatten.join(',').split(/,/)
64
107
  end
@@ -109,10 +109,15 @@ module Main
109
109
  names.first
110
110
  end
111
111
 
112
- def default
112
+ def default(*values)
113
+ defaults(values) unless values.empty?
113
114
  defaults.first
114
115
  end
115
116
 
117
+ def default=(value)
118
+ default(value)
119
+ end
120
+
116
121
  def typename
117
122
  prefix = '--' if type.to_s =~ %r/option/
118
123
  "#{ type }(#{ prefix }#{ name })"
@@ -248,6 +253,13 @@ module Main
248
253
  end
249
254
  end
250
255
 
256
+ def remove
257
+ main.parameters.delete(self)
258
+ end
259
+ alias_method('remove!', 'remove')
260
+ alias_method('ignore', 'remove')
261
+ alias_method('ignore!', 'ignore')
262
+
251
263
  class Argument < Parameter
252
264
  fattr 'required' => true
253
265
 
@@ -527,6 +539,15 @@ module Main
527
539
  delete(*a)
528
540
  super
529
541
  end
542
+
543
+ def [](*index)
544
+ first = index.first
545
+ if(index.size == 1 and (first.is_a?(String) or first.is_a?(Symbol)))
546
+ first = first.to_s
547
+ return detect{|param| param.name == first}
548
+ end
549
+ return super
550
+ end
530
551
  end
531
552
 
532
553
  class DSL
@@ -21,11 +21,11 @@ module Main
21
21
  fattr('exit_success'){ Main::EXIT_SUCCESS }
22
22
  fattr('exit_failure'){ Main::EXIT_FAILURE }
23
23
  fattr('exit_warn'){ Main::EXIT_WARN }
24
+ fattr('exit_warning'){ Main::EXIT_WARNING }
24
25
  fattr('parameters'){ Main::Parameter::List[] }
25
26
  fattr('can_has_hash'){ Hash.new }
26
27
  fattr('mixin_table'){ Hash.new }
27
28
 
28
- fattr('factory')
29
29
  fattr('argv')
30
30
  fattr('env')
31
31
  fattr('opts')
@@ -35,6 +35,10 @@ module Main
35
35
  end
36
36
  alias_method 'create', 'factory'
37
37
 
38
+ def factory=(factory)
39
+ @factory = factory
40
+ end
41
+
38
42
  class Factory
39
43
  def initialize(&block)
40
44
  @block = block || lambda{}
@@ -84,6 +88,10 @@ module Main
84
88
  instance
85
89
  end
86
90
 
91
+ def params
92
+ parameters
93
+ end
94
+
87
95
  def evaluate(&block)
88
96
  module_eval(&block)
89
97
  end
@@ -182,23 +190,23 @@ module Main
182
190
  end
183
191
 
184
192
  def parameter(*a, &b)
185
- (parameters << Parameter.create(:parameter, self, *a, &b)).last
193
+ (parameters << Parameter.create(:parameter, main=self, *a, &b)).last
186
194
  end
187
195
 
188
196
  def argument(*a, &b)
189
- (parameters << Parameter.create(:argument, self, *a, &b)).last
197
+ (parameters << Parameter.create(:argument, main=self, *a, &b)).last
190
198
  end
191
199
 
192
200
  def option(*a, &b)
193
- (parameters << Parameter.create(:option, self, *a, &b)).last
201
+ (parameters << Parameter.create(:option, main=self, *a, &b)).last
194
202
  end
195
203
 
196
204
  def keyword(*a, &b)
197
- (parameters << Parameter.create(:keyword, self, *a, &b)).last
205
+ (parameters << Parameter.create(:keyword, main=self, *a, &b)).last
198
206
  end
199
207
 
200
208
  def environment(*a, &b)
201
- (parameters << Parameter.create(:environment, self, *a, &b)).last
209
+ (parameters << Parameter.create(:environment, main=self, *a, &b)).last
202
210
  end
203
211
 
204
212
  def default_options!
@@ -259,6 +267,86 @@ module Main
259
267
  block ||= lambda{}
260
268
  define_method(:run, &block) if block
261
269
  end
270
+
271
+ def dotdir(*dotdir, &block)
272
+ @dotdir = File.join(Util.home, ".#{ name }") unless defined?(@dotdir)
273
+
274
+ @dotdir = dotdir.join('/') unless dotdir.empty?
275
+
276
+ if block
277
+ require 'fileutils' unless defined?(FileUtils)
278
+ FileUtils.mkdir_p(@dotdir) unless test(?d, @dotdir)
279
+ Dir.chdir(&block)
280
+ else
281
+ @dotdir
282
+ end
283
+ end
284
+
285
+ def db(*args, &block)
286
+ unless defined?(@db)
287
+ require 'sequel' unless defined?(Sequel)
288
+ require 'amalgalite' unless defined?(Amalgalite)
289
+ @db = dotdir{ Sequel.amalgalite(db_path) }
290
+ @db.instance_eval(&block) if block
291
+ end
292
+ @db
293
+ end
294
+
295
+ def db_path(*db_path)
296
+ @db_path = File.join(dotdir, 'db.sqlite') unless defined?(@db_path)
297
+ @db_path = File.join(*db_path) unless db_path.empty?
298
+ @db_path
299
+ end
300
+
301
+ def config(*args, &block)
302
+ unless defined?(@config)
303
+ require 'yaml' unless defined?(YAML)
304
+ if test(?s, config_path)
305
+ @config = YAML.load(IO.read(config_path))
306
+ else
307
+ config = args.last.is_a?(Hash) ? args.last : {}
308
+ lines = config.to_yaml.split(/\n/)
309
+ dash = lines.shift
310
+ open(config_path, 'w') do |fd|
311
+ fd.puts '### you may need to edit this config!'
312
+ fd.puts
313
+ fd.puts lines
314
+ end
315
+ editor = ENV['EDITOR'] || ENV['EDIT'] || 'vi'
316
+ system("#{ editor.inspect } #{ config_path }")
317
+ @config = YAML.load(IO.read(config_path))
318
+ end
319
+ end
320
+ @config
321
+ end
322
+
323
+ def config_path(*config_path)
324
+ @config_path = File.join(dotdir, 'config.yml') unless defined?(@config_path)
325
+ @config_path = File.join(*config_path) unless config_path.empty?
326
+ @config_path
327
+ end
328
+
329
+ def input(*args, &block)
330
+ first = args.first
331
+ args.push(:input) unless(first.is_a?(Symbol) or first.is_a?(String))
332
+ param = argument(*args, &block)
333
+ param.cast(:input)
334
+ param
335
+ end
336
+
337
+ def output(*args, &block)
338
+ first = args.first
339
+ args.push(:output) unless(first.is_a?(Symbol) or first.is_a?(String))
340
+ param = argument(*args, &block)
341
+ param.cast(:output)
342
+ param
343
+ end
344
+
345
+ def io(*args)
346
+ i = input(*[args.shift].compact).default('-')
347
+ o = output(*[args.shift].compact).default('-')
348
+ [i, o]
349
+ end
262
350
  end
263
351
 
264
352
  extend ClassMethods
@@ -16,7 +16,7 @@ module Main
16
16
 
17
17
  %w(
18
18
  program name synopsis description author version
19
- exit_status exit_success exit_failure exit_warn
19
+ exit_status exit_success exit_failure exit_warn exit_warning
20
20
  logger_level
21
21
  usage
22
22
  ).each{|a| fattr(a){ self.class.send a}}
@@ -31,9 +31,9 @@ module Main
31
31
  end
32
32
 
33
33
  %w( debug info warn fatal error ).each do |m|
34
- module_eval <<-code
35
- def #{ m } *a, &b
36
- logger.#{ m } *a, &b
34
+ module_eval <<-code, __FILE__, __LINE__
35
+ def #{ m }(*a, &b)
36
+ logger.#{ m }(*a, &b)
37
37
  end
38
38
  code
39
39
  end
@@ -87,7 +87,6 @@ module Main
87
87
  end
88
88
 
89
89
  def setup_io_restoration
90
- return
91
90
  @finalizers ||= []
92
91
  [STDIN, STDOUT, STDERR].each do |io|
93
92
  dup = io.dup
@@ -250,9 +249,9 @@ module Main
250
249
  end
251
250
 
252
251
  %w[ before instead after ].each do |which|
253
- module_eval <<-code
254
- def error_handler_#{ which } *argv, &block
255
- block.call *argv
252
+ module_eval <<-code, __FILE__, __LINE__
253
+ def error_handler_#{ which }(*argv, &block)
254
+ block.call(*argv)
256
255
  end
257
256
  code
258
257
  end
@@ -265,6 +264,26 @@ module Main
265
264
  singleton_class.module_eval{ define_method('__instance_eval_block', &block) }
266
265
  fcall(self, '__instance_eval_block', *argv, &block)
267
266
  end
267
+
268
+ def dotdir(&block)
269
+ self.class.dotdir(&block)
270
+ end
271
+
272
+ def db(&block)
273
+ self.class.db(&block)
274
+ end
275
+
276
+ def config(&block)
277
+ self.class.config(&block)
278
+ end
279
+
280
+ def input
281
+ @input ||= params[:input].value if params[:input]
282
+ end
283
+
284
+ def output
285
+ @output ||= params[:output].value if params[:output]
286
+ end
268
287
  end
269
288
 
270
289
  include InstanceMethods
data/lib/main/util.rb CHANGED
@@ -71,6 +71,20 @@ module Main
71
71
 
72
72
  return default
73
73
  end
74
+
75
+ def home
76
+ home =
77
+ catch :home do
78
+ ["HOME", "USERPROFILE"].each do |key|
79
+ throw(:home, ENV[key]) if ENV[key]
80
+ end
81
+ if ENV["HOMEDRIVE"] and ENV["HOMEPATH"]
82
+ throw(:home, "#{ ENV['HOMEDRIVE'] }:#{ ENV['HOMEPATH'] }")
83
+ end
84
+ File.expand_path("~") rescue(File::ALT_SEPARATOR ? "C:/" : "/")
85
+ end
86
+ File.expand_path(home)
87
+ end
74
88
  end
75
89
 
76
90
  BLESS = lambda do |other|
data/main.gemspec CHANGED
@@ -4,7 +4,7 @@
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "main"
6
6
  spec.description = 'a class factory and dsl for generating command line programs real quick'
7
- spec.version = "4.3.0"
7
+ spec.version = "4.4.0"
8
8
  spec.platform = Gem::Platform::RUBY
9
9
  spec.summary = "main"
10
10
 
data/samples/j.rb CHANGED
@@ -1,14 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ require 'open-uri'
4
+
2
5
  require 'main'
6
+ require 'digest/sha2'
7
+
8
+ # you have access to a sequel/amalgalite/sqlite db for free
9
+ #
3
10
 
4
11
  Main {
5
- mode( :foo ) {
6
- argument( :bar ) {
7
- required
8
- default 42
9
- }
10
- run {
11
- puts "Doing something with #{params['bar'].value}"
12
- }
12
+ name :i_can_haz_db
13
+
14
+ db {
15
+ create_table(:mp3s) do
16
+ primary_key :id
17
+ String :url
18
+ String :sha
19
+ end unless table_exists?(:mp3s)
13
20
  }
21
+
22
+ def run
23
+ url = 'http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3'
24
+ mp3 = open(url){|fd| fd.read}
25
+ sha = Digest::SHA2.hexdigest(mp3)
26
+
27
+ db[:mp3s].insert(:url => url, :sha => sha)
28
+ p db[:mp3s].all
29
+ p db
30
+ end
14
31
  }
data/test/main.rb CHANGED
@@ -258,7 +258,7 @@ class T < Test::Unit::TestCase
258
258
  }
259
259
  option('y'){
260
260
  argument_required
261
- process{|*values| values.join.split(',').map{|value| value.upcase}}
261
+ cast{|*values| values.join.split(',').map{|value| value.upcase}}
262
262
  }
263
263
  define_method('run'){ param = params }
264
264
  }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: main
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
4
+ hash: 47
5
5
  prerelease: false
6
6
  segments:
7
7
  - 4
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 4.3.0
10
+ version: 4.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ara T. Howard
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-07 01:00:00 -06:00
18
+ date: 2010-11-25 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency