remap 2.2.46 → 2.2.47

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71b1a0f8a9cb714d568939ace38b13d053e4c1ddf9131a6040630ff4a1479e4a
4
- data.tar.gz: fe768a12f868c085839145d28a609a707c4aacb10a18c16e2276e51b23de0fb5
3
+ metadata.gz: d745b7e030764a548c8cb8b2651e89cf22485154120bab89053743653d0ccd9a
4
+ data.tar.gz: '04408f1457593d3c2f3fb8fc5d52f275b74e9d3f0eb31a4088d073ee93ddeeb6'
5
5
  SHA512:
6
- metadata.gz: 2f5f657a29f997cf1161eda204a2ddd38f1c6dcc991c8467732d367bc31302c7bafd1e05f5a7655cc5ef46dea5498b9caec6fb9d75d2bd1e9aa5c7f34f7a8ec9
7
- data.tar.gz: 9263defd99a669a7bcee25381df7a74698cb2ab691b5a2cf22e7cfdb83a8898956b1a17e329e7560e920ad762093822b85c40587dd6bdcf77ab2433188857474
6
+ metadata.gz: 2fb3e7f89ed0dea90a33a33dee5f5a5b358f22de24b24a64e531a7a84196da067e621060ab21045efb810c02cc8af0f53e7ca43d36ddad3124fb1a2212973a81
7
+ data.tar.gz: ad67a4ec14390748e9df5d77f8093c44143ae63df023a5ea84434ab79f7c5a894f1df0cdf7b3ce38b19fea44668b19ba269b3185d18d6deaa435a4620f1a733f
data/lib/remap/base.rb CHANGED
@@ -105,6 +105,7 @@ module Remap
105
105
  # Mapper.call([1, 2, 3]) # => 2
106
106
  class Base < Mapper
107
107
  include ActiveSupport::Configurable
108
+ include Dry::Core::Memoizable
108
109
  include Dry::Core::Constants
109
110
  include Catchable
110
111
  extend Mapper::API
@@ -239,7 +240,7 @@ module Remap
239
240
  # @return [void]
240
241
  # rubocop:disable Layout/LineLength
241
242
  def self.define(target = Nothing, method: :new, strategy: :argument, backtrace: caller, &context)
242
- unless block_given?
243
+ unless context
243
244
  raise ArgumentError, "#{self}.define requires a block"
244
245
  end
245
246
 
@@ -318,5 +319,7 @@ module Remap
318
319
  def validation
319
320
  Contract.call(attributes: attributes, contract: contract, options: options, rules: rules)
320
321
  end
322
+
323
+ memoize :validation
321
324
  end
322
325
  end
@@ -32,7 +32,7 @@ module Remap
32
32
  #
33
33
  # @return [Rule]
34
34
  def self.call(backtrace: caller, &block)
35
- unless block_given?
35
+ unless block
36
36
  return Rule::VOID
37
37
  end
38
38
 
@@ -317,7 +317,7 @@ module Remap
317
317
  # @return [Rule::Each]]
318
318
  # @raise [ArgumentError] if no block given
319
319
  def each(backtrace: caller, &block)
320
- unless block_given?
320
+ unless block
321
321
  raise ArgumentError, "#each requires a block"
322
322
  end
323
323
 
@@ -350,7 +350,7 @@ module Remap
350
350
  # @return [Rule::Wrap]
351
351
  # @raise [ArgumentError] if type is not :array
352
352
  def wrap(type, backtrace: caller, &block)
353
- unless block_given?
353
+ unless block
354
354
  raise ArgumentError, "#wrap requires a block"
355
355
  end
356
356
 
@@ -33,15 +33,13 @@ module Remap
33
33
 
34
34
  key = path.first
35
35
 
36
- unless block_given?
36
+ unless fallback
37
37
  return get(*path, trace: trace) do
38
- raise PathError, trace + [key]
38
+ throw :ignore, trace + [key]
39
39
  end
