extlib 0.9.8 → 0.9.9

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.

Potentially problematic release.


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

Files changed (54) hide show
  1. data/History.txt +22 -0
  2. data/LICENSE +1 -1
  3. data/README +0 -0
  4. data/Rakefile +17 -12
  5. data/lib/extlib.rb +1 -1
  6. data/lib/extlib/blank.rb +51 -21
  7. data/lib/extlib/boolean.rb +1 -1
  8. data/lib/extlib/class.rb +12 -12
  9. data/lib/extlib/datetime.rb +20 -2
  10. data/lib/extlib/dictionary.rb +2 -2
  11. data/lib/extlib/hash.rb +57 -34
  12. data/lib/extlib/inflection.rb +0 -1
  13. data/lib/extlib/lazy_array.rb +327 -36
  14. data/lib/extlib/logger.rb +8 -8
  15. data/lib/extlib/mash.rb +45 -45
  16. data/lib/extlib/module.rb +1 -1
  17. data/lib/extlib/nil.rb +1 -1
  18. data/lib/extlib/numeric.rb +1 -1
  19. data/lib/extlib/object.rb +8 -21
  20. data/lib/extlib/object_space.rb +3 -3
  21. data/lib/extlib/pathname.rb +10 -0
  22. data/lib/extlib/pooling.rb +9 -17
  23. data/lib/extlib/rubygems.rb +7 -7
  24. data/lib/extlib/simple_set.rb +35 -8
  25. data/lib/extlib/string.rb +85 -42
  26. data/lib/extlib/struct.rb +10 -1
  27. data/lib/extlib/symbol.rb +11 -7
  28. data/lib/extlib/time.rb +31 -9
  29. data/lib/extlib/version.rb +1 -1
  30. data/lib/extlib/virtual_file.rb +1 -1
  31. data/spec/blank_spec.rb +85 -0
  32. data/spec/class_spec.rb +141 -0
  33. data/spec/datetime_spec.rb +22 -0
  34. data/spec/hash_spec.rb +537 -0
  35. data/spec/hook_spec.rb +1198 -0
  36. data/spec/inflection/plural_spec.rb +564 -0
  37. data/spec/inflection/singular_spec.rb +497 -0
  38. data/spec/inflection_extras_spec.rb +93 -0
  39. data/spec/lazy_array_spec.rb +1869 -0
  40. data/spec/mash_spec.rb +286 -0
  41. data/spec/module_spec.rb +58 -0
  42. data/spec/object_space_spec.rb +9 -0
  43. data/spec/object_spec.rb +114 -0
  44. data/spec/pooling_spec.rb +499 -0
  45. data/spec/simple_set_spec.rb +57 -0
  46. data/spec/spec_helper.rb +7 -0
  47. data/spec/string_spec.rb +220 -0
  48. data/spec/struct_spec.rb +12 -0
  49. data/spec/symbol_spec.rb +8 -0
  50. data/spec/time_spec.rb +22 -0
  51. data/spec/try_dup_spec.rb +45 -0
  52. data/spec/virtual_file_spec.rb +21 -0
  53. metadata +51 -26
  54. data/README.txt +0 -3
@@ -9,12 +9,12 @@ class Mash < Hash
9
9
  # If constructor is a Hash, a new mash will be created based on the keys of
10
10
  # the hash and no default value will be set.
11
11
  def initialize(constructor = {})
12
- if constructor.is_a?(Hash)
13
- super()
14
- update(constructor)
15
- else
16
- super(constructor)
17
- end
12
+ if constructor.is_a?(Hash)
13
+ super()
14
+ update(constructor)
15
+ else
16
+ super(constructor)
17
+ end
18
18
  end
19
19
 
20
20
  # @param key<Object> The default value for the mash. Defaults to nil.
@@ -22,15 +22,15 @@ class Mash < Hash
22
22
  # @details [Alternatives]
23
23
  # If key is a Symbol and it is a key in the mash, then the default value will
24
24
  # be set to the value matching the key.
25
- def default(key = nil)
26
- if key.is_a?(Symbol) && include?(key = key.to_s)
27
- self[key]
28
- else
29
- super
30
- end
31
- end
32
-
33
- alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
25
+ def default(key = nil)
26
+ if key.is_a?(Symbol) && include?(key = key.to_s)
27
+ self[key]
28
+ else
29
+ super
30
+ end
31
+ end
32
+
33
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
34
34
  alias_method :regular_update, :update unless method_defined?(:regular_update)
35
35
 
36
36
  # @param key<Object> The key to set.
@@ -39,8 +39,8 @@ class Mash < Hash
39
39
  #
40
40
  # @see Mash#convert_key
41
41
  # @see Mash#convert_value
