rtype-native 0.6.6 → 0.6.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9296a99a60b8f7ea3ec34c5464aad09d27c6ccd
4
- data.tar.gz: ec627f0a0fc11a3fbf9182d194954bb6d98a3dde
3
+ metadata.gz: 1532be5637819ff82d30dbd34a3ce0314af8cb04
4
+ data.tar.gz: b2ed2031f2ba992c59005fbd9008ac3de99ea89e
5
5
  SHA512:
6
- metadata.gz: 111203e0c9cc7ce0b0ee3c25eea6ee7e74d4c7bb604af1de6466788aaa5ec72668e2f3691232bcd1769dd1376bd0a7218923a45dcdf5bdda99f6679a7f64bfb0
7
- data.tar.gz: d4b8c28841bd430666a1fe08114fdc3c505bdb7ebfa03b50db7ac20048462a03085bebe99443c7e9f9662b7155ef11890d54581a605ffea5841883dbea43f674
6
+ metadata.gz: 007445e116ded093152f2bba33fc8d56259a16fbaa9e7cbe0848110053152b2040d8ff682f532aa81e0945a41d64e2692924fdaff40f0ee86581c0022bef9efb
7
+ data.tar.gz: fe39ccf6a59187b32c869a4fd09dc05d2fc0ba68a6a452e008297d0f3cb3c8eddd777fea51b0f81cb9e1910f0ff341155e3f43a89fcb0dc270f05914d12b0461
data/README.md CHANGED
@@ -12,17 +12,27 @@ class Test
12
12
  a.to_i + b
13
13
  end
14
14
 
15
- rtype {state: Boolean} => Boolean
15
+ rtype [{state: Boolean}] => Boolean
16
16
  def self.invert(state:)
17
17
  !state
18
18
  end
19
+
20
+ # Hashes of hashes params require () to prevent invalid syntax
21
+ rtype({state: Boolean} => Boolean)
22
+ def self.invert2(state:)
23
+ !state
24
+ end
19
25
  end
20
26
 
21
27
  Test.new.sum(123, "asd")
22
28
  # (Rtype::ArgumentTypeError) for 2nd argument:
23
29
  # Expected "asd" to be a Numeric
24
30
 
25
- Test::invert(state: 0)
31
+ Test.invert(state: 0)
32
+ # (Rtype::ArgumentTypeError) for 'state' argument:
33
+ # Expected 0 to be a Boolean
34
+
35
+ Test.invert2(state: 0)
26
36
  # (Rtype::ArgumentTypeError) for 'state' argument:
27
37
  # Expected 0 to be a Boolean
28
38
  ```
@@ -40,8 +50,10 @@ Test::invert(state: 0)
40
50
  - Provides type checking for [Keyword Argument](#keyword-argument)
41
51
  - [Type checking for hash elements](#hash)
42
52
  - [Duck Typing](#duck-typing)
43
- - [Typed Array](#typed-array)
53
+ - [Typed Array](#typed-array), Typed Set, Typed Hash
44
54
  - [Numeric check](#special-behaviors). e.g. `Int >= 0`
55
+ - [Type checking for getter and setter](#attr_accessor-with-rtype)
56
+ - [float_accessor](#float_accessor), [bool_accessor](#bool_accessor)
45
57
  - Custom type behavior
46
58
  - ...
47
59
 
@@ -67,16 +79,8 @@ gem 'rtype-native'
67
79
  ```
68
80
  then, Rtype uses it. (**Do not** `require 'rtype-native'`)
69
81
 
70
- #### Java extension for JRuby
71
- Run
72
- ```ruby
73
- gem install rtype-java
74
- ```
75
- or add to your `Gemfile`:
76
- ```ruby
77
- gem 'rtype-java'
78
- ```
79
- then, Rtype uses it. (**Do not** `require 'rtype-java'`)
82
+ #### Java extension for JRuby is automatic
83
+ **Do not** `require 'rtype-java'`
80
84
 
81
85
  ## Usage
82
86
 