40
40
  end
41
41
 
42
42
  fetch(key, &fallback).get(*path[1..], trace: trace + [key], &fallback)
43
- rescue TypeError
44
- raise PathError, trace + [key]
45
43
  end
46
44
  end
47
45
  end
@@ -38,9 +38,9 @@ module Remap
38
38
  def get(*path, trace: [], &fallback)
39
39
  return self if path.empty?
40
40
 
41
- unless block_given?
41
+ unless fallback
42
42
  return get(*path, trace: trace) do
43
- raise PathError, trace
43
+ throw :ignore, trace + path
44
44
  end
45
45
  end
46
46
 
data/lib/remap/failure.rb CHANGED
@@ -17,7 +17,7 @@ module Remap
17
17
  ]
18
18
  end
19
19
 
20
- failure = attributes.deep_merge(other.attributes) do |key, value1, value2|
20
+ failure = attributes.merge(other.attributes) do |key, value1, value2|
21
21
  case [key, value1, value2]
22
22
  in [:failures | :notices, Array, Array]
23
23
  value1 + value2
@@ -22,7 +22,7 @@ module Remap
22
22
  #
23
23
  # @return [Any, T]
24
24
  def call(input, backtrace: caller, **options, &error)
25
- unless block_given?
25
+ unless error
26
26
  return call(input, **options) do |failure|
27
27
  raise failure.exception(backtrace)
28
28
  end
@@ -25,7 +25,7 @@ module Remap
25
25
  #
26
26
  # @return [State]
27
27
  def call(state, &iterator)
28
- unless block_given?
28
+ unless iterator
29
29
  raise ArgumentError, "Input path requires an iterator block"
30
30
  end
31
31
 
@@ -26,8 +26,11 @@ module Remap
26
26
  s2 = state.set(fatal_id: fatal_id)
27
27
 
28
28
  catch_ignored(s1) do |s3, id:|
29
- rules.reduce(s3) do |s4, rule|
30
- s5 = rule.call(s2)
29
+ states = rules.map do |rule|
30
+ rule.call(s2)
31
+ end
32
+
33
+ states.reduce(s3) do |s4, s5|
31
34
  s6 = s5.set(id: id)
32
35
  s4.combine(s6)
33
36
  end
@@ -4,13 +4,9 @@ module Remap
4
4
  class Rule
5
5
  class Map
6
6
  class Enum < Proxy
7
- include Dry::Monads[:maybe]
8
-
9
7
  # @return [Hash]
10
- option :mappings, default: -> { Hash.new { default } }
11
-
12
- # @return [Maybe]
13
- option :default, default: -> { None() }
8
+ option :table, default: -> { {} }
9
+ option :default, default: -> { Undefined }
14
10
 
15
11
  alias execute instance_eval
16
12
 
@@ -37,7 +33,7 @@ module Remap
37
33
  new.tap { _1.execute(&block) }
38
34
  end
39
35
 
40
- # Translates key into a value using predefined mappings
36
+ # Translates key into a value using predefined table
41
37
  #
42
38
  # @param key [#hash]
43
39
  #
@@ -50,24 +46,21 @@ module Remap
50
46
  return get(key) { raise Error, _1 }
51
47
  end
52
48
 
53
- self[key].bind { return _1 }.or do
54
- error["Enum key [#{key}] not found among [#{mappings.keys.inspect}]"]
49
+ table.fetch(key) do
50
+ unless default == Undefined
51
+ return default
52
+ end
53
+
54
+ error["Enum key [#{key}] not found among [#{table.keys.inspect}]"]
55
55
  end
56
56
  end
57
57
  alias call get
58
58
 
59
- # @return [Maybe]
60
- def [](key)
61
- mappings[key]
62
- end
63
-
64
59
  # @return [void]
65
60
  def from(*keys, to:)
