backports 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,13 @@
1
1
  = Packable --- History
2
2
 
3
+ == Version 1.9.1 - September 29th, 2009
4
+
5
+ * Added Enumerable#chunk (Ruby 1.9)
6
+
7
+ * Added Kernel#respond_to_missing? (Ruby 1.9)
8
+
9
+ * Completed Process.exec (Ruby 1.8.7)
10
+
3
11
  == Version 1.9.0 - September 4th, 2009
4
12
 
5
13
  * In Ruby 1.9, most class methods of File accept filenames as String, or convertible via #to_str or #to_path.
@@ -46,14 +46,15 @@ Compatible with Ruby 1.8 & 1.9, jruby and rubinius.
46
46
 
47
47
  == Ruby 1.8.7
48
48
 
49
- Complete Ruby 1.8.7 backporting. Refer to the official list of changes[http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS].
49
+ Complete Ruby 1.8.7 backporting (core language). Refer to the official list of changes[http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS].
50
50
 
51
51
  Only exceptions:
52
52
  * String#gsub
53
53
  * GC.stress=
54
- * Process.exec
55
54
  * Array#choice (use Array#sample instead)
56
- * recursive data handling (Array and Hash)
55
+ * recursive data handling (Array, Hash, ...)
56
+
57
+ Libraries have not been backported. See at the end for list of known library backports
57
58
 
58
59
  == Ruby 1.9
59
60
 
@@ -64,6 +65,7 @@ Additionally, the following Ruby 1.9 have been backported:
64
65
 
65
66
  * Enumerable
66
67
  * +each_with_object+
68
+ * +chunk+
67
69
 
68
70
  * Enumerator
69
71
  * +new+ (with block)
@@ -82,6 +84,7 @@ Additionally, the following Ruby 1.9 have been backported:
82
84
 
83
85
  * Object
84
86
  * +define_singleton_method+
87
+ * +respond_to_missing?+
85
88
 
86
89
  * Proc
87
90
  * +yield+
@@ -122,6 +125,14 @@ Some generic methods from Rails methods have been copied:
122
125
  * +dasherize+, +demodulize+
123
126
  * +constantize+
124
127
 
128
+ == Libraries
129
+
130
+ Libraries have not been backported. I am aware of following the backport gems:
131
+
132
+ * Net::SMTP for Ruby 1.8.6: smtp_tls[http://seattlerb.rubyforge.org/smtp_tls/]
133
+
134
+ * Let me know of others...
135
+
125
136
  = License
126
137
 
127
138
  +backports+ is released under the terms of the MIT License, see the included LICENSE file.
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 9
3
+ :minor: 10
4
4
  :patch: 0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{backports}
8
- s.version = "1.9.0"
8
+ s.version = "1.10.0"
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{2009-09-05}
12
+ s.date = %q{2009-09-29}
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}
@@ -55,6 +55,7 @@ Gem::Specification.new do |s|
55
55
  "lib/backports/1.8.7/symbol.rb",
56
56
  "lib/backports/1.9.rb",
57
57
  "lib/backports/1.9/array.rb",
58
+ "lib/backports/1.9/dir.rb",
58
59
  "lib/backports/1.9/enumerable.rb",
59
60
  "lib/backports/1.9/enumerator.rb",
60
61
  "lib/backports/1.9/file.rb",
@@ -62,6 +63,7 @@ Gem::Specification.new do |s|
62
63
  "lib/backports/1.9/integer.rb",
63
64
  "lib/backports/1.9/io.rb",
64
65
  "lib/backports/1.9/kernel.rb",
66
+ "lib/backports/1.9/method.rb",
65
67
  "lib/backports/1.9/string.rb",
66
68
  "lib/backports/1.9/symbol.rb",
67
69
  "lib/backports/basic_object.rb",
@@ -80,6 +82,7 @@ Gem::Specification.new do |s|
80
82
  "test/enumerator_test.rb",
81
83
  "test/hash_test.rb",
82
84
  "test/kernel_test.rb",
85
+ "test/method_missing_test.rb",
83
86
  "test/method_test.rb",
84
87
  "test/module_test.rb",
85
88
  "test/object_test.rb",
@@ -102,6 +105,7 @@ Gem::Specification.new do |s|
102
105
  "test/enumerator_test.rb",
103
106
  "test/hash_test.rb",
104
107
  "test/kernel_test.rb",
108
+ "test/method_missing_test.rb",
105
109
  "test/method_test.rb",