@@ -106,7 +110,7 @@ then, Rtype uses it. (**Do not** `require 'rtype-java'`)
106
110
  - Example: [Hash](#hash)
107
111
 
108
112
  - [Special Behaviors](#special-behaviors)
109
- - `TypedArray`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
113
+ - `TypedArray, TypedSet, TypedHash`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
110
114
 
111
115
  ### Examples
112
116
 
@@ -204,34 +208,35 @@ def func(hash)
204
208
  puts hash[:msg]
205
209
  end
206
210
 
207
- # last hash is not hash argument but keyword arguments
208
- func({}, {})
211
+ func({})
209
212
  # (Rtype::ArgumentTypeError) for 1st argument:
210
213
  # Expected {} to be a hash with 1 elements:
211
214
  # - msg : Expected nil to be a String
212
215
 
213
- func({msg: 123}, {})
216
+ func({msg: 123})
214
217
  # (Rtype::ArgumentTypeError) for 1st argument:
215
218
  # Expected {:msg=>123} to be a hash with 1 elements:
216
219
  # - msg : Expected 123 to be a String
217
220
 
218
- func({msg: "hello", key: 'value'}, {})
221
+ func({msg: "hello", key: 'value'})
219
222
  # (Rtype::ArgumentTypeError) for 1st argument:
220
223
  # Expected {:msg=>"hello", :key=>"value"} to be a hash with 1 elements:
221
224
  # - msg : Expected "hello" to be a String
222
225
 
223
- func({"msg" => "hello hash"}, {})
226
+ func({"msg" => "hello hash"})
224
227
  # (Rtype::ArgumentTypeError) for 1st argument:
225
228
  # Expected {"msg"=>"hello hash"} to be a hash with 1 elements:
226
229
  # - msg : Expected nil to be a String
227
230
 
228
- func({msg: "hello hash"}, {}) # hello hash
231
+ func({msg: "hello hash"}) # hello hash
229
232
  ```
230
233
 
231
- #### rtype with attr_accessor
232
- `rtype_accessor` : calls `attr_accessor` if the accessor method(getter/setter) is not defined. and makes it typed
234
+ #### attr_accessor with rtype
235
+ - `rtype_accessor(*names, type)` : calls `attr_accessor` if the accessor methods(getter/setter) are not defined. and makes it typed
236
+ - `rtype_reader(*names, type)` : calls `attr_reader` if the getters are not defined. and makes it typed
237
+ - `rtype_writer(*names, type)` : calls `attr_writer` if the setters are not defined. and makes it typed
233
238
 
234
- You can use `rtype_accessor_self` for static accessor.
239
+ You can use `rtype_accessor_self` for static accessor. (`rtype_reader_self`, `rtype_writer_self` also exist)
235
240
 
236
241
  ```ruby
237
242
  require 'rtype'
@@ -285,6 +290,29 @@ sum([1, 2, 3]) # => 6
285
290
  sum([1.0, 2, 3]) # => 6.0
286
291
  ```
287
292
 
293
+ #### float_accessor
294
+ ```ruby
295
+ class Point
296
+ float_accessor :x, :y
297
+ end
298
+
299
+ v = Point.new
300
+ v.x = 1
301
+ v.x # => 1.0 (always Float)
302
+ ```
303
+
304
+ #### bool_accessor
305
+ ```ruby
306
+ class Human
307
+ bool_accessor :hungry
308
+ end
309
+
310
+ a = Human.new
311
+ a.hungry = true
312
+ a.hungry? # => true
313
+ a.hungry # NoMethodError
314
+ ```
315
+
288
316
  #### `rtype`
289
317
  ```ruby
290
318
  require 'rtype'
@@ -392,9 +420,14 @@ Example.new.method(:test).return_type
392
420
 
393
421
  #### Special Behaviors
394
422
  - `TypedArray` : Ensures value is an array with the type (type signature)
395
- - `Array::of(type)` (recommended)
396
- - or `Rtype::Behavior::TypedArray[type]`
423
+ - `Array.of(type)` (recommended)
397
424
  - Example: [TypedArray](#typed-array)
425
+
426
+ - `TypedSet` : Ensures value is a set with the type (type signature)
427
+ - `Set.of(type)` (recommended)
428
+
429
+ - `TypedHash` : Ensures value is a hash with the type (type signature)
430
+ - `Hash.of(key_type, value_type)` (recommended)
398
431
 
399
432
  - `Num, Int, Flo` : Numeric check
400
433
  - `Num/Int/Flo >/>=/</<=/== x`
@@ -403,19 +436,19 @@ Example.new.method(:test).return_type
403
436
  - e.g. `Flo >= 2` means value must be a `Float` and >= 2
404
437
 
405
438
  - `And` : Ensures value is valid for all given types
406
- - `Rtype::and(*types)`, `Rtype::Behavior::And[*types]`
439
+ - `Rtype.and(*types)`, `Rtype::Behavior::And[*types]`
407
440
  - or `Array#comb`, `Object#and(*others)`
408
441
 
409
442
  - `Xor` : Ensures value is valid for only one of given types
410
- - `Rtype::xor(*types)`, `Rtype::Behavior::Xor[*types]`
443
+ - `Rtype.xor(*types)`, `Rtype::Behavior::Xor[*types]`
411
444
  - or `Object#xor(*others)`
412
445
 
413
446
  - `Not` : Ensures value is not valid for all given types
414
- - `Rtype::not(*types)`, `Rtype::Behavior::Not[*types]`
447
+ - `Rtype.not(*types)`, `Rtype::Behavior::Not[*types]`
415
448
  - or `Object#not`
416
449
 
417
450
  - `Nilable` : Value can be nil
418
- - `Rtype::nilable(type)`, `Rtype::Behavior::Nilable[type]`
451
+ - `Rtype.nilable(type)`, `Rtype::Behavior::Nilable[type]`
419
452
  - or `Object#nilable`, `Object#or_nil`
420
453
 
421
454
  - You can create custom behaviors by extending `Rtype::Behavior::Base`
data/Rakefile CHANGED
@@ -8,5 +8,5 @@ task :default => [:spec]
8
8
  # Benchmark
9
9
  desc "Compare with pure ruby and other gems"
10
10
  task :benchmark do
11
- ruby "benchmark/benchmark.rb"
11
+ ruby "benchmark/benchmark.rb"
12
12
  end
@@ -2,5 +2,5 @@
2
2
  #define RTYPE_H
3
3
  #include "ruby.h"
4
4
  #include <string.h>
5
- #define RTYPE_NATIVE_EXT_VERSION "0.6.6"
5
+ #define RTYPE_NATIVE_EXT_VERSION "0.6.8"
6
6
  #endif
@@ -46,6 +46,10 @@ describe Rtype do
46
46
 
47
47
  def args_and_kwargs(a, b, c:, d:)
48
48
  end
49
+
50
+ public
51
+ def public_func
52
+ end
49
53
 
50
54
  protected
51
55
  def protected_func
@@ -149,7 +153,7 @@ describe Rtype do
149
153
  end
150
154
 
151
155
  it 'Kernel#rtype_accessor' do
152
- class TestClass
156
+ class AccessorTestClass
153
157
  rtype_accessor :value, :value2, String
154
158
 
155
159
  def initialize
@@ -157,23 +161,109 @@ describe Rtype do
157
161
  @value2 = 123
158
162
  end
159
163
  end
160
- expect {TestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
161
- expect {TestClass.new.value}.to raise_error Rtype::ReturnTypeError
162
- expect {TestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
163
- expect {TestClass.new.value2}.to raise_error Rtype::ReturnTypeError
164
+ expect {AccessorTestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
165
+ expect {AccessorTestClass.new.value}.to raise_error Rtype::ReturnTypeError
166
+ expect {AccessorTestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
167
+ expect {AccessorTestClass.new.value2}.to raise_error Rtype::ReturnTypeError
164
168
  end
165
169
 
166
170
  it 'Kernel#rtype_accessor_self' do
167
- class TestClass
171
+ class AccessorTestClass
168
172
  @@value = 123
169
173
  @@value2 = 123
170
-
171
174
  rtype_accessor_self :value, :value2, String
172
175
  end
173
- expect {TestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
174
- expect {TestClass::value}.to raise_error Rtype::ReturnTypeError
175
- expect {TestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
176
- expect {TestClass::value2}.to raise_error Rtype::ReturnTypeError
176
+ expect {AccessorTestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
177
+ expect {AccessorTestClass::value}.to raise_error Rtype::ReturnTypeError
178
+ expect {AccessorTestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
179
+ expect {AccessorTestClass::value2}.to raise_error Rtype::ReturnTypeError
180
+ end
181
+
182
+ it 'Kernel#rtype_reader' do
183
+ class ReaderTestClass
184
+ rtype_reader :value, :value2, String
185
+
186
+ def initialize
187
+ @value = 123
188
+ @value2 = 123
189
+ end
190
+ end
191
+ expect {ReaderTestClass.new.value}.to raise_error Rtype::ReturnTypeError
192
+ expect {ReaderTestClass.new.value2}.to raise_error Rtype::ReturnTypeError
193
+ end
194
+
195
+ it 'Kernel#rtype_reader_self' do
196
+ class ReaderTestClass
197
+ @@value = 123
198
+ @@value2 = 123
199
+ rtype_reader_self :value, :value2, String
200
+ end
201
+ expect {ReaderTestClass::value}.to raise_error Rtype::ReturnTypeError
202
+ expect {ReaderTestClass::value2}.to raise_error Rtype::ReturnTypeError
203
+ end
204
+
205
+ it 'Kernel#rtype_writer' do
206
+ class WriterTestClass
207
+ rtype_writer :value, :value2, String
208
+
209
+ def initialize
210
+ @value = 123
211
+ @value2 = 123
212
+ end
213
+ end
214
+ expect {WriterTestClass.new.value = 123}.to raise_error Rtype::ArgumentTypeError
215
+ expect {WriterTestClass.new.value2 = 123}.to raise_error Rtype::ArgumentTypeError
216
+ end
217
+
218
+ it 'Kernel#rtype_writer_self' do
219
+ class WriterTestClass
220
+ @@value = 123
221
+ @@value2 = 123
222
+ rtype_writer_self :value, :value2, String
223
+ end
224
+ expect {WriterTestClass::value = 123}.to raise_error Rtype::ArgumentTypeError
225
+ expect {WriterTestClass::value2 = 123}.to raise_error Rtype::ArgumentTypeError
226
+ end
227
+
228
+ it 'Kernel#float_accessor' do
229
+ class FloatAccessorTestClass
230
+ float_accessor :float, :int
231
+
232
+ def initialize
233
+ @float = 10.0
234
+ @int = 10
235
+ end
236
+ end
237
+
238
+ float_accessor_test = FloatAccessorTestClass.new
239
+
240
+ float_accessor_test.float
241
+ expect {float_accessor_test.int}.to raise_error Rtype::ReturnTypeError
242
+ float_accessor_test.float = 5.0
243
+ float_accessor_test.float = 5
244
+ expect(float_accessor_test.float).to eql(5.0) # be(expected) => passes if actual.eql?(expected)
245
+ expect(float_accessor_test.float).not_to eql(5)
246
+ end
247
+
248
+ it 'Kernel#bool_accessor' do
249
+ class BoolAccessorTestClass
250
+ bool_accessor :state, :invalid_var
251
+
252
+ def initialize
253
+ @state = false
254
+ @invalid_var = 123
255
+ end
256
+ end
257
+
258
+ bool_accessor_test = BoolAccessorTestClass.new
259
+
260
+ bool_accessor_test.state?
261
+ expect {bool_accessor_test.state}.to raise_error NoMethodError
262
+ expect(bool_accessor_test.state?).to eql(false)
263
+ bool_accessor_test.state = true
264
+ expect(bool_accessor_test.state?).to eql(true)
265
+ expect {bool_accessor_test.state = 123}.to raise_error Rtype::ArgumentTypeError
266
+ expect {bool_accessor_test.invalid_var?}.to raise_error Rtype::ReturnTypeError
177
267
  end
178
268
 
179
269
  describe 'Test type behaviors' do
@@ -475,6 +565,65 @@ describe Rtype do
475
565
  end
476
566
  end
477
567
 
568
+ describe 'Rtype::Behavior::TypedSet' do
569
+ it 'class singleton [] method' do
570
+ klass.send :rtype, :return_nil, [ Rtype::Behavior::TypedSet[Integer] ] => nil
571
+ instance.return_nil( Set.new([123]) )
572
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
573
+ expect { instance.return_nil(Set.new([1.0])) }.to raise_error Rtype::ArgumentTypeError
574
+ end
575
+
576
+ it 'core extension method (Set::of)' do
577
+ klass.send :rtype, :return_nil, [ Set.of(Integer) ] => nil
578
+ instance.return_nil( Set.new([123]) )
579
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
580
+ expect { instance.return_nil(Set.new([1.0])) }.to raise_error Rtype::ArgumentTypeError
581
+ end
582
+
583
+ it 'complicated type sig' do
584
+ klass.send :rtype, :return_nil, [ Set.of(:to_i.and(:chars)) ] => nil
585
+ instance.return_nil( Set.new(["hello"]) )
586
+ expect {instance.return_nil("hello")}.to raise_error Rtype::ArgumentTypeError
587
+ expect { instance.return_nil(Set.new([123])) }.to raise_error Rtype::ArgumentTypeError
588
+ end
589
+
590
+ it 'allows empty set' do
591
+ klass.send :rtype, :return_nil, [ Set.of(Integer) ] => nil
592
+ instance.return_nil(Set.new)
593
+ end
594
+ end
595
+
596
+ describe 'Rtype::Behavior::TypedHash' do
597
+ it 'class singleton [] method' do
598
+ klass.send :rtype, :return_nil, [ Rtype::Behavior::TypedHash[Symbol, Integer] ] => nil
599
+ instance.return_nil( {key: 123} )
600
+ expect {instance.return_nil(:key)}.to raise_error Rtype::ArgumentTypeError
601
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
602
+ expect {instance.return_nil( {"key" => 123} )}.to raise_error Rtype::ArgumentTypeError
603
+ end
604
+
605
+ it 'core extension method (Hash::of)' do
606
+ klass.send :rtype, :return_nil, [ Hash.of(Symbol, Integer) ] => nil
607
+ instance.return_nil( {key: 123} )
608
+ expect {instance.return_nil(:key)}.to raise_error Rtype::ArgumentTypeError
609
+ expect {instance.return_nil(123)}.to raise_error Rtype::ArgumentTypeError
610
+ expect {instance.return_nil( {"key" => 123} )}.to raise_error Rtype::ArgumentTypeError
611
+ end
612
+
613
+ it 'complicated type sig' do
614
+ klass.send :rtype, :return_nil, [ Hash.of(:to_i.and(:chars), :to_i.and(:chars)) ] => nil
615
+ instance.return_nil( {"key" => "val"} )
616
+ expect {instance.return_nil("hello")}.to raise_error Rtype::ArgumentTypeError
617
+ expect {instance.return_nil( {key: "val"} )}.to raise_error Rtype::ArgumentTypeError
618
+ expect {instance.return_nil( {"key" => :val} )}.to raise_error Rtype::ArgumentTypeError
619
+ end
620
+
621
+ it 'allows empty hash' do
622
+ klass.send :rtype, :return_nil, [ Hash.of(Symbol, Integer) ] => nil
623
+ instance.return_nil({})
624
+ end
625
+ end
626
+
478
627
  describe 'Numeric check' do
479
628
  it 'Num (Numeric)' do
480
629
  klass.send :rtype, :return_nil, [Num >= 0] => Any
@@ -751,6 +900,10 @@ describe Rtype do
751
900
  klass.send :rtype, :private_func, [] => Any
752
901
  expect {instance.private_func}.to raise_error NoMethodError
753
902
  end
903
+ it 'public' do
904
+ klass.send :rtype, :public_func, [] => Any
905
+ instance.public_func
906
+ end
754
907
  end
755
908
 
756
909
  context 'with empty argument signature' do
@@ -816,6 +969,32 @@ describe Rtype do
816
969
  AnnotationTest2.new.inst_one(123)
817
970
  AnnotationTest2::static_two(123)
818
971
  end
972
+
973
+ context 'when rtype signature duplicated' do
974
+ it 'the latest have priority' do
975
+ class PriorityTest1
976
+ rtype :test_priority, [String] => Any
977
+ def test_priority(arg)
978
+ end
979
+ rtype :test_priority, [Integer] => Any
980
+ end
981
+
982
+ PriorityTest1.new.test_priority(1)
983
+ expect { PriorityTest1.new.test_priority("str") }.to raise_error Rtype::ArgumentTypeError
984
+ end
985
+
986
+ it 'annotation mode have priority in contemporaneous signatures' do
987
+ class PriorityTest2
988
+ rtype :test_priority, [String] => Any
989
+ rtype [Integer] => Any
990
+ def test_priority(arg)
991
+ end
992
+ end
993
+
994
+ PriorityTest2.new.test_priority(1)
995
+ expect { PriorityTest2.new.test_priority("str") }.to raise_error Rtype::ArgumentTypeError
996
+ end
997
+ end
819
998
  end
820
999
 
821
1000
  describe "Call Rtype`s static method directly" do
@@ -3,6 +3,7 @@ Coveralls.wear!
3
3
 
4
4
  require 'rtype'
5
5
  require 'rspec'
6
+ require 'set'
6
7
 
7
8
  if !Rtype::NATIVE_EXT_VERSION.nil?
8
9
  puts "Rtype with native extension"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtype-native
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.6
4
+ version: 0.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sputnik Gugja
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2016-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rtype
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.6
19
+ version: 0.6.8
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
- version: 0.6.6
26
+ version: 0.6.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement