contracts 0.12.0 → 0.16.1

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.
@@ -7,7 +7,7 @@ RSpec.describe "Contracts:" do
7
7
  it "should fail for insufficient arguments" do
8
8
  expect do
9
9
  @o.hello
10
- end.to raise_error
10
+ end.to raise_error ArgumentError
11
11
  end
12
12
 
13
13
  it "should fail for insufficient contracts" do
@@ -32,7 +32,7 @@ RSpec.describe "Contracts:" do
32
32
  1
33
33
  end
34
34
  end
35
- end.to raise_error
35
+ end.to raise_error NameError
36
36
  end
37
37
  end
38
38
 
@@ -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
@@ -655,6 +637,28 @@ RSpec.describe "Contracts:" do
655
637
  end.to raise_error(ContractError, not_s(delim "String or Symbol"))
656
638
  end
657
639
 
640
+ it "should wrap and pretty print for long param contracts" do
641
+ expect do
642
+ @o.long_array_param_contracts(true)
643
+ end.to(
644
+ raise_error(
645
+ ParamContractError,
646
+ /\[\(String or Symbol\),\n \(String or Symbol\),/
647
+ )
648
+ )
649
+ end
650
+
651
+ it "should wrap and pretty print for long return contracts" do
652
+ expect do
653
+ @o.long_array_return_contracts
654
+ end.to(
655
+ raise_error(
656
+ ReturnContractError,
657
+ /\[\(String or Symbol\),\n \(String or Symbol\),/
658
+ )
659
+ )
660
+ end
661
+
658
662
  it "should not contain Contracts:: module prefix" do
659
663
  expect do
660
664
  @o.double("bad")
@@ -714,7 +718,7 @@ RSpec.describe "Contracts:" do
714
718
  it "should apply the contract to an inherited method" do
715
719
  c = Child.new
716
720
  expect { c.double(2) }.to_not raise_error
717
- expect { c.double("asd") }.to raise_error
721
+ expect { c.double("asd") }.to raise_error ParamContractError
718
722
  end
719
723
  end
720
724
 
@@ -745,5 +749,22 @@ RSpec.describe "Contracts:" do
745
749
  it "works correctly with methods with passing contracts" do
746
750
  expect { klass.new.foo(42) }.to raise_error(ContractError, /Expected: String/)
747
751
  end
752
+
753
+ # See the discussion on this issue:
754
+ # https://github.com/egonSchiele/contracts.ruby/issues/229
755
+ it "should not fail with 'undefined method 'Contract''" do
756
+ expect do
757
+ class ModuleThenContracts
758
+ include ModuleWithContracts
759
+ include Contracts::Core
760
+
761
+ # fails on this line
762
+ Contract C::Num => C::Num
763
+ def double(x)
764
+ x * 2
765
+ end
766
+ end
767
+ end.to_not raise_error
768
+ end
748
769
  end
749
770
  end
@@ -104,6 +104,10 @@ class GenericExample
104
104
  def person(data)
105
105
  end
106
106
 
107
+ Contract C::StrictHash[{ :name => String, :age => Fixnum }] => nil
108
+ def strict_person(data)
109
+ end
110
+
107
111
  Contract ({ :rigged => C::Or[TrueClass, FalseClass] }) => nil
108
112
  def hash_complex_contracts(data)
109
113
  end
@@ -119,6 +123,11 @@ class GenericExample
119
123
  def person_keywordargs(data)
120
124
  end
121
125
 
126
+ # Testing overloaded method
127
+ Contract String, Fixnum => nil
128
+ def person_keywordargs(name, age)
129
+ end
130
+
122
131
  Contract C::KeywordArgs[:hash => C::HashOf[Symbol, C::Num]] => nil
123
132
  def hash_keywordargs(data)
124
133
  end
@@ -143,6 +152,30 @@ class GenericExample
143
152
  def nested_array_complex_contracts(data)
144
153
  end
145
154
 
155
+ Contract [
156
+ C::Or[String, Symbol],
157
+ C::Or[String, Symbol],
158
+ C::Or[String, Symbol],
159
+ C::Or[String, Symbol],
160
+ C::Or[String, Symbol],
161
+ C::Or[String, Symbol],
162
+ C::Or[String, Symbol]
163
+ ] => nil
164
+ def long_array_param_contracts(data)
165
+ end
166
+
167
+ Contract C::None => [
168
+ C::Or[String, Symbol],
169
+ C::Or[String, Symbol],
170
+ C::Or[String, Symbol],
171
+ C::Or[String, Symbol],
172
+ C::Or[String, Symbol],
173
+ C::Or[String, Symbol],
174
+ C::Or[String, Symbol]
175
+ ]
176
+ def long_array_return_contracts
177
+ end
178
+
146
179
  Contract Proc => C::Any
147
180
  def do_call(&block)
148
181
  block.call
@@ -263,6 +296,10 @@ class GenericExample
263
296
  r.first
264
297
  end
265
298
 
299
+ Contract C::DescendantOf[Enumerable] => nil
300
+ def enumerable_descendant_test(enum)
301
+ end
302
+
266
303
  Contract C::Bool => nil
267
304
  def bool_test(x)
268
305
  end
@@ -621,6 +658,12 @@ class SingletonInheritanceExample
621
658
  end
622
659
 
623
660
  class SingletonInheritanceExampleSubclass < SingletonInheritanceExample
661
+ class << self
662
+ Contract Integer => Integer
663
+ def num(int)
664
+ int
665
+ end
666
+ end
624
667
  end
625
668
 
626
669
  class BareOptionalContractUsed
@@ -670,3 +713,18 @@ module ModuleContractExample
670
713
  :world
671
714
  end
672
715
  end
716
+
717
+ module ModuleWithContracts
718
+ def self.included(base)
719
+ base.extend ClassMethods
720
+ end
721
+
722
+ module ClassMethods
723
+ include Contracts::Core
724
+
725
+ Contract C::None => String
726
+ def foo
727
+ "bar"
728
+ end
729
+ end
730
+ end
@@ -0,0 +1,54 @@
1
+ RSpec.describe "Contracts:" do
2
+ describe "method called with blocks" do
3
+ module FuncTest
4
+ include Contracts::Core
5
+ include Contracts::Builtin
6
+
7
+ Contract Func[Num=>Num] => nil
8
+ def foo(&blk)
9
+ _ = blk.call(2)
10
+ nil
11
+ end
12
+
13
+ Contract Num, Func[Num=>Num] => nil
14
+ def foo2(a, &blk)
15
+ _ = blk.call(2)
16
+ nil
17
+ end
18
+
19
+ Contract Func[Num=>Num] => nil
20
+ def bar(blk)
21
+ _ = blk.call(2)
22
+ nil
23
+ end
24
+
25
+ Contract Num, Func[Num=>Num] => nil
26
+ def bar2(a, blk)
27
+ _ = blk.call(2)
28
+ nil
29
+ end
30
+ end
31
+
32
+ def obj
33
+ Object.new.tap do |o|
34
+ o.extend(FuncTest)
35
+ end
36
+ end
37
+
38
+ it "should enforce return value inside block with no other parameter" do
39
+ expect { obj.foo(&:to_s) }.to raise_error ReturnContractError
40
+ end
41
+
42
+ it "should enforce return value inside block with other parameter" do
43
+ expect { obj.foo2(2) { |x| x.to_s } }.to raise_error ReturnContractError
44
+ end
45
+
46
+ it "should enforce return value inside lambda with no other parameter" do
47
+ expect { obj.bar lambda { |x| x.to_s } }.to raise_error ReturnContractError
48
+ end
49
+
50
+ it "should enforce return value inside lambda with other parameter" do
51
+ expect { obj.bar2(2, lambda { |x| x.to_s }) }.to raise_error ReturnContractError
52
+ end
53
+ end
54
+ end
@@ -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,6 +7,11 @@ class GenericExample
7
7
  Contract ({foo: C::Nat}) => nil
8
8
  def nat_test_with_kwarg(foo: 10)
9
9
  end
10
+
11
+ Contract C::KeywordArgs[name: C::Optional[String]], C::Func[String => String] => String
12
+ def keyword_args_hello(name: "Adit", &block)
13
+ "Hey, #{yield name}!"
14
+ end
10
15
  end
11
16
 
12
17
  RSpec.describe "Contracts:" do
@@ -37,4 +42,14 @@ RSpec.describe "Contracts:" do
37
42
  expect { @o.nat_test_with_kwarg }.to raise_error(ContractError)
38
43
  end
39
44
  end
45
+
46
+ describe "keyword args with defaults, with a block" do
47
+ it "should work when both keyword args and a block is given" do
48
+ expect(@o.keyword_args_hello(name: "maggie", &:upcase)).to eq("Hey, MAGGIE!")
49
+ end
50
+
51
+ it "should work even when keyword args aren't given" do
52
+ expect(@o.keyword_args_hello(&:upcase)).to eq("Hey, ADIT!")
53
+ end
54
+ end
40
55
  end
@@ -51,7 +51,7 @@ RSpec.describe "Contracts:" do
51
51
  end.to raise_error(ContractError)
52
52
  end
53
53
 
54
- it "should fail when passed nil to an optional argument which contract shouldnt accept nil" do
54
+ it "should fail when passed nil to an optional argument which contract shouldn't accept nil" do
55
55
  expect do
56
56
  @o.complicated("a", true, :b, :c, 2.0, e: (1..5), f: nil, g: :d) do |x|
57
57
  x
@@ -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.16.1
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: 2021-04-17 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,12 +18,15 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - .gitignore
22
- - .rspec
23
- - .rubocop.yml
24
- - .travis.yml
21
+ - ".github/workflows/code_style_checks.yaml"
22
+ - ".github/workflows/tests.yaml"
23
+ - ".gitignore"
24
+ - ".rspec"
25
+ - ".rubocop.yml"
26
+ - ".rubocop_todo.yml"
25
27
  - CHANGELOG.markdown
26
28
  - Gemfile
29
+ - LICENSE
27
30
  - README.md
28
31
  - Rakefile
29
32
  - TODO.markdown
@@ -35,8 +38,10 @@ files:
35
38
  - benchmarks/wrap_test.rb
36
39
  - contracts.gemspec
37
40
  - cucumber.yml
41
+ - dependabot.yml
38
42
  - features/README.md
39
43
  - features/basics/functype.feature
44
+ - features/basics/pretty-print.feature
40
45
  - features/basics/simple_example.feature
41
46
  - features/builtin_contracts/README.md
42
47
  - features/builtin_contracts/and.feature
@@ -49,9 +54,11 @@ files:
49
54
  - features/builtin_contracts/exactly.feature
50
55
  - features/builtin_contracts/func.feature
51
56
  - features/builtin_contracts/hash_of.feature
57
+ - features/builtin_contracts/int.feature
52
58
  - features/builtin_contracts/keyword_args.feature
53
59
  - features/builtin_contracts/maybe.feature
54
60
  - features/builtin_contracts/nat.feature
61
+ - features/builtin_contracts/nat_pos.feature
55
62
  - features/builtin_contracts/neg.feature
56
63
  - features/builtin_contracts/none.feature
57
64
  - features/builtin_contracts/not.feature
@@ -65,6 +72,7 @@ files:
65
72
  - features/builtin_contracts/xor.feature
66
73
  - features/support/env.rb
67
74
  - lib/contracts.rb
75
+ - lib/contracts/attrs.rb
68
76
  - lib/contracts/builtin_contracts.rb
69
77
  - lib/contracts/call_with.rb
70
78
  - lib/contracts/core.rb
@@ -81,14 +89,15 @@ files:
81
89
  - lib/contracts/support.rb
82
90
  - lib/contracts/validators.rb
83
91
  - lib/contracts/version.rb
84
- - script/cucumber
85
92
  - script/docs-release
86
93
  - script/docs-staging
87
94
  - script/rubocop.rb
95
+ - spec/attrs_spec.rb
88
96
  - spec/builtin_contracts_spec.rb
89
97
  - spec/contracts_spec.rb
90
98
  - spec/fixtures/fixtures.rb
91
99
  - spec/invariants_spec.rb
100
+ - spec/methods_spec.rb
92
101
  - spec/module_spec.rb
93
102
  - spec/override_validators_spec.rb
94
103
  - spec/ruby_version_specific/contracts_spec_1.9.rb
@@ -98,26 +107,28 @@ files:
98
107
  - spec/support.rb
99
108
  - spec/support_spec.rb
100
109
  - spec/validators_spec.rb
101
- homepage: http://github.com/egonSchiele/contracts.ruby
102
- licenses: []
110
+ homepage: https://github.com/egonSchiele/contracts.ruby
111
+ licenses:
112
+ - BSD-2-Clause
103
113
  metadata: {}
104
- post_install_message:
114
+ post_install_message: "\n 0.16.x will be the supporting Ruby 2.x and be feature
115
+ frozen (only fixes will be released)\n For Ruby 3.x use 0.17.x or later (might
116
+ not be released yet)\n "
105
117
  rdoc_options: []
106
118
  require_paths:
107
119
  - lib
108
120
  required_ruby_version: !ruby/object:Gem::Requirement
109
121
  requirements:
110
- - - ! '>='
122
+ - - ">="
111
123
  - !ruby/object:Gem::Version
112
124
  version: '0'
113
125
  required_rubygems_version: !ruby/object:Gem::Requirement
114
126
  requirements:
115
- - - ! '>='
127
+ - - ">="
116
128
  - !ruby/object:Gem::Version
117
129
  version: '0'
118
130
  requirements: []
119
- rubyforge_project:
120
- rubygems_version: 2.4.8
131
+ rubygems_version: 3.0.3
121
132
  signing_key:
122
133
  specification_version: 4
123
134
  summary: Contracts for Ruby.