extlib 0.9.10 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of extlib might be problematic. Click here for more details.

data/History.txt CHANGED
@@ -1,3 +1,23 @@
1
+ === 0.9.11 / not released
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Added LazyModule, providing similar capabilities to traits in
6
+ Smalltalk
7
+
8
+ * 5 minor enhancements:
9
+
10
+ * Added Array#to_hash and Array#to_mash
11
+ * Silenced warnings when running in verbose mode
12
+ * Add ByteArray for representing binary data explicitly
13
+ * Alias Pathname#to_s to Pathname#to_str when not defined
14
+ * Added Object#try_call
15
+
16
+ * 2 bug fixes:
17
+
18
+ * Updated Module.find_const to use const_missing if constant not found
19
+ * Fixed LazyArray#equal? to compare object_ids
20
+
1
21
  === 0.9.10 / 2009-01-19
2
22
 
3
23
  * 1 major enhancement:
@@ -9,7 +29,7 @@
9
29
  * Updated LazyArray#eql? and LazyArray#== to compare without lazy
10
30
  loading if possible.
11
31
 
12
- 3 bug fixes:
32
+ * 3 bug fixes:
13
33
 
14
34
  * Fix for inheritance and hooks
15
35
  * Fix for Class inheritable accessor to use #try_dup
data/Rakefile CHANGED
@@ -9,7 +9,10 @@ require "fileutils"
9
9
  require Pathname('spec/rake/spectask')
10
10
  require Pathname('lib/extlib/version')
11
11
 
12
- ROOT = Pathname(__FILE__).dirname.expand_path
12
+ ROOT = Pathname(__FILE__).dirname.expand_path
13
+ JRUBY = RUBY_PLATFORM =~ /java/
14
+ WINDOWS = Gem.win_platform?
15
+ SUDO = (WINDOWS || JRUBY) ? '' : ('sudo' unless ENV['SUDOLESS'])
13
16
 
14
17
  ##############################################################################
15
18
  # Package && release
@@ -26,15 +29,7 @@ GEM_NAME = "extlib"
26
29
  PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
27
30
  GEM_VERSION = Extlib::VERSION + PKG_BUILD
28
31
 
29
- RELEASE_NAME = "REL #{GEM_VERSION}"
30
-
31
- WINDOWS = (RUBY_PLATFORM =~ /win32|mingw|bccwin|cygwin/) rescue nil
32
- JRUBY = (RUBY_PLATFORM =~ /java/) rescue nil
33
-
34
- # sudo is used by default, except on Windows, or if SUDOLESS env is true
35
- SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
36
- # RCov is run by default, except on the JRuby platform, or if NO_RCOV env is true
37
- RUN_RCOV = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
32
+ RELEASE_NAME = "REL #{GEM_VERSION}"
38
33
 
39
34
  require "lib/extlib/tasks/release"
40
35
 
@@ -73,13 +68,12 @@ task :spec => 'extlib:spec'
73
68
 
74
69
  namespace :extlib do
75
70
  Spec::Rake::SpecTask.new(:spec) do |t|
76
- t.spec_opts << '--format' << 'specdoc' << '--colour'
77
- t.spec_opts << '--loadby' << 'random'
71
+ t.spec_opts << '--options' << ROOT + 'spec/spec.opts'
78
72
  t.spec_files = Pathname.glob(ENV['FILES'] || 'spec/**/*_spec.rb').map { |f| f.to_s }
79
73
 
80
74
  begin
81
75
  gem 'rcov'
82
- t.rcov = RUN_RCOV
76
+ t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
83
77
  t.rcov_opts << '--exclude' << 'spec'
84
78
  t.rcov_opts << '--text-summary'
85
79
  t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
@@ -104,9 +98,13 @@ task :doc do
104
98
  end
105
99
  end
106
100
 
101
+ def sudo_gem(cmd)
102
+ sh "#{SUDO} #{RUBY} -S gem #{cmd}", :verbose => false
103
+ end
104
+
107
105
  desc "Install #{GEM_NAME}"
108
106
  task :install => :package do
109
- sh %{#{SUDO} gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources}
107
+ sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION}"
110
108
  end
111
109
 
112
110
  if WINDOWS
data/lib/extlib.rb CHANGED
@@ -1,30 +1,31 @@
1
1
  require 'pathname'
2
2
  require 'rubygems'
3
3
 
4
- __DIR__ = File.expand_path(File.dirname(__FILE__))
5
- $LOAD_PATH.unshift(__DIR__) unless $LOAD_PATH.include?(__DIR__)
4
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
5
 
7
6
  # for Pathname /
8
- require File.expand_path(File.join(__DIR__, 'extlib', 'pathname'))
7
+ require File.expand_path(File.join(File.dirname(__FILE__), 'extlib', 'pathname'))
9
8
 
10
9
  dir = Pathname(__FILE__).dirname.expand_path / 'extlib'
11
10
 
12
- require dir / "class.rb"
13
- require dir / "object"
14
- require dir / "object_space"
11
+ require dir / 'class.rb'
12
+ require dir / 'object'
13
+ require dir / 'object_space'
15
14
 
16
- require dir / "string"
17
- require dir / "symbol"
18
- require dir / "hash"
19
- require dir / "mash"
20
- require dir / "virtual_file"
21
- require dir / "logger"
22
- require dir / "time"
23
- require dir / "datetime"
15
+ require dir / 'array'
16
+ require dir / 'string'
17
+ require dir / 'symbol'
18
+ require dir / 'hash'
19
+ require dir / 'mash'
20
+ require dir / 'virtual_file'
21
+ require dir / 'logger'
22
+ require dir / 'time'
23
+ require dir / 'datetime'
24
24
 
