utilrb 3.0.1 → 3.2.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,26 +1,32 @@
1
1
  module Marshal
2
- if defined? BasicObject
3
- class BlackHole < BasicObject
4
- end
5
- end
6
-
7
2
  class BlackHole
8
3
  class << self
9
- :name
4
+ attr_reader :name
10
5
  end
11
6
 
12
7
  def initialize(*args)
13
8
  end
14
9
 
10
+ def hash
11
+ __id__
12
+ end
13
+
14
+ def eql?(obj)
15
+ equal?(obj)
16
+ end
17
+
15
18
  attr_reader :__content__
16
19
  def method_missing(*args)
20
+ ::Kernel.puts args.inspect
21
+ ::Kernel.puts ::Kernel.caller
17
22
  end
18
23
  def self._load(*args)
19
24
  hole = BlackHole.new
20
25
  hole.instance_variable_set(:@__content__, args)
21
26
  end
22
27
 
23
- def self.method_missing(*args)
28
+ def self.method_missing(*args, **options)
29
+ BlackHole.new
24
30
  end
25
31
  end
26
32
 
@@ -32,20 +38,11 @@ module Marshal
32
38
  self.load(str_or_io)
33
39
  rescue Exception => e
34
40
  case e.message
35
- when /undefined class\/module ((?:\w+::)+)$/
36
- names = $1.split('::')
37
- missing = names.pop
38
- base = names.inject(Object) { |m, n| m.const_get(n) }
39
- base.const_set(missing, Module.new)
40
-
41
- if original_pos
42
- str_or_io.seek(original_pos)
43
- end
44
- retry
45
- when /undefined class\/module ((?:\w+::)+)(\w+)$/
46
- mod, klass = $1, $2
47
- full_name = "#{mod}#{klass}"
48
- mod = mod.split('::').inject(Object) { |m, n| m.const_get(n) }
41
+ when /undefined class\/module ((?:\w+)(?:::\w+)*)(?:::)?$/
42
+ full_name = $1
43
+ path = $1.split('::')
44
+ *path, klass = *path
45
+ mod = path.inject(Object) { |m, n| m.const_get(n) }
49
46
 
50
47
  blackhole = Class.new(BlackHole) do
51
48
  @name = full_name
@@ -0,0 +1,3 @@
1
+ require 'utilrb/kernel/require'
2
+ require_dir(__FILE__)
3
+
@@ -1,10 +1,13 @@
1
- class Module
1
+ # frozen_string_literal: true
2
+
3
+ class Module # rubocop:disable Style/Documentation
2
4
  # call-seq:
3
5
  # dsl_attribute(name)
4
6
  # dsl_attribute(name,name2,name3)
5
7
  # dsl_attribute(name) { |value| ... }
6
8
  #
7
- # This defines a +name+ instance method on the given class which accepts zero or one argument
9
+ # This defines a +name+ instance method on the given class which accepts
10
+ # zero or one argument
8
11
  #
9
12
  # Without any argument, it acts as a getter for the +@name+ attribute. With
10
13
  # one argument, it acts instead as a setter for the same attribute and
@@ -13,8 +16,8 @@ class Module
13
16
  # instance variable. This block can therefore both filter the value
14
17
  # (convert it to a desired form) and validate it.
15
18
  #
16
- # The goal of this method is to have a nicer way to handle attribute in DSLs: instead
17
- # of
19
+ # The goal of this method is to have a nicer way to handle attribute in
20
+ # DSLs: instead of
18
21
  #
19
22
  # model = create_model do
20
23
  # self.my_model_attribute = 'bla'
@@ -35,37 +38,46 @@ class Module
35
38
  # end
36
39
  #
37
40
  def dsl_attribute(*names, &filter_block)
38
- if names.size > 1 && filter_block
39
- raise ArgumentError, "multiple names as argument are only supported if no block is given"
41
+ if names.size > 1
42
+ if filter_block
43
+ raise ArgumentError,
44
+ "multiple names as argument are only supported if no block is given"
45
+ end
46
+
47
+ names.each { |name| dsl_attribute(name) }
48
+ return
40
49
  end
41
- names.each do |name|
42
- class_eval do
50
+
51
+ name = names.first
52
+
53
+ class_eval do
43
54
  if filter_block
44
55
  define_method("__dsl_attribute__#{name}__filter__", &filter_block)
45
56
  end
46
57
 
47
- define_method(name) do |*value|
48
- if value.empty?
49
- instance_variable_get("@#{name}")
50
- elsif filter_block
51
- if filter_block.arity >= 0 && value.size != filter_block.arity
52
- raise ArgumentError, "too many arguments. Got #{value.size}, expected #{filter_block.arity}"
53
- end
54
-
55
- filtered_value = send("__dsl_attribute__#{name}__filter__", *value)
56
- instance_variable_set("@#{name}", filtered_value)
57
- self
58
- else
58
+ define_method(name) do |*value, **kw|
59
+ if value.empty? && kw.empty?
60
+ instance_variable_get("@#{name}")
61
+ elsif filter_block
62
+ # Ruby 2.7 madness. The second version would pass {} as
63
+ # second argument
64
+ filtered_value =
65
+ if kw.empty?
66
+ send("__dsl_attribute__#{name}__filter__", *value)
67
+ else
68
+ send("__dsl_attribute__#{name}__filter__", *value, **kw)
69
+ end
70
+ instance_variable_set("@#{name}", filtered_value)
71
+ self
72
+ else
59
73
  if value.size == 1
60
74
  instance_variable_set("@#{name}", value.first)
61
75
  else
62
76
  instance_variable_set("@#{name}", value)
63
77
  end
64
- self
65
- end
66
- end
67
- end
78
+ self
79
+ end
80
+ end
68
81
  end
69
82
  end
70
83
  end
71
-
@@ -1,8 +1,20 @@
1
1
 
2
2
  class Object
3
- # Return the object address (for non immediate
4
- # objects).
5
- def address; Object.address_from_id(object_id) end
3
+ if RUBY_VERSION < "2.7.0"
4
+ # Return the object address (for non immediate
5
+ # objects).
6
+ def address
7
+ Object.address_from_id(object_id)
8
+ end
9
+ else
10
+ BUILTIN_OBJECT_TO_S = Object.instance_method(:to_s)
11
+ def address
12
+ to_s = BUILTIN_OBJECT_TO_S.bind(self).call
13
+ if (m = /:(0x[0-9a-f]+)/.match(to_s))
14
+ Integer(m[1])
15
+ end
16
+ end
17
+ end
6
18
 
7
19
  # Converts the object_id of a non-immediate object
8
20
  # to its memory address
@@ -27,6 +27,8 @@ class Object
27
27
  class_eval <<-EOD, __FILE__, __LINE__+1
28
28
  def #{name}
29
29
  if instance_variable_defined?(:@#{name}) then @#{name}
30
+ elsif frozen?
31
+ #{name}_defval
30
32
  else @#{name} = #{name}_defval
31
33
  end
32
34
  end
@@ -40,4 +42,3 @@ class Object
40
42
  singleton_class.class_eval { attribute(attr_def, &init) }
41
43
  end
42
44
  end
43
-