backports 1.15.0 → 1.16.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,14 @@
1
1
  = Packable --- History
2
2
 
3
+ == Version 1.16.1 - April 11th, 2010
4
+
5
+ * Added a features of 1.9.2:
6
+
7
+ * Array#uniq, #uniq! (with block)
8
+ * Dir.home
9
+ * Hash#keep_if, select!
10
+ * Random (new class)
11
+
3
12
  == Version 1.15.0 - March 23rd, 2010
4
13
 
5
14
  * Added a features of 1.9.2:
@@ -104,12 +104,16 @@ but since it is only an imitation, it must be required explicitly:
104
104
 
105
105
  == Ruby 1.9.2
106
106
 
107
- Finally, some Ruby 1.9.2 features have been backported. As this version has not been feature frozen yet, changes are still possible.
107
+ Finally, most of Ruby 1.9.2 features have been backported. As this version has not been feature frozen yet, changes are still possible.
108
108
 
109
109
  * Array
110
110
  * <tt>rotate, rotate!</tt>
111
111
  * <tt>keep_if, select!</tt>
112
112
  * <tt>sort_by!</tt>
113
+ * <tt>uniq, #uniq!</tt> (with block)
114
+
115
+ * Dir
116
+ * +home+
113
117
 
114
118
  * Enumerable
115
119
  * +chunk+
@@ -119,10 +123,15 @@ but since it is only an imitation, it must be required explicitly:
119
123
 
120
124
  * Float::INFINITY, NAN
121
125
 
126
+ * Hash
127
+ * +keep_if+, <tt>select!</tt>
128
+
122
129
  * Object
123
130
  * <tt>respond_to_missing?</tt>
124
131
  * <tt>singleton_class</tt>
125
132
 
133
+ * Random (new class)
134
+
126
135
  To include all Ruby backports but not those of Rails, <tt>require "backports/1.9.2"</tt> (or "backports/1.9")
127
136
 
128
137
  == Rails
data/Rakefile CHANGED
@@ -17,13 +17,11 @@ begin
17
17
  gem.rdoc_options << '--title' << 'Backports library' <<
18
18
  '--main' << 'README.rdoc' <<
19
19
  '--line-numbers' << '--inline-source'
20
-
21
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
22
20
  gem.rubyforge_project = "backports"
23
- Jeweler::GemcutterTasks.new
24
21
  end
22
+ Jeweler::GemcutterTasks.new
25
23
  rescue LoadError
26
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
27
25
  end
28
26
 
29
27
  require 'rake/testtask'
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 1
3
3
  :build:
4
- :minor: 15
5
- :patch: 0
4
+ :minor: 16
5
+ :patch: 1
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{backports}
8
- s.version = "1.15.0"
8
+ s.version = "1.16.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Marc-Andr\303\251 Lafortune"]
12
- s.date = %q{2010-03-23}
12
+ s.date = %q{2010-04-11}
13
13
  s.description = %q{ Essential backports that enable some of the really nice features of ruby 1.8.7, ruby 1.9 and rails from ruby 1.8.6 and earlier.
14
14
  }
15
15
  s.email = %q{github@marc-andre.ca}
@@ -75,11 +75,18 @@ Gem::Specification.new do |s|
75
75
  "lib/backports/1.9.1/symbol.rb",
76
76
  "lib/backports/1.9.2.rb",
77
77
  "lib/backports/1.9.2/array.rb",
78
+ "lib/backports/1.9.2/dir.rb",
78
79
  "lib/backports/1.9.2/enumerable.rb",
79
80
  "lib/backports/1.9.2/float.rb",
81
+ "lib/backports/1.9.2/hash.rb",
80
82
  "lib/backports/1.9.2/kernel.rb",
81
83
  "lib/backports/1.9.2/match_data.rb",
82
84
  "lib/backports/1.9.2/method.rb",
85
+ "lib/backports/1.9.2/random.rb",
86
+ "lib/backports/1.9.2/random/MT19937.rb",
87
+ "lib/backports/1.9.2/random/bits_and_bytes.rb",
88
+ "lib/backports/1.9.2/random/implementation.rb",
89
+ "lib/backports/1.9.2/random/load.rb",
83
90
  "lib/backports/1.9.rb",
84
91
  "lib/backports/basic_object.rb",
85
92
  "lib/backports/rails.rb",
@@ -1,7 +1,7 @@
1
1
  class Array
2
2
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
3
3
  def combination(num)
