contracts 0.9 → 0.10

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.
@@ -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