dry-types 1.1.0 → 1.3.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 +378 -206
- data/LICENSE +17 -17
- data/README.md +14 -13
- data/dry-types.gemspec +27 -31
- data/lib/dry/types.rb +7 -11
- data/lib/dry/types/any.rb +2 -2
- data/lib/dry/types/array/member.rb +3 -3
- data/lib/dry/types/builder.rb +5 -1
- data/lib/dry/types/builder_methods.rb +22 -8
- data/lib/dry/types/coercions.rb +6 -0
- data/lib/dry/types/coercions/params.rb +1 -1
- data/lib/dry/types/compiler.rb +2 -2
- data/lib/dry/types/constrained.rb +2 -2
- data/lib/dry/types/constructor.rb +7 -34
- data/lib/dry/types/constructor/function.rb +17 -31
- data/lib/dry/types/core.rb +3 -1
- data/lib/dry/types/decorator.rb +3 -9
- data/lib/dry/types/default.rb +2 -2
- data/lib/dry/types/enum.rb +2 -2
- data/lib/dry/types/errors.rb +5 -5
- data/lib/dry/types/extensions.rb +4 -0
- data/lib/dry/types/extensions/maybe.rb +14 -14
- data/lib/dry/types/extensions/monads.rb +29 -0
- data/lib/dry/types/hash.rb +3 -2
- data/lib/dry/types/lax.rb +2 -5
- data/lib/dry/types/meta.rb +3 -3
- data/lib/dry/types/module.rb +3 -3
- data/lib/dry/types/nominal.rb +1 -1
- data/lib/dry/types/params.rb +6 -0
- data/lib/dry/types/predicate_inferrer.rb +197 -0
- data/lib/dry/types/predicate_registry.rb +34 -0
- data/lib/dry/types/primitive_inferrer.rb +97 -0
- data/lib/dry/types/printer.rb +7 -3
- data/lib/dry/types/result.rb +2 -2
- data/lib/dry/types/schema.rb +23 -2
- data/lib/dry/types/schema/key.rb +16 -3
- data/lib/dry/types/spec/types.rb +14 -1
- data/lib/dry/types/sum.rb +5 -5
- data/lib/dry/types/version.rb +1 -1
- metadata +26 -45
- data/.codeclimate.yml +0 -15
- data/.gitignore +0 -11
- data/.rspec +0 -2
- data/.travis.yml +0 -27
- data/.yardopts +0 -9
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -27
- data/Rakefile +0 -22
- data/benchmarks/hash_schemas.rb +0 -55
- data/benchmarks/lax_schema.rb +0 -15
- data/benchmarks/profile_invalid_input.rb +0 -15
- data/benchmarks/profile_lax_schema_valid.rb +0 -16
- data/benchmarks/profile_valid_input.rb +0 -15
- data/benchmarks/schema_valid_vs_invalid.rb +0 -21
- data/benchmarks/setup.rb +0 -17
@@ -15,7 +15,7 @@ module Dry
|
|
15
15
|
class Safe < Function
|
16
16
|
def call(input, &block)
|
17
17
|
@fn.(input, &block)
|
18
|
-
rescue NoMethodError, TypeError, ArgumentError => e
|
18
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
|
19
19
|
CoercionError.handle(e, &block)
|
20
20
|
end
|
21
21
|
end
|
@@ -30,7 +30,7 @@ module Dry
|
|
30
30
|
#
|
31
31
|
# @return [Function]
|
32
32
|
def self.call_class(method, public, safe)
|
33
|
-
@cache.fetch_or_store([method, public, safe]
|
33
|
+
@cache.fetch_or_store([method, public, safe]) do
|
34
34
|
if public
|
35
35
|
::Class.new(PublicCall) do
|
36
36
|
include PublicCall.call_interface(method, safe)
|
@@ -53,7 +53,7 @@ module Dry
|
|
53
53
|
#
|
54
54
|
# @return [::Module]
|
55
55
|
def self.call_interface(method, safe)
|
56
|
-
@interfaces.fetch_or_store([method, safe]
|
56
|
+
@interfaces.fetch_or_store([method, safe]) do
|
57
57
|
::Module.new do
|
58
58
|
if safe
|
59
59
|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
@@ -65,7 +65,7 @@ module Dry
|
|
65
65
|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
66
66
|
def call(input, &block)
|
67
67
|
@target.#{method}(input)
|
68
|
-
rescue NoMethodError, TypeError, ArgumentError => error
|
68
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => error
|
69
69
|
CoercionError.handle(error, &block)
|
70
70
|
end
|
71
71
|
RUBY
|
@@ -90,7 +90,7 @@ module Dry
|
|
90
90
|
class PrivateSafeCall < PrivateCall
|
91
91
|
def call(input, &block)
|
92
92
|
@target.send(@name, input)
|
93
|
-
rescue NoMethodError, TypeError, ArgumentError => e
|
93
|
+
rescue ::NoMethodError, ::TypeError, ::ArgumentError => e
|
94
94
|
CoercionError.handle(e, &block)
|
95
95
|
end
|
96
96
|
end
|
@@ -121,7 +121,7 @@ module Dry
|
|
121
121
|
# @param [#call] fn
|
122
122
|
# @return [Function]
|
123
123
|
def self.[](fn)
|
124
|
-
raise ArgumentError, 'Missing constructor block' if fn.nil?
|
124
|
+
raise ::ArgumentError, 'Missing constructor block' if fn.nil?
|
125
125
|
|
126
126
|
if fn.is_a?(Function)
|
127
127
|
fn
|
@@ -146,7 +146,7 @@ module Dry
|
|
146
146
|
last_arg.equal?(:block)
|
147
147
|
end
|
148
148
|
|
149
|
-
include Dry::Equalizer(:fn)
|
149
|
+
include ::Dry::Equalizer(:fn, immutable: true)
|
150
150
|
|
151
151
|
attr_reader :fn
|
152
152
|
|
@@ -163,36 +163,22 @@ module Dry
|
|
163
163
|
# @return [Array]
|
164
164
|
def to_ast
|
165
165
|
if fn.is_a?(::Proc)
|
166
|
-
[:id,
|
166
|
+
[:id, FnContainer.register(fn)]
|
167
167
|
else
|
168
168
|
[:callable, fn]
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
-
|
179
|
-
# @return [Function]
|
180
|
-
def <<(other)
|
181
|
-
proc = other.is_a?(::Proc) ? other : other.fn
|
182
|
-
Function[@fn << proc]
|
183
|
-
end
|
184
|
-
else
|
185
|
-
# @return [Function]
|
186
|
-
def >>(other)
|
187
|
-
proc = other.is_a?(::Proc) ? other : other.fn
|
188
|
-
Function[-> x { proc[@fn[x]] }]
|
189
|
-
end
|
172
|
+
# @return [Function]
|
173
|
+
def >>(other)
|
174
|
+
f = Function[other]
|
175
|
+
Function[-> x, &b { f.(self.(x, &b), &b) }]
|
176
|
+
end
|
190
177
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
end
|
178
|
+
# @return [Function]
|
179
|
+
def <<(other)
|
180
|
+
f = Function[other]
|
181
|
+
Function[-> x, &b { self.(f.(x, &b), &b) }]
|
196
182
|
end
|
197
183
|
end
|
198
184
|
end
|
data/lib/dry/types/core.rb
CHANGED
@@ -72,7 +72,9 @@ module Dry
|
|
72
72
|
|
73
73
|
# Register optional strict {NON_NIL} types
|
74
74
|
NON_NIL.each_key do |name|
|
75
|
-
|
75
|
+
type = self[name.to_s].optional
|
76
|
+
register("optional.strict.#{name}", type)
|
77
|
+
register("optional.#{name}", type)
|
76
78
|
end
|
77
79
|
|
78
80
|
# Register optional {COERCIBLE} types
|
data/lib/dry/types/decorator.rb
CHANGED
@@ -14,7 +14,7 @@ module Dry
|
|
14
14
|
attr_reader :type
|
15
15
|
|
16
16
|
# @param [Type] type
|
17
|
-
def initialize(type,
|
17
|
+
def initialize(type, *, **)
|
18
18
|
super
|
19
19
|
@type = type
|
20
20
|
end
|
@@ -44,13 +44,6 @@ module Dry
|
|
44
44
|
type.constrained?
|
45
45
|
end
|
46
46
|
|
47
|
-
# @return [Sum]
|
48
|
-
#
|
49
|
-
# @api public
|
50
|
-
def optional
|
51
|
-
Types['strict.nil'] | self
|
52
|
-
end
|
53
|
-
|
54
47
|
# @param [Symbol] meth
|
55
48
|
# @param [Boolean] include_private
|
56
49
|
#
|
@@ -90,7 +83,7 @@ module Dry
|
|
90
83
|
# @api private
|
91
84
|
def method_missing(meth, *args, &block)
|
92
85
|
if type.respond_to?(meth)
|
93
|
-
response = type.
|
86
|
+
response = type.public_send(meth, *args, &block)
|
94
87
|
|
95
88
|
if decorate?(response)
|
96
89
|
__new__(response)
|
@@ -101,6 +94,7 @@ module Dry
|
|
101
94
|
super
|
102
95
|
end
|
103
96
|
end
|
97
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
104
98
|
|
105
99
|
# Replace underlying type
|
106
100
|
#
|
data/lib/dry/types/default.rb
CHANGED
@@ -10,7 +10,7 @@ module Dry
|
|
10
10
|
class Default
|
11
11
|
# @api private
|
12
12
|
class Callable < Default
|
13
|
-
include Dry::Equalizer(:type, inspect: false)
|
13
|
+
include Dry::Equalizer(:type, inspect: false, immutable: true)
|
14
14
|
|
15
15
|
# Evaluates given callable
|
16
16
|
# @return [Object]
|
@@ -23,7 +23,7 @@ module Dry
|
|
23
23
|
include Decorator
|
24
24
|
include Builder
|
25
25
|
include Printable
|
26
|
-
include Dry::Equalizer(:type, :value, inspect: false)
|
26
|
+
include Dry::Equalizer(:type, :value, inspect: false, immutable: true)
|
27
27
|
|
28
28
|
# @return [Object]
|
29
29
|
attr_reader :value
|
data/lib/dry/types/enum.rb
CHANGED
@@ -9,7 +9,7 @@ module Dry
|
|
9
9
|
# @api public
|
10
10
|
class Enum
|
11
11
|
include Type
|
12
|
-
include Dry::Equalizer(:type, :mapping, inspect: false)
|
12
|
+
include Dry::Equalizer(:type, :mapping, inspect: false, immutable: true)
|
13
13
|
include Decorator
|
14
14
|
include Builder
|
15
15
|
|
@@ -27,7 +27,7 @@ module Dry
|
|
27
27
|
# @option options [Array] :values
|
28
28
|
#
|
29
29
|
# @api private
|
30
|
-
def initialize(type, options)
|
30
|
+
def initialize(type, **options)
|
31
31
|
super
|
32
32
|
@mapping = options.fetch(:mapping).freeze
|
33
33
|
@values = @mapping.keys.freeze
|
data/lib/dry/types/errors.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Dry
|
4
4
|
module Types
|
5
|
-
extend Dry::Core::ClassAttributes
|
5
|
+
extend ::Dry::Core::ClassAttributes
|
6
6
|
|
7
7
|
# @!attribute [r] namespace
|
8
8
|
# @return [Container{String => Nominal}]
|
@@ -12,7 +12,7 @@ module Dry
|
|
12
12
|
|
13
13
|
# Base class for coercion errors raise by dry-types
|
14
14
|
#
|
15
|
-
class CoercionError < StandardError
|
15
|
+
class CoercionError < ::StandardError
|
16
16
|
# @api private
|
17
17
|
def self.handle(exception, meta: Undefined)
|
18
18
|
if block_given?
|
@@ -34,7 +34,7 @@ module Dry
|
|
34
34
|
# @api private
|
35
35
|
def initialize(message, meta: Undefined, backtrace: Undefined)
|
36
36
|
unless message.is_a?(::String)
|
37
|
-
raise ArgumentError, "message must be a string, #{message.class} given"
|
37
|
+
raise ::ArgumentError, "message must be a string, #{message.class} given"
|
38
38
|
end
|
39
39
|
|
40
40
|
super(message)
|
@@ -74,9 +74,9 @@ module Dry
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
MapError = Class.new(CoercionError)
|
77
|
+
MapError = ::Class.new(CoercionError)
|
78
78
|
|
79
|
-
SchemaKeyError = Class.new(CoercionError)
|
79
|
+
SchemaKeyError = ::Class.new(CoercionError)
|
80
80
|
private_constant(:SchemaKeyError)
|
81
81
|
|
82
82
|
class MissingKeyError < SchemaKeyError
|
data/lib/dry/types/extensions.rb
CHANGED
@@ -10,11 +10,11 @@ module Dry
|
|
10
10
|
# @api public
|
11
11
|
class Maybe
|
12
12
|
include Type
|
13
|
-
include Dry::Equalizer(:type, :options, inspect: false)
|
13
|
+
include ::Dry::Equalizer(:type, :options, inspect: false, immutable: true)
|
14
14
|
include Decorator
|
15
15
|
include Builder
|
16
16
|
include Printable
|
17
|
-
include Dry::Monads::Maybe::Mixin
|
17
|
+
include ::Dry::Monads::Maybe::Mixin
|
18
18
|
|
19
19
|
# @param [Dry::Monads::Maybe, Object] input
|
20
20
|
#
|
@@ -23,7 +23,7 @@ module Dry
|
|
23
23
|
# @api private
|
24
24
|
def call_unsafe(input = Undefined)
|
25
25
|
case input
|
26
|
-
when Dry::Monads::Maybe
|
26
|
+
when ::Dry::Monads::Maybe
|
27
27
|
input
|
28
28
|
when Undefined
|
29
29
|
None()
|
@@ -37,14 +37,14 @@ module Dry
|
|
37
37
|
# @return [Dry::Monads::Maybe]
|
38
38
|
#
|
39
39
|
# @api private
|
40
|
-
def call_safe(input = Undefined
|
40
|
+
def call_safe(input = Undefined)
|
41
41
|
case input
|
42
|
-
when Dry::Monads::Maybe
|
42
|
+
when ::Dry::Monads::Maybe
|
43
43
|
input
|
44
44
|
when Undefined
|
45
45
|
None()
|
46
46
|
else
|
47
|
-
Maybe(type.call_safe(input
|
47
|
+
Maybe(type.call_safe(input) { |output = input| return yield(output) })
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -54,13 +54,13 @@ module Dry
|
|
54
54
|
#
|
55
55
|
# @api public
|
56
56
|
def try(input = Undefined)
|
57
|
-
|
58
|
-
None()
|
59
|
-
else
|
60
|
-
Maybe(type[input])
|
61
|
-
end
|
57
|
+
result = type.try(input)
|
62
58
|
|
63
|
-
|
59
|
+
if result.success?
|
60
|
+
Result::Success.new(Maybe(result.input))
|
61
|
+
else
|
62
|
+
result
|
63
|
+
end
|
64
64
|
end
|
65
65
|
|
66
66
|
# @return [true]
|
@@ -93,7 +93,7 @@ module Dry
|
|
93
93
|
#
|
94
94
|
# @api public
|
95
95
|
def maybe
|
96
|
-
Maybe.new(Types['
|
96
|
+
Maybe.new(Types['nil'] | self)
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
@@ -119,7 +119,7 @@ module Dry
|
|
119
119
|
|
120
120
|
# Register non-coercible maybe types
|
121
121
|
NON_NIL.each_key do |name|
|
122
|
-
register("maybe.strict.#{name}", self[
|
122
|
+
register("maybe.strict.#{name}", self[name.to_s].maybe)
|
123
123
|
end
|
124
124
|
|
125
125
|
# Register coercible maybe types
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/monads/result'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Types
|
7
|
+
# Monad extension for Result
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class Result
|
11
|
+
include Dry::Monads::Result::Mixin
|
12
|
+
|
13
|
+
# Turn result into a monad
|
14
|
+
#
|
15
|
+
# This makes result objects work with dry-monads (or anything with a compatible interface)
|
16
|
+
#
|
17
|
+
# @return [Dry::Monads::Success,Dry::Monads::Failure]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
def to_monad
|
21
|
+
if success?
|
22
|
+
Success(input)
|
23
|
+
else
|
24
|
+
Failure([error, input])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/dry/types/hash.rb
CHANGED
@@ -113,7 +113,7 @@ module Dry
|
|
113
113
|
|
114
114
|
type_map.map do |map_key, type|
|
115
115
|
name, options = key_name(map_key)
|
116
|
-
key = Schema::Key.new(resolve_type(type), name, options)
|
116
|
+
key = Schema::Key.new(resolve_type(type), name, **options)
|
117
117
|
type_transform.(key)
|
118
118
|
end
|
119
119
|
end
|
@@ -121,7 +121,8 @@ module Dry
|
|
121
121
|
# @api private
|
122
122
|
def resolve_type(type)
|
123
123
|
case type
|
124
|
-
when
|
124
|
+
when Type then type
|
125
|
+
when ::Class, ::String then Types[type]
|
125
126
|
else type
|
126
127
|
end
|
127
128
|
end
|
data/lib/dry/types/lax.rb
CHANGED
@@ -13,9 +13,9 @@ module Dry
|
|
13
13
|
include Decorator
|
14
14
|
include Builder
|
15
15
|
include Printable
|
16
|
-
include Dry::Equalizer(:type, inspect: false)
|
16
|
+
include Dry::Equalizer(:type, inspect: false, immutable: true)
|
17
17
|
|
18
|
-
|
18
|
+
undef :options, :constructor, :<<, :>>, :prepend, :append
|
19
19
|
|
20
20
|
# @param [Object] input
|
21
21
|
#
|
@@ -40,9 +40,6 @@ module Dry
|
|
40
40
|
# @api public
|
41
41
|
def try(input, &block)
|
42
42
|
type.try(input, &block)
|
43
|
-
rescue CoercionError => e
|
44
|
-
result = failure(input, e.message)
|
45
|
-
block ? yield(result) : result
|
46
43
|
end
|
47
44
|
|
48
45
|
# @see Nominal#to_ast
|
data/lib/dry/types/meta.rb
CHANGED
@@ -16,7 +16,7 @@ module Dry
|
|
16
16
|
# @return [Type]
|
17
17
|
#
|
18
18
|
# @api public
|
19
|
-
def with(options)
|
19
|
+
def with(**options)
|
20
20
|
super(meta: @meta, **options)
|
21
21
|
end
|
22
22
|
|
@@ -28,8 +28,8 @@ module Dry
|
|
28
28
|
# @return [Type] new type with added metadata
|
29
29
|
#
|
30
30
|
# @api public
|
31
|
-
def meta(data =
|
32
|
-
if
|
31
|
+
def meta(data = Undefined)
|
32
|
+
if Undefined.equal?(data)
|
33
33
|
@meta
|
34
34
|
elsif data.empty?
|
35
35
|
self
|
data/lib/dry/types/module.rb
CHANGED
@@ -18,10 +18,10 @@ module Dry
|
|
18
18
|
#
|
19
19
|
# @api public
|
20
20
|
class Module < ::Module
|
21
|
-
def initialize(registry, *args)
|
21
|
+
def initialize(registry, *args, **kwargs)
|
22
22
|
@registry = registry
|
23
|
-
check_parameters(*args)
|
24
|
-
constants = type_constants(*args)
|
23
|
+
check_parameters(*args, **kwargs)
|
24
|
+
constants = type_constants(*args, **kwargs)
|
25
25
|
define_constants(constants)
|
26
26
|
extend(BuilderMethods)
|
27
27
|
|
data/lib/dry/types/nominal.rb
CHANGED
@@ -19,7 +19,7 @@ module Dry
|
|
19
19
|
include Meta
|
20
20
|
include Builder
|
21
21
|
include Printable
|
22
|
-
include Dry::Equalizer(:primitive, :options, :meta, inspect: false)
|
22
|
+
include Dry::Equalizer(:primitive, :options, :meta, inspect: false, immutable: true)
|
23
23
|
|
24
24
|
# @return [Class]
|
25
25
|
attr_reader :primitive
|
data/lib/dry/types/params.rb
CHANGED
@@ -55,5 +55,11 @@ module Dry
|
|
55
55
|
register('params.symbol') do
|
56
56
|
self['nominal.symbol'].constructor(Coercions::Params.method(:to_symbol))
|
57
57
|
end
|
58
|
+
|
59
|
+
COERCIBLE.each_key do |name|
|
60
|
+
next if name.equal?(:string)
|
61
|
+
|
62
|
+
register("optional.params.#{name}", self['params.nil'] | self["params.#{name}"])
|
63
|
+
end
|
58
64
|
end
|
59
65
|
end
|