dry-core 0.7.1 → 1.0.1

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,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