extlib 0.9.8 → 0.9.9
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 +22 -0
- data/LICENSE +1 -1
- data/README +0 -0
- data/Rakefile +17 -12
- data/lib/extlib.rb +1 -1
- data/lib/extlib/blank.rb +51 -21
- data/lib/extlib/boolean.rb +1 -1
- data/lib/extlib/class.rb +12 -12
- data/lib/extlib/datetime.rb +20 -2
- data/lib/extlib/dictionary.rb +2 -2
- data/lib/extlib/hash.rb +57 -34
- data/lib/extlib/inflection.rb +0 -1
- data/lib/extlib/lazy_array.rb +327 -36
- data/lib/extlib/logger.rb +8 -8
- data/lib/extlib/mash.rb +45 -45
- data/lib/extlib/module.rb +1 -1
- data/lib/extlib/nil.rb +1 -1
- data/lib/extlib/numeric.rb +1 -1
- data/lib/extlib/object.rb +8 -21
- data/lib/extlib/object_space.rb +3 -3
- data/lib/extlib/pathname.rb +10 -0
- data/lib/extlib/pooling.rb +9 -17
- data/lib/extlib/rubygems.rb +7 -7
- data/lib/extlib/simple_set.rb +35 -8
- data/lib/extlib/string.rb +85 -42
- data/lib/extlib/struct.rb +10 -1
- data/lib/extlib/symbol.rb +11 -7
- data/lib/extlib/time.rb +31 -9
- data/lib/extlib/version.rb +1 -1
- data/lib/extlib/virtual_file.rb +1 -1
- data/spec/blank_spec.rb +85 -0
- data/spec/class_spec.rb +141 -0
- data/spec/datetime_spec.rb +22 -0
- data/spec/hash_spec.rb +537 -0
- data/spec/hook_spec.rb +1198 -0
- data/spec/inflection/plural_spec.rb +564 -0
- data/spec/inflection/singular_spec.rb +497 -0
- data/spec/inflection_extras_spec.rb +93 -0
- data/spec/lazy_array_spec.rb +1869 -0
- data/spec/mash_spec.rb +286 -0
- data/spec/module_spec.rb +58 -0
- data/spec/object_space_spec.rb +9 -0
- data/spec/object_spec.rb +114 -0
- data/spec/pooling_spec.rb +499 -0
- data/spec/simple_set_spec.rb +57 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/string_spec.rb +220 -0
- data/spec/struct_spec.rb +12 -0
- data/spec/symbol_spec.rb +8 -0
- data/spec/time_spec.rb +22 -0
- data/spec/try_dup_spec.rb +45 -0
- data/spec/virtual_file_spec.rb +21 -0
- metadata +51 -26
- data/README.txt +0 -3
data/lib/extlib/inflection.rb
CHANGED
data/lib/extlib/lazy_array.rb
CHANGED
@@ -1,30 +1,255 @@
|
|
1
1
|
class LazyArray # borrowed partially from StrokeDB
|
2
|
-
instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ send dup
|
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
4
|
include Enumerable
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class_eval <<-EOS, __FILE__, __LINE__
|
13
|
-
def #{method}(*args, &block)
|
6
|
+
# this avoids a strange Ruby 1.8.6 bug where it cannot delegate to super() in #first
|
7
|
+
if RUBY_VERSION <= '1.8.6'
|
8
|
+
def first(*args)
|
9
|
+
if lazy_possible?(@head, *args)
|
10
|
+
@head.first(*args)
|
11
|
+
else
|
14
12
|
lazy_load
|
15
|
-
|
16
|
-
|
13
|
+
@array.first(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
else
|
17
|
+
def first(*args)
|
18
|
+
if lazy_possible?(@head, *args)
|
19
|
+
@head.first(*args)
|
20
|
+
else
|
21
|
+
super
|
17
22
|
end
|
18
|
-
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
|
-
(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
def last(*args)
|
27
|
+
if lazy_possible?(@tail, *args)
|
28
|
+
@tail.last(*args)
|
29
|
+
else
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def at(index)
|
35
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
36
|
+
@head.at(index)
|
37
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
38
|
+
@tail.at(index)
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch(*args, &block)
|
45
|
+
index = args.first
|
46
|
+
|
47
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
48
|
+
@head.fetch(*args, &block)
|
49
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
50
|
+
@tail.fetch(*args, &block)
|
51
|
+
else
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def values_at(*args)
|
57
|
+
accumulator = []
|
58
|
+
|
59
|
+
lazy_possible = args.all? do |arg|
|
60
|
+
index, length = extract_slice_arguments(arg)
|
61
|
+
|
62
|
+
if index >= 0 && lazy_possible?(@head, index + (length || 1))
|
63
|
+
accumulator.concat(head.values_at(*arg))
|
64
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
65
|
+
accumulator.concat(tail.values_at(*arg))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if lazy_possible
|
70
|
+
accumulator
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def index(entry)
|
77
|
+
(lazy_possible?(@head) && @head.index(entry)) || super
|
78
|
+
end
|
79
|
+
|
80
|
+
def include?(entry)
|
81
|
+
(lazy_possible?(@tail) && @tail.include?(entry)) ||
|
82
|
+
(lazy_possible?(@head) && @head.include?(entry)) ||
|
83
|
+
super
|
84
|
+
end
|
85
|
+
|
86
|
+
def empty?
|
87
|
+
!any?
|
88
|
+
end
|
89
|
+
|
90
|
+
def any?
|
91
|
+
(lazy_possible?(@tail) && @tail.any?) ||
|
92
|
+
(lazy_possible?(@head) && @head.any?) ||
|
93
|
+
super
|
94
|
+
end
|
95
|
+
|
96
|
+
def [](*args)
|
97
|
+
index, length = extract_slice_arguments(*args)
|
98
|
+
|
99
|
+
if length.nil?
|
100
|
+
return at(index)
|
101
|
+
end
|
102
|
+
|
103
|
+
length ||= 1
|
104
|
+
|
105
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
106
|
+
@head.slice(*args)
|
107
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
108
|
+
@tail.slice(*args)
|
109
|
+
else
|
110
|
+
super
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
alias slice []
|
115
|
+
|
116
|
+
def slice!(*args)
|
117
|
+
index, length = extract_slice_arguments(*args)
|
118
|
+
|
119
|
+
length ||= 1
|
120
|
+
|
121
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
122
|
+
@head.slice!(*args)
|
123
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
124
|
+
@tail.slice!(*args)
|
125
|
+
else
|
126
|
+
super
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def []=(*args)
|
131
|
+
index, length = extract_slice_arguments(*args[0..-2])
|
132
|
+
|
133
|
+
length ||= 1
|
134
|
+
|
135
|
+
if index >= 0 && lazy_possible?(@head, index + length)
|
136
|
+
@head.[]=(*args)
|
137
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
|
138
|
+
@tail.[]=(*args)
|
139
|
+
else
|
140
|
+
super
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
alias splice []=
|
145
|
+
|
146
|
+
def reverse
|
147
|
+
dup.reverse!
|
148
|
+
end
|
149
|
+
|
150
|
+
def reverse!
|
151
|
+
# reverse without kicking if possible
|
152
|
+
if loaded?
|
153
|
+
@array = @array.reverse
|
154
|
+
else
|
155
|
+
@head, @tail = @tail.reverse, @head.reverse
|
156
|
+
|
157
|
+
proc = @load_with_proc
|
158
|
+
|
159
|
+
@load_with_proc = lambda do |v|
|
160
|
+
proc.call(v)
|
161
|
+
v.instance_variable_get(:@array).reverse!
|
26
162
|
end
|
27
|
-
|
163
|
+
end
|
164
|
+
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
def <<(entry)
|
169
|
+
if loaded?
|
170
|
+
super
|
171
|
+
else
|
172
|
+
@tail << entry
|
173
|
+
end
|
174
|
+
self
|
175
|
+
end
|
176
|
+
|
177
|
+
alias add <<
|
178
|
+
|
179
|
+
def concat(other)
|
180
|
+
if loaded?
|
181
|
+
super
|
182
|
+
else
|
183
|
+
@tail.concat(other.entries)
|
184
|
+
end
|
185
|
+
self
|
186
|
+
end
|
187
|
+
|
188
|
+
def push(*entries)
|
189
|
+
if loaded?
|
190
|
+
super
|
191
|
+
else
|
192
|
+
@tail.push(*entries)
|
193
|
+
end
|
194
|
+
self
|
195
|
+
end
|
196
|
+
|
197
|
+
def unshift(*entries)
|
198
|
+
if loaded?
|
199
|
+
super
|
200
|
+
else
|
201
|
+
@head.unshift(*entries)
|
202
|
+
end
|
203
|
+
self
|
204
|
+
end
|
205
|
+
|
206
|
+
def insert(index, *entries)
|
207
|
+
if index >= 0 && lazy_possible?(@head, index)
|
208
|
+
@head.insert(index, *entries)
|
209
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
|
210
|
+
@tail.insert(index, *entries)
|
211
|
+
else
|
212
|
+
super
|
213
|
+
end
|
214
|
+
self
|
215
|
+
end
|
216
|
+
|
217
|
+
def pop
|
218
|
+
if lazy_possible?(@tail)
|
219
|
+
@tail.pop
|
220
|
+
else
|
221
|
+
super
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def shift
|
226
|
+
if lazy_possible?(@head)
|
227
|
+
@head.shift
|
228
|
+
else
|
229
|
+
super
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def delete_at(index)
|
234
|
+
if index >= 0 && lazy_possible?(@head, index + 1)
|
235
|
+
@head.delete_at(index)
|
236
|
+
elsif index < 0 && lazy_possible?(@tail, index.abs)
|
237
|
+
@tail.delete_at(index)
|
238
|
+
else
|
239
|
+
super
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def delete_if(&block)
|
244
|
+
if loaded?
|
245
|
+
super
|
246
|
+
else
|
247
|
+
@reapers ||= []
|
248
|
+
@reapers << block
|
249
|
+
@head.delete_if(&block)
|
250
|
+
@tail.delete_if(&block)
|
251
|
+
end
|
252
|
+
self
|
28
253
|
end
|
29
254
|
|
30
255
|
def replace(other)
|
@@ -39,12 +264,12 @@ class LazyArray # borrowed partially from StrokeDB
|
|
39
264
|
self
|
40
265
|
end
|
41
266
|
|
42
|
-
def
|
267
|
+
def to_a
|
43
268
|
lazy_load
|
44
|
-
@array.
|
269
|
+
@array.to_a
|
45
270
|
end
|
46
271
|
|
47
|
-
alias
|
272
|
+
alias to_ary to_a
|
48
273
|
|
49
274
|
def load_with(&block)
|
50
275
|
@load_with_proc = block
|
@@ -55,50 +280,116 @@ class LazyArray # borrowed partially from StrokeDB
|
|
55
280
|
@loaded == true
|
56
281
|
end
|
57
282
|
|
58
|
-
def
|
59
|
-
|
60
|
-
@loaded = false
|
61
|
-
self
|
283
|
+
def kind_of?(klass)
|
284
|
+
super || @array.kind_of?(klass)
|
62
285
|
end
|
63
286
|
|
64
287
|
def respond_to?(method, include_private = false)
|
65
|
-
super || @array.respond_to?(method
|
288
|
+
super || @array.respond_to?(method)
|
289
|
+
end
|
290
|
+
|
291
|
+
def freeze
|
292
|
+
if loaded?
|
293
|
+
@array.freeze
|
294
|
+
else
|
295
|
+
@head.freeze
|
296
|
+
@tail.freeze
|
297
|
+
end
|
298
|
+
@frozen = true
|
299
|
+
self
|
66
300
|
end
|
67
301
|
|
68
|
-
def
|
69
|
-
@
|
302
|
+
def frozen?
|
303
|
+
@frozen == true
|
304
|
+
end
|
305
|
+
|
306
|
+
def eql?(other)
|
307
|
+
lazy_load
|
308
|
+
@array.eql?(other.entries)
|
309
|
+
end
|
310
|
+
|
311
|
+
alias == eql?
|
312
|
+
|
313
|
+
protected
|
314
|
+
|
315
|
+
attr_reader :head, :tail
|
316
|
+
|
317
|
+
def lazy_possible?(list, need_length = 1)
|
318
|
+
!loaded? && need_length <= list.size
|
70
319
|
end
|
71
320
|
|
72
321
|
private
|
73
322
|
|
74
|
-
def initialize
|
75
|
-
@
|
76
|
-
@
|
77
|
-
@
|
323
|
+
def initialize
|
324
|
+
@load_with_proc = lambda { |v| v }
|
325
|
+
@head = []
|
326
|
+
@tail = []
|
327
|
+
@array = []
|
78
328
|
end
|
79
329
|
|
80
330
|
def initialize_copy(original)
|
81
|
-
|
82
|
-
|
83
|
-
|
331
|
+
if original.loaded?
|
332
|
+
mark_loaded
|
333
|
+
@array = @array.dup
|
334
|
+
@head = @tail = nil
|
335
|
+
else
|
336
|
+
@head = @head.dup
|
337
|
+
@tail = @tail.dup
|
338
|
+
@array = @array.dup
|
339
|
+
end
|
84
340
|
end
|
85
341
|
|
86
342
|
def lazy_load
|
87
343
|
return if loaded?
|
88
344
|
mark_loaded
|
89
345
|
@load_with_proc[self]
|
346
|
+
@array.unshift(*@head)
|
347
|
+
@array.concat(@tail)
|
348
|
+
@head = @tail = nil
|
349
|
+
@reapers.each { |r| @array.delete_if(&r) } if @reapers
|
350
|
+
@array.freeze if frozen?
|
90
351
|
end
|
91
352
|
|
92
353
|
def mark_loaded
|
93
354
|
@loaded = true
|
94
355
|
end
|
95
356
|
|
357
|
+
##
|
358
|
+
# Extract arguments for #slice an #slice! and return index and length
|
359
|
+
#
|
360
|
+
# @param [Integer, Array(Integer), Range] *args the index,
|
361
|
+
# index and length, or range indicating first and last position
|
362
|
+
#
|
363
|
+
# @return [Integer] the index
|
364
|
+
# @return [Integer,NilClass] the length, if any
|
365
|
+
#
|
366
|
+
# @api private
|
367
|
+
def extract_slice_arguments(*args)
|
368
|
+
first_arg, second_arg = args
|
369
|
+
|
370
|
+
if args.size == 2 && first_arg.kind_of?(Integer) && second_arg.kind_of?(Integer)
|
371
|
+
return first_arg, second_arg
|
372
|
+
elsif args.size == 1
|
373
|
+
if first_arg.kind_of?(Integer)
|
374
|
+
return first_arg
|
375
|
+
elsif first_arg.kind_of?(Range)
|
376
|
+
index = first_arg.first
|
377
|
+
length = first_arg.last - index
|
378
|
+
length += 1 unless first_arg.exclude_end?
|
379
|
+
return index, length
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
raise ArgumentError, "arguments may be 1 or 2 Integers, or 1 Range object, was: #{args.inspect}", caller(1)
|
384
|
+
end
|
385
|
+
|
96
386
|
# delegate any not-explicitly-handled methods to @array, if possible.
|
97
387
|
# this is handy for handling methods mixed-into Array like group_by
|
98
388
|
def method_missing(method, *args, &block)
|
99
389
|
if @array.respond_to?(method)
|
100
390
|
lazy_load
|
101
|
-
@array.send(method, *args, &block)
|
391
|
+
results = @array.send(method, *args, &block)
|
392
|
+
results.equal?(@array) ? self : results
|
102
393
|
else
|
103
394
|
super
|
104
395
|
end
|
data/lib/extlib/logger.rb
CHANGED
@@ -21,14 +21,14 @@ require "time" # httpdate
|
|
21
21
|
# Merb.logger.info!(message<String>,&block)
|
22
22
|
# Merb.logger.debug!(message<String>,&block)
|
23
23
|
#
|
24
|
-
# Flush the buffer to
|
24
|
+
# Flush the buffer to
|
25
25
|
# Merb.logger.flush
|
26
26
|
#
|
27
27
|
# Remove the current log object
|
28
28
|
# Merb.logger.close
|
29
|
-
#
|
29
|
+
#
|
30
30
|
# ==== Private Merb Logger API
|
31
|
-
#
|
31
|
+
#
|
32
32
|
# To initialize the logger you create a new object, proxies to set_log.
|
33
33
|
# Merb::Logger.new(log{String, IO},level{Symbol, String})
|
34
34
|
module Extlib
|
@@ -53,10 +53,10 @@ module Extlib
|
|
53
53
|
# :warn:: A warning
|
54
54
|
# :info:: generic (useful) information about system operation
|
55
55
|
# :debug:: low-level information for developers
|
56
|
-
Levels =
|
56
|
+
Levels =
|
57
57
|
{
|
58
|
-
:fatal => 7,
|
59
|
-
:error => 6,
|
58
|
+
:fatal => 7,
|
59
|
+
:error => 6,
|
60
60
|
:warn => 4,
|
61
61
|
:info => 3,
|
62
62
|
:debug => 0
|
@@ -96,7 +96,7 @@ module Extlib
|
|
96
96
|
end
|
97
97
|
|
98
98
|
# Replaces an existing logger with a new one.
|
99
|
-
#
|
99
|
+
#
|
100
100
|
# ==== Parameters
|
101
101
|
# log<IO, String>:: Either an IO object or a name of a logfile.
|
102
102
|
# log_level<~to_sym>::
|
@@ -198,5 +198,5 @@ module Extlib
|
|
198
198
|
end
|
199
199
|
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
end
|