dry-types 1.2.1 → 1.5.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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +405 -221
  3. data/LICENSE +1 -1
  4. data/README.md +14 -13
  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 +6 -3
  14. data/lib/dry/types/coercions.rb +6 -17
  15. data/lib/dry/types/coercions/json.rb +22 -5
  16. data/lib/dry/types/coercions/params.rb +21 -4
  17. data/lib/dry/types/compiler.rb +10 -10
  18. data/lib/dry/types/constrained.rb +6 -10
  19. data/lib/dry/types/constraints.rb +3 -3
  20. data/lib/dry/types/constructor.rb +40 -7
  21. data/lib/dry/types/constructor/function.rb +47 -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 +15 -3
  27. data/lib/dry/types/enum.rb +4 -4
  28. data/lib/dry/types/errors.rb +6 -6
  29. data/lib/dry/types/extensions.rb +2 -2
  30. data/lib/dry/types/extensions/maybe.rb +17 -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 +4 -7
  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 -12
  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 +20 -7
  50. data/lib/dry/types/spec/types.rb +65 -42
  51. data/lib/dry/types/sum.rb +6 -6
  52. data/lib/dry/types/type.rb +1 -1
  53. data/lib/dry/types/version.rb +1 -1
  54. metadata +27 -84
  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 -34
  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 -89
  65. data/.yardopts +0 -9
  66. data/CODE_OF_CONDUCT.md +0 -13
  67. data/CONTRIBUTING.md +0 -29
  68. data/Gemfile +0 -32
  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
@@ -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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/inflector'
3
+ require "dry/inflector"
4
4
 
5
5
  module Dry
6
6
  module Types
@@ -1,35 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/coercions/json'
3
+ require "dry/types/coercions/json"
4
4
 
5
5
  module Dry
6
6
  module Types
7
- register('json.nil') do
8
- self['nominal.nil'].constructor(Coercions::JSON.method(:to_nil))
7
+ register("json.nil") do
8
+ self["nominal.nil"].constructor(Coercions::JSON.method(:to_nil))
9
9
  end
10
10
 
11
- register('json.date') do
12
- self['nominal.date'].constructor(Coercions::JSON.method(:to_date))
11
+ register("json.date") do
12
+ self["nominal.date"].constructor(Coercions::JSON.method(:to_date))
13
13
  end
14
14
 
15
- register('json.date_time') do
16
- self['nominal.date_time'].constructor(Coercions::JSON.method(:to_date_time))
15
+ register("json.date_time") do
16
+ self["nominal.date_time"].constructor(Coercions::JSON.method(:to_date_time))
17
17
  end
18
18
 
19
- register('json.time') do
20
- self['nominal.time'].constructor(Coercions::JSON.method(:to_time))
19
+ register("json.time") do
20
+ self["nominal.time"].constructor(Coercions::JSON.method(:to_time))
21
21
  end
22
22
 
23
- register('json.decimal') do
24
- self['nominal.decimal'].constructor(Coercions::JSON.method(:to_decimal))
23
+ register("json.decimal") do
24
+ self["nominal.decimal"].constructor(Coercions::JSON.method(:to_decimal))
25
25
  end
26
26
 
27
- register('json.symbol') do
28
- self['nominal.symbol'].constructor(Coercions::JSON.method(:to_symbol))
27
+ register("json.symbol") do
28
+ self["nominal.symbol"].constructor(Coercions::JSON.method(:to_symbol))
29
29
  end
30
30
 
31
- register('json.array') { self['array'] }
31
+ register("json.array") { self["array"] }
32
32
 
33
- register('json.hash') { self['hash'] }
33
+ register("json.hash") { self["hash"] }
34
34
  end
35
35
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/deprecations'
4
- require 'dry/types/decorator'
3
+ require "dry/core/deprecations"
4
+ require "dry/types/decorator"
5
5
 
6
6
  module Dry
7
7
  module Types
@@ -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
- undef :options, :constructor
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
@@ -21,7 +21,7 @@ module Dry
21
21
  #
22
22
  # @api public
23
23
  class Map < Nominal