106
110
  "test/module_test.rb",
107
111
  "test/object_test.rb",
@@ -7,8 +7,8 @@ class Array
7
7
  # Implementation note: slightly tricky.
8
8
  # Example: self = 1..7, num = 3
9
9
  picks = (0...num).to_a # picks start at 0, 1, 2
10
- max = ((size-num)...size).to_a # max (index for a given pick) is [4, 5, 6]
11
- pick_max_pairs = picks.zip(max).reverse # pick_max_pairs = [[2, 6], [1, 5], [0, 4]]
10
+ max_index = ((size-num)...size).to_a # max (index for a given pick) is [4, 5, 6]
11
+ pick_max_pairs = picks.zip(max_index).reverse # pick_max_pairs = [[2, 6], [1, 5], [0, 4]]
12
12
  lookup = pick_max_pairs.find(Proc.new{return self})
13
13
  loop do
14
14
  yield values_at(*picks)
@@ -1,9 +1,11 @@
1
1
  module GC
2
- def self.stress
3
- false
4
- end
2
+ class << self
3
+ def stress
4
+ false
5
+ end unless method_defined? :stress
5
6
 
6
- def self.stress=(flag)
7
- raise NotImplementedError
7
+ def stress=(flag)
8
+ raise NotImplementedError
9
+ end unless method_defined? :stress=
8
10
  end
9
11
  end
@@ -42,7 +42,7 @@ class IO
42
42
  end
43
43
 
44
44
  self
45
- end
45
+ end unless method_defined? :each_char
46
46
 
47
47
  alias_method :getbyte, :getc unless method_defined? :getbyte
48
48
  alias_method :readbyte, :readchar unless method_defined? :readchar
@@ -24,7 +24,7 @@ unless Method.method_defined? :name
24
24
  Backports.alias_method_chain self, :bind, :additional_info
25
25
  end
26
26
 
27
- class Object
27
+ module Kernel
28
28
  def method_with_additional_info(name)
29
29
  method_without_additional_info(name).tap do |bound|
30
30
  bound.name = name.to_sym
@@ -1,5 +1,3 @@
1
1
  module Process
2
- def self.exec(*args)
3
- raise NotImplementedError
4
- end
2
+ module_function :exec unless class << self; method_defined? :exec; end
5
3
  end
@@ -1,5 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + "/tools")
2
2
  Backports.require_relative "1.8.7"
3
- %w(array enumerable enumerator hash file integer io kernel string symbol).each do |lib|
3
+ %w(array dir enumerable enumerator hash file integer io kernel method string symbol).each do |lib|
4
4
  Backports.require_relative "1.9/#{lib}"
5
5
  end
@@ -7,6 +7,6 @@ class Array
7
7
  def try_convert(obj)
8
8
  return nil unless obj.respond_to?(:to_ary)
9
9
  Backports.coerce_to(obj, Array, :to_ary)
10
- end
10
+ end unless method_defined? :try_convert
11
11
  end
12
12
  end
@@ -0,0 +1,3 @@
1
+ class Dir
2
+ alias_method :to_path, :path unless method_defined? :to_path
3
+ end
@@ -5,4 +5,32 @@ module Enumerable
5
5
  each {|obj| block.call(obj, memo)}
6
6
  memo
7
7
  end unless method_defined? :each_with_object
8
+
9
+ def chunk(initial_state = nil, &original_block)
10
+ Enumerator.new do |yielder|
11
+ previous = Backports::Undefined
12
+ accumulate = []
13
+ block = initial_state.nil? ? original_block : Proc.new{|val| original_block.yield(val, initial_state.clone)}
14
+ each do |val|
15
+ case key = block.yield(val)
16
+ when nil, :_separator
17
+ next
18
+ when :_singleton
19
+ yielder.yield previous, accumulate unless accumulate.empty?
20
+ yielder.yield key, [val]
21
+ accumulate = []
22
+ previous = Backports::Undefined
23
+ when previous, Backports::Undefined
24
+ accumulate << val
25
+ previous = key
26
+ else
27
+ yielder.yield previous, accumulate unless accumulate.empty?
28
+ accumulate = [val]
29
+ previous = key
30
+ end
31
+ end
32
+ # what to do in case of a break?
33
+ yielder.yield previous, accumulate unless accumulate.empty?
34
+ end
35
+ end
8
36
  end
@@ -5,7 +5,7 @@ class Hash
5
5
  def try_convert(x)
6
6
  return nil unless x.respond_to? :to_hash
