dry-core 0.7.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/core/deprecations"
4
-
5
3
  module Dry
6
4
  module Core
7
5
  module Memoizable
@@ -13,6 +11,13 @@ module Dry
13
11
  def memoize(*names)
14
12
  prepend(Memoizer.new(self, names))
15
13
  end
14
+
15
+ def inherited(base)
16
+ super
17
+
18
+ memoizer = base.ancestors.find { _1.is_a?(Memoizer) }
19
+ base.prepend(memoizer.dup) if memoizer
20
+ end
16
21
  end
17
22
 
18
23
  module BasicObject
@@ -52,6 +57,12 @@ module Dry
52
57
 
53
58
  # @api private
54
59
  class Memoizer < ::Module
60
+ KERNEL = {
61
+ singleton: ::Kernel.instance_method(:singleton_class),
62
+ ivar_set: ::Kernel.instance_method(:instance_variable_set),
63
+ frozen: ::Kernel.instance_method(:frozen?)
64
+ }.freeze
65
+
55
66
  # @api private
56
67
  def initialize(klass, names)
57
68
  super()
@@ -65,20 +76,50 @@ module Dry
65
76
  private
66
77
 
67
78
  # @api private
68
- def define_memoizable(method:) # rubocop:disable Metrics/AbcSize
79
+ # rubocop:disable Metrics/AbcSize
80
+ # rubocop:disable Metrics/PerceivedComplexity
81
+ def define_memoizable(method:)
69
82
  parameters = method.parameters
83
+ mod = self
84
+ kernel = KERNEL
70
85
 
71
86
  if parameters.empty?