66
- value = Some(to)
67
-
68
61
  keys.each do |key|
69
- mappings[key] = value
70
- mappings[to] = value
62
+ table[key] = to
63
+ table[to] = to
71
64
  end
72
65
  end
73
66
 
@@ -80,7 +73,7 @@ module Remap
80
73
 
81
74
  # @return [void]
82
75
  def otherwise(value)
83
- mappings.default = Some(value)
76
+ @default = value
84
77
  end
85
78
  end
86
79
  end
@@ -26,7 +26,7 @@ module Remap
26
26
  #
27
27
  # @return [State<U>]
28
28
  def call(outer_state, &block)
29
- unless block_given?
29
+ unless block
30
30
  raise ArgumentError, "All selector requires an iteration block"
31
31
  end
32
32
 
@@ -31,7 +31,7 @@ module Remap
31
31
  #
32
32
  # @return [State<U>]
33
33
  def call(state, &block)
34
- unless block_given?
34
+ unless block
35
35
  raise ArgumentError, "The index selector requires an iteration block"
36
36
  end
37
37
 
@@ -28,7 +28,7 @@ module Remap
28
28
  #
29
29
  # @return [State<U>]
30
30
  def call(state, &block)
31
- unless block_given?
31
+ unless block
32
32
  raise ArgumentError, "The key selector requires an iteration block"
33
33
  end
34
34
 
@@ -46,11 +46,7 @@ module Remap
46
46
  # @returns [Hash] a hash containing the given path
47
47
  # @raise Europace::Error when path doesn't exist
48
48
  def only(*path)
49
- path.reduce(EMPTY_HASH) do |hash, key|
50
- next hash unless key?(key)
51
-
52
- hash.deep_merge(key => fetch(key))
53
- end
49
+ dup.extract!(*path)
54
50
  end
55
51
 
56
52
  # @see #notice
@@ -112,11 +108,30 @@ module Remap
112
108
  #
113
109
  # @return [State]
114
110
  def map(&block)
115
- bind do |value, state|
116
- Iteration.call(state: state, value: value).call do |other, **options|
117
- state.set(other, **options).then(&block)
118
- end.except(:index, :element, :key)
111
+ result = case self
112
+ in { value: Array => array }
113
+ array.each_with_index.each_with_object([]) do |(value, index), array|
114
+ s1 = block[set(value, index: index)]
115
+
116
+ if s1.key?(:value)
117
+ array << s1[:value]
118
+ end
119
+ end
120
+ in { value: Hash => hash }
121
+ hash.each_with_object({}) do |(key, value), acc|
122
+ s1 = block[set(value, key: key)]
123
+
124
+ if s1.key?(:value)
125
+ acc[key] = s1[:value]
126
+ end
127
+ end
128
+ in { value: }
129
+ fatal!("Expected an enumerable got %s", value.class)
130
+ else
131
+ return self
119
132
  end
133
+
134
+ set(result)
120
135
  end
121
136
 
122
137
  # @return [String]
@@ -130,10 +145,14 @@ module Remap
130
145
  #
131
146
  # @return [State]
132
147
  def combine(other)
133
- deep_merge(other) do |key, value1, value2|
148
+ merge(other) do |key, value1, value2|
134
149
  case [key, value1, value2]
135
- in [:value, Array => list1, Array => list2]
136
- list1 + list2
150
+ in [_, Hash => left, Hash => right]
151
+ left.merge(right)
152
+ in [:ids | :fatal_ids, _, right]
153
+ right
154
+ in [_, Array => left, Array => right]
155
+ left + right
137
156
  in [:value, left, right]
138
157
  other.fatal!(
139
158
  "Could not merge [%s] (%s) with [%s] (%s)",
@@ -142,15 +161,6 @@ module Remap
142
161
  right.formatted,
143
162
  right.class
144
163
  )