25
25
  require dir / 'assertions'
26
26
  require dir / 'blank'
27
27
  require dir / 'boolean'
28
+ require dir / 'byte_array'
28
29
  require dir / 'inflection'
29
30
  require dir / 'lazy_array'
30
31
  require dir / 'module'
@@ -35,13 +36,13 @@ require dir / 'simple_set'
35
36
  require dir / 'struct'
36
37
  require dir / 'symbol'
37
38
 
38
- Extlib.autoload("Hook", (dir / 'hook').to_s)
39
- Extlib.autoload("Pooling", (dir / 'pooling').to_s)
39
+ Extlib.autoload('Hook', (dir / 'hook').to_s)
40
+ Extlib.autoload('Pooling', (dir / 'pooling').to_s)
40
41
 
41
42
  module Extlib
42
43
 
43
44
  def self.exiting= bool
44
- if bool && Extlib.const_defined?("Pooling")
45
+ if bool && Extlib.const_defined?('Pooling')
45
46
  if Extlib::Pooling.scavenger?
46
47
  Extlib::Pooling.scavenger.wakeup
47
48
  end
@@ -50,7 +51,8 @@ module Extlib
50
51
  end
51
52
 
52
53
  def self.exiting
53
- @exiting
54
+ return @exiting if defined?(@exiting)
55
+ @exiting = false
54
56
  end
55
57
 
56
58
  end
@@ -0,0 +1,36 @@
1
+ class Array
2
+
3
+ ##
4
+ # Transforms an Array of key/value pairs into a Hash
5
+ #
6
+ # This is a better idiom than using Hash[*array.flatten] in Ruby 1.8.6
7
+ # because it is not possible to limit the flattening to a single
8
+ # level.
9
+ #
10
+ # @return [Hash]
11
+ # A Hash where each entry in the Array is turned into a key/value
12
+ #
13
+ # @api public
14
+ def to_hash
15
+ h = {}
16
+ each { |k,v| h[k] = v }
17
+ h
18
+ end
19
+
20
+ ##
21
+ # Transforms an Array of key/value pairs into a Mash
22
+ #
23
+ # This is a better idiom than using Mash[*array.flatten] in Ruby 1.8.6
24
+ # because it is not possible to limit the flattening to a single
25
+ # level.
26
+ #
27
+ # @return [Mash]
28
+ # A Hash where each entry in the Array is turned into a key/value
29
+ #
30
+ # @api public
31
+ def to_mash
32
+ m = Mash.new
33
+ each { |k,v| m[k] = v }
34
+ m
35
+ end
36
+ end # class Array
@@ -0,0 +1,4 @@
1
+ # This class has exists to represent binary data. This is mainly
2
+ # used by DataObjects. Binary data sometimes needs to be quoted differently
3
+ # than regular string data (even if the string is just plain ASCII).
4
+ class ByteArray < String; end
data/lib/extlib/class.rb CHANGED
@@ -115,12 +115,14 @@ class Class
115
115
  ivars.each do |ivar|
116
116
  self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
117
117
  def self.#{ivar}
118
- return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
118
+ return @#{ivar} if defined?(@#{ivar})
119
+ return nil if self.object_id == #{self.object_id}
119
120
  ivar = superclass.#{ivar}
120
- return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
121
+ return nil if ivar.nil?
121
122
  @#{ivar} = ivar.try_dup
122
123
  end
123
124
  RUBY
125
+
124
126
  unless instance_reader == false
125
127
  self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
126
128
  def #{ivar}
@@ -9,6 +9,7 @@ class DateTime
9
9
  # @return [Time] Time object representing the same moment as receiver
10
10
  #
11
11
  # @api public
12
+ remove_method :to_time if method_defined?(:to_time) || private_method_defined?(:to_time)
12
13
  def to_time
13
14
  Time.parse self.to_s
14
15
  end
@@ -21,6 +22,7 @@ class DateTime
21
22
  # @return [DateTime] Receiver
22
23
  #
23
24
  # @api public
25
+ remove_method :to_datetime if method_defined?(:to_datetime) || private_method_defined?(:to_datetime)
24
26
  def to_datetime
25
27
  self
26
28
  end
data/lib/extlib/hash.rb CHANGED
@@ -131,11 +131,11 @@ class Hash
131
131
  end
132
132
 
133
133
  stack.each do |parent, hash|
134
- hash.each do |key, value|
135
- if value.is_a?(Hash)
136
- stack << ["#{parent}[#{key}]", value]
134
+ hash.each do |k, v|
135
+ if v.is_a?(Hash)
136
+ stack << ["#{parent}[#{k}]", v]
137
137
  else
138
- param << normalize_param("#{parent}[#{key}]", value)
138
+ param << normalize_param("#{parent}[#{k}]", v)
139
139
  end
140
140
  end
141
141
  end
data/lib/extlib/hook.rb CHANGED
@@ -235,21 +235,26 @@ module Extlib
235
235
  after_hooks = hooks[target_method][:after]
236
236
  after_hooks = after_hooks.map{ |info| inline_call(info, scope) }.join("\n")
237
237
 
238
- source = %{
238
+ before_hook_name = hook_method_name(target_method, 'execute_before', 'hook_stack')
239
+ after_hook_name = hook_method_name(target_method, 'execute_after', 'hook_stack')
240
+
241
+ hooks[target_method][:in].class_eval <<-RUBY, __FILE__, __LINE__ + 1
242
+ #{scope == :class ? 'class << self' : ''}
243
+
239
244
  private
240
245
 
241
- def #{hook_method_name(target_method, 'execute_before', 'hook_stack')}(*args)
246
+ remove_method :#{before_hook_name} if method_defined?(:#{before_hook_name}) || private_method_defined?(:#{before_hook_name})
247
+ def #{before_hook_name}(*args)
242
248
  #{before_hooks}
243
249
  end
244
250
 
245
- def #{hook_method_name(target_method, 'execute_after', 'hook_stack')}(*args)
251
+ remove_method :#{after_hook_name} if method_defined?(:#{after_hook_name}) || private_method_defined?(:#{after_hook_name})
252
+ def #{after_hook_name}(*args)
246
253
  #{after_hooks}
247
254
  end
248
- }
249
255
 
