dry-core 0.6.0 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +4 -3
- data/dry-core.gemspec +1 -1
- data/lib/dry/core/cache.rb +2 -1
- data/lib/dry/core/class_attributes.rb +3 -3
- data/lib/dry/core/class_builder.rb +2 -4
- data/lib/dry/core/constants.rb +3 -3
- data/lib/dry/core/deprecations.rb +16 -12
- data/lib/dry/core/equalizer.rb +2 -1
- data/lib/dry/core/memoizable.rb +106 -32
- data/lib/dry/core/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5bebc041fb4b4179274ef429212f91054377d05b6d4e6f353eb515a008794bff
|
|
4
|
+
data.tar.gz: 58401fbebb0f25c9990d5f3f7a5dad7e5bc0512c1aa2787732e7c35016d913f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da17cd2eecc9cfdc1ac6210161b94cbf46a5e572a563ab4e1173fed488ad2690fedee3c64dcb8db55285dfc3277b988de794800d21a23161b8f537c14ec6ceff
|
|
7
|
+
data.tar.gz: 9a7530f8bdc1e5398638562a00021d689da2de8c52b704d4dc59817f0a70ce640b1e0fcc618690ff59853e437adc8456e3d8a4830978f2b0217c8bbe845bd352
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
|
2
2
|
|
|
3
|
+
## 0.7.0 2021-07-08
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- [memoizable] warnings when using keyword arguments (@flash-gordon)
|
|
9
|
+
- [deprecations] warnings show more relevant information about caller by default (@timriley)
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Minimal Ruby version is 2.6
|
|
14
|
+
|
|
15
|
+
[Compare v0.6.0...v0.7.0](https://github.com/dry-rb/dry-core/compare/v0.6.0...v0.7.0)
|
|
16
|
+
|
|
3
17
|
## 0.6.0 2021-06-03
|
|
4
18
|
|
|
5
19
|
|
data/README.md
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<!--- this file is synced from dry-rb/template-gem project -->
|
|
1
2
|
[gem]: https://rubygems.org/gems/dry-core
|
|
2
3
|
[actions]: https://github.com/dry-rb/dry-core/actions
|
|
3
4
|
[codacy]: https://www.codacy.com/gh/dry-rb/dry-core
|
|
@@ -14,15 +15,15 @@
|
|
|
14
15
|
|
|
15
16
|
## Links
|
|
16
17
|
|
|
17
|
-
* [User documentation](
|
|
18
|
+
* [User documentation](https://dry-rb.org/gems/dry-core)
|
|
18
19
|
* [API documentation](http://rubydoc.info/gems/dry-core)
|
|
19
20
|
|
|
20
21
|
## Supported Ruby versions
|
|
21
22
|
|
|
22
23
|
This library officially supports the following Ruby versions:
|
|
23
24
|
|
|
24
|
-
* MRI
|
|
25
|
-
* jruby
|
|
25
|
+
* MRI `>= 2.6.0`
|
|
26
|
+
* ~~jruby~~ `>= 9.3` (we are waiting for [2.6 support](https://github.com/jruby/jruby/issues/6161))
|
|
26
27
|
|
|
27
28
|
## License
|
|
28
29
|
|
data/dry-core.gemspec
CHANGED
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
|
26
26
|
spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-core"
|
|
27
27
|
spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-core/issues"
|
|
28
28
|
|
|
29
|
-
spec.required_ruby_version = ">= 2.
|
|
29
|
+
spec.required_ruby_version = ">= 2.6.0"
|
|
30
30
|
|
|
31
31
|
# to update dependencies edit project.yml
|
|
32
32
|
spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
|
data/lib/dry/core/cache.rb
CHANGED
|
@@ -46,7 +46,8 @@ module Dry
|
|
|
46
46
|
# this means you shouldn't pass Procs in args unless you're sure
|
|
47
47
|
# they are always the same instances, otherwise you introduce a memory leak
|
|
48
48
|
#
|
|
49
|
-
# @return [Object] block's return value (cached for subsequent calls with
|
|
49
|
+
# @return [Object] block's return value (cached for subsequent calls with
|
|
50
|
+
# the same argument values)
|
|
50
51
|
def fetch_or_store(*args, &block)
|
|
51
52
|
cache.fetch_or_store(args.hash, &block)
|
|
52
53
|
end
|
|
@@ -67,7 +67,7 @@ module Dry
|
|
|
67
67
|
# defines :one, coerce: Dry::Types['coercible.string']
|
|
68
68
|
# end
|
|
69
69
|
#
|
|
70
|
-
def defines(*args, type: ::Object, coerce: IDENTITY)
|
|
70
|
+
def defines(*args, type: ::Object, coerce: IDENTITY) # rubocop:disable Metrics/PerceivedComplexity
|
|
71
71
|
unless coerce.respond_to?(:call)
|
|
72
72
|
raise ::ArgumentError, "Non-callable coerce option: #{coerce.inspect}"
|
|
73
73
|
end
|
|
@@ -80,10 +80,10 @@ module Dry
|
|
|
80
80
|
if Undefined.equal?(value)
|
|
81
81
|
if instance_variable_defined?(ivar)
|
|
82
82
|
instance_variable_get(ivar)
|
|
83
|
-
else
|
|
83
|
+
else # rubocop:disable Style/EmptyElse
|
|
84
84
|
nil
|
|
85
85
|
end
|
|
86
|
-
elsif type === value
|
|
86
|
+
elsif type === value # rubocop:disable Style/CaseEquality
|
|
87
87
|
instance_variable_set(ivar, coerce.call(value))
|
|
88
88
|
else
|
|
89
89
|
raise InvalidClassAttributeValue.new(name, value)
|
|
@@ -6,9 +6,7 @@ module Dry
|
|
|
6
6
|
class ClassBuilder
|
|
7
7
|
ParentClassMismatch = Class.new(TypeError)
|
|
8
8
|
|
|
9
|
-
attr_reader :name
|
|
10
|
-
attr_reader :parent
|
|
11
|
-
attr_reader :namespace
|
|
9
|
+
attr_reader :name, :parent, :namespace
|
|
12
10
|
|
|
13
11
|
def initialize(name:, parent: nil, namespace: nil)
|
|
14
12
|
@name = name
|
|
@@ -83,7 +81,7 @@ module Dry
|
|
|
83
81
|
def create_base(namespace, name, parent)
|
|
84
82
|
begin
|
|
85
83
|
namespace.const_get(name)
|
|
86
|
-
rescue NameError
|
|
84
|
+
rescue NameError # rubocop:disable Lint/SuppressedException
|
|
87
85
|
end
|
|
88
86
|
|
|
89
87
|
if namespace.const_defined?(name, false)
|
data/lib/dry/core/constants.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Dry
|
|
|
25
25
|
# An empty set
|
|
26
26
|
EMPTY_SET = ::Set.new.freeze
|
|
27
27
|
# An empty string
|
|
28
|
-
EMPTY_STRING = ""
|
|
28
|
+
EMPTY_STRING = ""
|
|
29
29
|
# Identity function
|
|
30
30
|
IDENTITY = (-> x { x }).freeze
|
|
31
31
|
|
|
@@ -42,7 +42,7 @@ module Dry
|
|
|
42
42
|
# end
|
|
43
43
|
Undefined = Object.new.tap do |undefined|
|
|
44
44
|
# @api private
|
|
45
|
-
Self = -> { Undefined }
|
|
45
|
+
Self = -> { Undefined } # rubocop:disable Lint/ConstantDefinitionInBlock
|
|
46
46
|
|
|
47
47
|
# @api public
|
|
48
48
|
def undefined.to_s
|
|
@@ -62,7 +62,7 @@ module Dry
|
|
|
62
62
|
# 1 + Undefined.default(val, 2)
|
|
63
63
|
# end
|
|
64
64
|
#
|
|
65
|
-
def undefined.default(x, y = self)
|
|
65
|
+
def undefined.default(x, y = self) # rubocop:disable Naming/MethodParameterName
|
|
66
66
|
if equal?(x)
|
|
67
67
|
if equal?(y)
|
|
68
68
|
yield
|
|
@@ -37,12 +37,11 @@ module Dry
|
|
|
37
37
|
# Defaults to "deprecated"
|
|
38
38
|
# @param [Integer] Caller frame to add to the message
|
|
39
39
|
def warn(msg, tag: nil, uplevel: nil)
|
|
40
|
-
caller_info = uplevel.nil? ? nil :
|
|
41
|
-
tag = "[#{tag || "deprecated"}]"
|
|
40
|
+
caller_info = uplevel.nil? ? nil : "#{caller_locations(uplevel + 2, 1)[0]} "
|
|
41
|
+
tag = "[#{tag || "deprecated"}] "
|
|
42
42
|
hint = msg.gsub(/^\s+/, "")
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
)
|
|
43
|
+
|
|
44
|
+
logger.warn("#{caller_info}#{tag}#{hint}")
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
# Wraps arguments with a standard message format and prints a warning
|
|
@@ -50,6 +49,10 @@ module Dry
|
|
|
50
49
|
# @param [Object] name what is deprecated
|
|
51
50
|
# @param [String] msg additional message usually containing upgrade instructions
|
|
52
51
|
def announce(name, msg, tag: nil, uplevel: nil)
|
|
52
|
+
# Bump the uplevel (if provided) by one to account for the uplevel calculation
|
|
53
|
+
# taking place one frame deeper in `.warn`
|
|
54
|
+
uplevel += 1 if uplevel
|
|
55
|
+
|
|
53
56
|
warn(deprecation_message(name, msg), tag: tag, uplevel: uplevel)
|
|
54
57
|
end
|
|
55
58
|
|
|
@@ -99,7 +102,7 @@ module Dry
|
|
|
99
102
|
# @param [#warn] logger
|
|
100
103
|
#
|
|
101
104
|
# @api public
|
|
102
|
-
def set_logger!(output = $stderr)
|
|
105
|
+
def set_logger!(output = $stderr) # rubocop:disable Naming/AccessorMethodName
|
|
103
106
|
if output.respond_to?(:warn)
|
|
104
107
|
@logger = output
|
|
105
108
|
else
|
|
@@ -115,8 +118,9 @@ module Dry
|
|
|
115
118
|
end
|
|
116
119
|
|
|
117
120
|
# @api private
|
|
118
|
-
class Tagged < Module
|
|
121
|
+
class Tagged < ::Module
|
|
119
122
|
def initialize(tag)
|
|
123
|
+
super()
|
|
120
124
|
@tag = tag
|
|
121
125
|
end
|
|
122
126
|
|
|
@@ -152,8 +156,8 @@ module Dry
|
|
|
152
156
|
# @option [String] message optional deprecation message
|
|
153
157
|
def deprecate(old_name, new_name = nil, message: nil)
|
|
154
158
|
full_msg = Deprecations.deprecated_name_message(
|
|
155
|
-
"#{
|
|
156
|
-
new_name ? "#{
|
|
159
|
+
"#{name}##{old_name}",
|
|
160
|
+
new_name ? "#{name}##{new_name}" : nil,
|
|
157
161
|
message
|
|
158
162
|
)
|
|
159
163
|
mod = self
|
|
@@ -185,8 +189,8 @@ module Dry
|
|
|
185
189
|
# @option [String] message optional deprecation message
|
|
186
190
|
def deprecate_class_method(old_name, new_name = nil, message: nil)
|
|
187
191
|
full_msg = Deprecations.deprecated_name_message(
|
|
188
|
-
"#{
|
|
189
|
-
new_name ? "#{
|
|
192
|
+
"#{name}.#{old_name}",
|
|
193
|
+
new_name ? "#{name}.#{new_name}" : nil,
|
|
190
194
|
message
|
|
191
195
|
)
|
|
192
196
|
|
|
@@ -210,7 +214,7 @@ module Dry
|
|
|
210
214
|
remove_const(constant_name)
|
|
211
215
|
|
|
212
216
|
full_msg = Deprecations.deprecated_name_message(
|
|
213
|
-
"#{
|
|
217
|
+
"#{name}::#{constant_name}",
|
|
214
218
|
message
|
|
215
219
|
)
|
|
216
220
|
|
data/lib/dry/core/equalizer.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Dry
|
|
|
14
14
|
|
|
15
15
|
module Core
|
|
16
16
|
# Define equality, equivalence and inspection methods
|
|
17
|
-
class Equalizer < Module
|
|
17
|
+
class Equalizer < ::Module
|
|
18
18
|
# Initialize an Equalizer with the given keys
|
|
19
19
|
#
|
|
20
20
|
# Will use the keys with which it is initialized to define #cmp?,
|
|
@@ -29,6 +29,7 @@ module Dry
|
|
|
29
29
|
#
|
|
30
30
|
# @api private
|
|
31
31
|
def initialize(*keys, **options)
|
|
32
|
+
super()
|
|
32
33
|
@keys = keys.uniq
|
|
33
34
|
define_methods(**options)
|
|
34
35
|
freeze
|
data/lib/dry/core/memoizable.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "dry/core/deprecations"
|
|
4
|
+
|
|
3
5
|
module Dry
|
|
4
6
|
module Core
|
|
5
7
|
module Memoizable
|
|
@@ -27,7 +29,7 @@ module Dry
|
|
|
27
29
|
|
|
28
30
|
def new(*)
|
|
29
31
|
obj = super
|
|
30
|
-
obj.instance_variable_set(
|
|
32
|
+
obj.instance_variable_set(:@__memoized__, MEMOIZED_HASH.dup)
|
|
31
33
|
obj
|
|
32
34
|
end
|
|
33
35
|
|
|
@@ -48,9 +50,10 @@ module Dry
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
# @api private
|
|
51
|
-
class Memoizer < Module
|
|
53
|
+
class Memoizer < ::Module
|
|
52
54
|
# @api private
|
|
53
55
|
def initialize(klass, names)
|
|
56
|
+
super()
|
|
54
57
|
names.each do |name|
|
|
55
58
|
define_memoizable(
|
|
56
59
|
method: klass.instance_method(name)
|
|
@@ -62,45 +65,116 @@ module Dry
|
|
|
62
65
|
|
|
63
66
|
# @api private
|
|
64
67
|
def define_memoizable(method:)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
parameters = method.parameters
|
|
69
|
+
|
|
70
|
+
if parameters.empty?
|
|
71
|
+
key = method.name.hash
|
|
72
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
73
|
+
def #{method.name}
|
|
74
|
+
if @__memoized__.key?(#{key})
|
|
75
|
+
@__memoized__[#{key}]
|
|
76
|
+
else
|
|
77
|
+
@__memoized__[#{key}] = super
|
|
78
|
+
end
|
|
73
79
|
end
|
|
80
|
+
RUBY
|
|
81
|
+
else
|
|
82
|
+
mapping = parameters.to_h { |k, v = nil| [k, v] }
|
|
83
|
+
params, binds = declaration(parameters, mapping)
|
|
84
|
+
|
|
85
|
+
if parameters.last[0].eql?(:block)
|
|
86
|
+
Deprecations.warn(<<~WARN)
|
|
87
|
+
Memoization for block-accepting methods isn't safe.
|
|
88
|
+
Every call creates a new block instance bloating cached results.
|
|
89
|
+
In the future, blocks will still be allowed but won't participate in
|
|
90
|
+
cache key calculation.
|
|
91
|
+
WARN
|
|
74
92
|
end
|
|
75
|
-
RUBY
|
|
76
93
|
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
95
|
+
def #{method.name}(#{params.join(", ")})
|
|
96
|
+
key = [:"#{method.name}", #{binds.join(", ")}].hash
|
|
97
|
+
|
|
98
|
+
if @__memoized__.key?(key)
|
|
99
|
+
@__memoized__[key]
|
|
100
|
+
else
|
|
101
|
+
@__memoized__[key] = super
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
RUBY
|
|
105
|
+
|
|
106
|
+
if respond_to?(:ruby2_keywords, true) && mapping.key?(:reyrest)
|
|
107
|
+
ruby2_keywords(method.name)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @api private
|
|
113
|
+
def declaration(definition, lookup)
|
|
114
|
+
params = []
|
|
115
|
+
binds = []
|
|
116
|
+
defined = {}
|
|
117
|
+
|
|
118
|
+
definition.each do |type, name|
|
|
119
|
+
mapped_type = map_bind_type(type, lookup, defined) do
|
|
120
|
+
raise ::NotImplementedError, "type: #{type}, name: #{name}"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
if mapped_type
|
|
124
|
+
defined[mapped_type] = true
|
|
125
|
+
bind = name || make_bind_name(binds.size)
|
|
126
|
+
|
|
127
|
+
binds << bind
|
|
128
|
+
params << param(bind, mapped_type)
|
|
129
|
+
end
|
|
79
130
|
end
|
|
131
|
+
|
|
132
|
+
[params, binds]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @api private
|
|
136
|
+
def make_bind_name(idx)
|
|
137
|
+
:"__lv_#{idx}__"
|
|
80
138
|
end
|
|
81
139
|
|
|
82
140
|
# @api private
|
|
83
|
-
def
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
when :keyrest
|
|
93
|
-
"**#{name}"
|
|
94
|
-
when :block
|
|
95
|
-
"&#{name}"
|
|
96
|
-
when :opt
|
|
97
|
-
lookup.key?(:rest) ? nil : "*args"
|
|
98
|
-
when :key
|
|
99
|
-
lookup.key?(:keyrest) ? nil : "**kwargs"
|
|
141
|
+
def map_bind_type(type, original_params, defined_types) # rubocop:disable Metrics/PerceivedComplexity
|
|
142
|
+
case type
|
|
143
|
+
when :req
|
|
144
|
+
:reqular
|
|
145
|
+
when :rest, :keyreq, :keyrest, :block
|
|
146
|
+
type
|
|
147
|
+
when :opt
|
|
148
|
+
if original_params.key?(:rest) || defined_types[:rest]
|
|
149
|
+
nil
|
|
100
150
|
else
|
|
101
|
-
|
|
151
|
+
:rest
|
|
102
152
|
end
|
|
103
|
-
|
|
153
|
+
when :key
|
|
154
|
+
if original_params.key?(:keyrest) || defined_types[:keyrest]
|
|
155
|
+
nil
|
|
156
|
+
else
|
|
157
|
+
:keyrest
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
yield
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# @api private
|
|
165
|
+
def param(name, type)
|
|
166
|
+
case type
|
|
167
|
+
when :reqular
|
|
168
|
+
name
|
|
169
|
+
when :rest
|
|
170
|
+
"*#{name}"
|
|
171
|
+
when :keyreq
|
|
172
|
+
"#{name}:"
|
|
173
|
+
when :keyrest
|
|
174
|
+
"**#{name}"
|
|
175
|
+
when :block
|
|
176
|
+
"&#{name}"
|
|
177
|
+
end
|
|
104
178
|
end
|
|
105
179
|
end
|
|
106
180
|
end
|
data/lib/dry/core/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.7.0
|
|
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-
|
|
11
|
+
date: 2021-07-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|
|
@@ -107,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
107
107
|
requirements:
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: 2.
|
|
110
|
+
version: 2.6.0
|
|
111
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
112
|
requirements:
|
|
113
113
|
- - ">="
|