contracts 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MzAzMDEzNDY4MjVjYWM2Njk2ZWViYTI0MTQ4MTI5ZGZiMGZhOTNhNA==
5
- data.tar.gz: !binary |-
6
- NDFhYTJmODVkY2FlNWE3ZGI2ZjcxM2JiODMyODBlZjM4MmRjZDkwZQ==
2
+ SHA1:
3
+ metadata.gz: e31d0dc3c6a107d0255ab5af8229749e6ce825e6
4
+ data.tar.gz: 915617473470b5450ee855605380d7d6552d49a8
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZjNmODA2MDM5NGI0MjVjMzI0MDNlYmRjZWMzOTUxNmFhYmE0NWU1OGIwNzEz
10
- ZDAwMmNhZWVkMTMxMDZkZTUwOGMwN2VhYjBlOTg2MGFhNmEzNjM1N2Q0NTJi
11
- YzMzN2Y1ZTBiMWIwZDgyYWM0MmM5N2IyMjQ3ZWVmZGMwYzQxZDE=
12
- data.tar.gz: !binary |-
13
- ZTI2OWM5ZTNmYjFmMTI1NjU5ODUwNzM4MTg3NDBjYjkxM2RkZDJiYTBjNTcy
14
- ZGY4NzYzZWU2NmM3Njc2ZmFlZjAzYzBkZDdhYTQ3ZmViNDYyMDY5Yzc2N2M3
15
- Y2U5NTczYjdiODZjZjAxMzNiOGVjYTkyNzlhY2UyYmM3NDQzOWQ=
6
+ metadata.gz: 73c20ffc1467c52de7a44f91cf1711049c2db2f47aaf3b8faf517a0ba05030aa891c3748a0287ed6d5be799f96d3eb9b92eb8ea950041b0ff459e63262388a56
7
+ data.tar.gz: 0343d43d8437dcb11255392d53cb57e06119eb0dbd7f20880c0e0646d40b1abf9888e6b1fd5450464eed6ec4635444f7817b87228b1560eca81f0e4997a79eee
@@ -1,3 +1,9 @@
1
+ ## v0.13.0
2
+
3
+ - Enhancement: Add support for Ruby 2.3 - [Oleksii Fedorov](https://github.com/waterlink) [#216](https://github.com/egonSchiele/contracts.ruby/pull/216)
4
+ - Enhancement: Added Int, Nat and NatPos builtin contracts - [Simon George](https://github.com/sfcgeorge) [#212](https://github.com/egonSchiele/contracts.ruby/pull/212)
5
+ - Bugfix: Allow contracts on singleton of subclass - [Oleksii Federov](https://github.com/waterlink) [#211](https://github.com/egonSchiele/contracts.ruby/pull/211)
6
+
1
7
  ## v0.12.0
2
8
 
3
9
  - Feature: add `Regexp` validator - [Gert Goet](https://github.com/eval) [#196](https://github.com/egonSchiele/contracts.ruby/pull/196)
@@ -68,42 +68,44 @@ This can be useful if you're in a REPL and want to figure out how a function sho
68
68
  contracts.ruby comes with a lot of built-in contracts, including the following:
69
69
 
70
70
  * Basic types
71
- * [`Num`](http://www.rubydoc.info/gems/contracts/Contracts/Num) – checks that the argument is `Numeric`
72
- * [`Pos`](http://www.rubydoc.info/gems/contracts/Contracts/Pos) – checks that the argument is a positive number
73
- * [`Neg`](http://www.rubydoc.info/gems/contracts/Contracts/Neg) – checks that the argument is a negative number
74
- * [`Nat`](http://www.rubydoc.info/gems/contracts/Contracts/Nat) – checks that the argument is a natural number (>= 0)
75
- * [`Bool`](http://www.rubydoc.info/gems/contracts/Contracts/Bool) – checks that the argument is `true` or `false`
76
- * [`Any`](http://www.rubydoc.info/gems/contracts/Contracts/Any) – Passes for any argument. Use when the argument has no constraints.
77
- * [`None`](http://www.rubydoc.info/gems/contracts/Contracts/None) – Fails for any argument. Use when the method takes no arguments.
71
+ * [`Num`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Num) – checks that the argument is `Numeric`
72
+ * [`Pos`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Pos) – checks that the argument is a positive number
73
+ * [`Neg`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Neg) – checks that the argument is a negative number
74
+ * [`Int`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Int) – checks that the argument is an integer
75
+ * [`Nat`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Nat) – checks that the argument is a natural number (>= 0)
76
+ * [`NatPos`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/NatPos) – checks that the argument is a positive natural number (> 0)
77
+ * [`Bool`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Bool) – checks that the argument is `true` or `false`
78
+ * [`Any`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Any) – Passes for any argument. Use when the argument has no constraints.
79
+ * [`None`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/None) – Fails for any argument. Use when the method takes no arguments.
78
80
 
79
81
  * Logical combinations
80
- * [`Maybe`](http://www.rubydoc.info/gems/contracts/Contracts/Maybe) – specifies that a value _may be_ nil, e.g. `Maybe[String]` (equivalent to `Or[String,nil]`)
81
- * [`Or`](http://www.rubydoc.info/gems/contracts/Contracts/Or) – passes if any of the given contracts pass, e.g. `Or[Fixnum, Float]`
82
- * [`Xor`](http://www.rubydoc.info/gems/contracts/Contracts/Xor) – passes if exactly one of the given contracts pass, e.g. `Xor[Fixnum, Float]`
83
- * [`And`](http://www.rubydoc.info/gems/contracts/Contracts/And) – passes if all contracts pass, e.g. `And[Nat, -> (n) { n.even? }]`
84
- * [`Not`](http://www.rubydoc.info/gems/contracts/Contracts/Not) – passes if all contracts fail for the given argument, e.g. `Not[nil]`
82
+ * [`Maybe`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Maybe) – specifies that a value _may be_ nil, e.g. `Maybe[String]` (equivalent to `Or[String,nil]`)
83
+ * [`Or`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Or) – passes if any of the given contracts pass, e.g. `Or[Fixnum, Float]`
84
+ * [`Xor`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Xor) – passes if exactly one of the given contracts pass, e.g. `Xor[Fixnum, Float]`
85
+ * [`And`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/And) – passes if all contracts pass, e.g. `And[Nat, -> (n) { n.even? }]`
86
+ * [`Not`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Not) – passes if all contracts fail for the given argument, e.g. `Not[nil]`
85
87
 
86
88
  * Collections
87
- * [`ArrayOf`](http://www.rubydoc.info/gems/contracts/Contracts/ArrayOf) – checks that the argument is an array, and all elements pass the given contract, e.g. `ArrayOf[Num]`
88
- * [`SetOf`](http://www.rubydoc.info/gems/contracts/Contracts/SetOf) – checks that the argument is a set, and all elements pass the given contract, e.g. `SetOf[Num]`
89
- * [`HashOf`](http://www.rubydoc.info/gems/contracts/Contracts/HashOf) – checks that the argument is a hash, and all keys and values pass the given contract, e.g. `HashOf[Symbol => String]` or `HashOf[Symbol,String]`
90
- * [`RangeOf`](http://www.rubydoc.info/gems/contracts/Contracts/RangeOf) – checks that the argument is a range whose elements (#first and #last) pass the given contract, e.g. `RangeOf[Date]`
91
- * [`Enum`](http://www.rubydoc.info/gems/contracts/Contracts/Enum) – checks that the argument is part of a given collection of objects, e.g. `Enum[:a, :b, :c]`
89
+ * [`ArrayOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/ArrayOf) – checks that the argument is an array, and all elements pass the given contract, e.g. `ArrayOf[Num]`
90
+ * [`SetOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/SetOf) – checks that the argument is a set, and all elements pass the given contract, e.g. `SetOf[Num]`
91
+ * [`HashOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/HashOf) – checks that the argument is a hash, and all keys and values pass the given contract, e.g. `HashOf[Symbol => String]` or `HashOf[Symbol,String]`
92
+ * [`RangeOf`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/RangeOf) – checks that the argument is a range whose elements (#first and #last) pass the given contract, e.g. `RangeOf[Date]`
93
+ * [`Enum`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Enum) – checks that the argument is part of a given collection of objects, e.g. `Enum[:a, :b, :c]`
92
94
 
93
95
  * Keyword arguments
94
- * [`KeywordArgs`](http://www.rubydoc.info/gems/contracts/Contracts/KeywordArgs) – checks that the argument is an options hash, and all required keyword arguments are present, and all values pass their respective contracts, e.g. `KeywordArgs[:number => Num, :description => Optional[String]]`
95
- * [`Optional`](http://www.rubydoc.info/gems/contracts/Contracts/Optional) – checks that the keyword argument is either not present or pass the given contract, can not be used outside of `KeywordArgs` contract, e.g. `Optional[Num]`
96
+ * [`KeywordArgs`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/KeywordArgs) – checks that the argument is an options hash, and all required keyword arguments are present, and all values pass their respective contracts, e.g. `KeywordArgs[:number => Num, :description => Optional[String]]`
97
+ * [`Optional`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Optional) – checks that the keyword argument is either not present or pass the given contract, can not be used outside of `KeywordArgs` contract, e.g. `Optional[Num]`
96
98
 
97
99
  * Duck typing
98
- * [`RespondTo`](http://www.rubydoc.info/gems/contracts/Contracts/RespondTo) – checks that the argument responds to all of the given methods, e.g. `RespondTo[:password, :credit_card]`
99
- * [`Send`](http://www.rubydoc.info/gems/contracts/Contracts/Send) – checks that all named methods return a truthy value, e.g. `Send[:valid?]`
100
+ * [`RespondTo`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/RespondTo) – checks that the argument responds to all of the given methods, e.g. `RespondTo[:password, :credit_card]`
101
+ * [`Send`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Send) – checks that all named methods return a truthy value, e.g. `Send[:valid?]`
100
102
 
101
103
  * Miscellaneous
102
- * [`Exactly`](http://www.rubydoc.info/gems/contracts/Contracts/Exactly) – checks that the argument has the given type, not accepting sub-classes, e.g. `Exactly[Numeric]`.
103
- * [`Eq`](http://www.rubydoc.info/gems/contracts/Contracts/Eq) – checks that the argument is precisely equal to the given value, e.g. `Eq[String]` matches the class `String` and not a string instance.
104
- * [`Func`](http://www.rubydoc.info/gems/contracts/Contracts/Func) – specifies the contract for a proc/lambda e.g. `Contract ArrayOf[Num], Func[Num => Num] => ArrayOf[Num]`. See section "Contracts On Functions".
104
+ * [`Exactly`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Exactly) – checks that the argument has the given type, not accepting sub-classes, e.g. `Exactly[Numeric]`.
105
+ * [`Eq`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Eq) – checks that the argument is precisely equal to the given value, e.g. `Eq[String]` matches the class `String` and not a string instance.
106
+ * [`Func`](http://www.rubydoc.info/gems/contracts/Contracts/Builtin/Func) – specifies the contract for a proc/lambda e.g. `Contract ArrayOf[Num], Func[Num => Num] => ArrayOf[Num]`. See section "Contracts On Functions".
105
107
 
106
- To see all the built-in contracts and their full descriptions, check out the [RDoc](http://rubydoc.info/gems/contracts/Contracts).
108
+ To see all the built-in contracts and their full descriptions, check out the [RDoc](http://rubydoc.info/gems/contracts/Contracts/Builtin).
107
109
 
108
110
  It is recommended to use shortcut for referring builtin contracts:
109
111
 
@@ -1 +1,80 @@
1
- Feature: Args (TODO)
1
+ Feature: Args
2
+
3
+ Used for `*args` (variadic functions). Takes contract and uses it to validate
4
+ every element passed in through `*args`.
5
+
6
+ ```ruby
7
+ Contract C::Args[C::Num] => C::Bool
8
+ def example(*args)
9
+ ```
10
+
11
+ This example contract will validate all arguments passed through `*args` to
12
+ accept only numbers.
13
+
14
+ Background:
15
+ Given a file named "args_usage.rb" with:
16
+ """ruby
17
+ require "contracts"
18
+ C = Contracts
19
+
20
+ class Example
21
+ include Contracts::Core
22
+
23
+ Contract C::Args[C::Num] => C::Bool
24
+ def only_nums(*args)
25
+ args.inspect
26
+ end
27
+ end
28
+ """
29
+
30
+ Scenario: Accepts no arguments
31
+ Given a file named "accepts_no_arguments.rb" with:
32
+ """ruby
33
+ require "./args_usage"
34
+ puts Example.new.only_nums
35
+ """
36
+ When I run `ruby accepts_no_arguments.rb`
37
+ Then the output should contain:
38
+ """
39
+ []
40
+ """
41
+
42
+ Scenario: Accepts one valid argument
43
+ Given a file named "accepts_one_argument.rb" with:
44
+ """ruby
45
+ require "./args_usage"
46
+ puts Example.new.only_nums(42)
47
+ """
48
+ When I run `ruby accepts_one_argument.rb`
49
+ Then the output should contain:
50
+ """
51
+ [42]
52
+ """
53
+
54
+ Scenario: Accepts many valid arguments
55
+ Given a file named "accepts_many_arguments.rb" with:
56
+ """ruby
57
+ require "./args_usage"
58
+ puts Example.new.only_nums(42, 45, 17, 24)
59
+ """
60
+ When I run `ruby accepts_many_arguments.rb`
61
+ Then the output should contain:
62
+ """
63
+ [42, 45, 17, 24]
64
+ """
65
+
66
+ Scenario: Rejects invalid argument
67
+ Given a file named "rejects_invalid_argument.rb" with:
68
+ """ruby
69
+ require "./args_usage"
70
+ puts Example.new.only_nums(42, "foo", 17, 24)
71
+ """
72
+ When I run `ruby rejects_invalid_argument.rb`
73
+ Then the output should contain:
74
+ """
75
+ : Contract violation for argument 1 of 4: (ParamContractError)
76
+ Expected: (Args[Contracts::Builtin::Num]),
77
+ Actual: "foo"
78
+ Value guarded in: Example::only_nums
79
+ With Contract: Args => Bool
80
+ """
@@ -0,0 +1,93 @@
1
+ Feature: Int
2
+
3
+ Checks that an argument is an integer.
4
+
5
+ ```ruby
6
+ Contract C::Int => C::Int
7
+ ```
8
+
9
+ Background:
10
+ Given a file named "int_usage.rb" with:
11
+ """ruby
12
+ require "contracts"
13
+ C = Contracts
14
+
15
+ class Integr
16
+ include Contracts::Core
17
+
18
+ Contract C::Int => C::Int
19
+ def prev(number)
20
+ number - 1
21
+ end
22
+ end
23
+ """
24
+
25
+ Scenario: Accepts positive integers
26
+ Given a file named "accepts_positive_integers.rb" with:
27
+ """ruby
28
+ require "./int_usage"
29
+ puts Integr.new.prev(7)
30
+ """
31
+ When I run `ruby accepts_positive_integers.rb`
32
+ Then output should contain:
33
+ """
34
+ 6
35
+ """
36
+
37
+ Scenario: Accepts zero
38
+ Given a file named "accepts_zero.rb" with:
39
+ """ruby
40
+ require "./int_usage"
41
+ puts Integr.new.prev(1)
42
+ """
43
+ When I run `ruby accepts_zero.rb`
44
+ Then output should contain:
45
+ """
46
+ 0
47
+ """
48
+
49
+ Scenario: Accepts negative integers
50
+ Given a file named "accepts_negative_integers.rb" with:
51
+ """ruby
52
+ require "./int_usage"
53
+ puts Integr.new.prev(-1)
54
+ """
55
+ When I run `ruby accepts_negative_integers.rb`
56
+ Then output should contain:
57
+ """
58
+ -2
59
+ """
60
+
61
+ Scenario: Rejects floats
62
+ Given a file named "rejects_floats.rb" with:
63
+ """ruby
64
+ require "./int_usage"
65
+ puts Integr.new.prev(3.43)
66
+ """
67
+ When I run `ruby rejects_floats.rb`
68
+ Then output should contain:
69
+ """
70
+ : Contract violation for argument 1 of 1: (ParamContractError)
71
+ Expected: Int,
72
+ Actual: 3.43
73
+ Value guarded in: Integr::prev
74
+ With Contract: Int => Int
75
+ """
76
+ And output should contain "int_usage.rb:8"
77
+
78
+ Scenario: Rejects other values
79
+ Given a file named "rejects_others.rb" with:
80
+ """ruby
81
+ require "./int_usage"
82
+ puts Integr.new.prev("foo")
83
+ """
84
+ When I run `ruby rejects_others.rb`
85
+ Then output should contain:
86
+ """
87
+ : Contract violation for argument 1 of 1: (ParamContractError)
88
+ Expected: Int,
89
+ Actual: "foo"
90
+ Value guarded in: Integr::prev
91
+ With Contract: Int => Int
92
+ """
93
+ And output should contain "int_usage.rb:8"
@@ -0,0 +1,119 @@
1
+ Feature: NatPos
2
+
3
+ Checks that an argument is a positive natural number.
4
+
5
+ ```ruby
6
+ Contract C::NatPos => C::NatPos
7
+ ```
8
+
9
+ Background:
10
+ Given a file named "nat_pos_usage.rb" with:
11
+ """ruby
12
+ require "contracts"
13
+ C = Contracts
14
+
15
+ class NaturalPositive
16
+ include Contracts::Core
17
+
18
+ Contract C::NatPos => C::NatPos
19
+ def prev(number)
20
+ number - 1
21
+ end
22
+ end
23
+ """
24
+
25
+ Scenario: Accepts positive integers
26
+ Given a file named "accepts_positive_integers.rb" with:
27
+ """ruby
28
+ require "./nat_pos_usage"
29
+ puts NaturalPositive.new.prev(7)
30
+ """
31
+ When I run `ruby accepts_positive_integers.rb`
32
+ Then output should contain:
33
+ """
34
+ 6
35
+ """
36
+
37
+ Scenario: Rejects zero
38
+ Given a file named "rejects_zero.rb" with:
39
+ """ruby
40
+ require "./nat_pos_usage"
41
+ puts NaturalPositive.new.prev(0)
42
+ """
43
+ When I run `ruby rejects_zero.rb`
44
+ Then output should contain:
45
+ """
46
+ : Contract violation for argument 1 of 1: (ParamContractError)
47
+ Expected: NatPos,
48
+ Actual: 0
49
+ Value guarded in: NaturalPositive::prev
50
+ With Contract: NatPos => NatPos
51
+ """
52
+
53
+ Scenario: Rejects negative integers
54
+ Given a file named "rejects_negative_integers.rb" with:
55
+ """ruby
56
+ require "./nat_pos_usage"
57
+ puts NaturalPositive.new.prev(-1)
58
+ """
59
+ When I run `ruby rejects_negative_integers.rb`
60
+ Then output should contain:
61
+ """
62
+ : Contract violation for argument 1 of 1: (ParamContractError)
63
+ Expected: NatPos,
64
+ Actual: -1
65
+ Value guarded in: NaturalPositive::prev
66
+ With Contract: NatPos => NatPos
67
+ """
68
+ And output should contain "nat_pos_usage.rb:8"
69
+
70
+ Scenario: Rejects negative integers as a return value
71
+ Given a file named "rejects_negative_integers.rb" with:
72
+ """ruby
73
+ require "./nat_pos_usage"
74
+ puts NaturalPositive.new.prev(1)
75
+ """
76
+ When I run `ruby rejects_negative_integers.rb`
77
+ Then output should contain:
78
+ """
79
+ : Contract violation for return value: (ReturnContractError)
80
+ Expected: NatPos,
81
+ Actual: 0
82
+ Value guarded in: NaturalPositive::prev
83
+ With Contract: NatPos => NatPos
84
+ """
85
+ And output should contain "nat_pos_usage.rb:8"
86
+
87
+ Scenario: Rejects floats
88
+ Given a file named "rejects_floats.rb" with:
89
+ """ruby
90
+ require "./nat_pos_usage"
91
+ puts NaturalPositive.new.prev(3.43)
92
+ """
93
+ When I run `ruby rejects_floats.rb`
94
+ Then output should contain:
95
+ """
96
+ : Contract violation for argument 1 of 1: (ParamContractError)
97
+ Expected: NatPos,
98
+ Actual: 3.43
99
+ Value guarded in: NaturalPositive::prev
100
+ With Contract: NatPos => NatPos
101
+ """
102
+ And output should contain "nat_pos_usage.rb:8"
103
+
104
+ Scenario: Rejects other values
105
+ Given a file named "rejects_others.rb" with:
106
+ """ruby
107
+ require "./nat_pos_usage"
108
+ puts NaturalPositive.new.prev("foo")
109
+ """
110
+ When I run `ruby rejects_others.rb`
111
+ Then output should contain:
112
+ """
113
+ : Contract violation for argument 1 of 1: (ParamContractError)
114
+ Expected: NatPos,
115
+ Actual: "foo"
116
+ Value guarded in: NaturalPositive::prev
117
+ With Contract: NatPos => NatPos
118
+ """
119
+ And output should contain "nat_pos_usage.rb:8"
@@ -41,13 +41,27 @@ module Contracts
41
41
  end
42
42
  end
43
43
 
44
- # Check that an argument is a natural number.
44
+ # Check that an argument is an +Integer+.
45
+ class Int
46
+ def self.valid? val
47
+ val && val.is_a?(Integer)
48
+ end
49
+ end
50
+
51
+ # Check that an argument is a natural number (includes zero).
45
52
  class Nat
46
53
  def self.valid? val
47
54
  val && val.is_a?(Integer) && val >= 0
48
55
  end
49
56
  end
50
57
 
58
+ # Check that an argument is a positive natural number (excludes zero).
59
+ class NatPos
60
+ def self.valid? val
61
+ val && val.is_a?(Integer) && val > 0
62
+ end
63
+ end
64
+
51
65
  # Passes for any argument.
52
66
  class Any
53
67
  def self.valid? val
@@ -4,6 +4,10 @@ module Contracts
4
4
  Engine.apply(klass)
5
5
  end
6
6
 
7
+ def inherited(subclass)
8
+ Engine.fetch_from(subclass).set_eigenclass_owner
9
+ end
10
+
7
11
  def method_added(name)
8
12
  MethodHandler.new(name, false, self).handle
9
13
  super
@@ -18,6 +18,10 @@ module Contracts
18
18
  return Engine.fetch_from(eigenclass) if Engine.applied?(eigenclass)
19
19
 
20
20
  Target.new(eigenclass).apply(Eigenclass)
21
+ eigenclass.extend(MethodDecorators)
22
+ # FIXME; this should detect what user uses `include Contracts` or
23
+ # `include Contracts;;Core`
24
+ eigenclass.send(:include, Contracts)
21
25
  Engine.fetch_from(owner).set_eigenclass_owner
22
26
  Engine.fetch_from(eigenclass)
23
27
  end
@@ -53,6 +53,8 @@ module Contracts
53
53
 
54
54
  self.class.new(eigenclass).apply(Eigenclass)
55
55
  eigenclass.extend(MethodDecorators)
56
+ # FIXME; this should detect what user uses `include Contracts` or
57
+ # `include Contracts;;Core`
56
58
  eigenclass.send(:include, Contracts)
57
59
  end
58
60
 
@@ -1,3 +1,3 @@
1
1
  module Contracts
2
- VERSION = "0.12.0"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -141,32 +141,6 @@ RSpec.describe "Contracts:" do
141
141
  end.to raise_error(ContractError, /Expected: String/)
142
142
  end
143
143
 
144
- context "when owner class does not include Contracts" do
145
- let(:error) do
146
- # NOTE Unable to support this user-friendly error for ruby
147
- # 1.8.7 and jruby 1.8, 1.9 it has much less support for
148
- # singleton inheritance hierarchy
149
- if Contracts::Support.eigenclass_hierarchy_supported?
150
- [Contracts::ContractsNotIncluded, Contracts::ContractsNotIncluded::DEFAULT_MESSAGE]
151
- else
152
- [NoMethodError, /undefined method `Contract'/]
153
- end
154
- end
155
-
156
- it "fails with descriptive error" do
157
- expect do
158
- Class.new(GenericExample) do
159
- class << self
160
- Contract String => String
161
- def hoge(name)
162
- "super#{name}"
163
- end
164
- end
165
- end
166
- end.to raise_error(*error)
167
- end
168
- end
169
-
170
144
  describe "builtin contracts usage" do
171
145
  it "allows to use builtin contracts without namespacing and redundant Contracts inclusion" do
172
146
  expect do
@@ -176,6 +150,14 @@ RSpec.describe "Contracts:" do
176
150
  end
177
151
  end
178
152
 
153
+ describe "usage in the singleton class of a subclass" do
154
+ subject { SingletonInheritanceExampleSubclass }
155
+
156
+ it "should work with a valid contract on a singleton method" do
157
+ expect(subject.num(1)).to eq(1)
158
+ end
159
+ end
160
+
179
161
  describe "no contracts feature" do
180
162
  it "disables normal contract checks" do
181
163
  object = NoContractsSimpleExample.new
@@ -621,6 +621,12 @@ class SingletonInheritanceExample
621
621
  end
622
622
 
623
623
  class SingletonInheritanceExampleSubclass < SingletonInheritanceExample
624
+ class << self
625
+ Contract Integer => Integer
626
+ def num(int)
627
+ int
628
+ end
629
+ end
624
630
  end
625
631
 
626
632
  class BareOptionalContractUsed
@@ -120,7 +120,7 @@ RSpec.describe Contract do
120
120
  end.to raise_error(ContractError)
121
121
 
122
122
  expect(obj.greet(double("name"))).to match(
123
- /hello, #\[Double "name"\]/
123
+ /hello, #\[.*Double.*"name"\]/
124
124
  )
125
125
  end
126
126
 
@@ -7,7 +7,7 @@ RSpec.describe "Contract validators" do
7
7
  it "passes when value is in range" do
8
8
  expect do
9
9
  o.method_with_range_contract(5)
10
- end.not_to raise_error(ContractError)
10
+ end.not_to raise_error
11
11
  end
12
12
 
13
13
  it "fails when value is not in range" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contracts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aditya Bhargava
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-20 00:00:00.000000000 Z
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This library provides contracts for Ruby. Contracts let you clearly express
14
14
  how your code behaves, and free you from writing tons of boilerplate, defensive
@@ -18,10 +18,10 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - .gitignore
22
- - .rspec
23
- - .rubocop.yml
24
- - .travis.yml
21
+ - ".gitignore"
22
+ - ".rspec"
23
+ - ".rubocop.yml"
24
+ - ".travis.yml"
25
25
  - CHANGELOG.markdown
26
26
  - Gemfile
27
27
  - README.md
@@ -49,9 +49,11 @@ files:
49
49
  - features/builtin_contracts/exactly.feature
50
50
  - features/builtin_contracts/func.feature
51
51
  - features/builtin_contracts/hash_of.feature
52
+ - features/builtin_contracts/int.feature
52
53
  - features/builtin_contracts/keyword_args.feature
53
54
  - features/builtin_contracts/maybe.feature
54
55
  - features/builtin_contracts/nat.feature
56
+ - features/builtin_contracts/nat_pos.feature
55
57
  - features/builtin_contracts/neg.feature
56
58
  - features/builtin_contracts/none.feature
57
59
  - features/builtin_contracts/not.feature
@@ -107,17 +109,17 @@ require_paths:
107
109
  - lib
108
110
  required_ruby_version: !ruby/object:Gem::Requirement
109
111
  requirements:
110
- - - ! '>='
112
+ - - ">="
111
113
  - !ruby/object:Gem::Version
112
114
  version: '0'
113
115
  required_rubygems_version: !ruby/object:Gem::Requirement
114
116
  requirements:
115
- - - ! '>='
117
+ - - ">="
116
118
  - !ruby/object:Gem::Version
117
119
  version: '0'
118
120
  requirements: []
119
121
  rubyforge_project:
120
- rubygems_version: 2.4.8
122
+ rubygems_version: 2.4.6
121
123
  signing_key:
122
124
  specification_version: 4
123
125
  summary: Contracts for Ruby.