4
- num = Backports.coerce_to num, Fixnum, :to_int
4
+ num = Backports.coerce_to_int(num)
5
5
  return to_enum(:combination, num) unless block_given?
6
6
  return self unless (0..size).include? num
7
7
  # Implementation note: slightly tricky.
@@ -24,7 +24,7 @@ class Array
24
24
  if n.nil?
25
25
  loop(&block)
26
26
  else
27
- n = Backports.coerce_to n, Fixnum, :to_int
27
+ n = Backports.coerce_to_int(n)
28
28
  n.times{each(&block)}
29
29
  end
30
30
  nil
@@ -46,7 +46,7 @@ class Array
46
46
  # made, returns nil, otherwise self.
47
47
  # Adapted from rubinius'
48
48
  def flatten_with_optional_argument!(level=-1)
49
- level = Backports.coerce_to(level, Integer, :to_int)
49
+ level = Backports.coerce_to_int(level)
50
50
  return flatten_without_optional_argument! unless level >= 0
51
51
 
52
52
  ret, out = nil, []
@@ -95,7 +95,7 @@ class Array
95
95
  return to_enum(:permutation, num) unless block_given?
96
96
  num = num.equal?(Backports::Undefined) ?
97
97
  size :
98
- Backports.coerce_to(num, Fixnum, :to_int)
98
+ Backports.coerce_to_int(num)
99
99
  return self unless (0..size).include? num
100
100
 
101
101
  final_lambda = lambda do |partial, remain|
@@ -119,7 +119,7 @@ class Array
119
119
  unless ([1].pop(1) rescue false)
120
120
  def pop_with_optional_argument(n = Backports::Undefined)
121
121
  return pop_without_optional_argument if n == Backports::Undefined
122
- n = Backports.coerce_to(n, Fixnum, :to_int)
122
+ n = Backports.coerce_to_int(n)
123
123
  raise ArgumentError, "negative array size" if n < 0
124
124
  first = size - n
125
125
  first = 0 if first < 0
@@ -136,7 +136,7 @@ class Array
136
136
  #
137
137
  result = []
138
138
 
139
- arg.map!{|x| Backports.coerce_to(x, Array, :to_ary)}
139
+ arg.map!(&Backports.method(:coerce_to_ary))
140
140
  arg.reverse! # to get the results in the same order as in MRI, vary the last argument first
141
141
  arg.push self
142
142
 
@@ -167,7 +167,7 @@ class Array
167
167
  # Note: was named #choice in 1.8.7 and renamed in later versions
168
168
  def sample(n = Backports::Undefined)
169
169
  return self[Kernel.rand(size)] if n == Backports::Undefined
170
- n = Backports.coerce_to(n, Fixnum, :to_int)
170
+ n = Backports.coerce_to_int(n)
171
171
  raise ArgumentError, "negative array size" if n < 0
172
172
  n = size if n > size
173
173
  result = Array.new(self)
@@ -183,7 +183,7 @@ class Array
183
183
  unless ([1].shift(1) rescue false)
184
184
  def shift_with_optional_argument(n = Backports::Undefined)
185
185
  return shift_without_optional_argument if n == Backports::Undefined
186
- n = Backports.coerce_to(n, Fixnum, :to_int)
186
+ n = Backports.coerce_to_int(n)
187
187
  raise ArgumentError, "negative array size" if n < 0
188
188
  slice!(0, n)
189
189
  end
@@ -17,7 +17,7 @@ module Enumerable
17
17
  def cycle(n = nil, &block)
18
18
  return to_enum(:cycle, n) unless block_given?
19
19
  return loop(&block) if nil == n
20
- n = Backports.coerce_to(n, Fixnum, :to_int)
20
+ n = Backports.coerce_to_int(n)
21
21
  if n >= 1
22
22
  cache = []
23
23
  each do |elem|
@@ -35,7 +35,7 @@ module Enumerable
35
35
 
36
36
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
37
37
  def drop(n)
38
- n = Backports.coerce_to(n, Fixnum, :to_int)
38
+ n = Backports.coerce_to_int(n)
39
39
  raise ArgumentError, "attempt to drop negative size" if n < 0
40
40
  ary = to_a
41
41
  return [] if n > ary.size
@@ -198,7 +198,7 @@ module Enumerable
198
198
 
199
199
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
200
200
  def take(n)
