contracts 0.7 → 0.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.
@@ -45,16 +45,23 @@ class C
45
45
  def good
46
46
  false
47
47
  end
48
+
48
49
  def bad
49
50
  true
50
51
  end
51
52
  end
52
53
 
54
+ class EmptyCont
55
+ def self.to_s
56
+ ""
57
+ end
58
+ end
59
+
53
60
  class GenericExample
54
61
  include Contracts
55
62
 
56
63
  Contract Num => Num
57
- def GenericExample.a_class_method x
64
+ def self.a_class_method x
58
65
  x + 1
59
66
  end
60
67
 
@@ -68,6 +75,11 @@ class GenericExample
68
75
  x * 2
69
76
  end
70
77
 
78
+ Contract 123, nil => nil
79
+ def constanty(num, nul)
80
+ 0
81
+ end
82
+
71
83
  Contract String => nil
72
84
  def hello(name)
73
85
  end
@@ -84,10 +96,29 @@ class GenericExample
84
96
  end
85
97
  end
86
98
 
87
- Contract ({:name => String, :age => Fixnum}) => nil
99
+ Contract ({ :name => String, :age => Fixnum }) => nil
88
100
  def person(data)
89
101
  end
90
102
 
103
+ Contract ({ :rigged => Or[TrueClass, FalseClass] }) => nil
104
+ def hash_complex_contracts(data)
105
+ end
106
+
107
+ Contract ({ :rigged => Bool,
108
+ :contents => { :kind => Or[String, Symbol],
109
+ :total => Num }
110
+ }) => nil
111
+ def nested_hash_complex_contracts(data)
112
+ end
113
+
114
+ Contract [Or[TrueClass, FalseClass]] => nil
115
+ def array_complex_contracts(data)
116
+ end
117
+
118
+ Contract [Bool, [Or[String, Symbol]]] => nil
119
+ def nested_array_complex_contracts(data)
120
+ end
121
+
91
122
  Contract Proc => Any
92
123
  def do_call(&blk)
93
124
  blk.call
@@ -118,6 +149,12 @@ class GenericExample
118
149
  blk[sum]
119
150
  end
120
151
 
152
+ # Important to use different arg types or it falsely passes
153
+ Contract Num, Args[String] => ArrayOf[String]
154
+ def arg_then_splat(n, *vals)
155
+ vals.map { |v| v * n }
156
+ end
157
+
121
158
  Contract Num, Proc => nil
122
159
  def double_with_proc(x, &blk)
123
160
  blk.call(x * 2)
@@ -132,6 +169,10 @@ class GenericExample
132
169
  def neg_test(x)
133
170
  end
134
171
 
172
+ Contract Nat => nil
173
+ def nat_test(x)
174
+ end
175
+
135
176
  Contract Any => nil
136
177
  def show(x)
137
178
  end
@@ -189,6 +230,24 @@ class GenericExample
189
230
  ret
190
231
  end
191
232
 
233
+ Contract ArrayOf[Any], Proc => ArrayOf[Any]
234
+ def tutorial_map(arr, func)
235
+ ret = []
236
+ arr.each do |x|
237
+ ret << func[x]
238
+ end
239
+ ret
240
+ end
241
+
242
+ # Need to test Func with weak contracts for other args
243
+ # and changing type from input to output otherwise it falsely passes!
244
+ Contract Array, Func[String => Num] => Array
245
+ def map_plain(arr, func)
246
+ arr.map do |x|
247
+ func[x]
248
+ end
249
+ end
250
+
192
251
  Contract Num => Num
193
252
  def default_args(x = 1)
194
253
  2
@@ -208,12 +267,23 @@ class GenericExample
208
267
  hash.values.max
209
268
  end
210
269
 
270
+ Contract EmptyCont => Any
271
+ def using_empty_contract(a)
272
+ a
273
+ end
274
+
211
275
  Contract nil => String
212
276
  def a_private_method
213
277
  "works"
214
278
  end
215
279
  private :a_private_method
216
280
 
281
+ Contract nil => String
282
+ def a_protected_method
283
+ "works"
284
+ end
285
+ protected :a_protected_method
286
+
217
287
  private
218
288
 
219
289
  Contract nil => String
@@ -221,6 +291,12 @@ class GenericExample
221
291
  "works for sure"