7
7
  x.to_hash
8
- end unless method_defined? :to_hash
8
+ end unless method_defined? :try_convert
9
9
  end
10
10
 
11
11
  # Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Hash.html]
@@ -0,0 +1,101 @@
1
+ # Standard in Ruby 1.9.2. How do you call the backport of a future feature?
2
+ unless Kernel.method_defined? :respond_to_missing?
3
+ module MissingMethod
4
+ attr_reader :name
5
+
6
+ def call(*arg, &block)
7
+ receiver.send :method_missing, @name, *arg, &block
8
+ end
9
+ alias_method :[], :call
10
+
11
+ def eql?(method)
12
+ method.is_a?(MissingMethod) &&
13
+ receiver == method.receiver &&
14
+ name == method.name
15
+ end
16
+ alias_method :==, :eql?
17
+
18
+ def arity
19
+ -1
20
+ end
21
+
22
+ def owner
23
+ @receiver.class
24
+ end
25
+
26
+ def source_location
27
+ nil
28
+ end
29
+
30
+ def to_proc
31
+ get_block {|*arg| @receiver.send :method_missing, *arg}
32
+ end
33
+
34
+ def unbind
35
+ MissingUnboundMethod.new(owner, name)
36
+ end
37
+
38
+ def self.new(receiver, name)
39
+ m = receiver.method :respond_to_missing?
40
+ m.extend self
41
+ m.instance_variable_set :@name, name
42
+ m
43
+ end
44
+ #private
45
+ def get_block(&block)
46
+ block
47
+ end
48
+ private :get_block
49
+ end
50
+
51
+ module MissingUnboundMethod
52
+ attr_reader :name
53
+ attr_reader :owner
54
+
55
+ def self.new(owner, name)
56
+ um = owner.instance_method :respond_to_missing?
57
+ um.extend self
58
+ um.instance_variable_set :@name, name
59
+ um.instance_variable_set :@owner, owner
60
+ um
61
+ end
62
+
63
+ def arity
64
+ -1
65
+ end
66
+
67
+ def source_location
68
+ nil
69
+ end
70
+
71
+ def bind(to)
72
+ raise TypeError, "bind argument must be an instance of #{@owner}" unless to.is_a? @owner
73
+ MissingMethod.new(to, @name)
74
+ end
75
+ end
76
+
77
+ module Kernel
78
+ def respond_to_missing? method
79
+ false
80
+ end
81
+
82
+ def respond_to_with_call_to_respond_to_missing? method
83
+ respond_to_without_call_to_respond_to_missing?(method) || respond_to_missing?(method)
84
+ end
85
+ Backports.alias_method_chain self, :respond_to?, :call_to_respond_to_missing
86
+
87
+ def method_with_new_repond_to_missing(method)
88
+ method_without_new_repond_to_missing(method)
89
+ rescue NameError
90
+ respond_to_missing?(method) ? MissingMethod.new(self, method): raise
91
+ end
92
+ Backports.alias_method_chain self, :method, :new_repond_to_missing
93
+
94
+ def public_method_with_new_repond_to_missing(method)
95
+ public_method_without_new_repond_to_missing(method)
96
+ rescue NameError
97
+ respond_to_missing?(method) ? MissingMethod.new(self, method): raise
98
+ end
99
+ Backports.alias_method_chain self, :public_method, :new_repond_to_missing if method_defined? :public_method
100
+ end
101
+ end
@@ -7,7 +7,7 @@ class EnumerableTest < Test::Unit::TestCase
7
7
  should "conform to doc" do
8
8
  assert_equal 4, (1..4).count
9
9
  assert_equal 1, (1..4).count(3)
10
- assert_equal 2, (1..4).count{|obj| obj > 2 }
10
+ assert_equal 2, (1..4).count{|obj| obj > 2 }
11
11
  end
12
12
  end
13
13
 
@@ -16,21 +16,21 @@ class EnumerableTest < Test::Unit::TestCase
16
16
  assert_equal ["a", "b", "c", "a", "b", "c"], ('a'..'c').cycle(2).to_a
17
17
  end
18
18
  end
19
-
19
+
20
20
  context "#drop" do
21
21
  should "conform to doc" do
22
22
  assert_equal [5, 8, 13], [ 1, 1, 2, 3, 5, 8, 13 ].drop(4)
23
23
  assert_equal [], [ 1, 1, 2, 3, 5, 8, 13 ].drop(99)
24
24
  end
