dry-types 0.9.0 → 0.15.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 (61) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +15 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +43 -0
  5. data/.travis.yml +15 -14
  6. data/.yardopts +5 -0
  7. data/CHANGELOG.md +494 -88
  8. data/CONTRIBUTING.md +29 -0
  9. data/Gemfile +7 -6
  10. data/README.md +1 -3
  11. data/Rakefile +8 -3
  12. data/benchmarks/hash_schemas.rb +7 -7
  13. data/dry-types.gemspec +11 -9
  14. data/lib/dry/types/any.rb +36 -0
  15. data/lib/dry/types/array/member.rb +29 -4
  16. data/lib/dry/types/array.rb +6 -4
  17. data/lib/dry/types/builder.rb +48 -6
  18. data/lib/dry/types/builder_methods.rb +111 -0
  19. data/lib/dry/types/coercions/json.rb +3 -0
  20. data/lib/dry/types/coercions/{form.rb → params.rb} +23 -3
  21. data/lib/dry/types/coercions.rb +16 -3
  22. data/lib/dry/types/compat.rb +0 -0
  23. data/lib/dry/types/compiler.rb +66 -39
  24. data/lib/dry/types/constrained/coercible.rb +7 -1
  25. data/lib/dry/types/constrained.rb +42 -3
  26. data/lib/dry/types/constraints.rb +3 -0
  27. data/lib/dry/types/constructor.rb +98 -16
  28. data/lib/dry/types/container.rb +2 -0
  29. data/lib/dry/types/core.rb +30 -14
  30. data/lib/dry/types/decorator.rb +31 -5
  31. data/lib/dry/types/default.rb +34 -8
  32. data/lib/dry/types/enum.rb +71 -14
  33. data/lib/dry/types/errors.rb +23 -6
  34. data/lib/dry/types/extensions/maybe.rb +35 -16
  35. data/lib/dry/types/fn_container.rb +34 -0
  36. data/lib/dry/types/hash/constructor.rb +20 -0
  37. data/lib/dry/types/hash.rb +103 -23
  38. data/lib/dry/types/inflector.rb +7 -0
  39. data/lib/dry/types/json.rb +7 -7
  40. data/lib/dry/types/map.rb +98 -0
  41. data/lib/dry/types/module.rb +115 -0
  42. data/lib/dry/types/nominal.rb +119 -0
  43. data/lib/dry/types/options.rb +29 -7
  44. data/lib/dry/types/params.rb +53 -0
  45. data/lib/dry/types/printable.rb +12 -0
  46. data/lib/dry/types/printer.rb +309 -0
  47. data/lib/dry/types/result.rb +12 -2
  48. data/lib/dry/types/safe.rb +27 -1
  49. data/lib/dry/types/schema/key.rb +130 -0
  50. data/lib/dry/types/schema.rb +298 -0
  51. data/lib/dry/types/spec/types.rb +102 -0
  52. data/lib/dry/types/sum.rb +75 -13
  53. data/lib/dry/types/type.rb +6 -0
  54. data/lib/dry/types/version.rb +1 -1
  55. data/lib/dry/types.rb +104 -38
  56. data/log/.gitkeep +0 -0
  57. metadata +81 -50
  58. data/lib/dry/types/definition.rb +0 -79
  59. data/lib/dry/types/form.rb +0 -53
  60. data/lib/dry/types/hash/schema.rb +0 -156
  61. data/lib/spec/dry/types.rb +0 -56