222
292
  end
223
293
 
294
+ protected
295
+
296
+ Contract nil => String
297
+ def a_really_protected_method
298
+ "works for sure"
299
+ end
224
300
  end
225
301
 
226
302
  # for testing inheritance
@@ -247,11 +323,40 @@ class GenericExample
247
323
  end
248
324
  end
249
325
 
326
+ # for testing equality
327
+ class Foo
328
+ end
329
+ module Bar
330
+ end
331
+ Baz = 1
332
+
333
+ class GenericExample
334
+ Contract Eq[Foo] => Any
335
+ def eq_class_test(x)
336
+ end
337
+
338
+ Contract Eq[Bar] => Any
339
+ def eq_module_test(x)
340
+ end
341
+
342
+ Contract Eq[Baz] => Any
343
+ def eq_value_test(x)
344
+ end
345
+ end
346
+
250
347
  # pattern matching example with possible deep contract violation
251
348
  class PatternMatchingExample
252
349
  include Contracts
253
350
 
254
- class Success < Struct.new(:request)
351
+ class Success
352
+ attr_accessor :request
353
+ def initialize request
354
+ @request = request
355
+ end
356
+
357
+ def ==(other)
358
+ request == other.request
359
+ end
255
360
  end
256
361
 
257
362
  class Failure
@@ -261,13 +366,13 @@ class PatternMatchingExample
261
366
 
262
367
  class StringWithHello
263
368
  def self.valid?(string)
264
- String === string && !!string.match(/hello/i)
369
+ string.is_a?(String) && !!string.match(/hello/i)
265
370
  end
266
371
  end
267
372
 
268
373
  Contract Success => Response
269
374
  def process_request(status)
270
- Success[decorated_request(status.request)]
375
+ Success.new(decorated_request(status.request))
271
376
  end
272
377
 
273
378
  Contract Failure => Response
@@ -279,15 +384,31 @@ class PatternMatchingExample
279
384
  def decorated_request(request)
280
385
  request + "!"
281
386
  end
387
+
388
+ Contract Num, String => String
389
+ def do_stuff(number, string)
390
+ "foo"
391
+ end
392
+
393
+ Contract Num, String, Num => String
394
+ def do_stuff(number, string, other_number)
395
+ "bar"
396
+ end
282
397
  end
283
398
 
284
399
  # invariant example (silliest implementation ever)
285
- class MyBirthday < Struct.new(:day, :month)
400
+ class MyBirthday
286
401
  include Contracts
287
402
  include Contracts::Invariants
288
403
 
289
- Invariant(:day) { 1 <= day && day <= 31 }
290
- Invariant(:month) { 1 <= month && month <= 12 }
404
+ invariant(:day) { 1 <= day && day <= 31 }
405
+ invariant(:month) { 1 <= month && month <= 12 }
406
+
407
+ attr_accessor :day, :month
408
+ def initialize(day, month)
409
+ @day = day
410
+ @month = month
411
+ end
291
412
 
292
413
  Contract None => Fixnum
293
414
  def silly_next_day!
@@ -354,7 +475,7 @@ with_enabled_no_contracts do
354
475
 
355
476
  attr_accessor :day
356
477
 
357
- Invariant(:day_rule) { 1 <= day && day <= 7 }
478
+ invariant(:day_rule) { 1 <= day && day <= 7 }
358
479
 
359
480
  Contract None => nil
360
481
  def next_day
@@ -1,6 +1,5 @@
1
1
  module Contracts
2
2
  RSpec.describe Invariants do
3
-
4
3
  def new_subject
5
4
  MyBirthday.new(31, 12)
6
5
  end
@@ -14,6 +13,5 @@ module Contracts
14
13
  expect { new_subject.silly_next_day! }.to raise_error(InvariantError, /day condition to be true/)
15
14
  expect { new_subject.silly_next_month! }.to raise_error(InvariantError, /month condition to be true/)
16
15
  end
17
-
18
16
  end
19
17
  end
@@ -3,7 +3,7 @@ module Mod
3
3
 
4
4
  Contract Num => Num
5
5
  def self.a_module_method a
6
- a + 1
6
+ a + 1
7
7
  end
8
8
  end
9
9
 
