dry-types 1.2.2 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +405 -225
  3. data/LICENSE +1 -1
  4. data/README.md +14 -12
  5. data/dry-types.gemspec +26 -31
  6. data/lib/dry-types.rb +1 -1
  7. data/lib/dry/types.rb +55 -40
  8. data/lib/dry/types/any.rb +2 -2
  9. data/lib/dry/types/array.rb +2 -2
  10. data/lib/dry/types/array/constructor.rb +1 -1
  11. data/lib/dry/types/array/member.rb +1 -1
  12. data/lib/dry/types/builder.rb +70 -18
  13. data/lib/dry/types/builder_methods.rb +1 -2
  14. data/lib/dry/types/coercions.rb +0 -17
  15. data/lib/dry/types/coercions/json.rb +22 -5
  16. data/lib/dry/types/coercions/params.rb +20 -3
  17. data/lib/dry/types/compiler.rb +10 -10
  18. data/lib/dry/types/constrained.rb +6 -9
  19. data/lib/dry/types/constraints.rb +3 -3
  20. data/lib/dry/types/constructor.rb +40 -6
  21. data/lib/dry/types/constructor/function.rb +48 -32
  22. data/lib/dry/types/constructor/wrapper.rb +94 -0
  23. data/lib/dry/types/container.rb +1 -1
  24. data/lib/dry/types/core.rb +15 -13
  25. data/lib/dry/types/decorator.rb +2 -9
  26. data/lib/dry/types/default.rb +14 -1
  27. data/lib/dry/types/enum.rb +4 -3
  28. data/lib/dry/types/errors.rb +1 -1
  29. data/lib/dry/types/extensions.rb +2 -2
  30. data/lib/dry/types/extensions/maybe.rb +18 -17
  31. data/lib/dry/types/extensions/monads.rb +1 -1
  32. data/lib/dry/types/fn_container.rb +1 -1
  33. data/lib/dry/types/hash.rb +9 -15
  34. data/lib/dry/types/hash/constructor.rb +1 -1
  35. data/lib/dry/types/inflector.rb +1 -1
  36. data/lib/dry/types/json.rb +15 -15
  37. data/lib/dry/types/lax.rb +3 -6
  38. data/lib/dry/types/map.rb +2 -2
  39. data/lib/dry/types/meta.rb +3 -3
  40. data/lib/dry/types/module.rb +6 -6
  41. data/lib/dry/types/nominal.rb +11 -11
  42. data/lib/dry/types/params.rb +31 -28
  43. data/lib/dry/types/predicate_inferrer.rb +52 -11
  44. data/lib/dry/types/predicate_registry.rb +1 -1
  45. data/lib/dry/types/primitive_inferrer.rb +1 -1
  46. data/lib/dry/types/printer.rb +25 -25
  47. data/lib/dry/types/result.rb +3 -3
  48. data/lib/dry/types/schema.rb +26 -13
  49. data/lib/dry/types/schema/key.rb +15 -6
  50. data/lib/dry/types/spec/types.rb +65 -42
  51. data/lib/dry/types/sum.rb +6 -5
  52. data/lib/dry/types/type.rb +1 -1
  53. data/lib/dry/types/version.rb +1 -1
  54. metadata +27 -78
  55. data/.codeclimate.yml +0 -12
  56. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
  57. data/.github/ISSUE_TEMPLATE/---bug-report.md +0 -30
  58. data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
  59. data/.github/workflows/custom_ci.yml +0 -76
  60. data/.github/workflows/docsite.yml +0 -34
  61. data/.github/workflows/sync_configs.yml +0 -34
  62. data/.gitignore +0 -11
  63. data/.rspec +0 -4
  64. data/.rubocop.yml +0 -92
  65. data/.yardopts +0 -9
  66. data/CODE_OF_CONDUCT.md +0 -13
  67. data/CONTRIBUTING.md +0 -29
  68. data/Gemfile +0 -34
  69. data/Rakefile +0 -22
  70. data/benchmarks/hash_schemas.rb +0 -55
  71. data/benchmarks/lax_schema.rb +0 -15
  72. data/benchmarks/profile_invalid_input.rb +0 -15
  73. data/benchmarks/profile_lax_schema_valid.rb +0 -16
  74. data/benchmarks/profile_valid_input.rb +0 -15
  75. data/benchmarks/schema_valid_vs_invalid.rb +0 -21
  76. data/benchmarks/setup.rb +0 -17
  77. data/docsite/source/array-with-member.html.md +0 -13
  78. data/docsite/source/built-in-types.html.md +0 -116
  79. data/docsite/source/constraints.html.md +0 -31
  80. data/docsite/source/custom-types.html.md +0 -93
  81. data/docsite/source/default-values.html.md +0 -91
  82. data/docsite/source/enum.html.md +0 -69
  83. data/docsite/source/extensions.html.md +0 -15
  84. data/docsite/source/extensions/maybe.html.md +0 -57
  85. data/docsite/source/extensions/monads.html.md +0 -61
  86. data/docsite/source/getting-started.html.md +0 -57
  87. data/docsite/source/hash-schemas.html.md +0 -169
  88. data/docsite/source/index.html.md +0 -156
  89. data/docsite/source/map.html.md +0 -17
  90. data/docsite/source/optional-values.html.md +0 -35
  91. data/docsite/source/sum.html.md +0 -21
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ module Types
5
+ # @api public
6
+ class Constructor < Nominal
7
+ module Wrapper
8
+ # @return [Object]
9
+ #
10
+ # @api private
11
+ def call_safe(input, &block)
12
+ fn.(input, type, &block)
13
+ end
14
+
15
+ # @return [Object]
16
+ #
17
+ # @api private
18
+ def call_unsafe(input)
19
+ fn.(input, type)
20
+ end
21
+
22
+ # @param [Object] input
23
+ # @param [#call,nil] block
24
+ #
25
+ # @return [Logic::Result, Types::Result]
26
+ # @return [Object] if block given and try fails
27
+ #
28
+ # @api public
29
+ def try(input, &block)
30
+ value = fn.(input, type)
31
+ rescue CoercionError => e
32
+ failure = failure(input, e)
33
+ block_given? ? yield(failure) : failure
34
+ else
35
+ type.try(value, &block)
36
+ end
37
+
38
+ # Define a constructor for the type
39
+ #
40
+ # @param [#call,nil] constructor
41
+ # @param [Hash] options
42
+ # @param [#call,nil] block
43
+ #
44
+ # @return [Constructor]
45
+ #
46
+ # @api public
47
+ define_method(:constructor, Builder.instance_method(:constructor))
48
+ alias_method :append, :constructor
49
+ alias_method :>>, :constructor
50
+
51
+ # Build a new constructor by prepending a block to the coercion function
52
+ #
53
+ # @param [#call, nil] new_fn
54
+ # @param [Hash] options
55
+ # @param [#call, nil] block
56
+ #
57
+ # @return [Constructor]
58
+ #
59
+ # @api public
60
+ def prepend(new_fn = nil, **options, &block)
61
+ prep_fn = Function[new_fn || block]
62
+
63
+ decorated =
64
+ if prep_fn.wrapper?
65
+ type.constructor(prep_fn, **options)
66
+ else
67
+ type.prepend(prep_fn, **options)
68
+ end
69
+
70
+ __new__(decorated)
71
+ end
72
+ alias_method :<<, :prepend
73
+
74
+ # @return [Constructor]
75
+ #
76
+ # @api public
77
+ def lax
78
+ # return self back because wrapping function
79
+ # can handle failed type check
80
+ self
81
+ end
82
+
83
+ private
84
+
85
+ # Replace underlying type
86
+ #
87
+ # @api private
88
+ def __new__(type)
89
+ self.class.new(type, *@__args__.drop(1), **@options)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/container'
3
+ require "dry/container"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/any'
3
+ require "dry/types/any"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -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
- register("optional.strict.#{name}", self["strict.#{name}"].optional)
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
@@ -81,17 +83,17 @@ module Dry
81
83
  end