24
- def initialize(_primitive, key_type: Types['any'], value_type: Types['any'], meta: EMPTY_HASH)
24
+ def initialize(_primitive, key_type: Types["any"], value_type: Types["any"], meta: EMPTY_HASH)
25
25
  super(_primitive, key_type: key_type, value_type: value_type, meta: meta)
26
26
  end
27
27
 
@@ -43,7 +43,7 @@ module Dry
43
43
  #
44
44
  # @api public
45
45
  def name
46
- 'Map'
46
+ "Map"
47
47
  end
48
48
 
49
49
  # @param [Hash] hash
@@ -11,7 +11,7 @@ module Dry
11
11
  @meta = meta.freeze
12
12
  end
13
13
 
14
- # @param [Hash] new_options
14
+ # @param options [Hash] new_options
15
15
  #
16
16
  # @return [Type]
17
17
  #
@@ -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 = nil)
32
- if !data
31
+ def meta(data = Undefined)
32
+ if Undefined.equal?(data)
33
33
  @meta
34
34
  elsif data.empty?
35
35
  self
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/deprecations'
4
- require 'dry/types/builder_methods'
3
+ require "dry/core/deprecations"
4
+ require "dry/types/builder_methods"
5
5
 
6
6
  module Dry
7
7
  module Types
@@ -31,7 +31,7 @@ module Dry
31
31
  base.instance_exec(const_get(:Nominal, false)) do |nominal|
32
32
  extend Dry::Core::Deprecations[:'dry-types']
33
33
  const_set(:Definition, nominal)
34
- deprecate_constant(:Definition, message: 'Nominal')
34
+ deprecate_constant(:Definition, message: "Nominal")
35
35
  end
36
36
  end
37
37
  end
@@ -69,7 +69,7 @@ module Dry
69
69
  def registry_tree
