contracts 0.9 → 0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,162 @@
1
+ RSpec.describe Contract do
2
+ describe ".override_validator" do
3
+ around do |example|
4
+ Contract.reset_validators
5
+ example.run
6
+ Contract.reset_validators
7
+ end
8
+
9
+ it "allows to override simple validators" do
10
+ Contract.override_validator(Hash) do |contract|
11
+ lambda do |arg|
12
+ return false unless arg.is_a?(Hash)
13
+ # Any hash in my system should have :it_is_a_hash key!
14
+ return false unless arg.key?(:it_is_a_hash)
15
+ contract.keys.all? do |k|
16
+ Contract.valid?(arg[k], contract[k])
17
+ end
18
+ end
19
+ end
20
+
21
+ klass = Class.new do
22
+ include Contracts
23
+
24
+ Contract ({ :a => Contracts::Num, :b => String }) => nil
25
+ def something(opts)
26
+ nil
27
+ end
28
+ end
29
+
30
+ obj = klass.new
31
+
32
+ expect do
33
+ obj.something(:a => 35, :b => "hello")
34
+ end.to raise_error(ContractError)
35
+
36
+ expect do
37
+ obj.something(
38
+ :a => 35,
39
+ :b => "hello",
40
+ :it_is_a_hash => true
41
+ )
42
+ end.not_to raise_error
43
+ end
44
+
45
+ it "allows to override valid contract" do
46
+ Contract.override_validator(:valid) do |contract|
47
+ if contract.respond_to?(:in_valid_state?)
48
+ lambda do |arg|
49
+ contract.in_valid_state? && contract.valid?(arg)
50
+ end
51
+ else
52
+ lambda { |arg| contract.valid?(arg) }
53
+ end
54
+ end
55
+
56
+ stateful_contract = Class.new(Contracts::CallableClass) do
57
+ def initialize(contract)
58
+ @contract = contract
59
+ @state = 0
60
+ end
61
+
62
+ def in_valid_state?
63
+ @state < 3
64
+ end
65
+
66
+ def valid?(arg)
67
+ @state += 1
68
+ Contract.valid?(arg, @contract)
69
+ end
70
+ end
71
+
72
+ klass = Class.new do
73
+ include Contracts
74
+
75
+ Contract stateful_contract[Contracts::Num] => Contracts::Num
76
+ def only_three_times(x)
77
+ x * x
78
+ end
79
+ end
80
+
81
+ obj = klass.new
82
+
83
+ expect(obj.only_three_times(3)).to eq(9)
84
+ expect(obj.only_three_times(3)).to eq(9)
85
+ expect(obj.only_three_times(3)).to eq(9)
86
+
87
+ expect do
88
+ obj.only_three_times(3)
89
+ end.to raise_error(ContractError)
90
+
91
+ expect do
92
+ obj.only_three_times(3)
93
+ end.to raise_error(ContractError)
94
+ end
95
+
96
+ it "allows to override class validator" do
97
+ # Make contracts accept all rspec doubles
98
+ Contract.override_validator(:class) do |contract|
99
+ lambda do |arg|
100
+ arg.is_a?(RSpec::Mocks::Double) ||
101
+ arg.is_a?(contract)
102
+ end
103
+ end
104
+
105
+ klass = Class.new do
106
+ include Contracts
107
+
108
+ Contract String => String
109
+ def greet(name)
110
+ "hello, #{name}"
111
+ end
112
+ end
113
+
114
+ obj = klass.new
115
+
116
+ expect(obj.greet("world")).to eq("hello, world")
117
+
118
+ expect do
119
+ obj.greet(4)
120
+ end.to raise_error(ContractError)
121
+
122
+ expect(obj.greet(double("name"))).to match(
123
+ /hello, #\[Double "name"\]/
124
+ )
125
+ end
126
+
127
+ it "allows to override default validator" do
128
+ spy = double("spy")
129
+
130
+ Contract.override_validator(:default) do |contract|
131
+ lambda do |arg|
132
+ spy.log("#{arg} == #{contract}")
133
+ arg == contract
134
+ end
135
+ end
136
+
137
+ klass = Class.new do
138
+ include Contracts
139
+
140
+ Contract 1, Contracts::Num => Contracts::Num
141
+ def gcd(_, b)
142
+ b
143
+ end
144
+
145
+ Contract Contracts::Num, Contracts::Num => Contracts::Num
146
+ def gcd(a, b)
147
+ gcd(b % a, a)
148
+ end
149
+ end
150
+
151
+ obj = klass.new
152
+
153
+ expect(spy).to receive(:log).with("8 == 1").ordered.once
154
+ expect(spy).to receive(:log).with("5 == 1").ordered.once
155
+ expect(spy).to receive(:log).with("3 == 1").ordered.once
156
+ expect(spy).to receive(:log).with("2 == 1").ordered.once
157
+ expect(spy).to receive(:log).with("1 == 1").ordered.once
158
+
159
+ obj.gcd(8, 5)
160
+ end
161
+ end
162
+ end
@@ -1,6 +1,6 @@
1
1
  class GenericExample