82
84
 
83
85
  # Register `:bool` since it's common and not a built-in Ruby type :(
84
- register('nominal.bool', self['nominal.true'] | self['nominal.false'])
85
- bool = self['strict.true'] | self['strict.false']
86
- register('strict.bool', bool)
87
- register('bool', bool)
88
-
89
- register('any', Any)
90
- register('nominal.any', Any)
91
- register('strict.any', Any)
86
+ register("nominal.bool", self["nominal.true"] | self["nominal.false"])
87
+ bool = self["strict.true"] | self["strict.false"]
88
+ register("strict.bool", bool)
89
+ register("bool", bool)
90
+
91
+ register("any", Any)
92
+ register("nominal.any", Any)
93
+ register("strict.any", Any)
92
94
  end
93
95
  end
94
96
 
95
- require 'dry/types/coercions'
96
- require 'dry/types/params'
97
- require 'dry/types/json'
97
+ require "dry/types/coercions"
98
+ require "dry/types/params"
99
+ require "dry/types/json"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/options'
3
+ require "dry/types/options"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -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
  #
@@ -107,7 +100,7 @@ module Dry
107
100
  #
108
101
  # @api private
109
102
  def __new__(type)
110
- self.class.new(type, *@__args__[1..-1], **@options)
103
+ self.class.new(type, *@__args__.drop(1), **@options)
111
104
  end
