backports 1.8.4 → 1.9.0

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.9.0 - September 4th, 2009
4
+
5
+ * In Ruby 1.9, most class methods of File accept filenames as String, or convertible via #to_str or #to_path.
6
+ File#to_path is also an alias to File#path. These have been backported.
7
+
8
+ * File.binread (actually IO.binread)
9
+
10
+ * BasicObject available via "require 'backports/basic_object"
11
+
3
12
  == Version 1.8.4 - September 3rd, 2009
4
13
 
5
14
  Added Dir.mktmpdir for older version of 1.8.6
@@ -68,6 +68,11 @@ Additionally, the following Ruby 1.9 have been backported:
68
68
  * Enumerator
69
69
  * +new+ (with block)
70
70
 
71
+ * File
72
+ * +binread+
73
+ * +to_path+
74
+ * All class methods accepting filenames will accept files or anything with a #to_path method.
75
+
71
76
  * Hash
72
77
  * +try_convert+
73
78
  * <tt>default_proc=</tt>
@@ -90,6 +95,10 @@ Additionally, the following Ruby 1.9 have been backported:
90
95
 
91
96
  +Enumerator+ can be accessed directly (instead of <tt>Enumerable::Enumerator</tt>)
92
97
 
98
+ Moreover, a pretty good imitation of BasicObject is available, but it must be required explicitely:
99
+
100
+ require 'backports/basic_object'
101
+
93
102
  == Rails
94
103
 
95
104
  Some generic methods from Rails methods have been copied:
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 8
4
- :patch: 4
3
+ :minor: 9
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.8.4"
8
+ s.version = "1.9.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-03}
12
+ s.date = %q{2009-09-05}
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}
@@ -57,11 +57,14 @@ Gem::Specification.new do |s|
57
57
  "lib/backports/1.9/array.rb",
58
58
  "lib/backports/1.9/enumerable.rb",
59
59
  "lib/backports/1.9/enumerator.rb",
60
+ "lib/backports/1.9/file.rb",
60
61
  "lib/backports/1.9/hash.rb",
61
62
  "lib/backports/1.9/integer.rb",
63
+ "lib/backports/1.9/io.rb",
62
64
  "lib/backports/1.9/kernel.rb",
63
65
  "lib/backports/1.9/string.rb",
64
66
  "lib/backports/1.9/symbol.rb",
67
+ "lib/backports/basic_object.rb",
65
68
  "lib/backports/rails.rb",
66
69
  "lib/backports/rails/array.rb",
67
70
  "lib/backports/rails/enumerable.rb",
@@ -71,6 +74,7 @@ Gem::Specification.new do |s|
71
74
  "lib/backports/rails/string.rb",
72
75
  "lib/backports/tools.rb",
73
76
  "test/array_test.rb",
77
+ "test/basic_object_test.rb",
74
78
  "test/binding_test.rb",
75
79
  "test/enumerable_test.rb",
76
80
  "test/enumerator_test.rb",
@@ -92,6 +96,7 @@ Gem::Specification.new do |s|
92
96
  s.summary = %q{Backports or ruby 1.8.7+ & rails for older ruby.}