@@ -1,79 +0,0 @@
1
- require 'dry/types/builder'
2
- require 'dry/types/result'
3
- require 'dry/types/options'
4
-
5
- module Dry
6
- module Types
7
- class Definition
8
- include Dry::Equalizer(:primitive, :options)
9
- include Options
10
- include Builder
11
-
12
- attr_reader :options
13
-
14
- attr_reader :primitive
15
-
16
- def self.[](primitive)
17
- if primitive == ::Array
18
- Types::Array
19
- elsif primitive == ::Hash
20
- Types::Hash
21
- else
22
- self
23
- end
24
- end
25
-
26
- def initialize(primitive, options = {})
27
- super
28
- @primitive = primitive
29
- freeze
30
- end
31
-
32
- def name
33
- primitive.name
34
- end
35
-
36
- def default?
37
- false
38
- end
39
-
40
- def constrained?
41
- false
42
- end
43
-
44
- def call(input)
45
- input
46
- end
47
- alias_method :[], :call
48
-
49
- def try(input, &block)
50
- if valid?(input)
51
- success(input)
52
- else
53
- failure = failure(input, "#{input.inspect} must be an instance of #{primitive}")
54
- block ? yield(failure) : failure
55
- end
56
- end
57
-
58
- def success(*args)
59
- result(Result::Success, *args)
60
- end
61
-
62
- def failure(*args)
63
- result(Result::Failure, *args)
64
- end
65
-
66
- def result(klass, *args)
67
- klass.new(*args)
68
- end
69
-
70
- def primitive?(value)
71
- value.is_a?(primitive)
72
- end
73
- alias_method :valid?, :primitive?
74
- end
75
- end
76
- end
77
-
78
- require 'dry/types/array'
79
- require 'dry/types/hash'
@@ -1,53 +0,0 @@
1
- require 'dry/types/coercions/form'
2
-
3
- module Dry
4
- module Types
5
- register('form.nil') do
6
- self['nil'].constructor(Coercions::Form.method(:to_nil))
7
- end
8
-
9
- register('form.date') do
10
- self['date'].constructor(Coercions::Form.method(:to_date))
11
- end
12
-
13
- register('form.date_time') do
14
- self['date_time'].constructor(Coercions::Form.method(:to_date_time))
15
- end
16
-
17
- register('form.time') do
18
- self['time'].constructor(Coercions::Form.method(:to_time))
19
- end
20
-
21
- register('form.true') do
22
- self['true'].constructor(Coercions::Form.method(:to_true))
23
- end
24
-
25
- register('form.false') do
26
- self['false'].constructor(Coercions::Form.method(:to_false))
27
- end
28
-
29
- register('form.bool') do
30
- (self['form.true'] | self['form.false']).safe
31
- end
32
-
33
- register('form.int') do
34
- self['int'].constructor(Coercions::Form.method(:to_int))
35
- end
36
-
37
- register('form.float') do
38
- self['float'].constructor(Coercions::Form.method(:to_float))
39
- end
40
-
41
- register('form.decimal') do
42
- self['decimal'].constructor(Coercions::Form.method(:to_decimal))
43
- end
44
-
45
- register('form.array') do
46
- self['array'].constructor(Coercions::Form.method(:to_ary)).safe
47
- end
48
-
49
- register('form.hash') do
50
- self['hash'].constructor(Coercions::Form.method(:to_hash)).safe
51
- end
52
- end
53
- end
@@ -1,156 +0,0 @@
1
- module Dry
2
- module Types
3
- class Hash < Definition
4
- class Schema < Hash
5
- attr_reader :member_types
6
-
7
- def initialize(_primitive, options)
8
- @member_types = options.fetch(:member_types)
9
- super
10
- end
11
-
12
- def call(hash)
13
- coerce(hash)
14
- end
15
- alias_method :[], :call
16
-
17
- def try(hash, &block)
18
- success = true
19
- output = {}
20
-
21
- begin
22
- result = try_coerce(hash) do |key, member_result|
23
- success &&= member_result.success?
24
- output[key] = member_result.input
25
-
26
- member_result
27
- end
28
- rescue ConstraintError, UnknownKeysError, SchemaError => e
29
- success = false
30
- result = e
31
- end
32
-
33
- if success
34
- success(output)
35
- else
36
- failure = failure(output, result)
37
- block ? yield(failure) : failure
38
- end
39
- end
40
-
41
- private
42
-
43
- def try_coerce(hash)
44
- resolve(hash) do |type, key, value|
45
- yield(key, type.try(value))
46
- end
47
- end
48
-
49
- def coerce(hash)
50
- resolve(hash) do |type, key, value|
51
- begin
52
- type.call(value)
53
- rescue ConstraintError
54
- raise SchemaError.new(key, value)
55
- end
56
- end
57
- end
58
-
59
- def resolve(hash)
60
- member_types.each_with_object({}) do |(key, type), result|
61
- if hash.key?(key)
62
- result[key] = yield(type, key, hash[key])
63
- else
64
- resolve_missing_value(result, key, type)
65
- end
66
- end
67
- end
68
-
69
- def resolve_missing_value(result, key, type)
70
- if type.default?
71
- result[key] = type.evaluate
72
- else
73
- super
74
- end
75
- end
76
- end
77
-
78
- class Permissive < Schema
79
- private
80
-
81
- def resolve_missing_value(_, key, _)
82
- raise MissingKeyError, key
83
- end
84
- end
85
-
86
- class Strict < Permissive
87
- private
88
-
89
- def resolve(hash)
90
- unexpected = hash.keys - member_types.keys
91
- raise UnknownKeysError.new(*unexpected) unless unexpected.empty?
92
-
93
- super do |member_type, key, value|
94
- type = member_type.default? ? member_type.type : member_type
95
-
96
- yield(type, key, value)
97
- end
98
- end
99
- end
100
-
101
- class StrictWithDefaults < Strict
102
- private
103
-
104
- def resolve_missing_value(result, key, type)
105
- if type.default?
106
- result[key] = type.value
107
- else
108
- super
109
- end
110
- end
111
- end
112
-
113
- class Weak < Schema
114
- def self.new(primitive, options)
115
- member_types = options.
116
- fetch(:member_types).
117
- each_with_object({}) { |(k, t), res| res[k] = t.safe }
118
-
119
- super(primitive, options.merge(member_types: member_types))
120
- end
121
-
122
- def try(hash, &block)
123
- if hash.instance_of?(::Hash)
124
- super
125
- else
126
- result = failure(hash, "#{hash} must be a hash")
127
- block ? yield(result) : result
128
- end
129
- end
130
- end
131
-
132
- class Symbolized < Weak
133
- private
134
-
135
- def resolve(hash)
136
- member_types.each_with_object({}) do |(key, type), result|
137
- keyname =
138
- if hash.key?(key)
139
- key
140
- elsif hash.key?(string_key = key.to_s)
141
- string_key
142
- end
143
-
144
- if keyname
145
- result[key] = yield(type, key, hash[keyname])
146
- else
147
- resolve_missing_value(result, key, type)
148
- end
149
- end
150
- end
151
- end
152
-
153
- private_constant(*constants(false))
154
- end
155
- end
156
- end
@@ -1,56 +0,0 @@
1
- RSpec.shared_examples_for 'Dry::Types::Definition without primitive' do
2
- def be_boolean
3
- satisfy { |x| x == true || x == false }
4
- end
5
-
6
- describe '#constrained?' do
7
- it 'returns a boolean value' do
8
- expect(type.constrained?).to be_boolean
9
- end
10
- end
11
-
12
- describe '#default?' do
13
- it 'returns a boolean value' do
14
- expect(type.default?).to be_boolean
15
- end
16
- end
17
-
18
- describe '#valid?' do
19
- it 'returns a boolean value' do
20
- expect(type.valid?(1)).to be_boolean
21
- end
22
- end
23
-
24
- describe '#eql?' do
25
- it 'has #eql? defined' do
26
- expect(type).to eql(type)
27
- end
28
- end
29
-
30
- describe '#==' do
31
- it 'has #== defined' do
32
- expect(type).to eq(type)
33
- end
34
- end
35
- end
36
-
37
- RSpec.shared_examples_for 'Dry::Types::Definition#meta' do
38
- describe '#meta' do
39
- it 'allows setting meta information' do
40
- with_meta = type.meta(foo: :bar).meta(baz: '1')
41
-
42
- expect(with_meta).to be_instance_of(type.class)
43
- expect(with_meta.meta).to eql(foo: :bar, baz: '1')
44
- end
45
- end
46
- end
47
-
48
- RSpec.shared_examples_for Dry::Types::Definition do
49
- it_behaves_like 'Dry::Types::Definition without primitive'
50
-
51
- describe '#primitive' do
52
- it 'returns a class' do
53
- expect(type.primitive).to be_instance_of(Class)
54
- end
55
- end
56
- end