@@ -15,4 +15,4 @@ RSpec.describe "module methods" do
15
15
  it "should fail for incorrect input" do
16
16
  expect { Mod.a_module_method("bad") }.to raise_error(ContractError)
17
17
  end
18
- end
18
+ end
@@ -0,0 +1,18 @@
1
+ class GenericExample
2
+ Contract Args[String], Num => ArrayOf[String]
3
+ def splat_then_arg(*vals, n)
4
+ vals.map { |v| v * n }
5
+ end
6
+ end
7
+
8
+ RSpec.describe "Contracts:" do
9
+ before :all do
10
+ @o = GenericExample.new
11
+ end
12
+
13
+ describe "Splat not last (or penultimate to block)" do
14
+ it "should work with arg after splat" do
15
+ expect { @o.splat_then_arg("hello", "world", 3) }.to_not raise_error
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ class GenericExample
2
+ Contract Args[String], { repeat: Maybe[Num] } => ArrayOf[String]
3
+ def splat_then_optional_named(*vals, repeat: 2)
4
+ vals.map { |v| v * repeat }
5
+ end
6
+ end
7
+
8
+ RSpec.describe "Contracts:" do
9
+ before :all do
10
+ @o = GenericExample.new
11
+ end
12
+
13
+ describe "Optional named arguments" do
14
+ it "should work with optional named argument unfilled after splat" do
15
+ expect { @o.splat_then_optional_named("hello", "world") }.to_not raise_error
16
+ end
17
+
18
+ it "should work with optional named argument filled after splat" do
19
+ expect { @o.splat_then_optional_named("hello", "world", repeat: 3) }.to_not raise_error
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
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]
4
+ def complicated(a, b = true, *c, d, e:, f:2, **g, &h)
5
+ h.call [h, g, f, e, d, c, b, a]
6
+ end
7
+ end
8
+
9
+ RSpec.describe "Contracts:" do
10
+ before :all do
11
+ @o = GenericExample.new
12
+ end
13
+
14
+ describe "Required named arguments" do
15
+ describe "really complicated method signature" do
16
+ it "should work with default named args used" do
17
+ expect do
18
+ @o.complicated("a", false, :b, 2.0, e: (1..5)) { |x| x }
19
+ end.to_not raise_error
20
+ end
21
+
22
+ it "should work with all args filled manually, with extra splat and hash" do
23
+ expect do
24
+ @o.complicated("a", true, :b, :c, 2.0, e: (1..5), f: 8.3, g: :d) do |x|
25
+ x
26
+ end
27
+ end.to_not raise_error
28
+ end
29
+
30
+ it "should fail when the return is invalid" do
31
+ expect do
32
+ @o.complicated("a", true, :b, 2.0, e: (1..5)) { |_x| "bad" }
33
+ end.to raise_error(ContractError)
34
+ end
35
+
36
+ it "should fail when args are invalid" do
37
+ expect do
38
+ @o.complicated("a", "bad", :b, 2.0, e: (1..5)) { |x| x }
39
+ end.to raise_error(ContractError)
40
+ end
41
+
42
+ it "should fail when splat is invalid" do
43
+ expect do
44
+ @o.complicated("a", true, "bad", 2.0, e: (1..5)) { |x| x }
45
+ end.to raise_error(ContractError)
46
+ end
47
+
48
+ it "should fail when named argument is invalid" do
49
+ expect do
50
+ @o.complicated("a", true, :b, 2.0, e: "bad") { |x| x }
51
+ end.to raise_error(ContractError)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -19,6 +19,13 @@ require File.expand_path(File.join(__FILE__, "../fixtures/fixtures"))
19
19
  #
20
20
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
21
  RSpec.configure do |config|
22
+ config.pattern = "*.rb"
23
+
24
+ # Only load tests who's syntax is valid in the current Ruby
25
+ [1.9, 2.0, 2.1].each do |ver|
26
+ config.pattern << ",ruby_version_specific/*#{ver}.rb" if ruby_version >= ver
27
+ end
28
+
22
29
  # rspec-expectations config goes here. You can use an alternate
23
30
  # assertion/expectation library such as wrong or the stdlib/minitest
24
31
  # assertions if you prefer.
@@ -58,7 +65,7 @@ RSpec.configure do |config|
58
65
 
