sorbet-coerce 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e72cc347e68ca6df5bfd3378ec9482aa1463c43cf9f03f203f110cbde5da4e6f
4
- data.tar.gz: c22aa7e85408cd2306d3cf582382ef5aac8c49873bd250f77fa17f4fa4cc91ec
3
+ metadata.gz: e5eefb63dc137b65889fa5dd16b05fcf3bef550474d7f7f175746ccca96e640d
4
+ data.tar.gz: 0ca052e76b580d9979d24444b8bee8d564a49c6d2162acd36469fbd205cb6354
5
5
  SHA512:
6
- metadata.gz: c2a1141237ad7bc7bb666d50c03b2b4c7507789236ae2e0542d50603e7bdf1cc353a4d5faf9bbc10f1927a81bed6887715078e5252842bd10648f5e38224d49a
7
- data.tar.gz: 0d82e8842ee6cbac0aefd823f023f71128088d414681a4600dc1c7b025c92c1010673b3334123d9a4c64a4315a26b39ea64f6f507ff010f9518799a9aad17519
6
+ metadata.gz: afb06e4b35972579d9ff0ffb0d9eb48c1de7465911b0f56a07a1d7dcda528f70d525834f5ac81c300394132ae5e8fec7d614814c900710778fa13296ed2db7f3
7
+ data.tar.gz: eecba6f2089a944984b2e6ba595ad21bbff2d11bb3fc56d38532fff94f029fe6beac3e1fce25272d46162e893d3040a548fe4240058db8a258900ee815acb946
@@ -0,0 +1,15 @@
1
+ # typed: true
2
+ require 'sorbet-runtime'
3
+
4
+ module T::Coerce
5
+ module Configuration
6
+ class << self
7
+ extend T::Sig
8
+
9
+ sig { returns(T::Boolean) }
10
+ attr_accessor :raise_coercion_error
11
+ end
12
+ end
13
+ end
14
+
15
+ T::Coerce::Configuration.raise_coercion_error = true
@@ -5,8 +5,6 @@ require 'polyfill'
5
5
 
6
6
  using Polyfill(Hash: %w[#slice])
7
7
 
8
- module T; end
9
-
10
8
  module T::Private
11
9
  class Converter
12
10
  extend T::Sig
@@ -22,12 +20,12 @@ module T::Private
22
20
  ], T.untyped)
23
21
 
24
22
  protected