112
105
  end
113
106
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/decorator'
3
+ require "dry/core/equalizer"
4
+ require "dry/types/decorator"
4
5
 
5
6
  module Dry
6
7
  module Types
@@ -17,6 +18,11 @@ module Dry
17
18
  def evaluate
18
19
  value.call(type)
19
20
  end
21
+
22
+ # @return [true]
23
+ def callable?
24
+ true
25
+ end
20
26
  end
21
27
 
22
28
  include Type
@@ -111,6 +117,13 @@ module Dry
111
117
  Undefined.default(type.call_safe(input, &block)) { evaluate }
112
118
  end
113
119
  end
120
+
121
+ # @return [false]
122
+ #
123
+ # @api private
124
+ def callable?
125
+ false
126
+ end
114
127
  end
115
128
  end
116
129
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/decorator'
3
+ require "dry/core/equalizer"
4
+ require "dry/types/decorator"
4
5
 
5
6
  module Dry
6
7
  module Types
@@ -58,8 +59,8 @@ module Dry
58
59
 
59
60
  # @api private
60
61
  def default(*)
61
- raise '.enum(*values).default(value) is not supported. Call '\
62
- '.default(value).enum(*values) instead'
62
+ raise ".enum(*values).default(value) is not supported. Call "\
63
+ ".default(value).enum(*values) instead"
63
64
  end
64
65
 
65
66
  # Check whether a value is in the enum
@@ -56,7 +56,7 @@ module Dry
56
56
 
57
57
  # @return string
58
58
  def message
59
- errors.map(&:message).join(', ')
59
+ errors.map(&:message).join(", ")
60
60
  end
61
61
 
62
62
  # @return [Array]
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Dry::Types.register_extension(:maybe) do
4
- require 'dry/types/extensions/maybe'
4
+ require "dry/types/extensions/maybe"
5
5
  end
6
6
 
7
7
  Dry::Types.register_extension(:monads) do
8
- require 'dry/types/extensions/monads'
8
+ require "dry/types/extensions/monads"
9
9
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads/maybe'
4
- require 'dry/types/decorator'
3
+ require "dry/core/equalizer"
4
+ require "dry/monads/maybe"
5
+ require "dry/types/decorator"
5
6
 
6
7
  module Dry
7
8
  module Types
@@ -10,11 +11,11 @@ module Dry
10
11
  # @api public
11
12
  class Maybe
12
13
  include Type
13
- include Dry::Equalizer(:type, :options, inspect: false, immutable: true)
14
+ include ::Dry::Equalizer(:type, :options, inspect: false, immutable: true)
14
15
  include Decorator
15
16
  include Builder
16
17
  include Printable
17
- include Dry::Monads::Maybe::Mixin
18
+ include ::Dry::Monads::Maybe::Mixin
18
19
 
19
20
  # @param [Dry::Monads::Maybe, Object] input
20
21
  #
@@ -23,7 +24,7 @@ module Dry
23
24
  # @api private
24
25
  def call_unsafe(input = Undefined)
25
26
  case input
26
- when Dry::Monads::Maybe
27
+ when ::Dry::Monads::Maybe
27
28
  input
28
29
  when Undefined
29
30
  None()
@@ -37,14 +38,14 @@ module Dry
37
38
  # @return [Dry::Monads::Maybe]
38
39
  #
39
40
  # @api private
40
- def call_safe(input = Undefined, &block)
41
+ def call_safe(input = Undefined)
41
42
  case input
42
- when Dry::Monads::Maybe
43
+ when ::Dry::Monads::Maybe
43
44
  input
44
45
  when Undefined
45
46
  None()
46
47
  else
47
- Maybe(type.call_safe(input, &block))
48
+ Maybe(type.call_safe(input) { |output = input| return yield(output) })
48
49
  end
49
50
  end