59
66
  # This setting enables warnings. It's recommended, but in some cases may
60
67
  # be too noisy due to issues in dependencies.
61
- #config.warnings = true
68
+ # config.warnings = true
62
69
 
63
70
  # Many RSpec users commonly either run the entire suite or an individual
64
71
  # file, and it's useful to allow more verbose output when running an
@@ -67,7 +74,7 @@ RSpec.configure do |config|
67
74
  # Use the documentation formatter for detailed output,
68
75
  # unless a formatter has already been configured
69
76
  # (e.g. via a command-line flag).
70
- config.default_formatter = 'doc'
77
+ config.default_formatter = "doc"
71
78
  end
72
79
 
73
80
  # Print the 10 slowest examples and example groups at the
@@ -4,3 +4,7 @@ def with_enabled_no_contracts
4
4
  yield
5
5
  ENV["NO_CONTRACTS"] = no_contracts
6
6
  end
7
+
8
+ def ruby_version
9
+ RUBY_VERSION.match(/\d+\.\d+/)[0].to_f
10
+ end
@@ -0,0 +1,21 @@
1
+ module Contracts
2
+ RSpec.describe Support do
3
+ describe "eigenclass?" do
4
+ it "is falsey for non-singleton classes" do
5
+ expect(Contracts::Support.eigenclass? String).to be_falsey
6
+ end
7
+
8
+ it "is truthy for singleton classes" do
9
+ singleton_class = String.instance_exec { class << self; self; end }
10
+ expect(Contracts::Support.eigenclass? singleton_class).to be_truthy
11
+ end
12
+ end
13
+
14
+ describe "eigenclass_of" do
15
+ it "returns the eigenclass of a given object" do
16
+ singleton_class = String.instance_exec { class << self; self; end }
17
+ expect(Contracts::Support.eigenclass_of String).to eq singleton_class
18
+ end
19
+ end
20
+ end
21
+ 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.7'
4
+ version: '0.8'
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-02-16 00:00:00.000000000 Z
11
+ date: 2015-04-02 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
@@ -20,6 +20,7 @@ extra_rdoc_files: []
20
20
  files:
21
21
  - ".gitignore"
22
22
  - ".rspec"
23
+ - ".rubocop.yml"
23
24
  - ".travis.yml"
24
25
  - Gemfile
25
26
  - Gemfile.lock
@@ -28,27 +29,33 @@ files:
28
29
  - TUTORIAL.md
29
30
  - benchmarks/bench.rb
30
31
  - benchmarks/invariants.rb
32
+ - benchmarks/io.rb
31
33
  - benchmarks/wrap_test.rb
32
34
  - contracts.gemspec
33
35
  - lib/contracts.rb
34
36
  - lib/contracts/builtin_contracts.rb
35
- - lib/contracts/core_ext.rb
36
37
  - lib/contracts/decorators.rb
37
38
  - lib/contracts/eigenclass.rb
38
39
  - lib/contracts/errors.rb
40
+ - lib/contracts/formatters.rb
39
41
  - lib/contracts/invariants.rb
40
42
  - lib/contracts/method_reference.rb
41
43
  - lib/contracts/modules.rb
42
44
  - lib/contracts/support.rb
43
45
  - lib/contracts/testable.rb
44
46
  - lib/contracts/version.rb
47
+ - script/rubocop.rb
45
48
  - spec/builtin_contracts_spec.rb
46
49
  - spec/contracts_spec.rb
47
50
  - spec/fixtures/fixtures.rb
48
51
  - spec/invariants_spec.rb
49
52
  - spec/module_spec.rb
53
+ - spec/ruby_version_specific/contracts_spec_1.9.rb
54
+ - spec/ruby_version_specific/contracts_spec_2.0.rb
55
+ - spec/ruby_version_specific/contracts_spec_2.1.rb
50
56
  - spec/spec_helper.rb
51
57
  - spec/support.rb
58
+ - spec/support_spec.rb
52
59
  homepage: http://github.com/egonSchiele/contracts.ruby
53
60
  licenses: []
54
61
  metadata: {}
@@ -73,3 +80,4 @@ signing_key:
73
80
  specification_version: 4
74
81
  summary: Contracts for Ruby.
75
82
  test_files: []
83
+ has_rdoc: