Module: Backports

Defined in:
lib/backports/ractor/errors.rb,
lib/backports/version.rb,
lib/backports/tools/io.rb,
lib/backports/3.2.0/data.rb,
lib/backports/tools/path.rb,
lib/backports/3.0.0/ractor.rb,
lib/backports/ractor/cloner.rb,
lib/backports/ractor/queues.rb,
lib/backports/ractor/ractor.rb,
lib/backports/tools/std_lib.rb,
lib/backports/ractor/sharing.rb,
lib/backports/random/MT19937.rb,
lib/backports/tools/arguments.rb,
lib/backports/tools/deprecation.rb,
lib/backports/tools/alias_method.rb,
lib/backports/tools/extreme_object.rb,
lib/backports/ractor/filtered_queue.rb,
lib/backports/random/bits_and_bytes.rb,
lib/backports/random/implementation.rb,
lib/backports/tools/alias_method_chain.rb,
lib/backports/tools/make_block_optional.rb,
lib/backports/tools/require_relative_dir.rb,
lib/backports/tools/float_integer_conversion.rb,
lib/backports/tools/suppress_verbose_warnings.rb

Overview

shareable_constant_value: literal

Defined Under Namespace

Modules: StdLib Classes: Data, FilteredQueue, Ractor, Random

Constant Summary collapse

VERSION =

the guard is against a redefinition warning that happens on Travis

"3.25.0"
Undefined =

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

Object.new
EXCLUDED_CHILDREN =
['.', '..'].freeze
MOST_EXTREME_OBJECT_EVER =

:nodoc:

Object.new

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.warnedObject

private



3
4
5
# File 'lib/backports/tools/deprecation.rb', line 3

def warned
  @warned
end

Class Method Details

.alias_method(mod, new_name, old_name) ⇒ Object

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



3
4
5
6
7
# File 'lib/backports/tools/alias_method.rb', line 3

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)



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/backports/tools/alias_method_chain.rb', line 4

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)


6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/backports/tools/arguments.rb', line 6

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



23
24
25
# File 'lib/backports/tools/arguments.rb', line 23

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)


59
60
61
62
63
64
# File 'lib/backports/tools/arguments.rb', line 59

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_hash(obj) ⇒ Object



31
32
33
# File 'lib/backports/tools/arguments.rb', line 31

def self.coerce_to_hash(obj)
  coerce_to(obj, Hash, :to_hash)
end

.coerce_to_int(obj) ⇒ Object



19
20
21
# File 'lib/backports/tools/arguments.rb', line 19

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

.coerce_to_option(obj, option) ⇒ Object



40
41
42
# File 'lib/backports/tools/arguments.rb', line 40

def self.coerce_to_option(obj, option)
  coerce_to_options(obj, option)[0]
end

.coerce_to_options(obj, *options) ⇒ Object



35
36
37
38
# File 'lib/backports/tools/arguments.rb', line 35

def self.coerce_to_options(obj, *options)
  hash = coerce_to_hash(obj)
  hash.values_at(*options)
end

.coerce_to_str(obj) ⇒ Object



27
28
29
# File 'lib/backports/tools/arguments.rb', line 27

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)



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/backports/tools/io.rb', line 4

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) && options == Backports::Undefined
  options = {} if options == nil || options == Backports::Undefined
  options = coerce_to_hash(options)
  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



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/backports/tools/io.rb', line 32

def self.combine_mode_perm_and_option(mode = nil, perm = Backports::Undefined, 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
  [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



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/backports/tools/path.rb', line 31

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



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/backports/tools/path.rb', line 6

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



48
49
50
51
52
53
54
# File 'lib/backports/tools/path.rb', line 48

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

.float_to_integer(float) ⇒ Object



3
4
5
# File 'lib/backports/tools/float_integer_conversion.rb', line 3

def float_to_integer(float)
  map_via_packing(float, 'D', 'q')
end

.frown_upon(kind, msg) ⇒ Object



6
7
8
# File 'lib/backports/tools/deprecation.rb', line 6

def frown_upon kind, msg
  warn kind, msg if $VERBOSE
end

.integer_to_float(int) ⇒ Object



7
8
9
# File 'lib/backports/tools/float_integer_conversion.rb', line 7

def integer_to_float(int)
  map_via_packing(int, 'q', 'D')
end

.is_array?(obj) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/backports/tools/arguments.rb', line 44

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



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/backports/tools/make_block_optional.rb', line 6

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



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/backports/tools/require_relative_dir.rb', line 2

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|
        path = '../../' + short_path + f
        if Kernel.private_method_defined?(:require_relative)
          require_relative path
        else
          require File.expand_path(path)
        end
      end
end

.suppress_verbose_warningsObject



2
3
4
5
6
7
8
# File 'lib/backports/tools/suppress_verbose_warnings.rb', line 2

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

.symbol_namesObject

WeakMaps accept symbols only in Ruby 2.7+



4
5
6
# File 'lib/backports/3.0.0/symbol/name.rb', line 4

def Backports.symbol_names
  @symbol_names ||= ObjectSpace::WeakMap.new
end

.try_convert(obj, cls, meth) ⇒ Object

Raises:

  • (TypeError)


48
49
50
51
52
53
54
# File 'lib/backports/tools/arguments.rb', line 48

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

.warn(kind, msg) ⇒ Object Also known as: deprecate



10
11
12
13
14
# File 'lib/backports/tools/deprecation.rb', line 10

def warn kind, msg
  return if warned[kind]
  super msg
  warned[kind] = msg
end

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



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/backports/tools/io.rb', line 44

def self.write(binary, filename, string, offset, options)
  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]
  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