50
51
 
@@ -54,13 +55,13 @@ module Dry
54
55
  #
55
56
  # @api public
56
57
  def try(input = Undefined)
57
- res = if input.equal?(Undefined)
58
- None()
59
- else
60
- Maybe(type[input])
61
- end
58
+ result = type.try(input)
62
59
 
63
- Result::Success.new(res)
60
+ if result.success?
61
+ Result::Success.new(Maybe(result.input))
62
+ else
63
+ result
64
+ end
64
65
  end
65
66
 
66
67
  # @return [true]
@@ -79,7 +80,7 @@ module Dry
79
80
  # @api public
80
81
  def default(value)
81
82
  if value.nil?
82
- raise ArgumentError, 'nil cannot be used as a default of a maybe type'
83
+ raise ArgumentError, "nil cannot be used as a default of a maybe type"
83
84
  else
84
85
  super
85
86
  end
@@ -93,7 +94,7 @@ module Dry
93
94
  #
94
95
  # @api public
95
96
  def maybe
96
- Maybe.new(Types['strict.nil'] | self)
97
+ Maybe.new(Types["nil"] | self)
97
98
  end
98
99
  end
99
100
 
@@ -119,7 +120,7 @@ module Dry
119
120
 
120
121
  # Register non-coercible maybe types
121
122
  NON_NIL.each_key do |name|
122
- register("maybe.strict.#{name}", self["strict.#{name}"].maybe)
123
+ register("maybe.strict.#{name}", self[name.to_s].maybe)
123
124
  end
124
125
 
125
126
  # Register coercible maybe types
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads/result'
3
+ require "dry/monads/result"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/container'
3
+ require "dry/types/container"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/hash/constructor'
3
+ require "dry/types/hash/constructor"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -8,7 +8,7 @@ module Dry
8
8
  #
9
9
  # @api public
10
10
  class Hash < Nominal
11
- NOT_REQUIRED = { required: false }.freeze
11
+ NOT_REQUIRED = {required: false}.freeze
12
12
 
13
13
  # @overload schema(type_map, meta = EMPTY_HASH)
14
14
  # @param [{Symbol => Dry::Types::Nominal}] type_map
@@ -50,8 +50,8 @@ module Dry
50
50
 
51
51
  # @api private
52
52
  def weak(*)
53
- raise 'Support for old hash schemas was removed, please refer to the CHANGELOG '\
54
- 'on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
53
+ raise "Support for old hash schemas was removed, please refer to the CHANGELOG "\
54
+ "on how to proceed with the new API https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md"
55
55
  end
56
56
  alias_method :permissive, :weak
57
57
  alias_method :strict, :weak
@@ -69,7 +69,7 @@ module Dry
69
69
  def with_type_transform(proc = nil, &block)
70
70
  fn = proc || block
71
71
 
72
- raise ArgumentError, 'a block or callable argument is required' if fn.nil?
72
+ raise ArgumentError, "a block or callable argument is required" if fn.nil?
73
73
 
74
74
  handle = Dry::Types::FnContainer.register(fn)
75
75
  with(type_transform_fn: handle)
@@ -95,13 +95,7 @@ module Dry
95
95
  #
96
96
  # @api public
97
97
  def to_ast(meta: true)
98
- opts = if RUBY_VERSION >= '2.5'
99
- options.slice(:type_transform_fn)
100
- else
101
- options.select { |k, _| k == :type_transform_fn }
102
- end
103
-
104
- [:hash, [opts, meta ? self.meta : EMPTY_HASH]]
98
+ [:hash, [options.slice(:type_transform_fn), meta ? self.meta : EMPTY_HASH]]
105
99
  end
106
100
 
107
101
  private
@@ -129,7 +123,7 @@ module Dry
129
123
 
130
124
  # @api private
131
125
  def key_name(key)
132
- if key.to_s.end_with?('?')
126
+ if key.to_s.end_with?("?")
133
127
  [key.to_s.chop.to_sym, NOT_REQUIRED]
134
128
  else
135
129
  [key, EMPTY_HASH]
@@ -139,5 +133,5 @@ module Dry
139
133
  end
140
134
  end
141
135
 
142
- require 'dry/types/schema/key'
143
- require 'dry/types/schema'
136
+ require "dry/types/schema/key"
137
+ require "dry/types/schema"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/constructor'
3
+ require "dry/types/constructor"
4
4
 
5
5
  module Dry
6
6
  module Types