25
-
25
+
26
26
  should "work with enums" do
27
27
  assert_equal [14,15], (10...16).drop(4)
28
28
  end
29
29
  end
30
-
30
+
31
31
  context "#drop_while" do
32
32
  should "conform to doc" do
33
- assert_equal [8, 13], [ 1, 1, 2, 3, 5, 8, 13 ].drop_while {|item| item < 6 }
33
+ assert_equal [8, 13], [ 1, 1, 2, 3, 5, 8, 13 ].drop_while {|item| item < 6 }
34
34
  end
35
35
 
36
36
  should "work with enums" do
@@ -42,13 +42,13 @@ class EnumerableTest < Test::Unit::TestCase
42
42
  assert_equal [], (10...16).drop_while {|item| true}
43
43
  end
44
44
  end
45
-
45
+
46
46
  context "#each_cons" do
47
47
  should "conform to doc" do
48
48
  assert_equal [[1,2],[2,3],[3,4]], (1..4).each_cons(2).to_a
49
49
  end
50
50
  end
51
-
51
+
52
52
  context "#each_slice" do
53
53
  should "conform to doc" do
54
54
  res = []
@@ -60,10 +60,10 @@ class EnumerableTest < Test::Unit::TestCase
60
60
 
61
61
  context "#each_with_index" do
62
62
  should "conform to doc" do
63
- hash = Hash.new
64
- %w(cat dog wombat).each_with_index do |item, index|
65
- hash[item] = index
66
- end
63
+ hash = Hash.new
64
+ %w(cat dog wombat).each_with_index do |item, index|
65
+ hash[item] = index
66
+ end
67
67
  assert_equal({"cat"=>0, "wombat"=>2, "dog"=>1}, hash)
68
68
  end
69
69
 
@@ -76,9 +76,9 @@ class EnumerableTest < Test::Unit::TestCase
76
76
 
77
77
  context "#each_with_object" do
78
78
  should "conform to doc" do
79
- hash = %w(cat dog wombat).each_with_object({}) do |item, memo|
80
- memo[item] = item.upcase.reverse
81
- end
79
+ hash = %w(cat dog wombat).each_with_object({}) do |item, memo|
80
+ memo[item] = item.upcase.reverse
81
+ end
82
82
  assert_equal({"cat"=>"TAC", "dog"=>"GOD", "wombat"=>"TABMOW"}, hash)
83
83
  end
84
84
  end
@@ -123,28 +123,28 @@ class EnumerableTest < Test::Unit::TestCase
123
123
 
124
124
  context "#max_by" do
125
125
  should "conform to doc" do
126
- a = %w(albatross dog horse fox)
126
+ a = %w(albatross dog horse fox)
127
127
  assert_equal "albatross" , a.max_by {|item| item.length }
128
128
  assert_equal "fox", a.max_by {|item| item.reverse }
129
129
  end
130
- end
130
+ end
131
131
 
132
132
  context "#min_by" do
133
133
  should "conform to doc" do
134
- a = %w(albatross dog horse fox)
134
+ a = %w(albatross dog horse fox)
135
135
  assert_equal "dog" , a.min_by {|item| item.length }
136
136
  assert_equal "horse", a.min_by {|item| item.reverse }
137
137
  end
138
- end
138
+ end
139
139
 
140
140
  context "#minmax" do
141
141
  should "conform to doc" do
142
- a = %w(albatross dog horse)
142
+ a = %w(albatross dog horse)
143
143
  assert_equal ["albatross", "horse"], a.minmax
144
144
  assert_equal ["dog", "albatross"], a.minmax {|a,b| a.length <=> b.length }
145
145
  end
146
146
  end
147
-
147
+
148
148
  context "#one" do
149
149
  should "conform to doc" do
150
150
  assert_equal false, %w{ ant bear cat}.one? {|word| word.length >= 3}
@@ -152,25 +152,25 @@ class EnumerableTest < Test::Unit::TestCase
152
152
  assert_equal true, [ nil, nil, 99 ].one?
153
153
  end
154
154
  end
155
-
155
+
156
156
  context "#reverse_each" do
157
157
  should "work as expected" do
158
158
  assert_equal [4,3,2], (1..4).reverse_each.take(3)
159
159
  end
160
160
  end
161
-
161
+
162
162
  context "#take" do
163
163
  should "conform to doc" do
164
164
  assert_equal [1, 2, 3], (1..7).take(3)