70
70
  @registry_tree ||= @registry.keys.each_with_object({}) { |key, tree|
71
71
  type = @registry[key]
72
- *modules, const_name = key.split('.').map { |part|
72
+ *modules, const_name = key.split(".").map { |part|
73
73
  Inflector.camelize(part).to_sym
74
74
  }
75
75
  next if modules.empty?
@@ -87,14 +87,14 @@ module Dry
87
87
  referenced.concat(aliases.keys)
88
88
 
89
89
  known = @registry.keys.map { |k|
90
- ns, *path = k.split('.')
90
+ ns, *path = k.split(".")
91
91
  ns.to_sym unless path.empty?
92
92
  }.compact.uniq
93
93
 
94
94
  (referenced.uniq - known).each do |name|
95
95
  raise ArgumentError,
96
96
  "#{name.inspect} is not a known type namespace. "\
97
- "Supported options are #{known.map(&:inspect).join(', ')}"
97
+ "Supported options are #{known.map(&:inspect).join(", ")}"
98
98
  end
99
99
  end
100
100
 
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/deprecations'
4
- require 'dry/types/builder'
5
- require 'dry/types/result'
6
- require 'dry/types/options'
7
- require 'dry/types/meta'
3
+ require "dry/core/deprecations"
4
+ require "dry/types/builder"
5
+ require "dry/types/result"
6
+ require "dry/types/options"
7
+ require "dry/types/meta"
8
8
 
9
9
  module Dry
10
10
  module Types
@@ -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
@@ -98,7 +98,6 @@ module Dry
98
98
  end
99
99
 
100
100
  # @param [Object] input
101
- # @param [#call,nil] block
102
101
  #
103
102
  # @yieldparam [Failure] failure
104
103
  # @yieldreturn [Result]
@@ -126,7 +125,7 @@ module Dry
126
125
  #
127
126
  # @api public
128
127
  def failure(input, error)
129
- raise ArgumentError, 'error must be a CoercionError' unless error.is_a?(CoercionError)
128
+ raise ArgumentError, "error must be a CoercionError" unless error.is_a?(CoercionError)
130
129
 
131
130
  Result::Failure.new(input, error)
132
131
  end
@@ -201,10 +200,10 @@ module Dry
201
200
 
202
201
  extend Dry::Core::Deprecations[:'dry-types']
203
202
  Definition = Nominal
204
- deprecate_constant(:Definition, message: 'Nominal')
203
+ deprecate_constant(:Definition, message: "Nominal")
205
204
  end
206
205
  end
207
206
 
208
- require 'dry/types/array'
209
- require 'dry/types/hash'
210
- require 'dry/types/map'
207
+ require "dry/types/array"
208
+ require "dry/types/hash"
209
+ require "dry/types/map"
@@ -1,64 +1,67 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/types/coercions/params'
3
+ require "dry/types/coercions/params"
4
4
 
5
5
  module Dry
6
6
  module Types
7
- register('params.nil') do
8
- self['nominal.nil'].constructor(Coercions::Params.method(:to_nil))
7
+ register("params.nil") do
8
+ self["nominal.nil"].constructor(Coercions::Params.method(:to_nil))
9
9
  end
10
10
 
11
- register('params.date') do
12
- self['nominal.date'].constructor(Coercions::Params.method(:to_date))
11
+ register("params.date") do
12
+ self["nominal.date"].constructor(Coercions::Params.method(:to_date))
13
13
  end
14
14
 
15
- register('params.date_time') do
16
- self['nominal.date_time'].constructor(Coercions::Params.method(:to_date_time))
15
+ register("params.date_time") do
16
+ self["nominal.date_time"].constructor(Coercions::Params.method(:to_date_time))
17
17
  end
18
18
 
19
- register('params.time') do
20
- self['nominal.time'].constructor(Coercions::Params.method(:to_time))
19
+ register("params.time") do
20
+ self["nominal.time"].constructor(Coercions::Params.method(:to_time))
21
21
  end
22
22
 
23
- register('params.true') do
24
- self['nominal.true'].constructor(Coercions::Params.method(:to_true))
23
+ register("params.true") do
24
+ self["nominal.true"].constructor(Coercions::Params.method(:to_true))
25
25
  end
26
26
 
27
- register('params.false') do
28
- self['nominal.false'].constructor(Coercions::Params.method(:to_false))
27
+ register("params.false") do
28
+ self["nominal.false"].constructor(Coercions::Params.method(:to_false))
29
29
  end
30
30
 
31
- register('params.bool') do
32
- self['params.true'] | self['params.false']
31
+ register("params.bool") do
32
+ self["params.true"] | self["params.false"]
33
33
  end
34
34
 
35
- register('params.integer') do
36
- self['nominal.integer'].constructor(Coercions::Params.method(:to_int))
35
+ register("params.integer") do
36
+ self["nominal.integer"].constructor(Coercions::Params.method(:to_int))
37
37
  end
38
38
 
39
- register('params.float') do
40
- self['nominal.float'].constructor(Coercions::Params.method(:to_float))
39
+ register("params.float") do
40
+ self["nominal.float"].constructor(Coercions::Params.method(:to_float))
41
41
  end
42
42
 
43
- register('params.decimal') do
44
- self['nominal.decimal'].constructor(Coercions::Params.method(:to_decimal))
43
+ register("params.decimal") do
44
+ self["nominal.decimal"].constructor(Coercions::Params.method(:to_decimal))
45
45
  end
46
46
 
47
- register('params.array') do
48
- self['nominal.array'].constructor(Coercions::Params.method(:to_ary))
47
+ register("params.array") do
48
+ self["nominal.array"].constructor(Coercions::Params.method(:to_ary))
49
49
  end
50
50
 
51
- register('params.hash') do
52
- self['nominal.hash'].constructor(Coercions::Params.method(:to_hash))
51
+ register("params.hash") do
52
+ self["nominal.hash"].constructor(Coercions::Params.method(:to_hash))
53
53
  end
54
54
 
55
- register('params.symbol') do
56
- self['nominal.symbol'].constructor(Coercions::Params.method(:to_symbol))
55
+ register("params.symbol") do
56
+ self["nominal.symbol"].constructor(Coercions::Params.method(:to_symbol))
57
57
  end
58
58
 
59
+ register("params.string", self["string"])
60
+
59
61
  COERCIBLE.each_key do |name|
60
62
  next if name.equal?(:string)
61
- register("optional.params.#{name}", self['params.nil'] | self["params.#{name}"])
63
+
64
+ register("optional.params.#{name}", self["params.nil"] | self["params.#{name}"])
62
65
  end
63
66
  end
64
67
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/cache'
4
- require 'dry/types/predicate_registry'
3
+ require "dry/core/cache"
4
+ require "dry/core/class_attributes"
5
+ require "dry/types/predicate_registry"
5
6
 
6
7
  module Dry
7
8
  module Types
@@ -12,13 +13,17 @@ module Dry
12
13
  extend Core::Cache
13
14
 
14
15
  TYPE_TO_PREDICATE = {
15
- DateTime => :date_time?,
16
- FalseClass => :false?,
17
- Integer => :int?,
18
- NilClass => :nil?,
19
- String => :str?,
20
- TrueClass => :true?,
21
- BigDecimal => :decimal?
16
+ ::DateTime => :date_time?,
17
+ ::Date => :date?,
18
+ ::Time => :time?,
19
+ ::FalseClass => :false?,
20
+ ::Integer => :int?,
21
+ ::Float => :float?,
22
+ ::NilClass => :nil?,
23
+ ::String => :str?,
24
+ ::TrueClass => :true?,
25
+ ::BigDecimal => :decimal?,
26
+ ::Array => :array?
22
27
  }.freeze
23
28
 
24
29
  REDUCED_TYPES = {
@@ -35,6 +40,11 @@ module Dry
35
40
  #
36
41
  # @api private
37
42
  class Compiler
43
+ extend Core::ClassAttributes
44
+
45
+ defines :infer_predicate_by_class_name
46
+ infer_predicate_by_class_name nil
47
+
38
48
  # @return [PredicateRegistry]
39
49
  # @api private
40
50
  attr_reader :registry
@@ -46,7 +56,37 @@ module Dry
46
56
 
47
57
  # @api private
48
58
  def infer_predicate(type)
49
- [TYPE_TO_PREDICATE.fetch(type) { :"#{type.name.split('::').last.downcase}?" }]
59
+ pred = TYPE_TO_PREDICATE.fetch(type) do
60
+ if type.name.nil? || self.class.infer_predicate_by_class_name.equal?(false)
61
+ nil
62
+ else
63
+ candidate = :"#{type.name.split("::").last.downcase}?"
64
+
65
+ if registry.key?(candidate)
66
+ if self.class.infer_predicate_by_class_name
67
+ candidate
68
+ else
69
+ raise ::KeyError, <<~MESSAGE
70
+ Automatic predicate inferring from class names is deprecated
71
+ and will be removed in dry-types 2.0.
72
+ Use `Dry::Types::PredicateInferrer::Compiler.infer_predicate_by_class_name true`
73
+ to restore the previous behavior
74
+ or `Dry::Types::PredicateInferrer::Compiler.infer_predicate_by_class_name false`
75
+ to explicitly opt-out (i.e. no exception + no inferring).
76
+ Note: for dry-schema and dry-validation use Dry::Schema::PredicateInferrer::Compiler.
77
+ MESSAGE
78
+ end
79
+ else
80
+ nil
81
+ end
82
+ end
83
+ end
84
+
85
+ if pred.nil?
86
+ EMPTY_ARRAY
87
+ else
88
+ [pred]
89
+ end
50
90
  end
51
91
 
52
92
  # @api private
@@ -60,7 +100,7 @@ module Dry
60
100
  type = node[0]
61
101
  predicate = infer_predicate(type)
62
102
 
63
- if registry.key?(predicate[0])
103
+ if !predicate.empty? && registry.key?(predicate[0])
64
104
  predicate
65
105
  else
66
106
  [type?: type]
@@ -71,6 +111,7 @@ module Dry
71
111
  def visit_hash(_)
72
112
  HASH
73
113
  end
114
+ alias_method :visit_schema, :visit_hash
74
115
 
75
116
  # @api private
76
117
  def visit_array(_)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/logic/predicates'
3
+ require "dry/logic/predicates"
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/core/cache'
3
+ require "dry/core/cache"
4
4
 
5
5
  module Dry
6
6
  module Types