145
- in [:notices, Array => n1, Array => n2]
146
- n1 + n2
147
- in [:ids, i1, i2] if i1.all? { i2.include?(_1) }
148
- i2
149
- in [:ids, i1, i2] if i2.all? { i1.include?(_1) }
150
- i1
151
- in [:ids, i1, i2]
152
- other.fatal!("Could not merge #ids [%s] (%s) with [%s] (%s)", i1, i1.class, i2,
153
- i2.class)
154
164
  in [Symbol, _, value]
155
165
  value
156
166
  end
@@ -160,31 +170,39 @@ module Remap
160
170
  # @todo Merge with {#remove_fatal_id}
161
171
  # @return [State]
162
172
  def remove_id
163
- case self
173
+ state = dup
174
+
175
+ case state
164
176
  in { ids: [], id: }
165
- except(:id)
177
+ state.except!(:id)
166
178
  in { ids:, id: }
167
- merge(ids: ids[1...], id: ids[0])
179
+ state.merge!(ids: ids[1...], id: ids[0])
168
180
  in { ids: [] }
169
- self
181
+ state
170
182
  in { ids: }
171
183
  raise ArgumentError, "[BUG] #ids for state are set, but not #id: %s" % formatted
172
- end._
184
+ end
185
+
186
+ state
173
187
  end
174
188
 
175
189
  # @todo Merge with {#remove_id}
176
190
  # @return [State]
177
191
  def remove_fatal_id
178
- case self
192
+ state = dup
193
+
194
+ case state
179
195
  in { fatal_ids: [], fatal_id: }
180
- except(:fatal_id)
181
- in { fatal_ids: ids, fatal_id: id }
182
- merge(fatal_ids: ids[1...], fatal_id: ids[0])
196
+ state.except!(:fatal_id)
197
+ in { fatal_ids: ids, fatal_id: }
198
+ state.merge!(fatal_ids: ids[1...], fatal_id: ids[0])
183
199
  in { fatal_ids: [] }
184
- self
200
+ state
185
201
  in { fatal_ids: }
186
202
  raise ArgumentError, "[BUG] #ids for state are set, but not #id: %s" % formatted
187
- end._
203
+ end
204
+
205
+ state
188
206
  end
189
207
 
190
208
  # Creates a new state with params
@@ -198,24 +216,30 @@ module Remap
198
216
  return set(**options, value: value)
199
217
  end
200
218
 
201
- case [self, options]
202
- in [{notices:}, {notice: notice, **rest}]
203
- merge(notices: notices + [notice]).set(**rest)
204
- in [{value:}, {mapper:, **rest}]
205
- merge(scope: value, mapper: mapper).set(**rest)
206
- in [{path:}, {key:, **rest}]
207
- merge(path: path + [key], key: key).set(**rest)
208
- in [{path:}, {index:, value:, **rest}]
209
- merge(path: path + [index], element: value, index: index, value: value).set(**rest)
210
- in [{path:}, {index:, **rest}]
211
- merge(path: path + [index], index: index).set(**rest)
212
- in [{ids:, id: old_id}, {id: new_id, **rest}]
213
- merge(ids: [old_id] + ids, id: new_id).set(**rest)
214
- in [{fatal_ids:, fatal_id: old_id}, {fatal_id: new_id, **rest}]
215
- merge(fatal_ids: [old_id] + fatal_ids, fatal_id: new_id).set(**rest)
219
+ state = dup
220
+
221
+ case [state, options]
222
+ in [{notices:}, {notice: notice}]
223
+ state.merge!(notices: notices + [notice])
224
+ in [{value:}, {mapper:}]
225
+ state.merge!(scope: value, mapper: mapper)
226
+ in [{path:}, {key:, value:}]
227
+ state.merge!(path: path + [key], key: key, value: value)
228
+ in [{path:}, {key:}]
229
+ state.merge!(path: path + [key], key: key)
230
+ in [{path:}, {index:, value:}]
231
+ state.merge!(path: path + [index], element: value, index: index, value: value)
232
+ in [{path:}, {index:}]
233
+ state.merge!(path: path + [index], index: index)
234
+ in [{ids:, id: old_id}, {id: new_id}]
235
+ state.merge!(ids: [old_id] + ids, id: new_id)
236
+ in [{fatal_ids:, fatal_id: old_id}, {fatal_id: new_id}]
237
+ state.merge!(fatal_ids: [old_id] + fatal_ids, fatal_id: new_id)
216
238
  else
