dry-types 1.2.1 → 1.5.0

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 -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