201
- n = Backports.coerce_to(n, Fixnum, :to_int)
201
+ n = Backports.coerce_to_int(n)
202
202
  raise ArgumentError, "attempt to take negative size: #{n}" if n < 0
203
203
  [].tap do |array|
204
204
  each do |elem|
@@ -3,7 +3,7 @@ class Array
3
3
  class << self
4
4
  def self.try_convert(obj)
5
5
  return nil unless obj.respond_to?(:to_ary)
6
- Backports.coerce_to(obj, Array, :to_ary)
6
+ Backports.coerce_to_ary(obj)
7
7
  end unless method_defined? :try_convert
8
8
  end
9
9
  end
@@ -3,7 +3,7 @@ class Regexp
3
3
  class << self
4
4
  def self.try_convert(obj)
5
5
  return nil unless obj.respond_to?(:to_regexp)
6
- Backports.coerce_to(obj, Array, :to_regexp)
6
+ Backports.coerce_to(obj, Regexp, :to_regexp)
7
7
  end unless method_defined? :try_convert
8
8
  end
9
9
  end
@@ -24,5 +24,27 @@ class Array
24
24
  return to_enum(:sort_by!) unless block_given?
25
25
  replace sort_by(&block)
26
26
  end unless method_defined? :sort_by!
27
+
28
+ unless [1,2].uniq!{}
29
+ def uniq_with_block!(&block)
30
+ return uniq_without_block! unless block_given?
31
+ u = uniq(&block)
32
+ replace u unless u.size == size
33
+ end
34
+ Backports.alias_method_chain self, :uniq!, :block
35
+ end
36
+
37
+ unless [1,2].uniq{}.size == 1
38
+ def uniq_with_block
39
+ return uniq_without_block unless block_given?
40
+ h = {}
41
+ each do |elem|
42
+ h[yield(elem)] ||= elem
43
+ end
44
+ h.values
45
+ end
46
+ Backports.alias_method_chain self, :uniq, :block
47
+ end
48
+
27
49
  end
28
50
 
