madvertise-logging 0.6.0 → 0.7.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/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 1.9.2
5
3
  - 1.9.3
4
+ - 1.9.2
5
+ - ruby-head
6
+ - jruby-head
data/Gemfile CHANGED
@@ -4,10 +4,10 @@ gemspec
4
4
 
5
5
  group :development, :test do
6
6
  gem 'bundler'
7
+ gem 'kramdown'
7
8
  gem 'pry'
8
9
  gem 'pry-doc'
9
10
  gem 'rake'
10
- gem 'redcarpet'
11
11
  gem 'reek'
12
12
  gem 'rspec'
13
13
  gem 'ruby2ruby', '=1.3.0' # 1.3.1 is broken :(
data/benchmark.rb ADDED
@@ -0,0 +1,52 @@
1
+ require 'bundler/setup'
2
+ require 'madvertise-logging'
3
+ require 'benchmark'
4
+
5
+ puts "Using " + %x(ruby -v)
6
+ puts
7
+
8
+ $log = Madvertise::Logging::ImprovedLogger.new(:buffer)
9
+
10
+ STRING_A = ("a string"*10).freeze
11
+ STRING_B = ("b string"*10).freeze
12
+
13
+ n = 2000000
14
+
15
+ puts ">>> Testing String interpolation vs. concatenation (n=#{n})"
16
+
17
+ Benchmark.bmbm do |x|
18
+ x.report("append double") { n.times do; "" << STRING_A << STRING_B << STRING_A; end }
19
+ x.report("concat double") { n.times do; STRING_A + STRING_B + STRING_A; end }
20
+ x.report("concat interp") { n.times do; "#{STRING_A}#{STRING_B}#{STRING_A}"; end }
21
+ end
22
+
23
+ n = 50000
24
+
25
+ puts
26
+ puts ">>> Testing caller"
27
+ Benchmark.bmbm do |x|
28
+ x.report("caller") { n.times do; caller; end }
29
+ end
30
+
31
+ $debug = false
32
+ $log.level = :info
33
+
34
+ puts
35
+ puts ">>> Testing log.debug with debug disabled (n=#{n})"
36
+ Benchmark.bmbm do |x|
37
+ x.report("debug w/ guard") { n.times do; $log.debug(STRING_A) if $debug; end }
38
+ x.report("debug w/ block") { n.times do; $log.debug{STRING_A}; end }
39
+ x.report("debug w/ block + concat") { n.times do; $log.debug{"#{STRING_A}#{STRING_B}#{STRING_A}"}; end }
40
+ x.report("debug w/o guard") { n.times do; $log.debug(STRING_A); end }
41
+ x.report("debug w/o guard + concat") { n.times do; $log.debug("#{STRING_A}#{STRING_B}#{STRING_A}"); end }
42
+ end
43
+
44
+ $debug = true
45
+ $log.level = :debug
46
+
47
+ puts
48
+ puts ">>> Testing log.debug with debug enabled (n=#{n})"
49
+ Benchmark.bmbm do |x|
50
+ x.report("debug w/ guard") { n.times do; $log.debug(STRING_A) if $debug; end }
51
+ x.report("debug w/o guard") { n.times do; $log.debug(STRING_A); end }
52
+ end
@@ -1,3 +1,6 @@
1
1
  require 'madvertise/logging/version'
2
2
  require 'madvertise/logging/improved_logger'
3
3
  require 'madvertise/logging/multi_logger'
4
+
5
+ ImprovedLogger = Madvertise::Logging::ImprovedLogger
6
+ MultiLogger = Madvertise::Logging::MultiLogger
@@ -3,6 +3,16 @@ require 'stringio'
3
3
 
4
4
  require 'madvertise/logging/improved_io'
5
5
 