250
- source = %{class << self\n#{source}\nend} if scope == :class
251
-
252
- hooks[target_method][:in].class_eval(source, __FILE__, __LINE__ - 12)
256
+ #{scope == :class ? 'end' : ''}
257
+ RUBY
253
258
  end
254
259
 
255
260
  # Returns ruby code that will invoke the hook. It checks the arity of the hook method
@@ -321,14 +326,25 @@ module Extlib
321
326
  #if this hook is previously declared in a sibling or cousin we must move the :in class
322
327
  #to the common ancestor to get both hooks to run.
323
328
  if !(hooks[target_method][:in] <=> self)
324
- hooks[target_method][:in].class_eval(
325
- %{def #{hook_method_name(target_method, 'execute_before', 'hook_stack')}(*args);super;end\n} +
326
- %{def #{hook_method_name(target_method, 'execute_after', 'hook_stack')}(*args);super;end},
327
- __FILE__,__LINE__ - 2
328
- )
329
+ before_hook_name = hook_method_name(target_method, 'execute_before', 'hook_stack')
330
+ after_hook_name = hook_method_name(target_method, 'execute_after', 'hook_stack')
331
+
332
+ hooks[target_method][:in].class_eval <<-RUBY, __FILE__, __LINE__ + 1
333
+ remove_method :#{before_hook_name} if method_defined?(:#{before_hook_name}) || private_method_defined?(:#{before_hook_name})
334
+ def #{before_hook_name}(*args)
335
+ super
336
+ end
337
+
338
+ remove_method :#{after_hook_name} if method_defined?(:#{after_hook_name}) || private_method_defined?(:#{after_hook_name})
339
+ def #{after_hook_name}(*args)
340
+ super
341
+ end
342
+ RUBY
343
+
329
344
  while !(hooks[target_method][:in] <=> self) do
330
345
  hooks[target_method][:in] = hooks[target_method][:in].superclass
331
346
  end
347
+
332
348
  define_hook_stack_execution_methods(target_method, scope)
333
349
  hooks[target_method][:in].class_eval{define_advised_method(target_method, scope)}
334
350
  end
@@ -1,17 +1,6 @@
1
1
  class LazyArray # borrowed partially from StrokeDB
2
2
  instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ send class dup object_id kind_of? respond_to? equal? assert_kind_of should should_not instance_variable_set instance_variable_get extend ].include?(m.to_s) }
3
3
 
4
- # add proxies for all Array and Enumerable methods
5
- ((Array.instance_methods(false) | Enumerable.instance_methods(false)).map { |m| m.to_s } - %w[ taguri= ]).each do |method|
6
- class_eval <<-EOS, __FILE__, __LINE__
7
- def #{method}(*args, &block)
8
- lazy_load
9
- results = @array.#{method}(*args, &block)
10
- results.equal?(@array) ? self : results
11
- end
12
- EOS
13
- end
14
-
15
4
  def first(*args)
16
5
  if lazy_possible?(@head, *args)
17
6
  @head.first(*args)
@@ -60,7 +49,7 @@ class LazyArray # borrowed partially from StrokeDB
60
49
  lazy_possible = args.all? do |arg|
61
50
  index, length = extract_slice_arguments(arg)
62
51
 
63
- if index >= 0 && lazy_possible?(@head, index + (length || 1))
52
+ if index >= 0 && lazy_possible?(@head, index + length)
64
53
  accumulator.concat(head.values_at(*arg))
65
54
  elsif index < 0 && lazy_possible?(@tail, index.abs)
66
55
  accumulator.concat(tail.values_at(*arg))
@@ -105,12 +94,10 @@ class LazyArray # borrowed partially from StrokeDB
105
94
  def [](*args)
106
95
  index, length = extract_slice_arguments(*args)
107
96
 
108
- if length.nil?
97
+ if length == 1 && args.size == 1 && args.first.kind_of?(Integer)
109
98
  return at(index)
110
99
  end
111
100
 
112
- length ||= 1
113
-
114
101
  if index >= 0 && lazy_possible?(@head, index + length)
115
102
  @head[*args]
116
103
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
@@ -126,8 +113,6 @@ class LazyArray # borrowed partially from StrokeDB
126
113
  def slice!(*args)
127
114
  index, length = extract_slice_arguments(*args)
128
115
 
129
- length ||= 1
130
-
131
116
  if index >= 0 && lazy_possible?(@head, index + length)
132
117
  @head.slice!(*args)
133
118
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
@@ -141,8 +126,6 @@ class LazyArray # borrowed partially from StrokeDB
141
126
  def []=(*args)
142
127
  index, length = extract_slice_arguments(*args[0..-2])
143
128
 
144
- length ||= 1
145
-
146
129
  if index >= 0 && lazy_possible?(@head, index + length)
147
130
  @head.[]=(*args)
148
131
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
@@ -265,7 +248,6 @@ class LazyArray # borrowed partially from StrokeDB
265
248
  lazy_load
266
249
  @array.delete_if(&block)
267
250
  else
268
- @reapers ||= []
269
251
  @reapers << block
270
252
  @head.delete_if(&block)
271
253
  @tail.delete_if(&block)
@@ -326,58 +308,31 @@ class LazyArray # borrowed partially from StrokeDB
326
308
  @frozen == true
327
309
  end
328
310
 
329
- def eql?(other)
330
- return true if equal?(other)
331
- return false unless other.class.equal?(self.class)
332
-
333
- unless loaded?
334
- # compare the head against the beginning of other. start at index
335
- # 0 and incrementally compare each entry. if other is a LazyArray
336
- # this has a lesser likelyhood of triggering a lazy load
337
- 0.upto(@head.size - 1) do |i|
338
- return false unless @head[i].eql?(other[i])
339
- end
340
-
341
- # compare the tail against the end of other. start at index
342
- # -1 and decrementally compare each entry. if other is a LazyArray
343
- # this has a lesser likelyhood of triggering a lazy load
344
- -1.downto(@tail.size * -1) do |i|
345
- return false unless @tail[i].eql?(other[i])
346
- end
347
-
348
- lazy_load
311
+ def ==(other)
312
+ if equal?(other)
313
+ return true
349
314
  end
350
315
 
351
- # convert other to an Array before checking equality
352
- @array.eql?(other.to_ary)
353
- end
354
-
355
- def ==(other)
356
- return true if equal?(other)
357
- return false unless other.respond_to?(:to_ary)
316
+ unless other.respond_to?(:to_ary)
317
+ return false
318
+ end
358
319
 
359
320
  # if necessary, convert to something that can be compared
360
321
  other = other.to_ary unless other.respond_to?(:[])
361
322
 
362
- unless loaded?
363
- # compare the head against the beginning of other. start at index
364
- # 0 and incrementally compare each entry. if other is a LazyArray
365
- # this has a lesser likelyhood of triggering a lazy load
366
- 0.upto(@head.size - 1) do |i|
367
- return false unless @head[i] == other[i]
368
- end
323
+ cmp?(other, :==)
324
+ end
369
325
 
370
- # compare the tail against the end of other. start at index
371
- # -1 and decrementally compare each entry. if other is a LazyArray
372
- # this has a lesser likelyhood of triggering a lazy load
373
- -1.downto(@tail.size * -1) do |i|
374
- return false unless @tail[i] == other[i]
375
- end
326
+ def eql?(other)
327
+ if equal?(other)
328
+ return true
329
+ end
376
330
 
377
- lazy_load
331
+ unless other.class.equal?(self.class)
332
+ return false
378
333
  end
379
334
 
380
- @array == other
335
+ cmp?(other, :eql?)
381
336
  end
382
337
 
383
338
  protected
@@ -391,10 +346,13 @@ class LazyArray # borrowed partially from StrokeDB
391
346
  private
392
347
 
393
348
  def initialize
349
+ @frozen = false
350
+ @loaded = false
394
351
  @load_with_proc = lambda { |v| v }
395
352
  @head = []
396
353
  @tail = []
397
354
  @array = []
355
+ @reapers = []
398
356
  end
399
357
 
400
358
  def initialize_copy(original)
@@ -441,7 +399,7 @@ class LazyArray # borrowed partially from StrokeDB
441
399
  return first_arg, second_arg
442
400
  elsif args.size == 1
443
401
  if first_arg.kind_of?(Integer)
444
- return first_arg
402
+ return first_arg, 1
445
403
  elsif first_arg.kind_of?(Range)
446
404
  index = first_arg.first
447
405
  length = first_arg.last - index
@@ -464,4 +422,46 @@ class LazyArray # borrowed partially from StrokeDB
464
422
  super
465
423
  end
466
424
  end
425
+
426
+ def cmp?(other, operator)
427
+ unless loaded?
428
+ # compare the head against the beginning of other. start at index
429
+ # 0 and incrementally compare each entry. if other is a LazyArray
430
+ # this has a lesser likelyhood of triggering a lazy load
431
+ 0.upto(@head.size - 1) do |i|
432
+ return false unless @head[i].send(operator, other[i])
433
+ end
434
+
435
+ # compare the tail against the end of other. start at index
436
+ # -1 and decrementally compare each entry. if other is a LazyArray
437
+ # this has a lesser likelyhood of triggering a lazy load
438
+ -1.downto(@tail.size * -1) do |i|
439
+ return false unless @tail[i].send(operator, other[i])
440
+ end
441
+
442
+ lazy_load
443
+ end
444
+
445
+ @array.send(operator, other.to_ary)
446
+ end
447
+
448
+ # add proxies for all remaining Array and Enumerable methods
449
+ (Array.public_instance_methods(false) | Enumerable.public_instance_methods(false)).each do |method|
450
+ next if public_method_defined?(method)
451
+
452
+ target = if method.to_s[-1, 1] == '='
453
+ "send(:#{method}, *args, &block)"
454
+ else
455
+ "#{method}(*args, &block)"
456
+ end
457
+
458
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
459
+ public
460
+ def #{method}(*args, &block) # def []=(*args, &block)
461
+ lazy_load # lazy_load
462
+ results = @array.#{target} # results = @array.send(:[]=, *args, &block)
463
+ results.equal?(@array) ? self : results # results.equal?(@array) ? self : results
464
+ end # end
465
+ RUBY
466
+ end
467
467
  end
@@ -0,0 +1,18 @@
1
+ class LazyModule < Module
2
+ def self.new(&blk)
3
+ # passing no-op block overrides &blk
4
+ m = super{ }
5
+ class << m
6
+ include ClassMethods
7
+ end
8
+ m.lazy_evaluated_body = blk
9
+ m
10
+ end
11
+
12
+ module ClassMethods
13
+ attr_accessor :lazy_evaluated_body
14
+ def included(host)
15
+ host.class_eval(&@lazy_evaluated_body)
16
+ end
17
+ end
18
+ end
data/lib/extlib/logger.rb CHANGED
@@ -1,36 +1,36 @@
1
1
  require "time" # httpdate
2
- # ==== Public Merb Logger API
2
+ # ==== Public Extlib Logger API
3
3
  #
4
4
  # To replace an existing logger with a new one:
5
- # Merb::Logger.set_log(log{String, IO},level{Symbol, String})
5
+ # Extlib::Logger.set_log(log{String, IO},level{Symbol, String})
6
6
  #
7
7
  # Available logging levels are
8
- # Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
8
+ # Extlib::Logger::{ Fatal, Error, Warn, Info, Debug }
9
9
  #
10
10
  # Logging via:
11
- # Merb.logger.fatal(message<String>,&block)
12
- # Merb.logger.error(message<String>,&block)
13
- # Merb.logger.warn(message<String>,&block)
14
- # Merb.logger.info(message<String>,&block)
15
- # Merb.logger.debug(message<String>,&block)
11
+ # Extlib.logger.fatal(message<String>,&block)
12
+ # Extlib.logger.error(message<String>,&block)
13
+ # Extlib.logger.warn(message<String>,&block)
14
+ # Extlib.logger.info(message<String>,&block)
15
+ # Extlib.logger.debug(message<String>,&block)
16
16
  #
17
17
  # Logging with autoflush:
18
- # Merb.logger.fatal!(message<String>,&block)
19
- # Merb.logger.error!(message<String>,&block)
20
- # Merb.logger.warn!(message<String>,&block)
21
- # Merb.logger.info!(message<String>,&block)
22
- # Merb.logger.debug!(message<String>,&block)
18
+ # Extlib.logger.fatal!(message<String>,&block)
19
+ # Extlib.logger.error!(message<String>,&block)
20
+ # Extlib.logger.warn!(message<String>,&block)
21
+ # Extlib.logger.info!(message<String>,&block)
22
+ # Extlib.logger.debug!(message<String>,&block)
23
23
  #
24
24
  # Flush the buffer to
25
- # Merb.logger.flush
25
+ # Extlib.logger.flush
26
26
  #
27
27
  # Remove the current log object
28
- # Merb.logger.close
28
+ # Extlib.logger.close
29
29
  #
30
- # ==== Private Merb Logger API
30
+ # ==== Private Extlib Logger API
31
31
  #
32
32
  # To initialize the logger you create a new object, proxies to set_log.
33
- # Merb::Logger.new(log{String, IO},level{Symbol, String})
33
+ # Extlib::Logger.new(log{String, IO},level{Symbol, String})
34
34
  module Extlib
35
35
 
36
36
  class << self
@@ -110,8 +110,6 @@ module Extlib
110
110
  def set_log(log, log_level = nil, delimiter = " ~ ", auto_flush = false)
111
111
  if log_level && Levels[log_level.to_sym]
112
112
  @level = Levels[log_level.to_sym]
113
- elsif Merb.environment == "production"
114
- @level = Levels[:warn]
115
113
  else
116
114
  @level = Levels[:debug]
117
115
  end
@@ -120,8 +118,6 @@ module Extlib
120
118
  @auto_flush = auto_flush
121
119
 
122
120
  initialize_log(log)
123
-
124
- Merb.logger = self
125
121
  end
126
122
 
127
123
  # Flush the entire buffer to the log object.
@@ -157,7 +153,7 @@ module Extlib
157
153
  end
158
154
  alias :push :<<
159
155
 
160
- # Generate the logging methods for Merb.logger for each log level.
156
+ # Generate the logging methods for Extlib.logger for each log level.
161
157
  Levels.each_pair do |name, number|
162
158
  class_eval <<-LEVELMETHODS, __FILE__, __LINE__
163
159
 
data/lib/extlib/module.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  class Module
2
2
  def find_const(const_name)
3
3
  if const_name[0..1] == '::'
4
- Object.find_const(const_name[2..-1])
4
+ Object.full_const_get(const_name[2..-1])
5
5
  else
6
6
  nested_const_lookup(const_name)
7
7
  end
@@ -15,31 +15,33 @@ class Module
15
15
 
16
16
  # Doesn't do any caching since constants can change with remove_const
17
17
  def nested_const_lookup(const_name)
18
- constants = [ Object ]
18
+ unless equal?(Object)
19
+ constants = []
19
20
 
20
- unless self == Object
21
- self.name.split('::').each do |part|
22
- constants.unshift(constants.first.const_get(part))
21
+ name.split('::').each do |part|
22
+ const = constants.first || Object
23
+ constants << const.const_get(part)
23
24
  end
24
- end
25
25
 
26
- parts = const_name.split('::')
27
-
28
- # from most to least specific constant, use each as a base and try
29
- # to find a constant with the name const_name within them
30
- constants.each do |const|
31
- # return the nested constant if available
32
- return const if parts.all? do |part|
33
- const = if RUBY_VERSION >= '1.9.0'
34
- const.const_defined?(part, false) ? const.const_get(part, false) : nil
35
- else
36
- const.const_defined?(part) ? const.const_get(part) : nil
26
+ parts = const_name.split('::')
27
+
28
+ # from most to least specific constant, use each as a base and try
29
+ # to find a constant with the name const_name within them
30
+ constants.reverse_each do |const|
31
+ # return the nested constant if available
32
+ return const if parts.all? do |part|
33
+ const = if RUBY_VERSION >= '1.9.0'
34
+ const.const_defined?(part, false) ? const.const_get(part, false) : nil
35
+ else
36
+ const.const_defined?(part) ? const.const_get(part) : nil
37
+ end
37
38
  end
38
39
  end
39
40
  end
40
41
 
41
- # if we get this far then the nested constant was not found
42
- raise NameError, "uninitialized constant #{const_name}"
42
+ # no relative constant found, fallback to an absolute lookup and
43
+ # use const_missing if not found
44
+ Object.full_const_get(const_name)
43
45
  end
44
46
 
45
47
  end # class Module
data/lib/extlib/object.rb CHANGED
@@ -97,7 +97,7 @@ class Object
97
97
  current_module = self
98
98
  mod.each do |x|
99
99
  unless current_module.const_defined?(x)
100
- current_module.class_eval "module #{x}; end"
100
+ current_module.class_eval "module #{x}; end", __FILE__, __LINE__
101
101
  end
102
102
  current_module = current_module.const_get(x)
103
103
  end
@@ -136,6 +136,19 @@ class Object
136
136
  self.dup
137
137
  end
138
138
 
139
+ # If receiver is callable, calls it and
140
+ # returns result. If not, just returns receiver
141
+ # itself
142
+ #
143
+ # @return <Object>
144
+ def try_call(*args)
145
+ if self.respond_to?(:call)
146
+ self.call(*args)
147
+ else
148
+ self
149
+ end
150
+ end
151
+
139
152
  # @param arrayish<#include?> Container to check, to see if it includes the object.
140
153
  # @param *more<Array>:: additional args, will be flattened into arrayish
141
154
  #
@@ -12,4 +12,9 @@ class Pathname
12
12
  def /(path)
13
13
  (self + path).expand_path
14
14
  end
15
+
16
+ # alias to_s to to_str when to_str not defined
17
+ unless public_instance_methods(false).any? { |m| m.to_s == 'to_str' }
18
+ alias to_str to_s
19
+ end
15
20
  end # class Pathname
@@ -26,11 +26,11 @@ module Extlib
26
26
  module Pooling
27
27
 
28
28
  def self.scavenger?
29
- @scavenger && @scavenger.alive?
29
+ defined?(@scavenger) && !@scavenger.nil? && @scavenger.alive?
30
30
  end
31
31
 
32
32
  def self.scavenger
33
- if @scavenger.nil? || !@scavenger.alive?
33
+ unless scavenger?
34
34
  @scavenger = Thread.new do
35
35
  running = true
36
36
  while running do
@@ -72,7 +72,7 @@ module Extlib
72
72
  lock.synchronize do
73
73
  pools << pool
74
74
  end
75
- Extlib::Pooling::scavenger
75
+ Extlib::Pooling.scavenger
76
76
  end
77
77
 
78
78
  def self.lock
@@ -118,6 +118,10 @@ module Extlib
118
118
  @__pool.release(self) unless @__pool.nil?
119
119
  end
120
120
 
121
+ def detach
122
+ @__pool.delete(self) unless @__pool.nil?
123
+ end
124
+
121
125
  class Pool
122
126
  attr_reader :available
123
127
  attr_reader :used
@@ -132,7 +136,7 @@ module Extlib
132
136
 
133
137
  @available = []
134
138
  @used = {}
135
- Extlib::Pooling::append_pool(self)
139
+ Extlib::Pooling.append_pool(self)
136
140
  end
137
141
 
138
142
  def lock
@@ -209,7 +213,7 @@ module Extlib
209
213
  def dispose
210
214
  flush!
211
215
  @resource.__pools.delete(@args)
212
- !Extlib::Pooling::pools.delete?(self).nil?
216
+ !Extlib::Pooling.pools.delete?(self).nil?
213
217
  end
214
218
 
215
219
  def expired?
data/lib/extlib/time.rb CHANGED
@@ -23,6 +23,7 @@ class Time
23
23
  # @return [Time] Receiver
24
24
  #
25
25
  # @api public
26
+ remove_method :to_time if method_defined?(:to_time) || private_method_defined?(:to_time)
26
27
  def to_time
27
28
  self
28
29
  end
@@ -35,6 +36,7 @@ class Time
35
36
  # @return [DateTime] DateTime object representing the same moment as receiver
36
37
  #
37
38
  # @api public
39
+ remove_method :to_datetime if method_defined?(:to_datetime) || private_method_defined?(:to_datetime)
38
40
  def to_datetime
39
41
  DateTime.parse self.to_s
40
42
  end
@@ -1,3 +1,3 @@
1
1
  module Extlib
2
- VERSION = '0.9.10'
2
+ VERSION = '0.9.11'
3
3
  end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe Array do
4
+ before :all do
5
+ @array = [ [ :a, [ 1 ] ], [ :b, [ 2 ] ], [ :c, [ 3 ] ] ].freeze
6
+ end
7
+
8
+ it { @array.should respond_to(:to_hash) }
9
+
10
+ describe '#to_hash' do
11
+ before :all do
12
+ @return = @array.to_hash
13
+ end
14
+
15
+ it 'should return a Hash' do
16
+ @return.should be_kind_of(Hash)
17
+ end
18
+
19
+ it 'should return expected value' do
20
+ @return.should == { :a => [ 1 ], :b => [ 2 ], :c => [ 3 ] }
21
+ end
22
+ end
23
+
24
+ it { @array.should respond_to(:to_mash) }
25
+
26
+ describe '#to_mash' do
27
+ before :all do
28
+ @return = @array.to_mash
29
+ end
30
+
31
+ it 'should return a Mash' do
32
+ @return.should be_kind_of(Mash)
33
+ end
34
+
35
+ it 'should return expected value' do
36
+ @return.should == { 'a' => [ 1 ], 'b' => [ 2 ], 'c' => [ 3 ] }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe ByteArray do
4
+ it 'should be a String' do
5
+ ByteArray.new.should be_kind_of(String)
6
+ end
7
+ end
data/spec/hook_spec.rb CHANGED
@@ -2,7 +2,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
2
 
3
3
  describe Extlib::Hook do
4
4
 
5
- before(:each) do
5
+ before do
6
6
  @module = Module.new do
7
7
  def greet; greetings_from_module; end;
8
8
  end
@@ -405,7 +405,9 @@ describe Extlib::Hook do
405
405
  def self.method_with_args(one, two, three); end;
406
406
  def self.before_method_with_args(one, two, three); hi_mom!; end;
407
407
  before_class_method(:method_with_args, :before_method_with_args)
408
+ orig_verbose, $VERBOSE = $VERBOSE, false
408
409
  def self.before_method_with_args; hi_dad!; end;
410
+ $VERBOSE = orig_verbose
409
411
  end
410
412
 
411
413
  @class.should_not_receive(:hi_mom1)
@@ -440,7 +442,9 @@ describe Extlib::Hook do
440
442
  def self.method_with_args(word, lol); end;
441
443
  def self.before_method_with_args; hi_mom!; end;
442
444
  before_class_method(:method_with_args, :before_method_with_args)
445
+ orig_verbose, $VERBOSE = $VERBOSE, false
443
446
  def self.before_method_with_args(word, lol); hi_dad!(word, lol); end;
447
+ $VERBOSE = orig_verbose
444
448
  end
445
449
 
446
450
  @class.should_not_receive(:hi_mom!)
@@ -541,7 +545,9 @@ describe Extlib::Hook do
541
545
  def method_with_args(one, two, three); end;
542
546
  def before_method_with_args(one, two, three); hi_mom!; end;
543
547
  before(:method_with_args, :before_method_with_args)
548
+ orig_verbose, $VERBOSE = $VERBOSE, false
544
549
  def before_method_with_args; hi_dad!; end;
550
+ $VERBOSE = orig_verbose
545
551
  end
546
552
 
547
553
  inst = @class.new
@@ -578,7 +584,9 @@ describe Extlib::Hook do
578
584
  def method_with_args(word, lol); end;
579
585
  def before_method_with_args; hi_mom!; end;
580
586
  before(:method_with_args, :before_method_with_args)
587
+ orig_verbose, $VERBOSE = $VERBOSE, false
581
588
  def before_method_with_args(word, lol); hi_dad!(word, lol); end;
589
+ $VERBOSE = orig_verbose
582
590
  end
583
591
 
584
592
  inst = @class.new
@@ -1913,6 +1913,7 @@ end
1913
1913
  describe 'a method mixed into Array' do
1914
1914
  before :all do
1915
1915
  Enumerable.class_eval do
1916
+ remove_method :lazy_spec if method_defined?(:lazy_spec) || private_method_defined?(:lazy_spec)
1916
1917
  def lazy_spec
1917
1918
  true
1918
1919
  end
@@ -0,0 +1,38 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+ require 'extlib/lazy_module'
3
+
4
+ describe LazyModule do
5
+ describe "instantiated with a block" do
6
+ it "defers block body evaluation" do
7
+ lambda do
8
+ LazyModule.new do
9
+ raise "Will only be evaluated when mixed in"
10
+ end
11
+ end.should_not raise_error
12
+ end
13
+ end
14
+
15
+
16
+ describe "included into hosting class" do
17
+ before :all do
18
+ KlazzyLazyModule = LazyModule.new do
19
+ def self.klassy
20
+ "Klazz"
21
+ end
22
+
23
+ def instancy
24
+ "Instanzz"
25
+ end
26
+ end
27
+
28
+ @klass = Class.new do
29
+ include KlazzyLazyModule
30
+ end
31
+ end
32
+
33
+ it "class evals block body" do
34
+ @klass.klassy.should == "Klazz"
35
+ @klass.new.instancy.should == "Instanzz"
36
+ end
37
+ end
38
+ end
data/spec/pooling_spec.rb CHANGED
@@ -2,8 +2,11 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
2
  require 'timeout'
3
3
 
4
4
  module Extlib::Pooling
5
- def self.scavenger_interval
6
- 1
5
+ class << self
6
+ remove_method :scavenger_interval if method_defined?(:scavenger_interval) || private_method_defined?(:scavenger_interval)
7
+ def scavenger_interval
8
+ 1
9
+ end
7
10
  end
8
11
  end
9
12
 
@@ -11,7 +14,7 @@ describe "Extlib::Pooling" do
11
14
  before do
12
15
 
13
16
  Object.send(:remove_const, :Person) if defined?(Person)
14
- class Person
17
+ class ::Person
15
18
  include Extlib::Pooling
16
19
 
17
20
  attr_accessor :name
@@ -26,7 +29,7 @@ describe "Extlib::Pooling" do
26
29
  end
27
30
 
28
31
  Object.send(:remove_const, :Overwriter) if defined?(Overwriter)
29
- class Overwriter
32
+ class ::Overwriter
30
33
 
31
34
  def self.new(*args)
32
35
  instance = allocate
@@ -52,13 +55,16 @@ describe "Extlib::Pooling" do
52
55
  @overwritten = value
53
56
  end
54
57
 
55
- def self.pool_size
56
- pool_size = if RUBY_PLATFORM =~ /java/
57
- 20
58
- else
59
- 2
58
+ class << self
59
+ remove_method :pool_size if method_defined?(:pool_size) || private_method_defined?(:pool_size)
60
+ def pool_size
61
+ pool_size = if RUBY_PLATFORM =~ /java/
62
+ 20
63
+ else
64
+ 2
65
+ end
66
+ pool_size
60
67
  end
61
- pool_size
62
68
  end
63
69
 
64
70
  def dispose
@@ -146,7 +152,6 @@ describe "Extlib::Pooling" do
146
152
  end
147
153
 
148
154
  it "should wake up the scavenger thread when exiting" do
149
- pending 'Fix for JRuby' if RUBY_PLATFORM =~ /java/
150
155
  bob = Person.new('Bob')
151
156
  bob.release
152
157
  Extlib.exiting = true
@@ -154,6 +159,13 @@ describe "Extlib::Pooling" do
154
159
  Extlib::Pooling.scavenger?.should be_false
155
160
  end
156
161
 
162
+ it "should be able to detach an instance from the pool" do
163
+ bob = Person.new('Bob')
164
+ Person.__pools[['Bob']].size.should == 1
165
+ bob.detach
166
+ Person.__pools[['Bob']].size.should == 0
167
+ end
168
+
157
169
  end
158
170
 
159
171
  # describe Extlib::Pooling::ResourcePool do
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --loadby random
3
+ --backtrace
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,6 @@
1
-
2
1
  $TESTING=true
3
2
  require "rubygems"
4
3
  require "spec"
5
4
  require "yaml"
6
5
 
7
- require File.join(File.dirname(__FILE__), '..', 'lib', 'extlib')
6
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'extlib'))
@@ -0,0 +1,73 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe "#try_call" do
4
+ describe "with an Object" do
5
+ before :all do
6
+ @receiver = Object.new
7
+ end
8
+
9
+ it "returns receiver itself" do
10
+ @receiver.try_call.should == @receiver
11
+ end
12
+ end
13
+
14
+ describe "with a number" do
15
+ before :all do
16
+ @receiver = 42
17
+ end
18
+
19
+ it "returns receiver itself" do
20
+ @receiver.try_call.should == @receiver
21
+ end
22
+ end
23
+
24
+ describe "with a String" do
25
+ before :all do
26
+ @receiver = "Ruby, programmer's best friend"
27
+ end
28
+
29
+ it "returns receiver itself" do
30
+ @receiver.try_call.should == @receiver
31
+ end
32
+ end
33
+
34
+ describe "with a hash" do
35
+ before :all do
36
+ @receiver = { :functional_programming => "FTW" }
37
+ end
38
+
39
+ it "returns receiver itself" do
40
+ @receiver.try_call.should == @receiver
41
+ end
42
+ end
43
+
44
+ describe "with a Proc" do
45
+ before :all do
46
+ @receiver = Proc.new { 5 * 7 }
47
+ end
48
+
49
+ it "returns result of calling of a proc" do
50
+ @receiver.try_call.should == 35
51
+ end
52
+ end
53
+
54
+ describe "with a Proc that takes 2 arguments" do
55
+ before :all do
56
+ @receiver = Proc.new { |one, other| one + other }
57
+ end
58
+
59
+ it "passes arguments to #call, returns result of calling of a proc" do
60
+ @receiver.try_call(10, 20).should == 30
61
+ end
62
+ end
63
+
64
+ describe "with a Proc that takes 3 arguments" do
65
+ before :all do
66
+ @receiver = Proc.new { |a, b, c| (a + b) * c }
67
+ end
68
+
69
+ it "passes arguments to #call, returns result of calling of a proc" do
70
+ @receiver.try_call(10, 20, 3).should == 90
71
+ end
72
+ end
73
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extlib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.10
4
+ version: 0.9.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Smoot
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-19 00:00:00 -08:00
12
+ date: 2009-03-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -29,9 +29,11 @@ files:
29
29
  - Rakefile