@@ -0,0 +1,5 @@
1
+ class << Dir
2
+ def home(user = "")
3
+ File.expand_path "~#{user}"
4
+ end unless method_defined? :home
5
+ end
@@ -0,0 +1,11 @@
1
+ class Hash
2
+ def keep_if
3
+ return to_enum(:keep_if) unless block_given?
4
+ delete_if{|key, value| ! yield key, value}
5
+ end unless method_defined? :keep_if
6
+
7
+ def select!(&block)
8
+ return to_enum(:select!) unless block_given?
9
+ reject!{|key, value| ! yield key, value}
10
+ end unless method_defined? :select!
11
+ end
@@ -0,0 +1 @@
1
+ autoload :Random, File.expand_path(File.dirname(__FILE__) + "/random/load")
@@ -0,0 +1,78 @@
1
+ class Random
2
+ # An implementation of Mersenne Twister MT19937 in Ruby
3
+ class MT19937
4
+ STATE_SIZE = 624
5
+ LAST_STATE = STATE_SIZE - 1
6
+ PAD_32_BITS = 0xffffffff
7
+
8
+ attr_reader :state, :last_read
9
+
10
+ # See seed=
11
+ def initialize(seed)
12
+ self.seed = seed
13
+ end
14
+
15
+ LAST_31_BITS = 0x7fffffff
16
+ OFFSET = 397
17
+
18
+ # Generates a completely new state out of the previous one.
19
+ def next_state
20
+ STATE_SIZE.times do |i|
21
+ mix = @state[i] & 0x80000000 | @state[i+1 - STATE_SIZE] & 0x7fffffff
22
+ @state[i] = @state[i+OFFSET - STATE_SIZE] ^ (mix >> 1)
23
+ @state[i] ^= 0x9908b0df if mix.odd?
24
+ end
25
+ @last_read = -1
26
+ end
27
+
28
+ # Seed must be either an Integer (only the first 32 bits will be used)
29
+ # or an Array of Integers (of which only the first 32 bits will be used)
30
+ #
31
+ # No conversion or type checking is done at this level
32
+ def seed=(seed)
33
+ case seed
34
+ when Integer
35
+ @state = Array.new(STATE_SIZE)
36
+ @state[0] = seed & PAD_32_BITS
37
+ (1..LAST_STATE).each do |i|
38
+ @state[i] = (1812433253 * (@state[i-1] ^ @state[i-1]>>30) + i)& PAD_32_BITS
39
+ end
40
+ @last_read = LAST_STATE
41
+ when Array
42
+ self.seed = 19650218
43
+ i=1
44
+ j=0
45
+ [STATE_SIZE, seed.size].max.times do
46
+ @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1664525) + j + seed[j] & PAD_32_BITS
47
+ if (i+=1) >= STATE_SIZE
48
+ @state[0] = @state[-1]
49
+ i = 1
50
+ end
51
+ j = 0 if (j+=1) >= seed.size
52
+ end
53
+ (STATE_SIZE-1).times do
54
+ @state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1566083941) - i & PAD_32_BITS
55
+ if (i+=1) >= STATE_SIZE
56
+ @state[0] = @state[-1]
57
+ i = 1
58
+ end
59
+ end
60
+ @state[0] = 0x80000000
61
+ else
62
+ raise ArgumentError, "Seed must be an Integer or an Array"
63
+ end
64
+ end
65
+
66
+ # Returns a random Integer from the range 0 ... (1 << 32)
67
+ def random_32_bits
68
+ next_state if @last_read >= LAST_STATE
69
+ @last_read += 1
70
+ y = @state[@last_read]
71
+ # Tempering
72
+ y ^= (y >> 11)
73
+ y ^= (y << 7) & 0x9d2c5680
74
+ y ^= (y << 15) & 0xefc60000
75
+ y ^= (y >> 18)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,73 @@
1
+ class Random
2
+ # Supplement the MT19937 class with methods to do
3
+ # conversions the same way as MRI.
4
+ # No argument checking is done here either.
5
+
6
+ class MT19937
7
+ FLOAT_FACTOR = 1.0/9007199254740992.0
8
+ # generates a random number on [0,1) with 53-bit resolution
9
+ def random_float
10
+ ((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
11
+ end
12
+
13
+ # Returns an integer within 0...upto
14
+ def random_integer(upto)
15
+ n = upto - 1
16
+ nb_full_32 = 0
17
+ while n > PAD_32_BITS
18
+ n >>= 32
19
+ nb_full_32 += 1
20
+ end
21
+ mask = mask_32_bits(n)
22
+ begin
23
+ rand = random_32_bits & mask
24
+ nb_full_32.times do
25
+ rand <<= 32
26
+ rand |= random_32_bits
27
+ end
28
+ end until rand < upto
29
+ rand
30
+ end
31
+
32
+ def random_bytes(nb)
33
+ nb_32_bits = (nb + 3) / 4
34
+ random = nb_32_bits.times.map { random_32_bits }
35
+ random.pack("L" * nb_32_bits)[0, nb]
36
+ end
37
+
38
+ def to_bignum
39
+ b = 0
40
+ state.each_with_index do |val, i|
41
+ b |= val << (32 * i)
42
+ end
43
+ b
44
+ end
45
+
46
+ # Convert an Integer seed of arbitrary size to either a single 32 bit integer, or an Array of 32 bit integers
47
+ def self.convert_seed(seed)
48
+ seed = seed.abs
49
+ long_values = []
50
+ begin
51
+ long_values << (seed & PAD_32_BITS)
52
+ seed >>= 32
53
+ end until seed == 0
54
+
55
+ long_values.pop if long_values[-1] == 1 && long_values.size > 1 # Done to allow any kind of sequence of integers
56
+
57
+ long_values.size > 1 ? long_values : long_values.first
58
+ end
59
+
60
+ def self.[](seed)
61
+ new(convert_seed(seed))
62
+ end
63
+
64
+ private
65
+ MASK_BY = [1,2,4,8,16]
66
+ def mask_32_bits(n)
67
+ MASK_BY.each do |shift|
68
+ n |= n >> shift
69
+ end
70
+ n
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,87 @@
1
+ class Random
2
+ # Implementation corresponding to the actual Random class of Ruby
3
+ # The actual random generator (mersenne twister) is in MT19937.
4
+ # Ruby specific conversions are handled in bits_and_bytes.
5
+ # The high level stuff (argument checking) is done here.
6
+ #
7
+ module Implementation
8
+ attr_reader :seed
9
+
10
+ def initialize(seed = 0)
11
+ super()
12
+ srand(seed)
13
+ end
14
+
15
+ def srand(new_seed = 0)
16
+ new_seed = Backports.coerce_to_int(new_seed)
17
+ old, @seed = @seed, new_seed.nonzero? || Random.new_seed
18
+ @mt = MT19937[ @seed ]
19
+ old
20
+ end
21
+
22
+ def rand(limit = Backports::Undefined)
23
+ case limit
24
+ when Backports::Undefined
25
+ @mt.random_float
26
+ when Float
27
+ limit * @mt.random_float unless limit <= 0
28
+ when Range
29
+ _rand_range(limit)
30
+ else
31
+ limit = Backports.coerce_to_int(limit)
32
+ @mt.random_integer(limit) unless limit <= 0
33
+ end || raise(ArgumentError, "invalid argument #{limit}")
34
+ end
35
+
36
+ def bytes(nb)
37
+ nb = Backports.coerce_to_int(nb)
38
+ raise ArgumentError, "negative size" if nb < 0
39
+ @mt.random_bytes(nb)
40
+ end
41
+
42
+ def ==(other)
43
+ other.is_a?(Random) &&
44
+ seed == other.seed &&
45
+ left == other.send(:left) &&
46
+ state == other.send(:state)
47
+ end
48
+
49
+ private
50
+ def state
51
+ @mt.to_bignum
52
+ end
53
+
54
+ def left
55
+ MT19937::STATE_SIZE - @mt.last_read
56
+ end
57
+
58
+ def _rand_range(limit)
59
+ if limit.end.is_a?(Float)
60
+ from = Backports.coerce_to(limit.begin, Float, :to_f)
61
+ to = limit.end
62
+ range = to - from
63
+ if range < 0
64
+ nil
65
+ elsif limit.exclude_end?
66
+ from + @mt.random_float * range unless range <= 0
67
+ else
68
+ # cheat a bit... this will reduce the nb of random bits
69
+ loop do
70
+ r = @mt.random_float * range * 1.0001
71
+ break from + r unless r > range
72
+ end
73
+ end
74
+ else
75
+ from, to = [limit.begin, limit.end].map(&Backports.method(:coerce_to_int))
76
+ to += 1 unless limit.exclude_end?
77
+ range = to - from
78
+ from + @mt.random_integer(range) unless range <= 0
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.new_seed
84
+ Kernel::srand # use the built-in seed generator
85
+ Kernel::srand # return the generated seed
86
+ end
87
+ end
@@ -0,0 +1,11 @@
1
+ require_relative "MT19937"
2
+ require_relative "bits_and_bytes"
3
+ require_relative "implementation"
4
+
5
+ class Random
6
+ include Implementation
7
+ class << self
8
+ include Implementation
9
+ end
10
+ srand
11
+ end
@@ -145,6 +145,14 @@ module Backports
145
145
  ret
146
146
  end
147
147
 
148
+ def self.coerce_to_int(obj)
149
+ coerce_to(obj, Integer, :to_int)
150
+ end
151
+
152
+ def self.coerce_to_ary(obj)
153
+ coerce_to(obj, Array, :to_ary)
154
+ end
155
+
148
156
  # Checks for a failed comparison (in which case it throws an ArgumentError)
149
157
  # Additionally, it maps any negative value to -1 and any positive value to +1
150
158
  # (from Rubinius)
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
- - 15
8
- - 0
9
- version: 1.15.0
7
+ - 16
8
+ - 1
9
+ version: 1.16.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Marc-Andr\xC3\xA9 Lafortune"
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-23 00:00:00 -04:00
17
+ date: 2010-04-11 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -85,11 +85,18 @@ files:
85
85
  - lib/backports/1.9.1/symbol.rb
86
86
  - lib/backports/1.9.2.rb
87
87
  - lib/backports/1.9.2/array.rb
88
+ - lib/backports/1.9.2/dir.rb
88
89
  - lib/backports/1.9.2/enumerable.rb
89
90
  - lib/backports/1.9.2/float.rb
91
+ - lib/backports/1.9.2/hash.rb
90
92
  - lib/backports/1.9.2/kernel.rb
91
93
  - lib/backports/1.9.2/match_data.rb
92
94
  - lib/backports/1.9.2/method.rb
95
+ - lib/backports/1.9.2/random.rb
96
+ - lib/backports/1.9.2/random/MT19937.rb
97
+ - lib/backports/1.9.2/random/bits_and_bytes.rb
98
+ - lib/backports/1.9.2/random/implementation.rb
99
+ - lib/backports/1.9.2/random/load.rb
93
100
  - lib/backports/1.9.rb
94
101
  - lib/backports/basic_object.rb
95
102
  - lib/backports/rails.rb