93
97
  s.test_files = [
94
98
  "test/array_test.rb",
99
+ "test/basic_object_test.rb",
95
100
  "test/binding_test.rb",
96
101
  "test/enumerable_test.rb",
97
102
  "test/enumerator_test.rb",
@@ -7,24 +7,26 @@ class String
7
7
  chars.first
8
8
  end unless method_defined? :chr
9
9
 
10
- Backports.make_block_optional self, :each_byte, :each, :each_line, :test_on => "abc"
11
-
10
+ Backports.make_block_optional self, :each_byte, :each_line, :test_on => "abc"
11
+
12
+ Backports.make_block_optional self, :each, :test_on => "abc" if "is there still an each?".respond_to? :each
13
+
12
14
  # gsub: Left alone because of $~, $1, etc... which needs to be "pushed" up one level
13
15
  # It's possible to do so, but gsub is used everywhere so i felt
14
16
  # the performance hit was too big compared to the dubious gain.
15
-
17
+
16
18
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
17
19
  unless method_defined? :each_char
18
20
  def each_char(&block)
19
21
  return to_enum(:each_char) unless block_given?
20
22
  scan(/./, &block)
21
- end
23
+ end
22
24
 
23
25
  alias_method :chars, :each_char unless method_defined? :chars
24
26
  end
25
-
27
+
26
28
  alias_method :lines, :each_line unless method_defined? :lines
27
-
29
+
28
30
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
29
31
  def end_with?(*suffixes)
30
32
  suffixes.each do |suffix|
@@ -34,12 +36,12 @@ class String
34
36
  end
35
37
  false
36
38
  end unless method_defined? :end_with?
37
-
39
+
38
40
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
39
41
  unless ("check partition".partition(" ") rescue false)
40
42
  def partition_with_new_meaning(pattern = Backports::Undefined, &block)
41
43
  return partition_without_new_meaning(&block) if pattern == Backports::Undefined
42
- pattern = Backports.coerce_to(pattern, String, :to_str) unless pattern.is_a? Regexp
44
+ pattern = Backports.coerce_to(pattern, String, :to_str) unless pattern.is_a? Regexp
43
45
  i = index(pattern)
44
46
  return [self, "", ""] unless i
45
47
  if pattern.is_a? Regexp
@@ -58,7 +60,7 @@ class String
58
60
  pattern = Backports.coerce_to(pattern, String, :to_str) unless pattern.is_a? Regexp
59
61
  i = rindex(pattern)
60
62
  return ["", "", self] unless i
61
-
63
+
62
64
  if pattern.is_a? Regexp
63
65
  match = Regexp.last_match
64
66
  [match.pre_match, match[0], match.post_match]
@@ -67,7 +69,7 @@ class String
67
69
  [self[0...i], self[i...last], self[last...length]]
68
70
  end
69
71
  end unless method_defined? :rpartition
70
-
72
+
71
73
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
72
74
  def start_with?(*prefixes)
73
75
  prefixes.each do |prefix|
@@ -77,7 +79,7 @@ class String
77
79
  end
78
80
  false
79
81
  end unless method_defined? :start_with?
80
-
82
+
81
83
  # Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
82
84
  unless ("abc".upto("def", true) rescue false)
83
85
  def upto_with_exclusive(to, excl=false, &block)
@@ -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 integer kernel string symbol).each do |lib|
3
+ %w(array enumerable enumerator hash file integer io kernel string symbol).each do |lib|
4
4
  Backports.require_relative "1.9/#{lib}"
5
5
  end
@@ -0,0 +1,23 @@
1
+ class File
2
+ def size
3
+ stat.size
4
+ end unless method_defined? :size
5
+
6
+ alias_method :to_path, :path unless method_defined? :to_path
7
+
8
+ class << self
9
+ if RUBY_VERSION < '1.9' # can't see any other reasonable way to test than this
10
+ Backports.convert_all_arguments_to_path self, 0, :delete, :unlink, :join
11
+ Backports.convert_all_arguments_to_path self, 1, :chmod, :lchmod
12
+ Backports.convert_all_arguments_to_path self, 2, :chown, :lchown
13
+
14
+ Backports.convert_first_argument_to_path self, :atime, :basename,
15
+ :blockdev?, :chardev?, :ctime, :directory?, :dirname, :executable?, :executable_real?,
16
+ :exist?, :exists?, :expand_path, :extname, :file?, :ftype, :grpowned?,
17
+ :link, :lstat, :mtime, :new, :open, :owned?, :pipe?, :readable?, :readable_real?,
18
+ :readlink, :rename, :setgid?, :setuid?, :size, :size?, :socket?,
19
+ :split, :stat, :sticky?, :symlink, :symlink?, :truncate, :writable?,
20
+ :writable_real?, :zero?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ class IO
2
+ class << self
3
+ def binread(file, *arg)
4
+ raise ArgumentError, "wrong number of arguments (#{1+arg.size} for 1..3)" unless arg.size < 3
5
+ File.open(Backports.convert_to_path(file),"rb") do |f|
6
+ f.read(*arg)
7
+ end
8
+ end unless method_defined? :binread
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ # Note: Must be required explicitely!
2
+ # This is a best attempt to fake BasicObject in Ruby 1.8.x
3
+ # What you do get:
4
+ # * as few methods as the real BasicObject (at the moment the library is required...)
5
+ # * BasicObject === <anything> # ==> returns true
6
+ # What you don't get:
7
+ # * BasicObject is not in the ancestor list of all classes and thus
8
+ # * Comparisons between classes won't work, e.g.
9
+ # Object < BasicObject # ==> returns true instead of false
10
+ # * Instance methods added to Object or Kernel after you require 'backports/basic_object'
11
+ # might also be available in instances of BasicObject and subclasses
12
+ # (they will only be undefined whenever a subclass of BasicObject is created)
13
+ # Because of all the fineprint, BasicObject must be required explicitely
14
+
15
+ require File.expand_path(File.dirname(__FILE__) + "/tools")
16
+ Backports.require_relative '1.8.7'
17
+
18
+ class BasicObject
19
+ KEEP = [:instance_eval, :instance_exec, :__send__,
20
+ "instance_eval", "instance_exec", "__send__"]
21
+ # undefine almost all instance methods
22
+ begin
23
+ old_verbose, $VERBOSE = $VERBOSE, nil # silence the warning for undefining __id__
24
+ (instance_methods - KEEP).each do |method|
25
+ undef_method method
26
+ end
27
+ ensure
28
+ $VERBOSE = old_verbose
29
+ end
30
+
31
+ class << self
32
+ def === (cmp)
33
+ true
34
+ end
35
+
36
+ # Let's try to keep things clean, in case methods have been added to Object
37
+ # either directly or through an included module.
38
+ # We'll do this whenever a class is derived from BasicObject
39
+ # Ideally, we'd do this by trapping Object.method_added
40
+ # and M.method_added for any module M included in Object or a submodule
41
+ # Seems really though to get right, but pull requests welcome ;-)
42
+ def inherited(sub)
43
+ BasicObject.class_eval do
44
+ (instance_methods - KEEP).each do |method|
45
+ if Object.method_defined?(method) && instance_method(method).owner == Object.instance_method(method).owner
46
+ undef_method method
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end unless Kernel.const_defined? :BasicObject
@@ -4,12 +4,12 @@ module Backports
4
4
  # Adapted from Pragmatic's "Programming Ruby" (since their version was buggy...)