6
+ class String
7
+ def clean_quote
8
+ if index(/["\s]/)
9
+ %{"#{tr('"', "'")}"}
10
+ else
11
+ self
12
+ end
13
+ end
14
+ end
15
+
6
16
  module Madvertise
7
17
  module Logging
8
18
 
@@ -18,6 +28,12 @@ module Madvertise
18
28
  # Arbitrary token to prefix log messages with.
19
29
  attr_accessor :token
20
30
 
31
+ # Log the file/line where the message came from
32
+ attr_accessor :log_caller
33
+
34
+ # Log filename for file backend.
35
+ attr_reader :logfile
36
+
21
37
  @severities = {
22
38
  :debug => Logger::DEBUG,
23
39
  :info => Logger::INFO,
@@ -41,6 +57,7 @@ module Madvertise
41
57
  def initialize(backend = STDERR, progname = nil)
42
58
  self.progname = progname || File.basename($0)
43
59
  self.logger = backend
60
+ self.log_caller = false
44
61
  end
45
62
 
46
63
  # Get the backend logger.
@@ -58,7 +75,8 @@ module Madvertise
58
75
  # @return [Logger] The newly created backend logger object.
59
76
  def logger=(value)
60
77
  @backend = value
61
- create_backend
78
+ @logger = create_backend
79
+ define_level_methods
62
80
  end
63
81
 
64
82
  # Close any connections/descriptors that may have been opened by the
@@ -79,7 +97,8 @@ module Madvertise
79
97
  #
80
98
  # @return [Symbol] Current logging level.
81
99
  def level
82
- self.class.severities.invert[@logger.level]
100
+ @severities_inverted ||= self.class.severities.invert
101
+ @severities_inverted[@logger.level]
83
102
  end
84
103
 
85
104
  # Set the logging level.
@@ -87,41 +106,33 @@ module Madvertise
87
106
  # @param [Symbol, Fixnum] level New level as Symbol or Fixnum from Logger class.
88
107
  # @return [Fixnum] New level converted to Fixnum from Logger class.
89
108
  def level=(level)
90
- level = level.is_a?(Symbol) ? self.class.severities[level] : level
91
- logger.level = level
92
- end
93
-
94
- # Log a debug level message.
95
- def debug(msg)
96
- add(:debug, msg)
97
- end
98
-
99
- # Log an info level message.
100
- def info(msg)
101
- add(:info, msg)
109
+ logger.level = level.is_a?(Symbol) ? self.class.severities[level] : level
110
+ define_level_methods
102
111
  end
103
112
 
104
- # Log a warning level message.
105
- def warn(msg)
106
- add(:warn, msg)
107
- end
108
-
109
- # Log an error level message.
110
- def error(msg)
111
- add(:error, msg)
112
- end
113
-
114
- # Log a fatal level message.
115
- def fatal(msg)
116
- add(:fatal, msg)
117
- end
118
-
119
- # Log a message with unknown level.
120
- def unknown(msg)
121
- add(:unknown, msg)
113
+ # @private
114
+ def define_level_methods
115
+ # We do this dynamically here, so we can implement a no-op for levels
116
+ # which are disabled.
117
+ self.class.severities.each do |severity, num|
118
+ if num >= logger.level
119
+ instance_eval(<<-EOM, __FILE__, __LINE__)
120
+ def #{severity}(*args, &block)
121
+ if block_given?
122
+ add(:#{severity}, *yield)
123
+ else
124
+ add(:#{severity}, *args)
125
+ end
126
+ end
127
+ EOM
128
+ else
129
+ instance_eval("def #{severity}(*args); end", __FILE__, __LINE__)
130
+ end
131
+ end
122
132
  end
123
133
 
124
- # Log an info level message
134
+ # Compatibility method
135
+ # @private
125
136
  def <<(msg)
126
137
  add(:info, msg)
127
138
  end
@@ -130,14 +141,15 @@ module Madvertise
130
141
 
131
142
  # Log an exception with fatal level.
132
143
  #
133
- # @param [Exception, String] exc The exception to log. If exc is a
134
- # String no backtrace will be generated.
135
- # @param [String] prefix Additional message to log.
136
- def exception(exc, prefix=nil)
137
- msg = "EXCEPTION"
138
- msg << ": #{prefix}" if prefix
139
- msg << ": #{exc.message}: #{clean_trace(exc.backtrace)}" if exc.is_a?(::Exception)
140
- fatal(msg)
144
+ # @param [Exception] exc The exception to log.
145
+ # @param [String] message Additional reason to log.
146
+ def exception(exc, message=nil)
147
+ fatal("exception", {
148
+ class: exc.class,
149
+ reason: exc.message,
150
+ message: message,
151
+ backtrace: clean_trace(exc.backtrace)
152
+ })
141
153
  end
142
154
 
143
155
  # Save the current token and associate it with obj#object_id.
@@ -187,14 +199,15 @@ module Madvertise
187
199
  line.match(/(improved_logger|multi_logger)\.rb/).nil?
188
200
  end
189
201
 
190
- file, num, discard = location.split(':')
202
+ file, num, _ = location.split(':')
191
203
  [ File.basename(file), num ].join(':')
192
204
  end
193
205
 
194
- def add(severity, message)
206
+ def add(severity, message, attribs={})
195
207
  severity = self.class.severities[severity]
196
- message = "#{called_from}: #{message}"
208
+ message = "#{called_from}: #{message}" if @log_caller
197
209
  message = "[#{@token}] #{message}" if @token
210
+ message = "#{message} #{attribs.map{|k,v| "#{k}=#{v.to_s.clean_quote}"}.join(' ')}" if attribs.any?
198
211
  logger.add(severity) { message }
199
212
  return nil
200
213
  end
@@ -275,8 +288,7 @@ module Madvertise
275
288
 
276
289
  # @private
277
290
  def call(severity, time, progname, msg)
278
- # this is so ugly because ruby 1.8 does not support %N in strftime
279
- time = time.strftime("%Y-%m-%d %H:%M:%S.") + sprintf('%.6f', time.usec.to_f/1000/1000)[2..-1]
291
+ time = time.strftime("%Y-%m-%d %H:%M:%S.%N")
280
292
  self.class.format % [time, progname, $$, severity, msg.to_s]
281
293
  end
282
294
  end
@@ -1,6 +1,6 @@
1
1
  module Madvertise
2
2
  module Logging
3
3
  # @private
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
6
6
  end
@@ -6,50 +6,50 @@ include Madvertise::Logging
6
6
 
7
7
  RSpec::Matchers.define :have_received_message do |expected|
8
8
  match do |actual|
9
- last = IO.readlines(actual).last
10
- last ? last.match(Regexp.new(expected)) : false
9
+ @last = IO.readlines(actual).last rescue nil
10
+ @last ? @last.match(Regexp.new(expected)) : false
11
11
  end
12
- end
13
-
14
- describe ImprovedLogger do
15
12
 
16
- before(:each) do
17
- @logfile = Tempfile.new("spec").path
18
- @logger = ImprovedLogger.new(@logfile)
19
- @logger.level = :debug
13
+ failure_message_for_should do |actual|
14
+ "expected #{@last.inspect} to contain #{expected}"
20
15
  end
21
16
 
22
- it "should be an IO object" do
23
- @logger.should be_a(IO)
17
+ failure_message_for_should_not do |actual|
18
+ "expected #{@last.inspect} to not contain #{expected}"
24
19
  end
20
+ end
25
21
 
26
- it "should have a backend logger" do
27
- @logger.logger.should_not be_nil
28
- end
22
+ describe ImprovedLogger do
29
23
 
30
- it "should accept a different backend" do
31
- l = Logger.new('/dev/null')
32
- @logger.logger = l
33
- @logger.logger.should == l
24
+ before(:all) do
25
+ Tempfile.new("spec").tap do |tmpfile|
26
+ @logfile = tmpfile.path
27
+ tmpfile.close
28
+ end
34
29
  end
35
30
 
36
- it "should support reopening log files" do
37
- @logger.close
38
-
39
- FileUtils.rm(@logfile)
40
-
41
- @logger.info('Reopen')
42
- @logfile.should have_received_message("Reopen")
31
+ after(:all) do
32
+ File.unlink(@logfile) rescue nil
43
33
  end
44
34
 
45
- it "should log debug level messages" do
46
- @logger.debug("Debug test")
47
- @logfile.should have_received_message(/\[DEBUG\].*Debug test/)
35
+ before(:each) do
36
+ File.unlink(@logfile) rescue nil
37
+ @logger = ImprovedLogger.new(@logfile)
38
+ @logger.level = :debug
48
39
  end
49
40
 
50
- it "should log info level messages" do
51
- @logger.info("Info test")
52
- @logfile.should have_received_message(/\[INFO\].*Info test/)
41
+ subject { @logger }
42
+
43
+ it { should be_a IO }
44
+ its(:logger) { should_not be_nil }
45
+
46
+ ImprovedLogger.severities.keys.each do |level|
47
+ describe level do
48
+ subject { @logfile }
49
+ before { @logger.send(level, "test") }
50
+ let(:prefix) { level == :unknown ? "ANY" : level.to_s.upcase }
51
+ it { should have_received_message(/\[#{prefix}\].*test/) }
52
+ end
53
53
  end
54
54
 
55
55
  it "should log info level messages with write and << compat methods" do
@@ -59,74 +59,82 @@ describe ImprovedLogger do
59
59
  @logfile.should have_received_message(/\[INFO\].*Info test2/)
60
60
  end
61
61
 
62
- it "should log warn level messages" do
63
- @logger.warn("Warn test")
64
- @logfile.should have_received_message(/\[WARN\].*Warn test/)
62
+ it "should support additional attributes" do
63
+ @logger.info("foo", key: "value", test: "with space")
64
+ @logfile.should have_received_message(/key=value test="with space"/)
65
65
  end
66
66
 
67
- it "should log error level messages" do
68
- @logger.error("Err test")
69
- @logfile.should have_received_message(/\[ERROR\].*Err test/)
67
+ it "should support lazy-evaluation via blocks" do
68
+ @logger.debug { "debug message" }
69
+ @logfile.should have_received_message(/debug message/)
70
+ @logger.debug { ["debug message", {key: "value"}] }
71
+ @logfile.should have_received_message(/debug message.*key=value/)
70
72
  end
71
73
 
72
- it "should log fatal level messages" do
73
- @logger.fatal("Fatal test")
74
- @logfile.should have_received_message(/\[FATAL\].*Fatal test/)
74
+ it "should accept a different backend" do
75
+ l = Logger.new('/dev/null')
76
+ @logger.logger = l
77
+ @logger.logger.should == l
75
78
  end
76
79
 
77
- it "should log unknown level messages" do
78
- @logger.unknown("Unknown test")
79
- @logfile.should have_received_message(/\[ANY\].*Unknown test/)
80
+ it "should support reopening log files" do
81
+ @logger.close
82
+ FileUtils.rm(@logfile)
83
+ @logger.info('Reopen')
84
+ @logfile.should have_received_message("Reopen")
80
85
  end
81
86
 
82
- it "should log the caller file and line number" do
83
- f = File.basename(__FILE__)
84
- l = __LINE__ + 2
85
-
86
- @logger.info("Caller test")
87
- @logfile.should have_received_message("#{f}:#{l}:")
88
- end
87
+ describe :log_caller do
88
+ it "should log the caller file and line number" do
89
+ f = File.basename(__FILE__)
90
+ l = __LINE__ + 3
89
91
 
90
- it "should log exceptions with daemon traces" do
91
- fake_trace = [
92
- "/home/jdoe/app/libexec/app.rb:1:in `foo'",
93
- "/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
94
- ]
92
+ @logger.log_caller = true
93
+ @logger.info("Caller test")
94
+ @logfile.should have_received_message("#{f}:#{l}:")
95
+ end
95
96
 
96
- e = RuntimeError.new('Test error')
97
- e.set_backtrace(fake_trace)
97
+ it "should not log the caller file and line number" do
98
+ f = File.basename(__FILE__)
99
+ l = __LINE__ + 3
98
100
 
99
- @logger.exception(e)
100
- @logfile.should have_received_message("EXCEPTION: Test error")
101
+ @logger.log_caller = false
102
+ @logger.info("Caller test")
103
+ @logfile.should_not have_received_message("#{f}:#{l}:")
104
+ end
101
105
  end
102
106
 
103
- it "should log exceptions without framework traces" do
104
- fake_trace = [
105
- "/home/jdoe/app/libexec/app.rb:1:in `foo'",
106
- "/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
107
- ]
108
-
109
- clean_trace = @logger.clean_trace(fake_trace)
110
- clean_trace.should include("/home/jdoe/app/libexec/app.rb:1:in `foo'")
111
- clean_trace.should_not include("/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'")
107
+ let(:fake_trace) do
108
+ [
109
+ "/home/jdoe/app/libexec/app.rb:1:in `foo'",
110
+ "/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
111
+ ]
112
112
  end
113
113
 
114
- it "should not handle a backtrace if object is not an exception" do
115
- @logger.exception("not an exception object")
116
- @logfile.should_not have_received_message("EXCEPTION:")
117
- end
114
+ describe :exceptions do
115
+ let(:exc) do
116
+ RuntimeError.new('Test error').tap do |exc|
117
+ exc.set_backtrace(fake_trace)
118
+ end
119
+ end
118
120
 
119
- it "should log additional info on exceptions" do
120
- fake_trace = [
121
- "/home/jdoe/app/libexec/app.rb:1:in `foo'",
122
- "/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'"
123
- ]
121
+ subject { @logfile }
124
122
 
125
- e = RuntimeError.new('Test error')
126
- e.set_backtrace(fake_trace)
123
+ context "with exception object" do
124
+ before { @logger.exception(exc) }
125
+ it { should have_received_message("exception class=RuntimeError reason=\"Test error\"") }
126
+ end
127
127
 
128
- @logger.exception(e, "app failed to foo")
129
- @logfile.should have_received_message("app failed to foo")
128
+ context "with exception object and prefix" do
129
+ before { @logger.exception(exc, "app failed to foo") }
130
+ it { should have_received_message("app failed to foo") }
131
+ end
132
+ end
133
+
134
+ describe :clean_trace do
135
+ subject { @logger.clean_trace(fake_trace) }
136
+ it { should include("/home/jdoe/app/libexec/app.rb:1:in `foo'") }
137
+ it { should_not include("/usr/lib/ruby/gems/1.8/gems/madvertise-logging-0.1.0/lib/madvertise/logging/improved_logger.rb:42: in `info'") }
130
138
  end
131
139
 
132
140
  it "should support silencing" do
@@ -217,21 +225,10 @@ describe ImprovedLogger do
217
225
  @logger.close_write
218
226
  end
219
227
 
220
- it "should be in sync mode" do
221
- @logger.sync.should == true
222
- end
223
-
224
- it "should return self on flush" do
225
- @logger.flush.should == @logger
226
- end
227
-
228
- it "should return self on set_encoding" do
229
- @logger.set_encoding.should == @logger
230
- end
231
-
232
- it "should ne be a tty" do
233
- @logger.tty?.should == false
234
- end
228
+ its(:flush) { should == @logger }
229
+ its(:set_encoding) { should == @logger }
230
+ its(:sync) { should == true }
231
+ its(:tty?) { should == false }
235
232
 
236
233
  it "should support printf" do
237
234
  @logger.printf("%.2f %s", 1.12345, "foo")
@@ -249,11 +246,19 @@ describe ImprovedLogger do
249
246
  @logger.puts("a", "b")
250
247
  @logfile.should have_received_message("b")
251
248
  @logger.puts(["c", "d"])
252
- @logfile.should have_received_message("b")
249
+ @logfile.should have_received_message("d")
253
250
  @logger.puts(1, 2, 3)
254
251
  @logfile.should have_received_message("3")
255
252
  end
256
253
 
254
+ it "should not implement closed?" do
255
+ expect { @logger.closed? }.to raise_error(NotImplementedError)
256
+ end
257
+
258
+ it "should not implement sync=" do
259
+ expect { @logger.sync = false }.to raise_error(NotImplementedError)
260
+ end
261
+
257
262
  it "should implement readbyte, readchar, readline" do
258
263
  {
259
264
  :readbyte => :getbyte,
@@ -261,24 +266,10 @@ describe ImprovedLogger do
261
266
  :readline => :gets,
262
267
  }.each do |m, should|
263
268
  @logger.should_receive(should)
264
- lambda {
265
- @logger.send(m)
266
- }.should raise_error(IOError)
269
+ expect { @logger.send(m) }.to raise_error(IOError)
267
270
  end
268
271
  end
269
272
 
270
- it "should not implement closed?" do
271
- lambda {
272
- @logger.closed?
273
- }.should raise_error(NotImplementedError)
274
- end
275
-
276
- it "should not implement sync=" do
277
- lambda {
278
- @logger.sync = false
279
- }.should raise_error(NotImplementedError)
280
- end
281
-
282
273
  [
283
274
  :bytes,
284
275
  :chars,
@@ -299,41 +290,30 @@ describe ImprovedLogger do
299
290
  :ungetc
300
291
  ].each do |m|
301
292
  it "should raise IOError for method #{m}" do
302
- lambda {
303
- @logger.send(m)
304
- }.should raise_error(IOError)
293
+ expect { @logger.send(m) }.to raise_error(IOError)
305
294
  end
306
295
  end
307
296
  end
308
297
 
309
298
  context "buffer backend" do
310
- before(:each) do
311
- @logger = ImprovedLogger.new(:buffer)
312
- @logger.level = :debug
313
- end
299
+ before { @logger = ImprovedLogger.new(:buffer) }
300
+ its(:sync) { should == false }
314
301
 
315
302
  it "should support a buffered logger" do
316
303
  @logger.info "test"
317
304
  @logger.buffer.should match(/test/)
318
305
  end
319
-
320
- it "should not be in sync mode" do
321
- @logger.sync.should == false
322
- end
323
306
  end
324
307
 
325
308
  context "syslog backend" do
326
- before(:each) do
327
- @logger = ImprovedLogger.new(:syslog)
328
- @logger.level = :debug
329
- end
330
-
331
- it "should have a syslog backend" do
332
- @logger.logger.should be_instance_of(Syslogger)
333
- end
309
+ before { @logger = ImprovedLogger.new(:syslog) }
310
+ its(:sync) { should == true }
311
+ its(:logger) { should be_instance_of(Syslogger) }
312
+ end
334
313
 
335
- it "should be in sync mode" do
336
- @logger.sync.should == true
314
+ context "unknown backend" do
315
+ it "should raise for unknown backends " do
316
+ expect { ImprovedLogger.new(:unknown_logger) }.to raise_error(RuntimeError)
337
317
  end
338
318
  end
339
319
 
data/spec/spec.opts CHANGED
@@ -1 +1,2 @@
1
1
  --colour
2
+ --format documentation
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: madvertise-logging
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-11 00:00:00.000000000 Z
12
+ date: 2012-09-20 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Advanced logging classes with buffer backend, transactions, multi logger,
15
15
  etc
@@ -27,6 +27,7 @@ files:
27
27
  - LICENSE
28
28
  - README.md
29
29
  - Rakefile
30
+ - benchmark.rb
30
31
  - lib/madvertise-logging.rb
31
32
  - lib/madvertise/logging/improved_io.rb
32
33
  - lib/madvertise/logging/improved_logger.rb
@@ -55,7 +56,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
55
56
  version: '0'
56
57
  segments:
57
58
  - 0
58
- hash: -1250046391813060871
59
+ hash: -920573810095702507
59
60
  required_rubygems_version: !ruby/object:Gem::Requirement
60
61
  none: false
61
62
  requirements:
@@ -64,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
65
  version: '0'
65
66
  segments:
66
67
  - 0
67
- hash: -1250046391813060871
68
+ hash: -920573810095702507
68
69
  requirements: []
69
70
  rubyforge_project:
70
71
  rubygems_version: 1.8.17