217
- merge(options)
239
+ state.merge!(options)
218
240
  end
241
+
242
+ state
219
243
  end
220
244
 
221
245
  # Passes {#value} to block, if defined
@@ -235,22 +259,6 @@ module Remap
235
259
  end
236
260
  end
237
261
 
238
- # Creates a failure to be used in {Remap::Base} & {Remap::Mapper}
239
- #
240
- # @param reason [#to_s]
241
- #
242
- # @see State::Schema
243
- #
244
- # @return [Failure]
245
-
246
- # class Failure < Dry::Interface
247
- # attribute :notices, [Notice], min_size: 1
248
- # end
249
-
250
- def failure(reason = Undefined)
251
- raise NotImplementedError, "Not implemented"
252
- end
253
-
254
262
  # Passes {#value} to block, if defined
255
263
  # {options} are combine into the final state
256
264
  #
@@ -262,7 +270,7 @@ module Remap
262
270
  #
263
271
  # @return [Y]
264
272
  def bind(**options, &block)
265
- unless block_given?
273
+ unless block
266
274
  raise ArgumentError, "State#bind requires a block"
267
275
  end
268
276
 
@@ -282,19 +290,23 @@ module Remap
282
290
  # @return [State<U>]
283
291
  def execute(&block)
284
292
  bind do |value|
285
- result = context(value).instance_exec(value, &block)
293
+ result = catch :done do
294
+ tail_path = catch :ignore do
295
+ throw :done, context(value).instance_exec(value, &block)
296
+ rescue KeyError => e
297
+ [e.key]
298
+ rescue IndexError
299
+ []
300
+ end
301
+
302
+ set(path: path + tail_path).ignore!("Undefined path")
303
+ end
286
304
 
287
305
  if result.equal?(Dry::Core::Constants::Undefined)
288
306
  ignore!("Undefined returned, skipping!")
289
307
  end
290
308
 
291
309
  set(result)
292
- rescue KeyError => e
293
- set(path: path + [e.key]).ignore!(e.message)
294
- rescue IndexError => e
295
- ignore!(e.message)
296
- rescue PathError => e
297
- set(path: path + e.path).ignore!("Undefined path")
298
310
  end
299
311
  end
300
312
 
data/lib/remap/state.rb CHANGED
@@ -31,11 +31,11 @@ module Remap
31
31
  # @return [Hash] A valid state
32
32
  def self.call(value, mapper: Dummy, options: EMPTY_HASH)