30
30
  - History.txt
31
31
  - lib/extlib
32
+ - lib/extlib/array.rb
32
33
  - lib/extlib/assertions.rb
33
34
  - lib/extlib/blank.rb
34
35
  - lib/extlib/boolean.rb
36
+ - lib/extlib/byte_array.rb
35
37
  - lib/extlib/class.rb
36
38
  - lib/extlib/datetime.rb
37
39
  - lib/extlib/dictionary.rb
@@ -39,6 +41,7 @@ files:
39
41
  - lib/extlib/hook.rb
40
42
  - lib/extlib/inflection.rb
41
43
  - lib/extlib/lazy_array.rb
44
+ - lib/extlib/lazy_module.rb
42
45
  - lib/extlib/logger.rb
43
46
  - lib/extlib/mash.rb
44
47
  - lib/extlib/module.rb
@@ -59,7 +62,9 @@ files:
59
62
  - lib/extlib/version.rb
60
63
  - lib/extlib/virtual_file.rb
61
64
  - lib/extlib.rb
65
+ - spec/array_spec.rb
62
66
  - spec/blank_spec.rb
67
+ - spec/byte_array_spec.rb
63
68
  - spec/class_spec.rb
64
69
  - spec/datetime_spec.rb
65
70
  - spec/hash_spec.rb
@@ -69,17 +74,20 @@ files:
69
74
  - spec/inflection/singular_spec.rb
70
75
  - spec/inflection_extras_spec.rb
71
76
  - spec/lazy_array_spec.rb
77
+ - spec/lazy_module_spec.rb
72
78
  - spec/mash_spec.rb
73
79
  - spec/module_spec.rb
74
80
  - spec/object_space_spec.rb
75
81
  - spec/object_spec.rb
76
82
  - spec/pooling_spec.rb
77
83
  - spec/simple_set_spec.rb
84
+ - spec/spec.opts
78
85
  - spec/spec_helper.rb
79
86
  - spec/string_spec.rb
80
87
  - spec/struct_spec.rb
81
88
  - spec/symbol_spec.rb
82
89
  - spec/time_spec.rb
90
+ - spec/try_call_spec.rb
83
91
  - spec/try_dup_spec.rb
84
92
  - spec/virtual_file_spec.rb
85
93
  has_rdoc: false