72
- key = method.name.hash
73
- module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
74
- def #{method.name} # def slow_fetch
75
- if @__memoized__.key?(#{key}) # if @__memoized__.key?(12345678)
76
- @__memoized__[#{key}] # @__memoized__[12345678]
77
- else # else
78
- @__memoized__[#{key}] = super # @__memoized__[12345678] = super
79
- end # end
80
- end # end
81
- RUBY
87
+ key = "#{object_id}:#{method.name}".hash.abs
88
+
89
+ define_method(method.name) do
90
+ value = super()
91
+
92
+ if kernel[:frozen].bind_call(self)
93
+ # It's not possible to modify singleton classes
94
+ # of frozen objects
95
+ mod.remove_method(method.name)
96
+ mod.module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
97
+ def #{method.name} # def slow_calc
98
+ cached = @__memoized__[#{key}] # cached = @__memoized__[12345678]
99
+ #
100
+ if cached || @__memoized__.key?(#{key}) # if cached || @__memoized__.key?(12345678)
101
+ cached # cached
102
+ else # else
103
+ @__memoized__[#{key}] = super # @__memoized__[12345678] = super
104
+ end # end
105
+ end # end
106
+ RUBY
107
+ else
108
+ # We make an attr_reader for computed value.
109
+ # Readers are "special-cased" in ruby so such
110
+ # access will be the fastest way, faster than you'd
111
+ # expect :)
112
+ attr_name = :"__memozed_#{key}__"
113
+ ivar_name = :"@#{attr_name}"
114
+ kernel[:ivar_set].bind_call(self, ivar_name, value)
115
+ eigenclass = kernel[:singleton].bind_call(self)
116
+ eigenclass.attr_reader(attr_name)
117
+ eigenclass.alias_method(method.name, attr_name)
118
+ eigenclass.remove_method(attr_name)
119
+ end
120
+
121
+ value
122
+ end
82
123
  else
83
124
  mapping = parameters.to_h { |k, v = nil| [k, v] }
84
125
  params, binds = declaration(parameters, mapping)
@@ -95,7 +136,7 @@ module Dry
95
136
 
96
137
  m = module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
97
138
  def #{method.name}(#{params.join(", ")}) # def slow_calc(arg1, arg2, arg3)
98
- key = [:"#{method.name}", #{binds.join(", ")}].hash # [:slow_calc, arg1, arg2, arg3].hash
139
+ key = [:"#{method.name}", #{binds.join(", ")}].hash # key = [:slow_calc, arg1, arg2, arg3].hash
99
140
  #
100
141
  if @__memoized__.key?(key) # if @__memoized__.key?(key)
101
142
  @__memoized__[key] # @__memoized__[key]
@@ -112,6 +153,8 @@ module Dry
112
153
  m
113
154
  end
114
155
  end
156
+ # rubocop:enable Metrics/AbcSize
157
+ # rubocop:enable Metrics/PerceivedComplexity
115
158
 
116
159
  # @api private
117
160
  def declaration(definition, lookup)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Core
5
- VERSION = "0.7.1"
5
+ VERSION = "1.0.1"
6
6
  end
7
7
  end
data/lib/dry/core.rb CHANGED
@@ -1,10 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "zeitwerk"
4
+
5
+ require "dry/core/constants"
6
+ require "dry/core/errors"
3
7
  require "dry/core/version"
4
8
 
5
9
  # :nodoc:
6
10
  module Dry
7
11
  # :nodoc:
8
12
  module Core
13
+ include Constants
14
+
15
+ def self.loader
16
+ @loader ||= Zeitwerk::Loader.new.tap do |loader|
17
+ root = File.expand_path("..", __dir__)
18
+ loader.tag = "dry-core"
19
+ loader.inflector = Zeitwerk::GemInflector.new("#{root}/dry-core.rb")
20
+ loader.push_dir(root)
21
+ loader.ignore(
22
+ "#{root}/dry-core.rb",
23
+ "#{root}/dry/core/{constants,errors,version}.rb"
24
+ )
25
+ loader.inflector.inflect("namespace_dsl" => "NamespaceDSL")
26
+ end
27
+ end
28
+
29
+ loader.setup
30
+
31
+ # Build an equalizer module for the inclusion in other class
32
+ #
33
+ # ## Credits
34
+ #
35
+ # Equalizer has been originally imported from the equalizer gem created by Dan Kubb
36
+ #
37
+ # @api public
38
+ def self.Equalizer(*keys, **options)
39
+ Equalizer.new(*keys, **options)
40
+ end
41
+ end
42
+
43
+ # See dry/core/equalizer.rb
44
+ unless singleton_class.method_defined?(:Equalizer)
45
+ # Build an equalizer module for the inclusion in other class
46
+ #
47
+ # ## Credits
48
+ #
49
+ # Equalizer has been originally imported from the equalizer gem created by Dan Kubb
50
+ #
51
+ # @api public
52
+ def self.Equalizer(*keys, **options)
53
+ Dry::Core::Equalizer.new(*keys, **options)
54
+ end
9
55
  end
10
56
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikita Shilnikov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-10 00:00:00.000000000 Z
11
+ date: 2023-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: zeitwerk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.6'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -79,10 +93,24 @@ files:
79
93
  - dry-core.gemspec
80
94
  - lib/dry-core.rb
81
95
  - lib/dry/core.rb
96
+ - lib/dry/core/basic_object.rb
82
97
  - lib/dry/core/cache.rb
83
98
  - lib/dry/core/class_attributes.rb
84
99
  - lib/dry/core/class_builder.rb
85
100
  - lib/dry/core/constants.rb
101
+ - lib/dry/core/container.rb
102
+ - lib/dry/core/container/config.rb
103
+ - lib/dry/core/container/configuration.rb
104
+ - lib/dry/core/container/item.rb
105
+ - lib/dry/core/container/item/callable.rb
106
+ - lib/dry/core/container/item/factory.rb
107
+ - lib/dry/core/container/item/memoizable.rb
108
+ - lib/dry/core/container/mixin.rb
109
+ - lib/dry/core/container/namespace.rb
110
+ - lib/dry/core/container/namespace_dsl.rb
111
+ - lib/dry/core/container/registry.rb
112
+ - lib/dry/core/container/resolver.rb
113
+ - lib/dry/core/container/stub.rb
86
114
  - lib/dry/core/deprecations.rb
87
115
  - lib/dry/core/descendants_tracker.rb
88
116
  - lib/dry/core/equalizer.rb
@@ -96,7 +124,7 @@ licenses:
96
124
  - MIT
97
125
  metadata:
98
126
  allowed_push_host: https://rubygems.org
99
- changelog_uri: https://github.com/dry-rb/dry-core/blob/master/CHANGELOG.md
127
+ changelog_uri: https://github.com/dry-rb/dry-core/blob/main/CHANGELOG.md
100
128
  source_code_uri: https://github.com/dry-rb/dry-core
101
129
  bug_tracker_uri: https://github.com/dry-rb/dry-core/issues
102
130
  post_install_message:
@@ -107,14 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
135
  requirements:
108
136
  - - ">="
109
137
  - !ruby/object:Gem::Version
110
- version: 2.6.0
138
+ version: 3.0.0
111
139
  required_rubygems_version: !ruby/object:Gem::Requirement
112
140
  requirements:
113
141
  - - ">="
114
142
  - !ruby/object:Gem::Version
115
143
  version: '0'
116
144
  requirements: []
117
- rubygems_version: 3.1.6
145
+ rubygems_version: 3.3.26
118
146
  signing_key:
119
147
  specification_version: 4
120
148
  summary: A toolset of small support modules used throughout the dry-rb ecosystem