rtype 0.5.0 → 0.5.1

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.
data/lib/rtype.rb CHANGED
@@ -1,321 +1,324 @@
1
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
2
- begin
3
- require 'java'
4
- require 'rtype/rtype_java'
5
- puts "Rtype with Java extension"
6
- rescue LoadError
7
- puts "Rtype without native extension"
8
- end
9
- else
10
- begin
11
- require "rtype/rtype_native"
12
- puts "Rtype with C native extension"
13
- rescue LoadError
14
- puts "Rtype without native extension"
15
- end
16
- end
17
-
18
- require_relative 'rtype/rtype_proxy'
19
- require_relative 'rtype/method_annotator'
20
- require_relative 'rtype/core_ext'
21
- require_relative 'rtype/version'
22
- require_relative 'rtype/type_signature_error'
23
- require_relative 'rtype/argument_type_error'
24
- require_relative 'rtype/return_type_error'
25
- require_relative 'rtype/type_signature'
26
- require_relative 'rtype/behavior'
27
-
28
- module Rtype
29
- extend self
30
-
31
- # This is just the 'information'
32
- # Any change of this doesn't affect type checking
33
- @@type_signatures = Hash.new({})
34
-
35
- def define_typed_method(owner, method_name, type_sig_info)
36
- method_name = method_name.to_sym
37
- raise ArgumentError, "method_name is nil" if method_name.nil?
38
- assert_valid_type_sig(type_sig_info)
39
-
40
- el = type_sig_info.first
41
- arg_sig = el[0]
42
- return_sig = el[1]
43
-
44
- if arg_sig.is_a?(Array)
45
- expected_args = arg_sig.dup
46
- if expected_args.last.is_a?(Hash)
47
- expected_kwargs = expected_args.pop
48
- else
49
- expected_kwargs = {}
50
- end
51
- elsif arg_sig.is_a?(Hash)
52
- expected_args = []
53
- expected_kwargs = arg_sig
54
- end
55
-
56
- sig = TypeSignature.new
57
- sig.argument_type = arg_sig
58
- sig.return_type = return_sig
59
- @@type_signatures[owner][method_name] = sig
60
-
61
- define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
62
- end
63
-
64
- def define_typed_accessor(owner, accessor_name, type_behavior)
65
- getter = accessor_name.to_sym
66
- setter = :"#{accessor_name}="
67
- valid?(type_behavior, nil)
68
- define_typed_method owner, getter, [] => type_behavior
69
- define_typed_method owner, setter, [type_behavior] => Any
70
- end
71
-
72
- def type_signatures
73
- @@type_signatures
74
- end
75
-
76
- =begin
77
- def assert_keyword_arguments_type(expected_kwargs, kwargs)
78
- kwargs.each do |key, value|
79
- expected = expected_kwargs[key]
80
- unless expected.nil?
81
- unless valid?(expected, value)
82
- raise ArgumentTypeError, "for '#{key}' argument:\n" + type_error_message(expected, value)
83
- end
84
- end
85
- end
86
- end
87
- =end
88
-
89
- def arg_type_error_message(idx, expected, value)
90
- "#{arg_message(idx)}\n" + type_error_message(expected, value)
91
- end
92
-
93
- def kwarg_type_error_message(key, expected, value)
94
- "#{kwarg_message(key)}\n" + type_error_message(expected, value)
95
- end
96
-
97
- def arg_message(idx)
98
- "for #{(idx+1).ordinalize} argument:"
99
- end
100
-
101
- def kwarg_message(key)
102
- "for '#{key}' argument:"
103
- end
104
-
105
-
106
- def type_error_message(expected, value)
107
- case expected
108
- when Rtype::Behavior::Base
109
- expected.error_message(value)
110
- when Module
111
- "Expected #{value.inspect} to be a #{expected}"
112
- when Symbol
113
- "Expected #{value.inspect} to respond to :#{expected}"
114
- when Regexp
115
- "Expected stringified #{value.inspect} to match regexp #{expected.inspect}"
116
- when Range
117
- "Expected #{value.inspect} to be included in range #{expected.inspect}"
118
- when Array
119
- if value.is_a?(Array)
120
- arr = expected.map.with_index do |e, idx|
121
- if e.is_a?(Array) || e.is_a?(Hash)
122
- "- [#{idx}] index : {\n" + type_error_message(e, value[idx]) + "\n}"
123
- else
124
- "- [#{idx}] index : " + type_error_message(e, value[idx])
125
- end
126
- end
127
- "Expected #{value.inspect} to be an array with #{expected.length} elements:\n" + arr.join("\n")
128
- else
129
- "Expected #{value.inspect} to be an array"
130
- end
131
- when Hash
132
- if value.is_a?(Hash)
133
- arr = []
134
- expected.each do |k, v|
135
- if v.is_a?(Array) || v.is_a?(Hash)
136
- arr << "- #{k} : {\n" + type_error_message(v, value[k]) + "\n}"
137
- else
138
- arr << "- #{k} : " + type_error_message(v, value[k])
139
- end
140
- end
141
- "Expected #{value.inspect} to be an hash with #{expected.length} elements:\n" + arr.join("\n")
142
- else
143
- "Expected #{value.inspect} to be an hash"
144
- end
145
- when Proc
146
- "Expected #{value.inspect} to return a truthy value for proc #{expected}"
147
- when true
148
- "Expected #{value.inspect} to be a truthy value"
149
- when false
150
- "Expected #{value.inspect} to be a falsy value"
151
- when nil # for return
152
- "Expected #{value.inspect} to be nil"
153
- end
154
- end
155
-
156
- def assert_valid_type_sig(sig)
157
- unless sig.is_a?(Hash)
158
- raise TypeSignatureError, "Invalid type signature: type signature is not hash"
159
- end
160
- if sig.empty?
161
- raise TypeSignatureError, "Invalid type signature: type signature is empty hash"
162
- end
163
- assert_valid_arguments_type_sig(sig.first[0])
164
- assert_valid_return_type_sig(sig.first[1])
165
- end
166
-
167
- def assert_valid_arguments_type_sig(sig)
168
- if sig.is_a?(Array)
169
- sig = sig.dup
170
- if sig.last.is_a?(Hash)
171
- kwargs = sig.pop
172
- else
173
- kwargs = {}
174
- end
175
- sig.each { |e| assert_valid_argument_type_sig_element(e) }
176
- if kwargs.keys.any? { |e| !e.is_a?(Symbol) }
177
- raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
178
- end
179
- kwargs.each_value { |e| assert_valid_argument_type_sig_element(e) }
180
- elsif sig.is_a?(Hash)
181
- if sig.keys.any? { |e| !e.is_a?(Symbol) }
182
- raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
183
- end
184
- sig.each_value { |e| assert_valid_argument_type_sig_element(e) }
185
- else
186
- raise TypeSignatureError, "Invalid type signature: arguments type signature is neither array nor hash"
187
- end
188
- end
189
-
190
- def assert_valid_argument_type_sig_element(sig)
191
- case sig
192
- when Rtype::Behavior::Base
193
- when Module
194
- when Symbol
195
- when Regexp
196
- when Range
197
- when Array
198
- sig.each do |e|
199
- assert_valid_argument_type_sig_element(e)
200
- end
201
- when Hash
202
- sig.each_value do |e|
203
- assert_valid_argument_type_sig_element(e)
204
- end
205
- when Proc
206
- when true
207
- when false
208
- else
209
- raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{sig}"
210
- end
211
- end
212
-
213
- def assert_valid_return_type_sig(sig)
214
- assert_valid_argument_type_sig_element(sig) unless sig.nil?
215
- end
216
-
217
- private
218
- def define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
219
- # `send` is faster than `method(...).call`
220
- owner.send(:_rtype_proxy).send :define_method, method_name do |*args, **kwargs, &block|
221
- if kwargs.empty?
222
- ::Rtype::assert_arguments_type(expected_args, args)
223
- result = super(*args, &block)
224
- else
225
- ::Rtype::assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
226
- result = super(*args, **kwargs, &block)
227
- end
228
- ::Rtype::assert_return_type(return_sig, result)
229
- result
230
- end
231
- nil
232
- end
233
-
234
- public
235
- unless respond_to?(:valid?)
236
- # validate argument type
237
- def valid?(expected, value)
238
- case expected
239
- when Module
240
- value.is_a? expected
241
- when Symbol
242
- value.respond_to? expected
243
- when Regexp
244
- !!(expected =~ value.to_s)
245
- when Range
246
- expected.include?(value)
247
- when Hash
248
- return false unless value.is_a?(Hash)
249
- return false unless expected.keys == value.keys
250
- expected.all? { |k, v| valid?(v, value[k]) }
251
- when Array
252
- return false unless value.is_a?(Array)
253
- return false unless expected.length == value.length
254
- idx = -1
255
- expected.all? { |e| idx += 1; valid?(e, value[idx]) }
256
- when Proc
257
- !!expected.call(value)
258
- when true
259
- !!value
260
- when false
261
- !value
262
- when Rtype::Behavior::Base
263
- expected.valid? value
264
- else
265
- raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{expected}"
266
- end
267
- end
268
- end
269
-
270
- unless respond_to?(:assert_arguments_type)
271
- def assert_arguments_type(expected_args, args)
272
- # `length.times` is faster than `each_with_index`
273
- args.length.times do |i|
274
- expected = expected_args[i]
275
- value = args[i]
276
- unless expected.nil?
277
- unless valid?(expected, value)
278
- raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
279
- end
280
- end
281
- end
282
- end
283
- end
284
-
285
- unless respond_to?(:assert_arguments_type_with_keywords)
286
- def assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
287
- # `length.times` is faster than `each_with_index`
288
- args.length.times do |i|
289
- expected = expected_args[i]
290
- value = args[i]
291
- unless expected.nil?
292
- unless valid?(expected, value)
293
- raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
294
- end
295
- end
296
- end
297
- kwargs.each do |key, value|
298
- expected = expected_kwargs[key]
299
- unless expected.nil?
300
- unless valid?(expected, value)
301
- raise ArgumentTypeError, "#{kwarg_message(key)}\n" + type_error_message(expected, value)
302
- end
303
- end
304
- end
305
- end
306
- end
307
-
308
- unless respond_to?(:assert_return_type)
309
- def assert_return_type(expected, result)
310
- if expected.nil?
311
- unless result.nil?
312
- raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
313
- end
314
- else
315
- unless valid?(expected, result)
316
- raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
317
- end
318
- end
319
- end
320
- end
321
- end
1
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
2
+ begin
3
+ require 'java'
4
+ require 'rtype/rtype_java'
5
+ puts "Rtype with Java extension"
6
+ rescue LoadError
7
+ puts "Rtype without native extension"
8
+ end
9
+ else
10
+ begin
11
+ require "rtype/rtype_native"
12
+ puts "Rtype with C native extension"
13
+ rescue LoadError
14
+ puts "Rtype without native extension"
15
+ end
16
+ end
17
+
18
+ require_relative 'rtype/rtype_proxy'
19
+ require_relative 'rtype/method_annotator'
20
+ require_relative 'rtype/core_ext'
21
+ require_relative 'rtype/version'
22
+ require_relative 'rtype/type_signature_error'
23
+ require_relative 'rtype/argument_type_error'
24
+ require_relative 'rtype/return_type_error'
25
+ require_relative 'rtype/type_signature'
26
+ require_relative 'rtype/behavior'
27
+
28
+ module Rtype
29
+ extend self
30
+
31
+ # This is just the 'information'
32
+ # Any change of this doesn't affect type checking
33
+ @@type_signatures = Hash.new
34
+
35
+ def define_typed_method(owner, method_name, type_sig_info)
36
+ method_name = method_name.to_sym
37
+ raise ArgumentError, "method_name is nil" if method_name.nil?
38
+ assert_valid_type_sig(type_sig_info)
39
+
40
+ el = type_sig_info.first
41
+ arg_sig = el[0]
42
+ return_sig = el[1]
43
+
44
+ if arg_sig.is_a?(Array)
45
+ expected_args = arg_sig.dup
46
+ if expected_args.last.is_a?(Hash)
47
+ expected_kwargs = expected_args.pop
48
+ else
49
+ expected_kwargs = {}
50
+ end
51
+ elsif arg_sig.is_a?(Hash)
52
+ expected_args = []
53
+ expected_kwargs = arg_sig
54
+ end
55
+
56
+ sig = TypeSignature.new
57
+ sig.argument_type = arg_sig
58
+ sig.return_type = return_sig
59
+ unless @@type_signatures.key?(owner)
60
+ @@type_signatures[owner] = {}
61
+ end
62
+ @@type_signatures[owner][method_name] = sig
63
+
64
+ define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
65
+ end
66
+
67
+ def define_typed_accessor(owner, accessor_name, type_behavior)
68
+ getter = accessor_name.to_sym
69
+ setter = :"#{accessor_name}="
70
+ valid?(type_behavior, nil)
71
+ define_typed_method owner, getter, [] => type_behavior
72
+ define_typed_method owner, setter, [type_behavior] => Any
73
+ end
74
+
75
+ def type_signatures
76
+ @@type_signatures
77
+ end
78
+
79
+ =begin
80
+ def assert_keyword_arguments_type(expected_kwargs, kwargs)
81
+ kwargs.each do |key, value|
82
+ expected = expected_kwargs[key]
83
+ unless expected.nil?
84
+ unless valid?(expected, value)
85
+ raise ArgumentTypeError, "for '#{key}' argument:\n" + type_error_message(expected, value)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ =end
91
+
92
+ def arg_type_error_message(idx, expected, value)
93
+ "#{arg_message(idx)}\n" + type_error_message(expected, value)
94
+ end
95
+
96
+ def kwarg_type_error_message(key, expected, value)
97
+ "#{kwarg_message(key)}\n" + type_error_message(expected, value)
98
+ end
99
+
100
+ def arg_message(idx)
101
+ "for #{(idx+1).ordinalize} argument:"
102
+ end
103
+
104
+ def kwarg_message(key)
105
+ "for '#{key}' argument:"
106
+ end
107
+
108
+
109
+ def type_error_message(expected, value)
110
+ case expected
111
+ when Rtype::Behavior::Base
112
+ expected.error_message(value)
113
+ when Module
114
+ "Expected #{value.inspect} to be a #{expected}"
115
+ when Symbol
116
+ "Expected #{value.inspect} to respond to :#{expected}"
117
+ when Regexp
118
+ "Expected stringified #{value.inspect} to match regexp #{expected.inspect}"
119
+ when Range
120
+ "Expected #{value.inspect} to be included in range #{expected.inspect}"
121
+ when Array
122
+ if value.is_a?(Array)
123
+ arr = expected.map.with_index do |e, idx|
124
+ if e.is_a?(Array) || e.is_a?(Hash)
125
+ "- [#{idx}] index : {\n" + type_error_message(e, value[idx]) + "\n}"
126
+ else
127
+ "- [#{idx}] index : " + type_error_message(e, value[idx])
128
+ end
129
+ end
130
+ "Expected #{value.inspect} to be an array with #{expected.length} elements:\n" + arr.join("\n")
131
+ else
132
+ "Expected #{value.inspect} to be an array"
133
+ end
134
+ when Hash
135
+ if value.is_a?(Hash)
136
+ arr = []
137
+ expected.each do |k, v|
138
+ if v.is_a?(Array) || v.is_a?(Hash)
139
+ arr << "- #{k} : {\n" + type_error_message(v, value[k]) + "\n}"
140
+ else
141
+ arr << "- #{k} : " + type_error_message(v, value[k])
142
+ end
143
+ end
144
+ "Expected #{value.inspect} to be an hash with #{expected.length} elements:\n" + arr.join("\n")
145
+ else
146
+ "Expected #{value.inspect} to be an hash"
147
+ end
148
+ when Proc
149
+ "Expected #{value.inspect} to return a truthy value for proc #{expected}"
150
+ when true
151
+ "Expected #{value.inspect} to be a truthy value"
152
+ when false
153
+ "Expected #{value.inspect} to be a falsy value"
154
+ when nil # for return
155
+ "Expected #{value.inspect} to be nil"
156
+ end
157
+ end
158
+
159
+ def assert_valid_type_sig(sig)
160
+ unless sig.is_a?(Hash)
161
+ raise TypeSignatureError, "Invalid type signature: type signature is not hash"
162
+ end
163
+ if sig.empty?
164
+ raise TypeSignatureError, "Invalid type signature: type signature is empty hash"
165
+ end
166
+ assert_valid_arguments_type_sig(sig.first[0])
167
+ assert_valid_return_type_sig(sig.first[1])
168
+ end
169
+
170
+ def assert_valid_arguments_type_sig(sig)
171
+ if sig.is_a?(Array)
172
+ sig = sig.dup
173
+ if sig.last.is_a?(Hash)
174
+ kwargs = sig.pop
175
+ else
176
+ kwargs = {}
177
+ end
178
+ sig.each { |e| assert_valid_argument_type_sig_element(e) }
179
+ if kwargs.keys.any? { |e| !e.is_a?(Symbol) }
180
+ raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
181
+ end
182
+ kwargs.each_value { |e| assert_valid_argument_type_sig_element(e) }
183
+ elsif sig.is_a?(Hash)
184
+ if sig.keys.any? { |e| !e.is_a?(Symbol) }
185
+ raise TypeSignatureError, "Invalid type signature: keyword arguments contain non-symbol key"
186
+ end
187
+ sig.each_value { |e| assert_valid_argument_type_sig_element(e) }
188
+ else
189
+ raise TypeSignatureError, "Invalid type signature: arguments type signature is neither array nor hash"
190
+ end
191
+ end
192
+
193
+ def assert_valid_argument_type_sig_element(sig)
194
+ case sig
195
+ when Rtype::Behavior::Base
196
+ when Module
197
+ when Symbol
198
+ when Regexp
199
+ when Range
200
+ when Array
201
+ sig.each do |e|
202
+ assert_valid_argument_type_sig_element(e)
203
+ end
204
+ when Hash
205
+ sig.each_value do |e|
206
+ assert_valid_argument_type_sig_element(e)
207
+ end
208
+ when Proc
209
+ when true
210
+ when false
211
+ else
212
+ raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{sig}"
213
+ end
214
+ end
215
+
216
+ def assert_valid_return_type_sig(sig)
217
+ assert_valid_argument_type_sig_element(sig) unless sig.nil?
218
+ end
219
+
220
+ private
221
+ def define_typed_method_to_proxy(owner, method_name, expected_args, expected_kwargs, return_sig)
222
+ # `send` is faster than `method(...).call`
223
+ owner.send(:_rtype_proxy).send :define_method, method_name do |*args, **kwargs, &block|
224
+ if kwargs.empty?
225
+ ::Rtype::assert_arguments_type(expected_args, args)
226
+ result = super(*args, &block)
227
+ else
228
+ ::Rtype::assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
229
+ result = super(*args, **kwargs, &block)
230
+ end
231
+ ::Rtype::assert_return_type(return_sig, result)
232
+ result
233
+ end
234
+ nil
235
+ end
236
+
237
+ public
238
+ unless respond_to?(:valid?)
239
+ # validate argument type
240
+ def valid?(expected, value)
241
+ case expected
242
+ when Module
243
+ value.is_a? expected
244
+ when Symbol
245
+ value.respond_to? expected
246
+ when Regexp
247
+ !!(expected =~ value.to_s)
248
+ when Range
249
+ expected.include?(value)
250
+ when Hash
251
+ return false unless value.is_a?(Hash)
252
+ return false unless expected.keys == value.keys
253
+ expected.all? { |k, v| valid?(v, value[k]) }
254
+ when Array
255
+ return false unless value.is_a?(Array)
256
+ return false unless expected.length == value.length
257
+ idx = -1
258
+ expected.all? { |e| idx += 1; valid?(e, value[idx]) }
259
+ when Proc
260
+ !!expected.call(value)
261
+ when true
262
+ !!value
263
+ when false
264
+ !value
265
+ when Rtype::Behavior::Base
266
+ expected.valid? value
267
+ else
268
+ raise TypeSignatureError, "Invalid type signature: Unknown type behavior #{expected}"
269
+ end
270
+ end
271
+ end
272
+
273
+ unless respond_to?(:assert_arguments_type)
274
+ def assert_arguments_type(expected_args, args)
275
+ # `length.times` is faster than `each_with_index`
276
+ args.length.times do |i|
277
+ expected = expected_args[i]
278
+ value = args[i]
279
+ unless expected.nil?
280
+ unless valid?(expected, value)
281
+ raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
282
+ end
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ unless respond_to?(:assert_arguments_type_with_keywords)
289
+ def assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs)
290
+ # `length.times` is faster than `each_with_index`
291
+ args.length.times do |i|
292
+ expected = expected_args[i]
293
+ value = args[i]
294
+ unless expected.nil?
295
+ unless valid?(expected, value)
296
+ raise ArgumentTypeError, "#{arg_message(i)}\n" + type_error_message(expected, value)
297
+ end
298
+ end
299
+ end
300
+ kwargs.each do |key, value|
301
+ expected = expected_kwargs[key]
302
+ unless expected.nil?
303
+ unless valid?(expected, value)
304
+ raise ArgumentTypeError, "#{kwarg_message(key)}\n" + type_error_message(expected, value)
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
310
+
311
+ unless respond_to?(:assert_return_type)
312
+ def assert_return_type(expected, result)
313
+ if expected.nil?
314
+ unless result.nil?
315
+ raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
316
+ end
317
+ else
318
+ unless valid?(expected, result)
319
+ raise ReturnTypeError, "for return:\n" + type_error_message(expected, result)
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end