2
- Contract String, Bool, Args[Symbol], Float, { e: Range, f: Maybe[Num] }, Proc =>
3
- [Proc, Hash, Num, Range, Float, ArrayOf[Symbol], Bool, String]
2
+ Contract String, Bool, Args[Symbol], Float, KeywordArgs[e: Range, f: Optional[Num]], Proc =>
3
+ [Proc, Hash, Maybe[Num], Range, Float, ArrayOf[Symbol], Bool, String]
4
4
  def complicated(a, b = true, *c, d, e:, f:2, **g, &h)
5
5
  h.call [h, g, f, e, d, c, b, a]
6
6
  end
@@ -50,6 +50,14 @@ RSpec.describe "Contracts:" do
50
50
  @o.complicated("a", true, :b, 2.0, e: "bad") { |x| x }
51
51
  end.to raise_error(ContractError)
52
52
  end
53
+
54
+ it "should fail when passed nil to an optional argument which contract shouldnt accept nil" do
55
+ expect do
56
+ @o.complicated("a", true, :b, :c, 2.0, e: (1..5), f: nil, g: :d) do |x|
57
+ x
58
+ end
59
+ end.to raise_error(ContractError, /Expected: \(KeywordArgs\[{:e=>Range, :f=>Optional\[Num\]}\]\)/)
60
+ end
53
61
  end
54
62
  end
55
63
  end
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.9'
4
+ version: '0.10'
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-04-24 00:00:00.000000000 Z
11
+ date: 2015-07-07 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
@@ -28,20 +28,26 @@ files:
28
28
  - TODO.markdown
29
29
  - TUTORIAL.md
30
30
  - benchmarks/bench.rb
31
+ - benchmarks/hash.rb
31
32
  - benchmarks/invariants.rb
32
33
  - benchmarks/io.rb
33
34
  - benchmarks/wrap_test.rb
34
35
  - contracts.gemspec
35
36
  - lib/contracts.rb
36
37
  - lib/contracts/builtin_contracts.rb
38
+ - lib/contracts/call_with.rb
37
39
  - lib/contracts/decorators.rb
38
- - lib/contracts/eigenclass.rb
40
+ - lib/contracts/engine.rb
41
+ - lib/contracts/engine/base.rb
42
+ - lib/contracts/engine/eigenclass.rb
43
+ - lib/contracts/engine/target.rb
39
44
  - lib/contracts/errors.rb
40
45
  - lib/contracts/formatters.rb
41
46
  - lib/contracts/invariants.rb
47
+ - lib/contracts/method_handler.rb
42
48
  - lib/contracts/method_reference.rb
43
- - lib/contracts/modules.rb
44
49
  - lib/contracts/support.rb
50
+ - lib/contracts/validators.rb
45
51
  - lib/contracts/version.rb
46
52
  - script/rubocop.rb
47
53
  - spec/builtin_contracts_spec.rb
@@ -49,6 +55,7 @@ files:
49
55
  - spec/fixtures/fixtures.rb
50
56
  - spec/invariants_spec.rb
51
57
  - spec/module_spec.rb
58
+ - spec/override_validators_spec.rb
52
59
  - spec/ruby_version_specific/contracts_spec_1.9.rb
53
60
  - spec/ruby_version_specific/contracts_spec_2.0.rb
54
61
  - spec/ruby_version_specific/contracts_spec_2.1.rb
@@ -74,9 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
81
  version: '0'
75
82
  requirements: []
76
83
  rubyforge_project:
77
- rubygems_version: 2.2.2
84
+ rubygems_version: 2.4.6
78
85
  signing_key:
79
86
  specification_version: 4
80
87
  summary: Contracts for Ruby.
81
88
  test_files: []
82
- has_rdoc:
@@ -1,38 +0,0 @@
1
- module Contracts
2
- module Eigenclass
3
- def self.extended(eigenclass)
4
- return if eigenclass.respond_to?(:owner_class=)
5
-
6
- class << eigenclass
7
- attr_accessor :owner_class
8
- end
9
- end
10
-
11
- def self.lift(base)
12
- return NullEigenclass if Support.eigenclass? base
13
-
14
- eigenclass = Support.eigenclass_of base
15
-
16
- eigenclass.extend(Eigenclass) unless eigenclass.respond_to?(:owner_class=)
17
-
18
- unless eigenclass.respond_to?(:pop_decorators)
19
- eigenclass.extend(MethodDecorators)
20
- eigenclass.send(:include, Contracts)
21
- end
22
-
23
- eigenclass.owner_class = base
24
-
25
- eigenclass
26
- end
27
-
28
- module NullEigenclass
29
- def self.owner_class
30
- self
31
- end
32
-
33
- def self.pop_decorators
34
- []
35
- end
36
- end
37
- end
38
- end
@@ -1,17 +0,0 @@
1
- module Contracts
2
- module Modules
3
- def self.included(base)
4
- common(base)
5
- end
6
-
7
- def self.extended(base)
8
- common(base)
9
- end
10
-
11
- def self.common(base)
12
- return unless base.instance_of?(Module)
13
- base.extend(MethodDecorators)
14
- Eigenclass.lift(base)
15
- end
16
- end
17
- end