dry-core 0.4.8 → 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.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
3
+ require "set"
4
4
 
5
5
  module Dry
6
6
  module Core
@@ -7,15 +7,15 @@ module Dry
7
7
  # List of supported backends
8
8
  BACKENDS = {
9
9
  activesupport: [
10
- 'active_support/inflector',
10
+ "active_support/inflector",
11
11
  proc { ::ActiveSupport::Inflector }
12
12
  ],
13
13
  dry_inflector: [
14
- 'dry/inflector',
14
+ "dry/inflector",
15
15
  proc { Dry::Inflector.new }
16
16
  ],
17
17
  inflecto: [
18
- 'inflecto',
18
+ "inflecto",
19
19
  proc { ::Inflecto }
20
20
  ]
21
21
  }.freeze
@@ -49,6 +49,7 @@ module Dry
49
49
  if name && !BACKENDS.key?(name)
50
50
  raise NameError, "Invalid inflector library selection: '#{name}'"
51
51
  end
52
+
52
53
  @inflector = name ? realize_backend(*BACKENDS[name]) : detect_backend
53
54
  end
54
55
 
@@ -1,69 +1,181 @@
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
6
8
  MEMOIZED_HASH = {}.freeze
7
9
 
8
10
  module ClassInterface
9
- def memoize(*names)
10
- prepend(Memoizer.new(self, names))
11
+ module Base
12
+ def memoize(*names)
13
+ prepend(Memoizer.new(self, names))
14
+ end
11
15
  end
12
16
 
13
- def new(*)
14
- obj = super
15
- obj.instance_variable_set(:'@__memoized__', MEMOIZED_HASH.dup)
16
- obj
17
+ module BasicObject
18
+ include Base
19
+
20
+ def new(*)
21
+ obj = super
22
+ obj.instance_eval { @__memoized__ = MEMOIZED_HASH.dup }
23
+ obj
24
+ end
25
+ end
26
+
27
+ module Object
28
+ include Base
29
+
30
+ def new(*)
31
+ obj = super
32
+ obj.instance_variable_set(:@__memoized__, MEMOIZED_HASH.dup)
33
+ obj
34
+ end
35
+
36
+ if respond_to?(:ruby2_keywords, true)
37
+ ruby2_keywords(:new)
38
+ end
17
39
  end
18
40
  end
19
41
 
20
42
  def self.included(klass)
21
43
  super
22
- klass.extend(ClassInterface)
23
- end
24
44
 
25
- attr_reader :__memoized__
45
+ if klass <= Object
46
+ klass.extend(ClassInterface::Object)
47
+ else
48
+ klass.extend(ClassInterface::BasicObject)
49
+ end
50
+ end
26
51
 
27
52
  # @api private
28
- class Memoizer < Module
29
- attr_reader :klass
30
- attr_reader :names
31
-
53
+ class Memoizer < ::Module
32
54
  # @api private
33
55
  def initialize(klass, names)
34
- @names = names
35
- @klass = klass
36
- define_memoizable_names!
56
+ super()
57
+ names.each do |name|
58
+ define_memoizable(
59
+ method: klass.instance_method(name)
60
+ )
61
+ end
37
62
  end
38
63
 
39
64
  private
40
65
 
41
66
  # @api private
42
- def define_memoizable_names!
43
- names.each do |name|
44
- meth = klass.instance_method(name)
45
-
46
- if meth.parameters.size > 0
47
- define_method(name) do |*args|
48
- name_with_args = :"#{name}_#{args.hash}"
67
+ def define_memoizable(method:)
68
+ parameters = method.parameters
49
69
 
50
- if __memoized__.key?(name_with_args)
51
- __memoized__[name_with_args]
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}]
52
76
  else
53
- __memoized__[name_with_args] = super(*args)
77
+ @__memoized__[#{key}] = super
54
78
  end
55
79
  end
56
- else
57
- define_method(name) do
58
- if __memoized__.key?(name)
59
- __memoized__[name]
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
92
+ end
93
+
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]
60
100
  else
61
- __memoized__[name] = super()
101
+ @__memoized__[key] = super
62
102
  end
63
103
  end
104
+ RUBY
105
+
106
+ if respond_to?(:ruby2_keywords, true) && mapping.key?(:reyrest)
107
+ ruby2_keywords(method.name)
64
108
  end
65
109
  end
66
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
130
+ end
131
+
132
+ [params, binds]
133
+ end
134
+
135
+ # @api private
136
+ def make_bind_name(idx)
137
+ :"__lv_#{idx}__"
138
+ end
139
+
140
+ # @api private
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
150
+ else
151
+ :rest
152
+ end
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
178
+ end
67
179
  end
68
180
  end
