contracts 0.12.0 → 0.13.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.
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.