25
- sig { params(value: T.untyped, type: T.untyped).returns(T.untyped) }
26
- def _convert(value, type)
23
+ sig { params(value: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
24
+ def _convert(value, type, raise_coercion_error)
27
25
  if type.is_a?(T::Types::TypedArray)
28
- _convert_to_a(value, type.type)
26
+ _convert_to_a(value, type.type, raise_coercion_error)
29
27
  elsif type.is_a?(T::Types::Simple)
30
- _convert(value, type.raw_type)
28
+ _convert(value, type.raw_type, raise_coercion_error)
31
29
  elsif type.is_a?(T::Types::Union)
32
30
  true_idx = T.let(nil, T.nilable(Integer))
33
31
  false_idx = T.let(nil, T.nilable(Integer))
@@ -49,25 +47,25 @@ module T::Private
49
47
  )
50
48
 
51
49
  if !true_idx.nil? && !false_idx.nil?
52
- _convert_simple(value, T::Boolean)
50
+ _convert_simple(value, T::Boolean, raise_coercion_error)
53
51
  else
54
- _convert(value, type.types[nil_idx == 0 ? 1 : 0])
52
+ _convert(value, type.types[nil_idx == 0 ? 1 : 0], raise_coercion_error)
55
53
  end
54
+ elsif Object.const_defined?('T::Private::Types::TypeAlias') &&
55
+ type.is_a?(T::Private::Types::TypeAlias)
56
+ _convert(value, type.aliased_type, raise_coercion_error)
56
57
  elsif type < T::Struct
57
- args = _build_args(value, type.props)
58
- begin
59
- type.new(args)
60
- rescue T::Props::InvalidValueError, ArgumentError
61
- nil
62
- end
58
+ args = _build_args(value, type, raise_coercion_error)
59
+ type.new(args)
63
60
  else
64
- _convert_simple(value, type)
61
+ _convert_simple(value, type, raise_coercion_error)
65
62
  end
66
63
  end
67
64
 
68
- sig { params(value: T.untyped, type: T.untyped).returns(T.untyped) }
69
- def _convert_simple(value, type)
70
- return nil if value.nil?
65
+ sig { params(value: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
66
+ def _convert_simple(value, type, raise_coercion_error)
67
+ return nil if _nil_like?(value, type)
68
+
71
69
  safe_type_rule = T.let(nil, T.untyped)
72
70
 
73
71
  if type == T::Boolean
@@ -81,38 +79,48 @@ module T::Private
81
79
  end
82
80
  SafeType::coerce(value, safe_type_rule)
83
81
  rescue SafeType::EmptyValueError, SafeType::CoercionError
84
- nil
85
- rescue SafeType::InvalidRuleError
86
- begin
87
- type.new(value)
88
- rescue
82
+ if raise_coercion_error
83
+ raise T::Coerce::CoercionError.new(value, type)
84
+ else
89
85
  nil
90
86
  end
87
+ rescue SafeType::InvalidRuleError
88
+ type.new(value)
91
89
  end
92
90
 
93
- sig { params(ary: T.untyped, type: T.untyped).returns(T.untyped) }
94
- def _convert_to_a(ary, type)
95
- ary = [ary] unless ary.is_a?(::Array)
96
- T.send(
97
- 'let',
98
- ary.map { |value| _convert(value, type) },
99
- T.const_get('Array')[type],
100
- )
101
- rescue TypeError
102
- []
91
+ sig { params(ary: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
92
+ def _convert_to_a(ary, type, raise_coercion_error)
93
+ return [] if _nil_like?(ary, type)
94
+
95
+ unless ary.respond_to?(:map)
96
+ raise T::Coerce::ShapeError.new(ary, type)
97
+ end
98
+
99
+ ary.map { |value| _convert(value, type, raise_coercion_error) }
103
100
  end
104
101
 
105
- sig { params(args: T.untyped, props: T.untyped).returns(T.untyped) }
106
- def _build_args(args, props)
107
- return {} if args.nil?
102
+ sig { params(args: T.untyped, type: T.untyped, raise_coercion_error: T::Boolean).returns(T.untyped) }
103
+ def _build_args(args, type, raise_coercion_error)
104
+ return {} if _nil_like?(args, Hash)
105
+
106
+ unless args.respond_to?(:each_pair)
107
+ raise T::Coerce::ShapeError.new(args, type)
108
+ end
109
+
110
+ props = type.props
108
111
  args.map { |name, value|
109
112
  key = name.to_sym
110
113
  [
111
114
  key,
112
115
  (!props.include?(key) || value.nil?) ?
113
- nil : _convert(value, props[key][:type]),
116
+ nil : _convert(value, props[key][:type], raise_coercion_error),
114
117
  ]
115
118
  }.to_h.slice(*props.keys)
116
119
  end
120
+
121
+ sig { params(value: T.untyped, type: T.untyped).returns(T::Boolean) }
122
+ def _nil_like?(value, type)
123
+ value.nil? || (value == '' && type != String)
124
+ end
117
125
  end
118
126
  end
@@ -1,22 +1,22 @@
1
1
  # typed: strict
2
+ require_relative 'configuration'
2
3
  require 'private/converter'
3
4
  require 'safe_type'
4
5
 
5
- module T
6
+ module T::Coerce
6
7
  class CoercionError < SafeType::CoercionError; end
8
+ class ShapeError < SafeType::CoercionError; end
7
9
 
8
- module Coerce
9
- define_singleton_method(:[]) do |type|
10
- Class.new(T::Private::Converter) do
11
- define_method(:to_s) { "#{name}#[#{type.to_s}]" }
10
+ define_singleton_method(:[]) do |type|
11
+ Class.new(T::Private::Converter) do
12
+ define_method(:to_s) { "#{name}#[#{type.to_s}]" }
12
13
 
13
- define_method(:from) do |args|
14
- begin
15
- T.send('let', send('_convert', args, type), type)
16
- rescue TypeError
17
- raise CoercionError.new(args, type)
18
- end
14
+ define_method(:from) do |args, raise_coercion_error: nil|
15
+ if raise_coercion_error.nil?
16
+ raise_coercion_error = T::Coerce::Configuration.raise_coercion_error
19
17
  end
18
+
19
+ T.send('let', send('_convert', args, type, raise_coercion_error), type)
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ module T
3
+ module Coerce
4
+ extend T::Sig
5
+ extend T::Generic
6
+
7
+ Elem = type_member
8
+
9
+ sig { params(args: T.untyped, raise_value_error: T.nilable(T::Boolean)).returns(Elem) }
10
+ def from(args, raise_value_error: nil); end
11
+ end
12
+
13
+ module Private
14
+ module Types
15
+ class TypeAlias
16
+ def aliased_type; end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,198 @@
1
+ # typed: ignore
2
+ require 'sorbet-coerce'
3
+ require 'sorbet-runtime'
4
+
5
+ describe T::Coerce do
6
+ context 'when given T::Struct' do
7
+ class ParamInfo < T::Struct
8
+ const :name, String
9
+ const :lvl, T.nilable(Integer)
10
+ const :skill_ids, T::Array[Integer]
11
+ end
12
+
13
+ class ParamInfo2 < T::Struct
14
+ const :a, Integer
15
+ const :b, Integer
16
+ const :notes, T::Array[String], default: []
17
+ end
18
+
19
+ class Param < T::Struct
20
+ const :id, Integer
21
+ const :role, String, default: 'wizard'
22
+ const :info, ParamInfo
23
+ const :opt, T.nilable(ParamInfo2)
24
+ end
25
+
26
+ class DefaultParams < T::Struct
27
+ const :a, Integer, default: 1
28
+ end
29
+
30
+ class CustomType
31
+ attr_reader :a
32
+
33
+ def initialize(a)
34
+ @a = a
35
+ end
36
+ end
37
+
38
+ class CustomType2
39
+ def self.new(a); 1; end
40
+ end
41
+
42
+ class UnsupportedCustomType
43
+ # Does not respond to new
44
+ end
45
+
46
+ let!(:param) {
47
+ T::Coerce[Param].new.from({
48
+ id: 1,
49
+ info: {
50
+ name: 'mango',
51
+ lvl: 100,
52
+ skill_ids: ['123', '456'],
53
+ },
54
+ opt: {
55
+ a: 1,
56
+ b: 2,
57
+ },
58
+ extra_attr: 'does not matter',
59
+ })
60
+ }
61
+
62
+ let!(:param2) {
63
+ T::Coerce[Param].new.from({
64
+ id: '2',
65
+ info: {
66
+ name: 'honeydew',
67
+ lvl: '5',
68
+ skill_ids: [],
69
+ },
70
+ opt: {
71
+ a: '1',
72
+ b: '2',
73
+ notes: [],
74
+ },
75
+ })
76
+ }
77
+
78
+ it 'reveals the right type' do
79
+ T.assert_type!(param, Param)
80
+ T.assert_type!(param.id, Integer)
81
+ T.assert_type!(param.info, ParamInfo)
82
+ T.assert_type!(param.info.name,String)
83
+ T.assert_type!(param.info.lvl, Integer)
84
+ T.assert_type!(param.opt, T.nilable(ParamInfo2))
85
+ end
86
+
87
+ it 'coerces correctly' do
88
+ expect(param.id).to eql 1
89
+ expect(param.role).to eql 'wizard'
90
+ expect(param.info.lvl).to eql 100
91
+ expect(param.info.name).to eql 'mango'
92
+ expect(param.info.skill_ids).to eql [123, 456]
93
+ expect(param.opt.notes).to eql []
94
+
95
+ expect(param2.id).to eql 2
96
+ expect(param2.info.name).to eql 'honeydew'
97
+ expect(param2.info.lvl).to eql 5
98
+ expect(param2.info.skill_ids).to eql []
99
+ expect(param2.opt.a).to eql 1
100
+ expect(param2.opt.b).to eql 2
101
+ expect(param2.opt.notes).to eql []
102
+
103
+ expect {
104
+ T::Coerce[Param].new.from({
105
+ id: 3,
106
+ info: {
107
+ # missing required name
108
+ lvl: 2,
109
+ },
110
+ })
111
+ }.to raise_error(ArgumentError)
112
+
113
+ expect(T::Coerce[DefaultParams].new.from(nil).a).to be 1
114
+ expect(T::Coerce[DefaultParams].new.from('').a).to be 1
115
+ end
116
+ end
117
+
118
+ context 'when the given T::Struct is invalid' do
119
+ class Param2 < T::Struct
120
+ const :id, Integer
121
+ const :info, T.any(Integer, String)
122
+ end
123
+
124
+ it 'raises an error' do
125
+ expect {
126
+ T::Coerce[Param2].new.from({id: 1, info: 1})
127
+ }.to raise_error(ArgumentError)
128
+ end
129
+ end
130
+
131
+ context 'when given primitive types' do
132
+ it 'reveals the right type' do
133
+ T.assert_type!(T::Coerce[Integer].new.from(1), Integer)
134
+ T.assert_type!(T::Coerce[Integer].new.from('1.0'), Integer)
135
+ T.assert_type!(T::Coerce[T.nilable(Integer)].new.from(nil), T.nilable(Integer))
136
+ end
137
+
138
+ it 'coreces correctly' do
139
+ expect{T::Coerce[Integer].new.from(nil)}.to raise_error(TypeError)
140
+ expect(T::Coerce[T.nilable(Integer)].new.from(nil) || 1).to eql 1
141
+ expect(T::Coerce[Integer].new.from(2)).to eql 2
142
+ expect(T::Coerce[Integer].new.from('1.0')).to eql 1
143
+
144
+ expect{T::Coerce[T.nilable(Integer)].new.from('invalid integer string')}.to raise_error(T::Coerce::CoercionError)
145
+ expect(T::Coerce[Float].new.from('1.0')).to eql 1.0
146
+
147
+ expect(T::Coerce[T::Boolean].new.from('false')).to be false
148
+ expect(T::Coerce[T::Boolean].new.from('true')).to be true
149
+
150
+ expect(T::Coerce[T.nilable(Integer)].new.from('')).to be nil
151
+ expect{T::Coerce[T.nilable(Integer)].new.from([])}.to raise_error(T::Coerce::CoercionError)
152
+ expect(T::Coerce[T.nilable(String)].new.from('')).to eql ''
153
+ end
154
+ end
155
+
156
+ context 'when given custom types' do
157
+ it 'coerces correctly' do
158
+ T.assert_type!(T::Coerce[CustomType].new.from(a: 1), CustomType)
159
+ expect(T::Coerce[CustomType].new.from(1).a).to be 1
160
+
161
+ expect{T::Coerce[UnsupportedCustomType].new.from(1)}.to raise_error(ArgumentError)
162
+ # CustomType2.new(anything) returns Integer 1; 1.is_a?(CustomType2) == false
163
+ expect{T::Coerce[CustomType2].new.from(1)}.to raise_error(TypeError)
164
+ end
165
+ end
166
+
167
+ context 'when dealing with arries' do
168
+ it 'coreces correctly' do
169
+ expect(T::Coerce[T::Array[Integer]].new.from(nil)).to eql []
170
+ expect(T::Coerce[T::Array[Integer]].new.from('')).to eql []
171
+ expect{T::Coerce[T::Array[Integer]].new.from('not an array')}.to raise_error(T::Coerce::ShapeError)
172
+ expect{T::Coerce[T::Array[Integer]].new.from('1')}.to raise_error(T::Coerce::ShapeError)
173
+ expect(T::Coerce[T::Array[Integer]].new.from(['1', '2', '3'])).to eql [1, 2, 3]
174
+ expect{T::Coerce[T::Array[Integer]].new.from(['1', 'invalid', '3'])}.to raise_error(T::Coerce::CoercionError)
175
+ expect{T::Coerce[T::Array[Integer]].new.from({a: 1})}.to raise_error(T::Coerce::CoercionError)
176
+
177
+ infos = T::Coerce[T::Array[ParamInfo]].new.from([{name: 'a', skill_ids: []}])
178
+ T.assert_type!(infos, T::Array[ParamInfo])
179
+ expect(infos.first.name).to eql 'a'
180
+
181
+ infos = T::Coerce[T::Array[ParamInfo]].new.from([{name: 'b', skill_ids: []}])
182
+ T.assert_type!(infos, T::Array[ParamInfo])
183
+ expect(infos.first.name).to eql 'b'
184
+
185
+ expect {
186
+ T::Coerce[ParamInfo2].new.from({a: nil, b: nil})
187
+ }.to raise_error(TypeError)
188
+ end
189
+ end
190
+
191
+ context 'when given a type alias' do
192
+ MyType = T.type_alias(T::Boolean)
193
+
194
+ it 'coerces correctly' do
195
+ expect(T::Coerce[MyType].new.from('false')).to be false
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,79 @@
1
+ # typed: false
2
+ require 'sorbet-coerce'
3
+ require 'sorbet-runtime'
4
+
5
+ describe T::Coerce do
6
+ context 'when given nested types' do
7
+ class User < T::Struct
8
+ const :id, Integer
9
+ const :valid, T.nilable(T::Boolean)
10
+ end
11
+
12
+ class NestedParam < T::Struct
13
+ const :users, T::Array[User]
14
+ const :params, T.nilable(NestedParam)
15
+ end
16
+
17
+ it 'works with nest T::Struct' do
18
+ converted = T::Coerce[NestedParam].new.from({
19
+ users: [{id: '1'}],
20
+ params: {
21
+ users: [{id: '2', valid: 'true'}],
22
+ params: {
23
+ users: [{id: '3', valid: 'true'}],
24
+ },
25
+ },
26
+ })
27
+ # => <NestedParam
28
+ # params=<NestedParam
29
+ # params=<NestedParam
30
+ # params=nil,
31
+ # users=[<User id=3 valid=true>]
32
+ # >,
33
+ # users=[<User id=2 valid=true>]
34
+ # >,
35
+ # users=[<User id=1 valid=nil>]
36
+ # >
37
+
38
+ expect(converted.users.map(&:id)).to eql([1])
39
+ expect(converted.params.users.map(&:id)).to eql([2])
40
+ expect(converted.params.params.users.map(&:id)).to eql([3])
41
+ end
42
+
43
+ it 'works with nest T::Array' do
44
+ expect {
45
+ T::Coerce[T::Array[T.nilable(Integer)]].new.from(['1', 'invalid', '3'])
46
+ }.to raise_error(T::Coerce::CoercionError)
47
+ expect(
48
+ T::Coerce[T::Array[T::Array[Integer]]].new.from([nil])
49
+ ).to eql([[]])
50
+ expect(
51
+ T::Coerce[T::Array[T::Array[Integer]]].new.from([['1'], ['2'], ['3']]),
52
+ ).to eql [[1], [2], [3]]
53
+
54
+ expect(T::Coerce[
55
+ T::Array[
56
+ T::Array[
57
+ T::Array[User]
58
+ ]
59
+ ]
60
+ ].new.from([[[{id: '1'}]]]).flatten.first.id).to eql(1)
61
+
62
+ expect(T::Coerce[
63
+ T::Array[
64
+ T::Array[
65
+ T::Array[
66
+ T::Array[
67
+ T::Array[User]
68
+ ]
69
+ ]
70
+ ]
71
+ ]
72
+ ].new.from([[[[[{id: 1}]]]]]).flatten.first.id).to eql 1
73
+
74
+ expect(T::Coerce[
75
+ T.nilable(T::Array[T.nilable(T::Array[T.nilable(User)])])
76
+ ].new.from([[{id: '1'}]]).flatten.map(&:id)).to eql([1])
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,66 @@
1
+ # typed: false
2
+ require 'sorbet-coerce'
3
+ require 'sorbet-runtime'
4
+
5
+ describe T::Coerce do
6
+ context 'when type errors are soft errors' do
7
+ let(:ignore_error) { Proc.new {} }
8
+
9
+ before(:each) do
10
+ allow(T::Coerce::Configuration).to receive(
11
+ :raise_coercion_error,
12
+ ).and_return(false)
13
+
14
+ allow(T::Configuration).to receive(
15
+ :inline_type_error_handler,
16
+ ).and_return(ignore_error)
17
+
18
+ allow(T::Configuration).to receive(
19
+ :call_validation_error_handler,
20
+ ).and_return(ignore_error)
21
+
22
+ allow(T::Configuration).to receive(
23
+ :sig_builder_error_handler,
24
+ ).and_return(ignore_error)
25
+ end
26
+
27
+ class ParamsWithSortError < T::Struct
28
+ const :a, Integer
29
+ end
30
+
31
+ class CustomTypeRaisesHardError
32
+ def initialize(value)
33
+ raise StandardError.new('value cannot be 1') if value == 1
34
+ end
35
+ end
36
+
37
+ class CustomTypeDoesNotRiaseHardError
38
+ def self.new(a); 1; end
39
+ end
40
+
41
+ let(:invalid_arg) { 'invalid integer string' }
42
+
43
+ it 'overwrites the global config when inline config is set' do
44
+ expect {
45
+ T::Coerce[Integer].new.from(invalid_arg, raise_coercion_error: true)
46
+ }.to raise_error(T::Coerce::CoercionError)
47
+ end
48
+
49
+ it 'works as expected' do
50
+ expect(T::Coerce[Integer].new.from(invalid_arg)).to eql(nil)
51
+
52
+ expect{T::Coerce[T::Array[Integer]].new.from(1)}.to raise_error(T::Coerce::ShapeError)
53
+ expect(T::Coerce[T::Array[Integer]].new.from({a: 1})).to eql([nil])
54
+
55
+ expect {
56
+ T::Coerce[CustomTypeRaisesHardError].new.from(1)
57
+ }.to raise_error(StandardError)
58
+ expect(T::Coerce[CustomTypeDoesNotRiaseHardError].new.from(1)).to eql(1)
59
+
60
+ sorbet_version = Gem.loaded_specs['sorbet-runtime'].version
61
+ if sorbet_version >= Gem::Version.new('0.4.4948')
62
+ expect(T::Coerce[ParamsWithSortError].new.from({a: invalid_arg}).a).to eql(nil)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,14 @@
1
+ # typed: strict
2
+ require 'byebug'
3
+ require 'simplecov'
4
+
5
+ SimpleCov.start
6
+
7
+ if ENV['CI'] == 'true'
8
+ require 'codecov'
9
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet-coerce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chan Zuckerberg Initiative
@@ -14,14 +14,14 @@ dependencies:
14
14
  name: sorbet
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.4.4704
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.4.4704
27
27
  - !ruby/object:Gem::Dependency
@@ -62,54 +62,54 @@ dependencies:
62
62
  name: sorbet-runtime
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: 0.4.4704
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
- - - "~>"
72
+ - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 0.4.4704
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: rspec
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ">="
79
+ - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '3.8'
82
- - - "~>"
82
+ - - ">="
83
83
  - !ruby/object:Gem::Version
84
84
  version: '3.8'
85
85
  type: :development
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - ">="
89
+ - - "~>"
90
90
  - !ruby/object:Gem::Version
91
91
  version: '3.8'
92
- - - "~>"
92
+ - - ">="
93
93
  - !ruby/object:Gem::Version
94
94
  version: '3.8'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: byebug
97
97
  requirement: !ruby/object:Gem::Requirement
98
98
  requirements:
99
- - - ">="
99
+ - - "~>"
100
100
  - !ruby/object:Gem::Version
101
101
  version: 11.0.1
102
- - - "~>"
102
+ - - ">="
103
103
  - !ruby/object:Gem::Version
104
104
  version: 11.0.1
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ">="
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: 11.0.1
112
- - - "~>"
112
+ - - ">="
113
113
  - !ruby/object:Gem::Version
114
114
  version: 11.0.1
115
115
  description:
@@ -118,9 +118,14 @@ executables: []
118
118
  extensions: []
119
119
  extra_rdoc_files: []
120
120
  files:
121
+ - lib/configuration.rb
121
122
  - lib/private/converter.rb
122
123
  - lib/sorbet-coerce.rb
123
- - lib/sorbet-coerce.rbi
124
+ - rbi/sorbet-coerce.rbi
125
+ - spec/coerce_spec.rb
126
+ - spec/nested_spec.rb
127
+ - spec/soft_error_spec.rb
128
+ - spec/spec_helper.rb
124
129
  homepage: https://github.com/chanzuckerberg/sorbet-coerce
125
130
  licenses:
126
131
  - MIT
@@ -133,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
138
  requirements:
134
139
  - - ">="
135
140
  - !ruby/object:Gem::Version
136
- version: 2.3.0
141
+ version: 2.4.0
137
142
  required_rubygems_version: !ruby/object:Gem::Requirement
138
143
  requirements:
139
144
  - - ">="
@@ -141,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
146
  version: '0'
142
147
  requirements: []
143
148
  rubyforge_project:
144
- rubygems_version: 2.7.9
149
+ rubygems_version: 2.7.7
145
150
  signing_key:
146
151
  specification_version: 4
147
152
  summary: A type coercion lib works with Sorbet's static type checker and type definitions;
@@ -1,13 +0,0 @@
1
- # typed: strong
2
-
3
- module T
4
- module Coerce
5
- extend T::Sig
6
- extend T::Generic
7
-
8
- Elem = type_member
9
-
10
- sig { params(args: T.untyped).returns(Elem) }
11
- def from(args); end
12
- end
13
- end