5
5
  def self.require_relative(relative_feature)
6
6
  file = caller.first.split(/:\d/,2).first
7
- if /\A\((.*)\)/ =~ file # eval, etc.
8
- raise LoadError, "require_relative is called in #{$1}"
9
- end
7
+ if /\A\((.*)\)/ =~ file # eval, etc.
8
+ raise LoadError, "require_relative is called in #{$1}"
9
+ end
10
10
  require File.expand_path(relative_feature, File.dirname(file))
11
11
  end
12
-
12
+
13
13
  # Metaprogramming utility to make block optional.
14
14
  # Tests first if block is already optional when given options
15
15
  def self.make_block_optional mod,*methods
@@ -23,7 +23,7 @@ module Backports
23
23
  test_on = options[:test_on] || self.new
24
24
  next if (test_on.send(selector, *options.fetch(:arg, [])) rescue false)
25
25
  end
26
-
26
+
27
27
  arity = mod.instance_method(selector).arity
28
28
  last_arg = []
29
29
  if arity < 0
@@ -43,6 +43,55 @@ module Backports
43
43
  end
44
44
  end
45
45
 
46
+ # Metaprogramming utility to convert the first file argument to path
47
+ def self.convert_first_argument_to_path mod,*methods
48
+ methods.each do |selector|
49
+ unless mod.method_defined? selector
50
+ warn "#{mod}##{selector} is not defined, so argument can't converted to path"
51
+ next
52
+ end
53
+ arity = mod.instance_method(selector).arity
54
+ last_arg = []
55
+ if arity < 0
56
+ last_arg = ["*rest"]
57
+ arity = -1-arity
58
+ end
59
+ arg_sequence = (["file"] + (1...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ")
60
+
61
+ alias_method_chain(mod, selector, :potential_path_argument) do |aliased_target, punctuation|
62
+ mod.module_eval <<-end_eval
63
+ def #{aliased_target}_with_potential_path_argument#{punctuation}(#{arg_sequence})
64
+ file = Backports.convert_to_path(file)
65
+ #{aliased_target}_without_potential_path_argument#{punctuation}(#{arg_sequence})
66
+ end
67
+ end_eval
68
+ end
69
+ end
70
+ end
71
+
72
+ # Metaprogramming utility to convert all file arguments to paths
73
+ def self.convert_all_arguments_to_path mod, skip, *methods
74
+ methods.each do |selector|
75
+ unless mod.method_defined? selector
76
+ warn "#{mod}##{selector} is not defined, so arguments can't converted to path"
77
+ next
78
+ end
79
+ first_args = (1..skip).map{|i| "arg_#{i}"}.join(",") + (skip > 0 ? "," : "")
80
+ alias_method_chain(mod, selector, :potential_path_arguments) do |aliased_target, punctuation|
81
+ mod.module_eval <<-end_eval
82
+ def #{aliased_target}_with_potential_path_arguments#{punctuation}(#{first_args}*files, &block)
83
+ files = files.map{|f| Backports.convert_to_path f}
84
+ #{aliased_target}_without_potential_path_arguments#{punctuation}(#{first_args}*files, &block)
85
+ end
86
+ end_eval
87
+ end
88
+ end
89
+ end
90
+
91
+ def self.convert_to_path(file_or_path)
92
+ coerce_to(file_or_path, String, :to_str) rescue coerce_to(file_or_path, String, :to_path) rescue file_or_path
93
+ end
94
+
46
95
  # Modified to avoid polluting Module if so desired
47
96
  # (from Rails)
48
97
  def self.alias_method_chain(mod, target, feature)
@@ -67,10 +116,10 @@ module Backports
67
116
  end
68
117
  end
69
118
  end
70
-
119
+
71
120
  # Helper method to coerce a value into a specific class.
72
121
  # Raises a TypeError if the coercion fails or the returned value
73
- # is not of the right class.
122
+ # is not of the right class.
74
123
  # (from Rubinius)
75
124
  def self.coerce_to(obj, cls, meth)
76
125
  return obj if obj.kind_of?(cls)
@@ -84,7 +133,7 @@ module Backports
84
133
  raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls
85
134
  ret
86
135
  end
87
-
136
+
88
137
  # Checks for a failed comparison (in which case it throws an ArgumentError)
89
138
  # Additionally, it maps any negative value to -1 and any positive value to +1
90
139
  # (from Rubinius)
@@ -98,7 +147,7 @@ module Backports
98
147
  # Used internally to make it easy to deal with optional arguments
99
148
  # (from Rubinius)
100
149
  Undefined = Object.new
101
-
150
+
102
151
  # A simple class which allows the construction of Enumerator from a block
103
152
  class Yielder
104
153
  def initialize(&block)
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+ require 'backports/basic_object'
3
+
4
+ class BasicObjectTest < Test::Unit::TestCase
5
+ context "BasicObject" do
6
+ should "do it's best to keep stuff undefined" do
7
+ # written in one big test because sequence matters
8
+ # and defining classes / methods can't really be undone
9
+
10
+ assert_equal 3, BasicObject.instance_methods.size
11
+
12
+ class Subclass < BasicObject
13
+ def foo
14
+ :bar
15
+ end
16
+ end
17
+
18
+ assert_equal 4, Subclass.instance_methods.size
19
+
20
+ module ::Kernel
21
+ def bar
22
+ :foo
23
+ end
24
+ end
25
+
26
+ assert Subclass.method_defined?(:bar) # for now
27
+
28
+ class ForceCleanup < Subclass
29
+ end
30
+
31
+ assert !Subclass.method_defined?(:bar) # should be cleaned up
32
+
33
+ module SomeExtension
34
+ def foo
35
+ 42
36
+ end
37
+ end
38
+
39
+ class ::Object
40
+ include SomeExtension
41
+ end
42
+
43
+ class ForceCleanupAgain < Subclass
44
+ end
45
+
46
+ # puts BasicObject.instance_methods - BasicObject.instance_methods(false)
47
+ # puts BasicObject.instance_method(:foo).owner
48
+ # puts SomeExtension <= Object
49
+ assert Subclass.method_defined?(:foo) # should not be cleaned up!
50
+ assert !BasicObject.method_defined?(:foo) # but BasicObject should have been cleaned up!
51
+
52
+ class BasicObject
53
+ def last_case
54
+ 1.0/0
55
+ end
56
+ end
57
+
58
+ module SomeExtension
59
+ def last_case
60
+ 0
61
+ end
62
+ end
63
+
64
+ class ForceCleanupForTheLastTime < BasicObject
65
+ end
66
+
67
+ assert BasicObject.method_defined?(:last_case)
68
+ end
69
+ end
70
+ 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.8.4
4
+ version: 1.9.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-03 00:00:00 -04:00
12
+ date: 2009-09-05 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -62,11 +62,14 @@ files:
62
62
  - lib/backports/1.9/array.rb
63
63
  - lib/backports/1.9/enumerable.rb
64
64
  - lib/backports/1.9/enumerator.rb
65
+ - lib/backports/1.9/file.rb
65
66
  - lib/backports/1.9/hash.rb
66
67
  - lib/backports/1.9/integer.rb
68
+ - lib/backports/1.9/io.rb
67
69
  - lib/backports/1.9/kernel.rb
68
70
  - lib/backports/1.9/string.rb
69
71
  - lib/backports/1.9/symbol.rb
72
+ - lib/backports/basic_object.rb
70
73
  - lib/backports/rails.rb
71
74
  - lib/backports/rails/array.rb
72
75
  - lib/backports/rails/enumerable.rb
@@ -76,6 +79,7 @@ files:
76
79
  - lib/backports/rails/string.rb
77
80
  - lib/backports/tools.rb
78
81
  - test/array_test.rb
82
+ - test/basic_object_test.rb
79
83
  - test/binding_test.rb
80
84
  - test/enumerable_test.rb
81
85
  - test/enumerator_test.rb
@@ -124,6 +128,7 @@ specification_version: 3
124
128
  summary: Backports or ruby 1.8.7+ & rails for older ruby.
125
129
  test_files:
126
130
  - test/array_test.rb
131
+ - test/basic_object_test.rb
127
132
  - test/binding_test.rb
128
133
  - test/enumerable_test.rb
129
134
  - test/enumerator_test.rb