Module: Backports

Defined in:
lib/vendor/backports-3.3.5/lib/backports/tools.rb,
lib/vendor/backports-3.3.5/lib/backports/version.rb

Overview

Methods used internally by the backports.

Defined Under Namespace

Modules: StdLib

Constant Summary collapse

MOST_EXTREME_OBJECT_EVER =

:nodoc:

Object.new
Undefined =

Used internally to make it easy to deal with optional arguments (from Rubinius)

Object.new
VERSION =

the guard is against a redefinition warning that happens on Travis

"3.3.5"

Class Method Summary collapse

Class Method Details

.alias_method(mod, new_name, old_name) ⇒ Object

Used internally. Safe alias_method that will only alias if the source exists and destination doesn’t



257
258
259
260
261
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 257

def self.alias_method(mod, new_name, old_name)
  mod.instance_eval do
    alias_method new_name, old_name
  end if mod.method_defined?(old_name) && !mod.method_defined?(new_name)
end

.alias_method_chain(mod, target, feature) ⇒ Object

Modified to avoid polluting Module if so desired (from Rails)



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 177

def self.alias_method_chain(mod, target, feature)
  mod.class_eval do
    # Strip out punctuation on predicates or bang methods since
    # e.g. target?_without_feature is not a valid method name.
    aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
    yield(aliased_target, punctuation) if block_given?

    with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"

    alias_method without_method, target
    alias_method target, with_method

    case
      when public_method_defined?(without_method)
        public target
      when protected_method_defined?(without_method)
        protected target
      when private_method_defined?(without_method)
        private target
    end
  end
end

.coerce_to(obj, cls, meth) ⇒ Object

Helper method to coerce a value into a specific class. Raises a TypeError if the coercion fails or the returned value is not of the right class. (from Rubinius)

Raises:

  • (TypeError)


204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 204

def self.coerce_to(obj, cls, meth)
  return obj if obj.kind_of?(cls)

  begin
    ret = obj.__send__(meth)
  rescue Exception => e
    raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \
                     "(#{e.message})"
  end
  raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls
  ret
end

.coerce_to_ary(obj) ⇒ Object



221
222
223
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 221

def self.coerce_to_ary(obj)
  coerce_to(obj, Array, :to_ary)
end

.coerce_to_comparison(a, b, cmp = (a <=> b)) ⇒ Object

Checks for a failed comparison (in which case it throws an ArgumentError) Additionally, it maps any negative value to -1 and any positive value to +1 (from Rubinius)

Raises:

  • (ArgumentError)


244
245
246
247
248
249
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 244

def self.coerce_to_comparison(a, b, cmp = (a <=> b))
  raise ArgumentError, "comparison of #{a} with #{b} failed" if cmp.nil?
  return 1 if cmp > 0
  return -1 if cmp < 0
  0
end

.coerce_to_int(obj) ⇒ Object



217
218
219
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 217

def self.coerce_to_int(obj)
  coerce_to(obj, Integer, :to_int)
end

.coerce_to_str(obj) ⇒ Object



225
226
227
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 225

def self.coerce_to_str(obj)
  coerce_to(obj, String, :to_str)
end

.combine_mode_and_option(mode = nil, options = Backports::Undefined) ⇒ Object

Used internally to combine IO|File options hash into mode (String or Integer)



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 264

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
  options = {} if options == nil || options == Backports::Undefined
  options = coerce_to(options, Hash, :to_hash)
  if mode && options[:mode]
    raise ArgumentError, "mode specified twice"
  end
  mode ||= options[:mode] || "r"
  mode = try_convert(mode, String, :to_str) || try_convert(mode, Integer, :to_int) || mode
  if options[:textmode] || options[:binmode]
    text = options[:textmode] || (mode.is_a?(String) && mode =~ /t/)
    bin  = options[:binmode]  || (mode.is_a?(String) ? mode =~ /b/ : mode & File::Constants::BINARY != 0)
    if text && bin
      raise ArgumentError, "both textmode and binmode specified"
    end
    case
      when !options[:binmode]
      when mode.is_a?(String)
        mode.insert(1, "b")
      else
        mode |= File::Constants::BINARY
    end
  end
  mode
end

.combine_mode_perm_and_option(mode = nil, perm = Backports::Undefined, options = Backports::Undefined) ⇒ Object

Used internally to combine IO|File options hash into mode (String or Integer) and perm



292
293
294
295
296
297
298
299
300
301
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 292

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
  perm = nil if perm == Backports::Undefined
  options = {} if options == Backports::Undefined
  if perm && options[:perm]
    raise ArgumentError, "perm specified twice"
  end
  [combine_mode_and_option(mode, options), perm || options[:perm]]
end

.convert_all_arguments_to_path(klass, selector, skip) ⇒ Object

Metaprogramming utility to convert all file arguments to paths



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 150