42
- def []=(key, value)
43
- regular_writer(convert_key(key), convert_value(value))
42
+ def []=(key, value)
43
+ regular_writer(convert_key(key), convert_value(value))
44
44
  end
45
45
 
46
46
  # @param other_hash<Hash>
@@ -48,19 +48,19 @@ class Mash < Hash
48
48
  # converted to Mash format.
49
49
  #
50
50
  # @return <Mash> The updated mash.
51
- def update(other_hash)
52
- other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
53
- self
54
- end
55
-
51
+ def update(other_hash)
52
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
53
+ self
54
+ end
55
+
56
56
  alias_method :merge!, :update
57
57
 
58
58
  # @param key<Object> The key to check for. This will be run through convert_key.
59
59
  #
60
60
  # @return <TrueClass, FalseClass> True if the key exists in the mash.
61
- def key?(key)
62
- super(convert_key(key))
63
- end
61
+ def key?(key)
62
+ super(convert_key(key))
63
+ end
64
64
 
65
65
  # def include? def has_key? def member?
66
66
  alias_method :include?, :key?
@@ -71,29 +71,29 @@ class Mash < Hash
71
71
  # @param *extras<Array> Default value.
72
72
  #
73
73
  # @return <Object> The value at key or the default value.
74
- def fetch(key, *extras)
75
- super(convert_key(key), *extras)
74
+ def fetch(key, *extras)
75
+ super(convert_key(key), *extras)
76
76
  end
77
77
 
78
78
  # @param *indices<Array>
79
79
  # The keys to retrieve values for. These will be run through +convert_key+.
80
80
  #
81
81
  # @return <Array> The values at each of the provided keys
82
- def values_at(*indices)
83
- indices.collect {|key| self[convert_key(key)]}
82
+ def values_at(*indices)
83
+ indices.collect {|key| self[convert_key(key)]}
84
84
  end
85
85
 
86
86
  # @param hash<Hash> The hash to merge with the mash.
87
87
  #
88
88
  # @return <Mash> A new mash with the hash values merged in.
89
- def merge(hash)
90
- self.dup.update(hash)
89
+ def merge(hash)
90
+ self.dup.update(hash)
91
91
  end
92
92
 
93
93
  # @param key<Object>
94
94
  # The key to delete from the mash.\
95
- def delete(key)
96
- super(convert_key(key))
95
+ def delete(key)
96
+ super(convert_key(key))
97
97
  end
98
98
 
99
99
  # @param *rejected<Array[(String, Symbol)] The mash keys to exclude.
@@ -111,12 +111,12 @@ class Mash < Hash
111
111
  #
112
112
  # @return <Mash> This mash unchanged.
113
113
  def stringify_keys!; self end
114
-
114
+
115
115
  # @return <Hash> The mash as a Hash with string keys.
116
- def to_hash
117
- Hash.new(default).merge(self)
118
- end
119
-
116
+ def to_hash
117
+ Hash.new(default).merge(self)
118
+ end
119
+
120
120
  protected
121
121
  # @param key<Object> The key to convert.
122
122
  #
@@ -125,8 +125,8 @@ class Mash < Hash
125
125
  # string.
126
126
  #
127
127
  # @api private
128
- def convert_key(key)
129
- key.kind_of?(Symbol) ? key.to_s : key
128
+ def convert_key(key)
129
+ key.kind_of?(Symbol) ? key.to_s : key
130
130
  end
131
131
 
132
132
  # @param value<Object> The value to convert.
@@ -136,13 +136,13 @@ class Mash < Hash
136
136
  # their Mash equivalents.
137
137
  #
138
138
  # @api private
139
- def convert_value(value)
139
+ def convert_value(value)
140
140
  if value.class == Hash
141
- value.to_mash
141
+ value.to_mash
142
142
  elsif value.is_a?(Array)
143
- value.collect { |e| convert_value(e) }
143
+ value.collect { |e| convert_value(e) }
144
144
  else
145
145
  value
146
- end
146
+ end
147
147
  end
148
- end
148
+ end
@@ -6,7 +6,7 @@ class Module
6
6
  nested_const_lookup(const_name)
7
7
  end
8
8
  end
9
-
9
+
10
10
  def try_dup
11
11
  self
12
12
  end
@@ -2,4 +2,4 @@ class NilClass
2
2
  def try_dup
3
3
  self
4
4
  end
5
- end
5
+ end
@@ -2,4 +2,4 @@ class Numeric
2
2
  def try_dup
3
3
  self
4
4
  end
5
- end
5
+ end
@@ -34,10 +34,10 @@ class Object
34
34
  # @example
35
35
  # MyString.foo
36
36
  # #=> NoMethodError: undefined method `foo' for MyString:Class
37
- # @example
37
+ # @example
38
38
  # MyString.bar
39
39
  # #=> MyString
40
- # @example
40
+ # @example
41
41
  # String.bar