33
33
  {
34
- fatal_ids: EMPTY_ARRAY,
35
- notices: EMPTY_ARRAY,
36
- path: EMPTY_ARRAY,
34
+ fatal_ids: [],
35
+ notices: [],
36
+ path: [],
37
37
  options: options,
38
- ids: EMPTY_ARRAY,
38
+ ids: [],
39
39
  mapper: mapper,
40
40
  values: value,
41
41
  value: value,
data/lib/remap/types.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/monads/maybe"
4
3
  require "dry/logic/operations/negation"
5
4
  require "dry/logic"
6
5
 
data/lib/remap.rb CHANGED
@@ -5,11 +5,11 @@ require "active_support/core_ext/enumerable"
5
5
  require "active_support/core_ext/array/wrap"
6
6
  require "active_support/proxy_object"
7
7
 
8
+ require "dry/core/memoizable"
8
9
  require "dry/validation"
9
10
  require "dry/interface"
10
11
  require "dry/schema"
11
12
  require "dry/struct"
12
- require "dry/monads"
13
13
  require "dry/types"
14
14
 
15
15
  require "neatjson"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remap
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.46
4
+ version: 2.2.47
5
5
  platform: ruby
6
6
  authors:
7
7
  - Linus Oleander
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.0.3
69
- - !ruby/object:Gem::Dependency
70
- name: dry-monads
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 1.4.0
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 1.4.0
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: dry-schema
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -264,10 +250,6 @@ files:
264
250
  - lib/remap/extensions/object.rb
265
251
  - lib/remap/failure.rb
266
252
  - lib/remap/failure/error.rb
267
- - lib/remap/iteration.rb
268
- - lib/remap/iteration/array.rb
269
- - lib/remap/iteration/hash.rb
270
- - lib/remap/iteration/other.rb
271
253
  - lib/remap/mapper.rb
272
254
  - lib/remap/mapper/and.rb
273
255
  - lib/remap/mapper/binary.rb
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Iteration
5
- using State::Extension
6
-
7
- # Implements an array iterator which defines index in state
8
- class Array < Concrete
9
- # @return [Array<T>]
10
- attribute :value, Types::Array, alias: :array
11
-
12
- # @return [State<Array<T>>]
13
- attribute :state, Types::State
14
-
15
- # @see Iteration#map
16
- def call(&block)
17
- array.each_with_index.reduce(init) do |state, (value, index)|
18
- reduce(state, value, index, &block)
19
- end
20
- end
21
-
22
- private
23
-
24
- def init
25
- state.set(EMPTY_ARRAY)
26
- end
27
-
28
- def reduce(state, value, index, &block)
29
- s0 = block[value, index: index]
30
- s1 = s0.set(**state.only(:ids, :fatal_id))
31
- state.combine(s1.fmap { [_1] })
32
- end
33
- end
34
- end
35
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Iteration
5
- using State::Extension
6
-
7
- # Implements a hash iterator which defines key in state
8
- class Hash < Concrete
9
- # @return [Hash]
10
- attribute :value, Types::Hash, alias: :hash
11
-
12
- # @return [State<Hash>]
13
- attribute :state, Types::State
14
-
15
- # @see Iteration#map
16
- def call(&block)
17
- hash.reduce(init) do |state, (key, value)|
18
- reduce(state, key, value, &block)
19
- end
20
- end
21
-
22
- private
23
-
24
- def reduce(state, key, value, &block)
25
- s0 = block[value, key: key]
26
- s1 = s0.set(fatal_id: state.fatal_id, ids: state.ids)
27
- state.combine(s1.fmap { { key => _1 } })
28
- end
29
-
30
- def init
31
- state.set(EMPTY_HASH)
32
- end
33
- end
34
- end
35
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Iteration
5
- using State::Extension
6
-
7
- # Default iterator which doesn't do anything
8
- class Other < Concrete
9
- attribute :value, Types::Any, alias: :other
10
- attribute :state, Types::State
11
-
12
- # @see Iteration#map
13
- def call(&block)
14
- state.fatal!("Expected an enumerable")
15
- end
16
- end
17
- end
18
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Iteration < Dry::Interface
5
- # @return [State<T>]
6
- attribute :state, Types::State
7
-
8
- # @return [T]
9
- attribute :value, Types::Any
10
-
11
- # Maps every element in {#value}
12
- #
13
- # @abstract
14
- #
15
- # @yieldparam element [V]
16
- # @yieldparam key [K, Integer]
17
- # @yieldreturn [Array<V>, Hash<V, K>]
18
- #
19
- # @return [Array<V>, Hash<V, K>]
20
- def call(state)
21
- raise NotImplementedError, "#{self.class}#call not implemented"
22
- end
23
-
24
- order :Hash, :Array, :Other
25
- end
26
- end