def self.convert_all_arguments_to_path(klass, selector, skip)
  mod = class << klass; self; end
  unless mod.method_defined? selector
    warn "#{mod}##{selector} is not defined, so arguments can't converted to path"
    return
  end
  first_args = (1..skip).map{|i| "arg_#{i}"}.join(",") + (skip > 0 ? "," : "")
  alias_method_chain(mod, selector, :potential_path_arguments) do |aliased_target, punctuation|
    mod.module_eval <<-end_eval, __FILE__, __LINE__ + 1
      def #{aliased_target}_with_potential_path_arguments#{punctuation}(#{first_args}*files, &block)
        files = files.map{|f| Backports.convert_path(f) }
        #{aliased_target}_without_potential_path_arguments#{punctuation}(#{first_args}*files, &block)
      end
    end_eval
  end
end

.convert_first_argument_to_path(klass, selector) ⇒ Object

Metaprogramming utility to convert the first file argument to path



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 125

def self.convert_first_argument_to_path(klass, selector)
  mod = class << klass; self; end
  unless mod.method_defined? selector
    warn "#{mod}##{selector} is not defined, so argument can't converted to path"
    return
  end
  arity = mod.instance_method(selector).arity
  last_arg = []
  if arity < 0
    last_arg = ["*rest"]
    arity = -1-arity
  end
  arg_sequence = (["file"] + (1...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ")

  alias_method_chain(mod, selector, :potential_path_argument) do |aliased_target, punctuation|
    mod.module_eval <<-end_eval, __FILE__, __LINE__ + 1
      def #{aliased_target}_with_potential_path_argument#{punctuation}(#{arg_sequence})
        file = Backports.convert_path(file)
        #{aliased_target}_without_potential_path_argument#{punctuation}(#{arg_sequence})
      end
    end_eval
  end
end

.convert_path(path) ⇒ Object



167
168
169
170
171
172
173
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 167

def self.convert_path(path)
  try_convert(path, IO, :to_io) ||
  begin
    path = path.to_path if path.respond_to?(:to_path)
    try_convert(path, String, :to_str) || path
  end
end

.is_array?(obj) ⇒ Boolean

Returns:

  • (Boolean)


229
230
231
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 229

def self.is_array?(obj)
  coerce_to(obj, Array, :to_ary) if obj.respond_to? :to_ary
end

.make_block_optional(mod, *methods) ⇒ Object

Metaprogramming utility to make block optional. Tests first if block is already optional when given options



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 86

def self.make_block_optional(mod, *methods)
  mod = class << mod; self; end unless mod.is_a? Module
  options = methods.last.is_a?(Hash) ? methods.pop : {}
  methods.each do |selector|
    unless mod.method_defined? selector
      warn "#{mod}##{selector} is not defined, so block can't be made optional"
      next
    end
    unless options[:force]
      # Check if needed
      test_on = options.fetch(:test_on)
      result =  begin
                  test_on.send(selector, *options.fetch(:arg, []))
                rescue LocalJumpError
                  false
                end
      next if result.class.name =~ /Enumerator$/
    end
    require 'enumerator'
    arity = mod.instance_method(selector).arity
    last_arg = []
    if arity < 0
      last_arg = ["*rest"]
      arity = -1-arity
    end
    arg_sequence = ((0...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ")

    alias_method_chain(mod, selector, :optional_block) do |aliased_target, punctuation|
      mod.module_eval <<-end_eval, __FILE__, __LINE__ + 1
        def #{aliased_target}_with_optional_block#{punctuation}(#{arg_sequence})
          return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, #{arg_sequence}) unless block_given?
          #{aliased_target}_without_optional_block#{punctuation}(#{arg_sequence})
        end
      end_eval
    end
  end
end

.require_relative_dirObject



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 14

def self.require_relative_dir
  dir = caller.first.split(/\.rb:\d/,2).first
  short_path = dir[/.*(backports\/.*)/, 1] << '/'
  Dir.entries(dir).
      map{|f| Regexp.last_match(1) if /^(.*)\.rb$/ =~ f}.
      compact.
      sort.
      each do |f|
        require short_path + f
      end
end

.suppress_verbose_warningsObject



316
317
318
319
320
321
322
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 316

def self.suppress_verbose_warnings
  before = $VERBOSE
  $VERBOSE = false if $VERBOSE # Set to false (default warning) but not nil (no warnings)
  yield
ensure
  $VERBOSE = before
end

.try_convert(obj, cls, meth) ⇒ Object

Raises:

  • (TypeError)


233
234
235
236
237
238
239
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 233

def self.try_convert(obj, cls, meth)
  return obj if obj.kind_of?(cls)
  return nil unless obj.respond_to?(meth)
  ret = obj.__send__(meth)
  raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.nil? || ret.kind_of?(cls)
  ret
end

.write(binary, filename, string, offset, options) ⇒ Object



303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/vendor/backports-3.3.5/lib/backports/tools.rb', line 303

def self.write(binary, filename, string, offset, options)
  offset, options = nil, offset if Hash === offset and options == Backports::Undefined
  options = {} if options == Backports::Undefined
  File.open(filename, 'a+'){} if offset # insure existence
  options = {:mode => offset.nil? ? "w" : "r+"}.merge(options)
  args = options[:open_args] || [options]
  File.open(filename, *Backports.combine_mode_perm_and_option(*args)) do |f|
    f.binmode if binary && f.respond_to?(:binmode)
    f.seek(offset) unless offset.nil?
    f.write(string)
  end
end