42
42
  # #=> NoMethodError: undefined method `bar' for String:Class
43
43
  # @example
@@ -65,19 +65,19 @@ class Object
65
65
  list = name.split("::")
66
66
  list.shift if list.first.blank?
67
67
  obj = self
68
- list.each do |x|
69
- # This is required because const_get tries to look for constants in the
68
+ list.each do |x|
69
+ # This is required because const_get tries to look for constants in the
70
70
  # ancestor chain, but we only want constants that are HERE
71
71
  obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x)
72
72
  end
73
73
  obj
74
74
  end
75
-
75
+
76
76
  # @param name<String> The name of the constant to get, e.g. "Merb::Router".
77
77
  # @param value<Object> The value to assign to the constant.
78
78
  #
79
79
  # @return <Object> The constant corresponding to the name.
80
- def full_const_set(name, value)
80
+ def full_const_set(name, value)
81
81
  list = name.split("::")
82
82
  toplevel = list.first.blank?
83
83
  list.shift if toplevel
@@ -128,14 +128,14 @@ class Object
128
128
  false
129
129
  end
130
130
  end
131
-
131
+
132
132
  # Override this in a child if it cannot be dup'ed
133
133
  #
134
134
  # @return <Object>
135
135
  def try_dup
136
136
  self.dup
137
137
  end
138
-
138
+
139
139
  # @param arrayish<#include?> Container to check, to see if it includes the object.
140
140
  # @param *more<Array>:: additional args, will be flattened into arrayish
141
141
  #
@@ -148,19 +148,6 @@ class Object
148
148
  arrayish = more.unshift(arrayish) unless more.empty?
149
149
  arrayish.include?(self)
150
150
  end
151
-
152
- # @note
153
- # For instances of objects that don't override the #inspect method, there
154
- # is an encoded hash to uniquely identify the object. This method
155
- # reproduces this to be used in #inspect in order to keep the same look
156
- # as well as provide this information.
157
- # This is inessential, but may be useful.
158
- #
159
- # @return <String>
160
- # Returns the 16-byte encoded hash for the object
161
- def encoded_hash
162
- (self.hash * 2).to_s(16)
163
- end
164
151
 
165
152
  # Add instance_variable_defined? for backward compatibility
166
153
  # @param variable<Symbol, String>
@@ -1,5 +1,5 @@
1
1
  module ObjectSpace
2
-
2
+
3
3
  class << self
4
4
 
5
5
  # @return <Array[Class]> All the classes in the object space.
@@ -9,5 +9,5 @@ module ObjectSpace
9
9
  klasses
10
10
  end
11
11
  end
12
-
13
- end
12
+
13
+ end
@@ -1,4 +1,14 @@
1
1
  class Pathname
2
+ # Append path segments and expand to absolute path
3
+ #
4
+ # file = Pathname(Dir.pwd) / "subdir1" / :subdir2 / "filename.ext"
5
+ #
6
+ # @param [Pathname, String, #to_s] path path segment to concatenate with receiver
7
+ #
8
+ # @return [Pathname]
9
+ # receiver with _path_ appended and expanded to an absolute path
10
+ #
11
+ # @api public
2
12
  def /(path)
3
13
  (self + path).expand_path
4
14
  end
@@ -82,9 +82,6 @@ module Extlib
82
82
  class InvalidResourceError < StandardError
83
83
  end
84
84
 
85
- class ThreadStopError < StandardError
86
- end
87
-
88
85
  def self.included(target)
89
86
  target.class_eval do
90
87
  class << self
@@ -165,17 +162,12 @@ module Extlib
165
162
  instance.instance_variable_set(:@__allocated_in_pool, Time.now)
166
163
  @used[instance.object_id] = instance
167
164
  else
168
- # Let's see whether we have multiple threads
169
- # If we do, there is a chance we might be released
170
- # at some point in the future and thus we wait.
171
- # If there are no other threads, we exhaust the pool
172
- # here and there is no more hope... So we throw an
173
- # exception.
174
- if ThreadGroup::Default.list.size <= 2
175
- raise ThreadStopError.new(size)
176
- else
177
- wait.wait(lock)
178
- end
165
+ # Wait for another thread to release an instance.
166
+ # If we exhaust the pool and don't release the active instance,
167
+ # we'll wait here forever, so it's *very* important to always
168
+ # release your services and *never* exhaust the pool within
169
+ # a single thread.
170
+ wait.wait(lock)
179
171
  end
180
172
  end
181
173
  end until instance
@@ -183,8 +175,8 @@ module Extlib
183
175
  end
184
176
 
185
177
  def release(instance)
186
- instance.instance_variable_set(:@__allocated_in_pool, Time.now)
187
178
  lock.synchronize do