69
181
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Core
5
- VERSION = '0.4.8'.freeze
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  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.4.8
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikita Shilnikov
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-23 00:00:00.000000000 Z
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -42,48 +42,40 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '3.0'
69
- description: A toolset of small support modules used throughout the dry-rb ecosystem.
68
+ version: '0'
69
+ description: A toolset of small support modules used throughout the dry-rb ecosystem
70
70
  email:
71
71
  - fg@flashgordon.ru
72
72
  executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - ".codeclimate.yml"
77
- - ".gitignore"
78
- - ".inch.yml"
79
- - ".rspec"
80
- - ".travis.yml"
81
76
  - CHANGELOG.md
82
- - CONTRIBUTING.md
83
- - Gemfile
84
- - LICENSE.txt
77
+ - LICENSE
85
78
  - README.md
86
- - Rakefile
87
79
  - dry-core.gemspec
88
80
  - lib/dry-core.rb
89
81
  - lib/dry/core.rb
@@ -93,16 +85,20 @@ files:
93
85
  - lib/dry/core/constants.rb
94
86
  - lib/dry/core/deprecations.rb
95
87
  - lib/dry/core/descendants_tracker.rb
88
+ - lib/dry/core/equalizer.rb
96
89
  - lib/dry/core/errors.rb
97
90
  - lib/dry/core/extensions.rb
98
91
  - lib/dry/core/inflector.rb
99
92
  - lib/dry/core/memoizable.rb
100
93
  - lib/dry/core/version.rb
101
- homepage: https://github.com/dry-rb/dry-core
94
+ homepage: https://dry-rb.org/gems/dry-core
102
95
  licenses:
103
96
  - MIT
104
97
  metadata:
105
98
  allowed_push_host: https://rubygems.org
99
+ changelog_uri: https://github.com/dry-rb/dry-core/blob/master/CHANGELOG.md
100
+ source_code_uri: https://github.com/dry-rb/dry-core
101
+ bug_tracker_uri: https://github.com/dry-rb/dry-core/issues
106
102
  post_install_message:
107
103
  rdoc_options: []
108
104
  require_paths:
@@ -111,15 +107,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
107
  requirements:
112
108
  - - ">="
113
109
  - !ruby/object:Gem::Version
114
- version: 2.1.0
110
+ version: 2.6.0
115
111
  required_rubygems_version: !ruby/object:Gem::Requirement
116
112
  requirements:
117
113
  - - ">="
118
114
  - !ruby/object:Gem::Version
119
115
  version: '0'
120
116
  requirements: []
121
- rubygems_version: 3.0.3
117
+ rubygems_version: 3.1.6
122
118
  signing_key:
123
119
  specification_version: 4
124
- summary: A toolset of small support modules used throughout the dry-rb ecosystem.
120
+ summary: A toolset of small support modules used throughout the dry-rb ecosystem
125
121
  test_files: []
data/.codeclimate.yml DELETED
@@ -1,15 +0,0 @@
1
- version: "2"
2
-
3
- prepare:
4
- fetch:
5
- - url: "https://raw.githubusercontent.com/dry-rb/devtools/master/.rubocop.yml"
6
- path: ".rubocop.yml"
7
-
8
- exclude_patterns:
9
- - "benchmarks/"
10
- - "examples/"
11
- - "spec/"
12
-
13
- plugins:
14
- rubocop:
15
- enabled: true
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- spec/examples.txt
11
- .rubocop.yml
data/.inch.yml DELETED
@@ -1,4 +0,0 @@
1
- files:
2
- excluded:
3
- - lib/dry/core.rb
4
- - lib/dry/core/version.rb
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format progress
2
- --color
3
- --require ./spec/spec_helper.rb
data/.travis.yml DELETED
@@ -1,32 +0,0 @@
1
- language: ruby
2
- dist: trusty
3
- sudo: required
4
- cache: bundler
5
- bundler_args: --without benchmarks tools
6
- after_success:
7
- - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
8
- before_install:
9
- - gem install bundler
10
- after_success:
11
- - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
12
- rvm:
13
- - 2.4.6
14
- - 2.5.5
15
- - 2.6.3
16
- - jruby-9.2.7.0
17
- - truffleruby
18
- env:
19
- global:
20
- - COVERAGE=true
21
- - JRUBY_OPTS='--dev -J-Xmx1024M'
22
- matrix:
23
- allow_failures:
24
- - rvm: truffleruby
25
- notifications:
26
- email: false
27
- webhooks:
28
- urls:
29
- - https://webhooks.gitter.im/e/19098b4253a72c9796db
30
- on_success: change # options: [always|never|change] default: always
31
- on_failure: always # options: [always|never|change] default: always
32
- on_start: false # default: false