165
165
  assert_equal [["a", 1], ["b", 2]], { 'a'=>1, 'b'=>2, 'c'=>3 }.take(2)
166
166
  end
167
-
167
+
168
168
  should "only consume what's needed" do
169
169
  assert_equal [], Enumerator.new(nil).take(0)
170
170
  assert_raises(NoMethodError) { Enumerator.new(nil).take(1) }
171
171
  end
172
172
  end
173
-
173
+
174
174
  context "#take_while" do
175
175
  should "conform to doc" do
176
176
  assert_equal [1,2], (1..7).take_while {|item| item < 3 }
@@ -189,5 +189,33 @@ class EnumerableTest < Test::Unit::TestCase
189
189
  end
190
190
  end
191
191
 
192
+ context "#chunk" do
193
+ context "given no argument" do
194
+ should "should chunk correctly even for non-consecutive but similar keys" do
195
+ e = (1..7).chunk{|i| (i/3) % 2}
196
+ assert_equal true, e.is_a?(Enumerator)
197
+ assert_equal [
198
+ [0, [1,2]],
199
+ [1, [3,4,5]],
200
+ [0, [6,7]]], e.to_a
201
+ end
202
+ end
203
+ context "given an initial_state argument" do
204
+ should "give a new copy" do
205
+ a = []
206
+ e = (1..3).chunk(a) do |i, x|
207
+ assert_equal true, x.empty?
208
+ x << :yo
209
+ :_singleton
210
+ end
211
+ assert_equal [
212
+ [:_singleton, [1]],
213
+ [:_singleton, [2]],
214
+ [:_singleton, [3]]], e.to_a
215
+ end
216
+ end
217
+
218
+ end
219
+
192
220
  end
193
221
  end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+
4
+ class MethodMissingTest < Test::Unit::TestCase
5
+
6
+ class A
7
+ def respond_to_missing? method
8
+ :ok_if_missing == method
9
+ end
10
+
11
+ def method_missing method, *args
12
+ :bar
13
+ end
14
+ end
15
+
16
+ context "#respond_to?" do
17
+ should "takes #respond_to_missing? into account" do
18
+ assert_equal true, A.new.respond_to?(:ok_if_missing)
19
+ assert_equal false, A.new.respond_to?(:not_ok_if_missing)
20
+ end
21
+ end
22
+
23
+ context "#method" do
24
+ should "returns a nice Method with respond_to_missing?" do
25
+ assert_equal :bar, A.new.method(:ok_if_missing).call
26
+ assert_raise(NameError){ A.new.method(:not_ok_if_missing) }
27
+ end
28
+ end
29
+
30
+ context "Method#unbind" do
31
+ should "works for missing Methods" do
32
+ assert_equal :ok_if_missing, A.new.method(:ok_if_missing).unbind.name
33
+ end
34
+ end
35
+
36
+
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backports
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Marc-Andr\xC3\xA9 Lafortune"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-05 00:00:00 -04:00
12
+ date: 2009-09-29 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -60,6 +60,7 @@ files:
60
60
  - lib/backports/1.8.7/symbol.rb
61
61
  - lib/backports/1.9.rb
62
62
  - lib/backports/1.9/array.rb
63
+ - lib/backports/1.9/dir.rb
63
64
  - lib/backports/1.9/enumerable.rb
64
65
  - lib/backports/1.9/enumerator.rb
65
66
  - lib/backports/1.9/file.rb
@@ -67,6 +68,7 @@ files:
67
68
  - lib/backports/1.9/integer.rb
68
69
  - lib/backports/1.9/io.rb
69
70
  - lib/backports/1.9/kernel.rb
71
+ - lib/backports/1.9/method.rb
70
72
  - lib/backports/1.9/string.rb
71
73
  - lib/backports/1.9/symbol.rb
72
74
  - lib/backports/basic_object.rb
@@ -85,6 +87,7 @@ files:
85
87
  - test/enumerator_test.rb
86
88
  - test/hash_test.rb
87
89
  - test/kernel_test.rb
90
+ - test/method_missing_test.rb
88
91
  - test/method_test.rb
89
92
  - test/module_test.rb
90
93
  - test/object_test.rb
@@ -134,6 +137,7 @@ test_files:
134
137
  - test/enumerator_test.rb
135
138
  - test/hash_test.rb
136
139
  - test/kernel_test.rb
140
+ - test/method_missing_test.rb
137
141
  - test/method_test.rb
138
142
  - test/module_test.rb
139
143
  - test/object_test.rb