backports 1.15.0 → 1.16.1

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.
@@ -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