179
+ instance.instance_variable_set(:@__allocated_in_pool, Time.now)
188
180
  @used.delete(instance.object_id)
189
181
  @available.push(instance)
190
182
  wait.signal
@@ -196,6 +188,7 @@ module Extlib
196
188
  lock.synchronize do
197
189
  instance.instance_variable_set(:@__pool, nil)
198
190
  @used.delete(instance.object_id)
191
+ wait.signal
199
192
  end
200
193
  nil
201
194
  end
@@ -221,12 +214,11 @@ module Extlib
221
214
 
222
215
  def expired?
223
216
  @available.each do |instance|
224
- if Extlib.exiting || instance.instance_variable_get(:@__allocated_in_pool) + Extlib::Pooling.scavenger_interval <= Time.now
217
+ if Extlib.exiting || instance.instance_variable_get(:@__allocated_in_pool) + Extlib::Pooling.scavenger_interval <= (Time.now + 0.02)
225
218
  instance.dispose
226
219
  @available.delete(instance)
227
220
  end
228
221
  end
229
-
230
222
  size == 0
231
223
  end
232
224
 
@@ -2,26 +2,26 @@
2
2
  require 'rubygems'
3
3
  module Gem
4
4
  class SourceIndex
5
-
5
+
6
6
  # This is resolved in 1.1
7
7
  if Version.new(RubyGemsVersion) < Version.new("1.1")
8
-
8
+
9
9
  # Overwrite this so that a gem of the same name and version won't push one
10
10
  # from the gems directory out entirely.
11
11
  #
12
12
  # @param gem_spec<Gem::Specification> The specification of the gem to add.
13
13
  def add_spec(gem_spec)
14
14
  unless gem_spec.instance_variable_get("@loaded_from") &&
15
- @gems[gem_spec.full_name].is_a?(Gem::Specification) &&
16
- @gems[gem_spec.full_name].installation_path ==
15
+ @gems[gem_spec.full_name].is_a?(Gem::Specification) &&
16
+ @gems[gem_spec.full_name].installation_path ==
17
17
  File.join(defined?(Merb) && Merb.respond_to?(:root) ? Merb.root : Dir.pwd,"gems")
18
-
18
+
19
19
  @gems[gem_spec.full_name] = gem_spec
20
20
  end
21
21
  end
22
-
22
+
23
23
  end
24
-
24
+
25
25
  end
26
26
 
27
27
  class Specification
@@ -6,28 +6,55 @@ module Extlib
6
6
  # a set of callable actions of controller.
7
7
  class SimpleSet < Hash
8
8
 
9
- # @param arr<Array> Initial set values.
9
+ ##
10
+ # Create a new SimpleSet containing the unique members of _arr_
10
11
  #
11
- # @return <Array> The array the Set was initialized with
12
+ # @param [Array] arr Initial set values.
13
+ #
14
+ # @return [Array] The array the Set was initialized with
15
+ #
16
+ # @api public
12
17
  def initialize(arr = [])
13
- arr.each {|x| self[x] = true}
18
+ Array(arr).each {|x| self[x] = true}
14
19
  end
15
20
 
16
- # @param value<Object> Value to add to set.
21
+ ##
22
+ # Add a value to the set, and return it
23
+ #
24
+ # @param [Object] value Value to add to set.
17
25
  #
18
- # @return <TrueClass>
26
+ # @return [SimpleSet] Receiver
27
+ #
28
+ # @api public
19
29
  def <<(value)
20
30
  self[value] = true
31
+ self
21
32
  end
22
33
 
23
- # @param arr<Array> Values to merge with set.
34
+ ##
35
+ # Merge _arr_ with receiver, producing the union of receiver & _arr_
36
+ #
37
+ # s = Extlib::SimpleSet.new([:a, :b, :c])
38
+ # s.merge([:c, :d, :e, f]) #=> #<SimpleSet: {:e, :c, :f, :a, :d, :b}>
24
39
  #
25
- # @return <SimpleSet> The set after the Array was merged in.
40
+ # @param [Array] arr Values to merge with set.
41
+ #
42
+ # @return [SimpleSet] The set after the Array was merged in.
43
+ #
44
+ # @api public
26
45
  def merge(arr)
27
46
  super(arr.inject({}) {|s,x| s[x] = true; s })
28
47
  end
29
48
 
30
- # @return <String> A human readable version of the set.
49
+ ##
50
+ # Get a human readable version of the set.
51
+ #
52
+ # s = SimpleSet.new([:a, :b, :c])
53
+ # s.inspect #=> "#<SimpleSet: {:c, :a, :b}>"
54
+ #
55
+ # @return [String] A human readable version of the set.
56
+ #
57
+ # @api public
31
58
  def inspect
32
59
  "#<SimpleSet: {#{keys.map {|x| x.inspect}.join(", ")}}>"
33
60
  end