Commit 4c57661e authored by Jérémy Bobbio's avatar Jérémy Bobbio

Imported Upstream version 3.6.0

parent 87641732
......@@ -5,6 +5,8 @@ rvm:
- "1.9.2"
- "1.9.3"
- "2.0.0"
- "2.1.0"
- ruby-head
- jruby-18mode
- jruby-19mode
- rbx-18mode
......
= Backports --- History
== Version 3.6.0 - February 14th, 2014
* Additional features of 2.1.0
* Bignum#bit_length
* Fixnum#bit_length
* Module#include (now public)
== Version 3.5.0 - February 3rd, 2014
* Additional features of 2.0.0
* Range#size
== Version 3.4.0 - December 29th, 2013
* Additional features of 2.1.0
* Array#to_h, Enumerable#to_h
== Version 3.3.0 - April 3rd, 2013
* Moved `Proc#yield` & `Hash#key` from 1.8.7 to 1.9.1
......
......@@ -7,7 +7,7 @@ GIT
PATH
remote: .
specs:
backports (3.3.4)
backports (3.6.0)
GEM
remote: http://rubygems.org/
......
......@@ -34,9 +34,9 @@ Let's be a bit more precise about the "breaking code" business. It is of course
A real incompatibility is, for example, <tt>Module::instance_methods</tt> which returns strings in 1.8 and symbols in 1.9. No change can be made without the risk of breaking existing code. Such incompatibilities are left unchanged, although you can require some of these changes in addition (see below)
All features of 1.8.7 are backported (well, almost all, see the exception list bellow), and many of 1.9 are also. Some features of 2.0.0 are backported too.
All features of 1.8.7 are backported (well, almost all, see the exception list bellow), and many of the following versions up to 2.1
Some generic and self-contained features of active-support are also included. By simple I mean that String#camelcase is there, but #pluralize isn't.
For historical reasons, some generic and self-contained features of active-support are also included. By simple I mean that String#camelcase is there, but #pluralize isn't. These will probably be removed in the future, so it's recommended to require those directly from active_support.
== Installation & compatibility
......@@ -65,26 +65,84 @@ With bundler, add to your Gemfile:
Run <tt>bundle install</tt> and require the desired backports.
Compatible with Ruby 1.8.6, 1.8.7, 1.9.1, 1.9.2, 1.9.3, JRuby and Rubinius.
Compatible with Ruby 1.8.6, 1.8.7, 1.9.1, 1.9.2, 1.9.3, 2.0, 2.1, JRuby and Rubinius.
= Complete List of backports
== Ruby 1.8.7
== Ruby 2.1 backports
Complete Ruby 1.8.7 backporting (core language). Refer to the official list of changes[https://github.com/ruby/ruby/blob/ruby_1_8_7/NEWS]. That's about 130 backports!
* Array
* +to_h+
* Bignum
* +bit_length+
* Enumerable
* +to_h+
* Fixnum
* +bit_length+
* Module
* +include+ (now public)
Only exceptions:
* String#gsub (the form returning an enumerator)
* GC.stress= (not implemented)
* Array#choice (removed in 1.9, use 1.9.1's Array#sample instead)
== Ruby 2.0 backports
* Array
* +bsearch+
* Enumerable
* +lazy+
* Enumerator::Lazy
* all methods
* Hash
* <tt>default_proc=</tt> (with nil argument)
* +to_h+
* nil.to_h
* Range
* +bsearch+
* Struct
* +to_h+
== Ruby 1.9.3 backports
* File
* +NULL+
* IO
* +advise+ (acts as a noop)
* +write+, +binwrite+
* String
* +byteslice+
* +prepend+
To include _only_ these backports, <tt>require "backports/1.8.7"</tt>
== Ruby 1.9.2 backports
== Ruby 1.8.8
* Array
* <tt>rotate, rotate!</tt>
* <tt>keep_if, select!</tt>
* +product+ (with block)
* +repeated_combination+, +repeated_permutation+
* <tt>sort_by!</tt>
* <tt>uniq, uniq!</tt> (with block)
* Complex
* +to_r+
* Dir
* +home+
* Enumerable
* +chunk+
* +flat_map+, +collect_concat+
* +join+
* +slice_before+
* Float::INFINITY, NAN
* Hash
* +keep_if+, <tt>select!</tt>
* Object
* <tt>singleton_class</tt>
Ruby 1.8.8 has been officially cancelled. As of version 2.2, <tt>require "backports/1.8.8"</tt> does nothing.
* Random (new class)
== Ruby 1.9.1
== Ruby 1.9.1 backports
Additionally, the following Ruby 1.9 features have been backported:
* Array
......@@ -168,101 +226,14 @@ but since it is only an imitation, it must be required explicitly:
require 'backports/basic_object'
== Ruby 1.9.2
Finally, most of Ruby 1.9.2 features have been backported:
* Array
* <tt>rotate, rotate!</tt>
* <tt>keep_if, select!</tt>
* +product+ (with block)
* +repeated_combination+, +repeated_permutation+
* <tt>sort_by!</tt>
* <tt>uniq, uniq!</tt> (with block)
* Complex
* +to_r+
* Dir
* +home+
* Enumerable
* +chunk+
* +flat_map+, +collect_concat+
* +join+
* +slice_before+
* Float::INFINITY, NAN
* Hash
* +keep_if+, <tt>select!</tt>
* Object
* <tt>singleton_class</tt>
* Random (new class)
To include _only_ these backports and earlier, <tt>require "backports/1.9.2"</tt>
== Ruby 1.9.3
Some features of Ruby 1.9.3 have been backported:
* File
* +NULL+
* IO
* +advise+ (acts as a noop)
* +write+, +binwrite+
* String
* +byteslice+
* +prepend+
To include all Ruby backports but not those of Ruby 2.0 or Rails, <tt>require "backports/1.9.3"</tt> (or "backports/1.9")
== Ruby 2.0.0
Some features of Ruby 2.0.0 have been backported:
* Array
* +bsearch+
* Enumerable
* +lazy+
* Enumerator::Lazy
* all methods
* Hash
* <tt>default_proc=</tt> (with nil argument)
* +to_h+
* nil.to_h
* Range
* +bsearch+
* Struct
* +to_h+
To include all Ruby backports but not those of Rails, <tt>require "backports/2.0"</tt> (or "backports/2.0.0")
== Rails
Some generic methods from Rails methods have been copied:
* Enumerable
* +sum+
* Hash
* +symbolize_keys+, <tt>symbolize_keys!</tt>
* +reverse_merge+, <tt>reverse_merge!</tt>
* Module
* +alias_method_chain+
* Object
* +try+
== Ruby 1.8.7
* String
* +camelize+, +underscore+
* +dasherize+, +demodulize+
* +constantize+
Complete Ruby 1.8.7 backporting (core language). Refer to the official list of changes[https://github.com/ruby/ruby/blob/ruby_1_8_7/NEWS]. That's about 130 backports!
To include _only_ these Rails backports but not those of Ruby, <tt>require "backports/rails"</tt>.
Only exceptions:
* String#gsub (the form returning an enumerator)
* GC.stress= (not implemented)
* Array#choice (removed in 1.9, use 1.9.1's Array#sample instead)
== Libraries
......@@ -304,6 +275,7 @@ These must be imported in addition to the backports gem, for example:
require "backports/force/hash_select"
{}.select{} # => {}, even in Ruby 1.8
== Thanks
Thanks for the bug reports and patches, in particular the repeat offenders:
......
......@@ -100,8 +100,7 @@ def mspec_cmds(pattern, action='ci')
-r ./set_version/#{version}
#{deps}
-r backports/#{version_path}
-C spec
rubyspec/core/#{path}_spec.rb
spec/rubyspec/core/#{path}_spec.rb
].join(' '), path
end
end
require "backports/tools"
require "backports/version"
require "backports/2.0"
require "backports/2.1"
require "backports/rails"
# require this file to load all the backports up to Ruby 1.8.8
# Ruby 1.8.8 has been officially cancelled. As of version 2.2 of backports, <tt>require "backports/1.8.8"</tt>
# does nothing more than require 1.8.7 backports
require 'backports/1.8.7'
......@@ -2,14 +2,27 @@ unless Array.method_defined? :sample
require 'backports/tools'
class Array
def sample(n = Backports::Undefined)
return self[Kernel.rand(size)] if n == Backports::Undefined
def sample(n = Backports::Undefined, options = Backports::Undefined)
if options == Backports::Undefined && n.respond_to?(:to_hash)
n, options = options, n
end
rng = Backports.coerce_to_option(options, :random) unless options == Backports::Undefined
generator = if rng.respond_to? :rand
Proc.new do |nb|
r = Backports::coerce_to_int(rng.rand(nb))
raise RangeError, "random generator returned #{r} which is not in 0...#{nb}" if r < 0 || r >= nb
r
end
else
Kernel.method(:rand)
end
return self[generator.call(size)] if n == Backports::Undefined
n = Backports.coerce_to_int(n)
raise ArgumentError, "negative array size" if n < 0
n = size if n > size
result = Array.new(self)
n.times do |i|
r = i + Kernel.rand(size - i)
r = i + generator.call(size - i)
result[i], result[r] = result[r], result[i]
end
result[n..size] = []
......
......@@ -3,8 +3,8 @@ begin
rescue TypeError
require 'backports/tools'
def open_with_options_hash(file, mode = nil, perm = Backports::Undefined, options = Backports::Undefined)
mode, perm = Backports.combine_mode_perm_and_option(mode, perm, options)
def open_with_options_hash(file, mode = nil, perm_or_options = Backports::Undefined)
mode, perm = Backports.combine_mode_perm_and_option(mode, perm_or_options)
perm ||= 0666 # Avoid error on Rubinius, see issue #52
if block_given?
open_without_options_hash(file, mode, perm){|f| yield f}
......@@ -13,7 +13,9 @@ rescue TypeError
end
end
Backports.alias_method_chain File, :open, :options_hash
class << File
Backports.alias_method_chain self, :open, :options_hash
end
end
if RUBY_VERSION < '1.9'
......
unless Range.method_defined? :size
class Range
def size
return nil unless self.begin.is_a?(Numeric) && self.end.is_a?(Numeric)
size = self.end - self.begin
return 0 if size <= 0
return size if size == Float::INFINITY
if exclude_end?
size.ceil
else
size.floor + 1
end
end
end
end
# require this file to load all the backports up to Ruby 2.1.0
require 'backports/2.0'
Backports.require_relative_dir
require 'backports/tools'
Backports.require_relative_dir
# No need to specialize it, just use Enumerable's implementation:
require 'backports/2.1.0/enumerable/to_h'
require 'backports/tools'
Backports.require_relative_dir
unless Bignum.method_defined? :bit_length
require 'backports/2.0.0/range/bsearch'
class Bignum
def bit_length
n = 8 * (size - 42.size)
smaller = self >> n
if smaller >= 0
smaller += 1
else
smaller = -smaller
end
n + (0...8 * 42.size).bsearch{|i| smaller <= (1 << i) }
end
end
end
require 'backports/tools'
Backports.require_relative_dir
unless Enumerable.method_defined?(:to_h)
require 'backports/tools'
module Enumerable
def to_h(*args)
h = {}
each_entry(*args) do |key_value|
key_value = Backports.coerce_to_ary(key_value)
if key_value.size != 2
raise ArgumentError, "element has wrong array length (expected 2, was #{key_value.size})"
end
h[ key_value[0] ] = key_value[1]
end
h
end
end
end
require 'backports/tools'
Backports.require_relative_dir
unless Fixnum.method_defined? :bit_length
require 'backports/2.0.0/range/bsearch'
class Fixnum
def bit_length
n = if self >= 0
self + 1
else
-self
end
(0...8 * size).bsearch{|i| n <= (1 << i) }
end
end
end
require 'backports/tools'
Backports.require_relative_dir
if Module.private_method_defined? :include
class Module
public :include
end
end
# require this file to load all the backports of Ruby 2.1 and below
require 'backports/2.1.0'
......@@ -226,6 +226,19 @@ module Backports
coerce_to(obj, String, :to_str)
end
def self.coerce_to_hash(obj)
coerce_to(obj, Hash, :to_hash)
end
def self.coerce_to_options(obj, *options)
hash = coerce_to_hash(obj)
hash.values_at(*options)
end
def self.coerce_to_option(obj, option)
coerce_to_options(obj, option)[0]
end
def self.is_array?(obj)
coerce_to(obj, Array, :to_ary) if obj.respond_to? :to_ary
end
......@@ -263,9 +276,9 @@ module Backports
# Used internally to combine {IO|File} options hash into mode (String or Integer)
def self.combine_mode_and_option(mode = nil, options = Backports::Undefined)
# Can't backport autoclose, {internal|external|}encoding
mode, options = nil, mode if mode.respond_to?(:to_hash) and options == Backports::Undefined
mode, options = nil, mode if mode.respond_to?(:to_hash) && options == Backports::Undefined
options = {} if options == nil || options == Backports::Undefined
options = coerce_to(options, Hash, :to_hash)
options = coerce_to_hash(options)
if mode && options[:mode]
raise ArgumentError, "mode specified twice"
end
......@@ -290,10 +303,11 @@ module Backports
# Used internally to combine {IO|File} options hash into mode (String or Integer) and perm
def self.combine_mode_perm_and_option(mode = nil, perm = Backports::Undefined, options = Backports::Undefined)
mode, options = nil, mode if mode.is_a?(Hash) and perm == Backports::Undefined
perm, options = nil, perm if perm.is_a?(Hash) and options == Backports::Undefined
mode, options = nil, mode if mode.respond_to?(:to_hash) && perm == Backports::Undefined
perm, options = nil, perm if perm.respond_to?(:to_hash) && options == Backports::Undefined
perm = nil if perm == Backports::Undefined
options = {} if options == Backports::Undefined
options = coerce_to_hash(options)
if perm && options[:perm]
raise ArgumentError, "perm specified twice"
end
......@@ -301,8 +315,9 @@ module Backports
end
def self.write(binary, filename, string, offset, options)
offset, options = nil, offset if Hash === offset and options == Backports::Undefined
offset, options = nil, offset if offset.respond_to?(:to_hash) && options == Backports::Undefined
options = {} if options == Backports::Undefined
options = coerce_to_hash(options)
File.open(filename, 'a+'){} if offset # insure existence
options = {:mode => offset.nil? ? "w" : "r+"}.merge(options)
args = options[:open_args] || [options]
......
module Backports
VERSION = "3.3.5" unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
VERSION = "3.6.0" unless const_defined? :VERSION # the guard is against a redefinition warning that happens on Travis
end
require File.expand_path(File.dirname(__FILE__) + "/setter")
fails:ARGF.each_line is a public method
fails:ARGF.each_line requires multiple arguments
fails:ARGF.each_line reads each line of files
fails:ARGF.each_line returns self when passed a block
fails:ARGF.each_line returns an Enumerator when passed no block
fails:ARGF.each_line with a separator yields each separated section of all streams
fails:ARGF.each is a public method
fails:ARGF.each requires multiple arguments
fails:ARGF.each reads each line of files
fails:ARGF.each returns self when passed a block
fails:ARGF.each returns an Enumerator when passed no block
fails:ARGF.each with a separator yields each separated section of all streams
fails:ARGF.lines is a public method
fails:ARGF.lines requires multiple arguments
fails:ARGF.lines reads each line of files
fails:ARGF.lines returns self when passed a block
fails:ARGF.lines returns an Enumerator when passed no block
fails:ARGF.lines with a separator yields each separated section of all streams
fails:Array#collect returns an Enumerator when no block given
fails:Array#collect does not copy untrusted status
fails:Array#collect! keeps untrusted status
fails:Array#collect! when frozen raises a RuntimeError
fails:Array#collect! when frozen raises a RuntimeError when empty
fails:Array#collect! when frozen raises a RuntimeError when calling #each on the returned Enumerator
fails:Array#collect! when frozen raises a RuntimeError when calling #each on the returned Enumerator when empty
......@@ -8,3 +8,6 @@ fails:File.open opens a file with a file descriptor d and a block
fails:File.open raises a SystemCallError if passed an invalid Integer type
fails:File.open raises an IOError when read in a block opened with File::RDONLY|File::APPEND mode
fails:File.open raises an IOError if the file exists when open with File::RDONLY|File::APPEND
fails:File.open defaults external_encoding to ASCII-8BIT for binary modes
fails:File.open when passed a file descriptor opens a file
fails:File.open when passed a file descriptor opens a file when passed a block
fails:Hash.[] raises an ArgumentError for arrays of more than 2 elements
fails:Hash.[] raises an ArgumentError when passed a list of value-invalid-pairs in an array
fails:Hash.[] removes the default_proc
fails:Hash#default_proc= raises an error if passed nil
fails:Hash#default_proc= raises a TypeError if passed a lambda with an arity other than 2
fails:Hash#default_proc= raises a RuntimeError if self is frozen
fails:Hash#delete_if raises a RuntimeError if called on a frozen instance
fails:Hash#each_pair yields a [[key, value]] Array for each pair to a block expecting |*args|
fails:Hash#keep_if raises an RuntimeError if called on a frozen instance
fails:Hash#keep_if raises a RuntimeError if called on a frozen instance
fails:Hash#rassoc only returns the first matching key-value pair
fails:Hash#reject! raises a RuntimeError if called on a frozen instance that is modified
fails:Hash#reject! raises a RuntimeError if called on a frozen instance that would not be modified
fails:Hash#select returns a Hash of entries for which block is true
fails:Hash#select! is equivalent to keep_if if changes are made
fails:Hash#select! returns nil if no changes were made
fails:Hash#select! raises a RuntimeError if called on an empty frozen instance
fails:Hash#select! raises a RuntimeError if called on a frozen instance that would not be modified
fails:Hash#select! returns an Enumerator if called on a non-empty hash without a block
fails:Hash#select! returns an Enumerator if called on an empty hash without a block
fails:Hash#select! returns an Enumerator if called on a frozen instance
fails:Integer#round raises a RangeError when passed Float::INFINITY
fails:Integer#round raises a RangeError when passed a big negative value
fails:IO.write uses encoding from given options, if provided
fails:IO.write uses an :open_args option
fails:IO.write disregards other options if :open_args is given
fails:IO.write uses the given encoding and returns the number of bytes written
fails:IO.write writes binary data if no encoding is given
......@@ -3,3 +3,4 @@ fails:Kernel.__callee__ returns the original name when aliased method
fails:Kernel.__callee__ returns the caller from blocks too
fails:Kernel.__callee__ returns nil when not called from a method
fails:Kernel.__callee__ returns the caller when sent as a string
fails:Kernel.__callee__ returns the aliased name when aliased method
fails:Kernel#require_relative with a relative path stores the missing path in a LoadError object
fails:Kernel#require_relative with a relative path when file is a symlink loads a path relative to current file
fails:Kernel#require_relative with an absolute path stores the missing path in a LoadError object
......@@ -2,3 +2,5 @@ fails:Math.log2 raises an Errno::EDOM if the argument is less than 0
fails:Math.log2 raises an TypeError if the argument cannot be coerced with Float()
fails:Math.log2 raises an TypeError if passed a numerical argument as a string
fails:Math.log2 returns NaN given NaN
fails:Math.log2 raises a TypeError if the argument cannot be coerced with Float()
fails:Math.log2 raises a TypeError if passed a numerical argument as a string
fails:Symbol#[] with a Regex slice without a capture index sets $~ to the MatchData if there is a match
fails:Symbol#[] with a Regex slice with a capture index sets $~ to the MatchData if there is a match
fails:Symbol#[] with a Regex slice without a capture index returns an untrusted string if the regexp is untrusted
fails:Symbol#[] with a Regex slice with a capture index returns an untrusted string if the regexp is untrusted
fails:Symbol#to_proc raises an ArgumentError when calling #call on the Proc without receiver
fails:File.open on a FIFO opens it as a normal file
fails:File.open raises a SystemCallError if passed an invalid Integer type
fails:File.open defaults external_encoding to ASCII-8BIT for binary modes
fails:File.open when passed a file descriptor opens a file
fails:File.open when passed a file descriptor opens a file when passed a block
fails:Hash#default_proc= raises an error if passed nil
fails:Hash#default_proc= raises a TypeError if passed a lambda with an arity other than 2
fails:Hash#default_proc= raises a RuntimeError if self is frozen
fails:Hash#keep_if raises an RuntimeError if called on a frozen instance
fails:Hash#keep_if raises a RuntimeError if called on a frozen instance
fails:Integer#round raises a RangeError when passed Float::INFINITY
fails:Integer#round raises a RangeError when passed a big negative value
......@@ -23,3 +23,10 @@ fails:IO.open coerces options as second argument with #to_hash
fails:IO.open raises ArgumentError if not passed a hash or nil for options
fails:IO.open sets external encoding to binary with :binmode option
fails:IO.open raises an error if passed binary/text mode two ways
fails:IO.open uses the :encoding option as the external encoding when only one is given
fails:IO.open uses the :encoding options as the external encoding when it's an Encoding object
fails:IO.open coerces :encoding option with #to_str
fails:IO.open coerces :external_encoding option with #to_str
fails:IO.open coerces :internal_encoding option with #to_str
fails:IO.open accepts an :autoclose option
fails:IO.open accepts any truthy option :autoclose
fails:IO.write uses encoding from given options, if provided
fails:IO.write uses an :open_args option
fails:IO.write disregards other options if :open_args is given
fails:IO.write uses the given encoding and returns the number of bytes written
fails:IO.write writes binary data if no encoding is given
......@@ -3,3 +3,4 @@ fails:Kernel.__callee__ returns the original name when aliased method
fails:Kernel.__callee__ returns the caller from blocks too
fails:Kernel.__callee__ returns nil when not called from a method
fails:Kernel.__callee__ returns the caller when sent as a string
fails:Kernel.__callee__ returns the aliased name when aliased method
fails:Kernel#require_relative with a relative path stores the missing path in a LoadError object
fails:Kernel#require_relative with a relative path when file is a symlink loads a path relative to current file
fails:Kernel#require_relative with an absolute path stores the missing path in a LoadError object
......@@ -2,3 +2,5 @@ fails:Math.log2 raises an Errno::EDOM if the argument is less than 0
fails:Math.log2 raises an TypeError if the argument cannot be coerced with Float()
fails:Math.log2 raises an TypeError if passed a numerical argument as a string
fails:Math.log2 returns NaN given NaN
fails:Math.log2 raises a TypeError if the argument cannot be coerced with Float()
fails:Math.log2 raises a TypeError if passed a numerical argument as a string
fails:Range#size returns nil if first and last are not Numeric
fails:Symbol#[] with a Regex slice without a capture index sets $~ to the MatchData if there is a match
fails:Symbol#[] with a Regex slice with a capture index sets $~ to the MatchData if there is a match
fails:Symbol#[] with a Regex slice without a capture index returns an untrusted string if the regexp is untrusted
fails:Symbol#[] with a Regex slice with a capture index returns an untrusted string if the regexp is untrusted
fails:IO.write uses encoding from given options, if provided
fails:IO.write uses an :open_args option
fails:IO.write uses the given encoding and returns the number of bytes written
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment