contracts-lite 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +30 -0
  3. data/.gitignore +6 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +131 -0
  6. data/.travis.yml +22 -0
  7. data/Gemfile +8 -4
  8. data/README.md +13 -3
  9. data/Rakefile +1 -0
  10. data/TUTORIAL.md +6 -6
  11. data/bin/console +11 -0
  12. data/{script → bin}/rubocop +1 -2
  13. data/contracts.gemspec +1 -1
  14. data/docs/_config.yml +1 -0
  15. data/docs/index.md +112 -0
  16. data/lib/contracts.rb +8 -210
  17. data/lib/contracts/args_validator.rb +96 -0
  18. data/lib/contracts/builtin_contracts.rb +42 -35
  19. data/lib/contracts/contract.rb +136 -0
  20. data/lib/contracts/contract/call_with.rb +119 -0
  21. data/lib/contracts/contract/failure_callback.rb +61 -0
  22. data/lib/contracts/{validators.rb → contract/validators.rb} +9 -14
  23. data/lib/contracts/core.rb +4 -25
  24. data/lib/contracts/decorators.rb +1 -1
  25. data/lib/contracts/engine/base.rb +4 -5
  26. data/lib/contracts/engine/eigenclass.rb +3 -4
  27. data/lib/contracts/engine/target.rb +1 -3
  28. data/lib/contracts/error_formatter.rb +6 -6
  29. data/lib/contracts/errors.rb +2 -2
  30. data/lib/contracts/formatters.rb +20 -21
  31. data/lib/contracts/invariants.rb +10 -6
  32. data/lib/contracts/method_handler.rb +26 -31
  33. data/lib/contracts/method_reference.rb +13 -14
  34. data/lib/contracts/support.rb +2 -16
  35. data/lib/contracts/version.rb +1 -1
  36. data/spec/contracts_spec.rb +25 -6
  37. data/spec/error_formatter_spec.rb +0 -1
  38. data/spec/fixtures/fixtures.rb +5 -5
  39. data/spec/ruby_version_specific/contracts_spec_1.9.rb +17 -1
  40. data/spec/ruby_version_specific/contracts_spec_2.0.rb +1 -1
  41. data/spec/ruby_version_specific/contracts_spec_2.1.rb +1 -1
  42. data/spec/spec_helper.rb +17 -68
  43. metadata +15 -8
  44. data/TODO.markdown +0 -6
  45. data/lib/contracts/call_with.rb +0 -97
@@ -2,7 +2,6 @@ RSpec.describe "Contracts::ErrorFormatters" do
2
2
  before :all do
3
3
  @o = GenericExample.new
4
4
  end
5
- C = Contracts::Builtin
6
5
 
7
6
  describe "self.class_for" do
8
7
  let(:keywordargs_contract) { C::KeywordArgs[:name => String, :age => Fixnum] }
@@ -161,20 +161,20 @@ class GenericExample
161
161
  block.call
162
162
  end
163
163
 
164
- Contract C::Args[C::Num], C::Maybe[Proc] => C::Any
164
+ Contract C::SplatArgs[C::Num], C::Maybe[Proc] => C::Any
165
165
  def maybe_call(*vals, &block)
166
166
  block.call if block
167
167
  vals
168
168
  end
169
169
 
170
- Contract C::Args[C::Num] => C::Num
170
+ Contract C::SplatArgs[C::Num] => C::Num
171
171
  def sum(*vals)
172
172
  vals.inject(0) do |acc, val|
173
173
  acc + val
174
174
  end
175
175
  end
176
176
 
177
- Contract C::Args[C::Num], Proc => C::Num
177
+ Contract C::SplatArgs[C::Num], Proc => C::Num
178
178
  def with_partial_sums(*vals, &blk)
179
179
  sum = vals.inject(0) do |acc, val|
180
180
  blk[acc]
@@ -183,7 +183,7 @@ class GenericExample
183
183
  blk[sum]
184
184
  end
185
185
 
186
- Contract C::Args[C::Num], C::Func[C::Num => C::Num] => C::Num
186
+ Contract C::SplatArgs[C::Num], C::Func[C::Num => C::Num] => C::Num
187
187
  def with_partial_sums_contracted(*vals, &blk)
188
188
  sum = vals.inject(0) do |acc, val|
189
189
  blk[acc]
@@ -193,7 +193,7 @@ class GenericExample
193
193
  end
194
194
 
195
195
  # Important to use different arg types or it falsely passes
196
- Contract C::Num, C::Args[String] => C::ArrayOf[String]
196
+ Contract C::Num, C::SplatArgs[String] => C::ArrayOf[String]
197
197
  def arg_then_splat(n, *vals)
198
198
  vals.map { |v| v * n }
199
199
  end
@@ -1,5 +1,5 @@
1
1
  class GenericExample
2
- Contract C::Args[String], C::Num => C::ArrayOf[String]
2
+ Contract C::SplatArgs[String], C::Num => C::ArrayOf[String]
3
3
  def splat_then_arg(*vals, n)
4
4
  vals.map { |v| v * n }
5
5
  end
@@ -21,4 +21,20 @@ RSpec.describe "Contracts:" do
21
21
  expect { @o.splat_then_arg("hello", "world", 3) }.to_not raise_error
22
22
  end
23
23
  end
24
+
25
+
26
+ context "Contracts::Args" do
27
+ it "should print deprecation warning when used" do
28
+ expect{
29
+ klass = Class.new do
30
+ include Contracts::Core
31
+
32
+ Contract C::Num, C::Args[String] => C::ArrayOf[String]
33
+ def arg_then_splat(n, *vals)
34
+ vals.map { |v| v * n }
35
+ end
36
+ end
37
+ }.to output(Regexp.new("DEPRECATION WARNING")).to_stdout
38
+ end
39
+ end
24
40
  end
@@ -1,5 +1,5 @@
1
1
  class GenericExample
2
- Contract C::Args[String], { repeat: C::Maybe[C::Num] } => C::ArrayOf[String]
2
+ Contract C::SplatArgs[String], { repeat: C::Maybe[C::Num] } => C::ArrayOf[String]
3
3
  def splat_then_optional_named(*vals, repeat: 2)
4
4
  vals.map { |v| v * repeat }
5
5
  end
@@ -1,5 +1,5 @@
1
1
  class GenericExample
2
- Contract String, C::Bool, C::Args[Symbol], Float, C::KeywordArgs[e: Range, f: C::Optional[C::Num], g: Symbol], Proc =>
2
+ Contract String, C::Bool, C::SplatArgs[Symbol], Float, C::KeywordArgs[e: Range, f: C::Optional[C::Num], g: Symbol], Proc =>
3
3
  [Proc, Hash, C::Maybe[C::Num], Range, Float, C::ArrayOf[Symbol], C::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]
@@ -1,86 +1,35 @@
1
+ if RUBY_VERSION.to_f > 2.0
2
+ require "byebug"
3
+ end
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start do
7
+ add_filter "/spec/"
8
+ add_filter "/.direnv/"
9
+ end
10
+ if ENV['CI']=='true'
11
+ require 'codecov'
12
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
13
+ end
14
+
1
15
  require "contracts"
2
16
  require File.expand_path(File.join(__FILE__, "../support"))
3
17
  require File.expand_path(File.join(__FILE__, "../fixtures/fixtures"))
4
18
 
5
- # This file was generated by the `rspec --init` command. Conventionally, all
6
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
- # The generated `.rspec` file contains `--require spec_helper` which will cause this
8
- # file to always be loaded, without a need to explicitly require it in any files.
9
- #
10
- # Given that it is always loaded, you are encouraged to keep this file as
11
- # light-weight as possible. Requiring heavyweight dependencies from this file
12
- # will add to the boot time of your test suite on EVERY test run, even for an
13
- # individual file that may not need all of that loaded. Instead, consider making
14
- # a separate helper file that requires the additional dependencies and performs
15
- # the additional setup, and require it from the spec files that actually need it.
16
- #
17
- # The `.rspec` file also contains a few flags that are not defaults but that
18
- # users commonly want.
19
- #
20
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
19
  RSpec.configure do |config|
22
20
  config.pattern = "*.rb"
23
21
 
24
- # Only load tests who's syntax is valid in the current Ruby
22
+ # Only load tests with valid syntax in the current Ruby
25
23
  [1.9, 2.0, 2.1].each do |ver|
26
24
  config.pattern << ",ruby_version_specific/*#{ver}.rb" if ruby_version >= ver
27
25
  end
28
26
 
29
- # rspec-expectations config goes here. You can use an alternate
30
- # assertion/expectation library such as wrong or the stdlib/minitest
31
- # assertions if you prefer.
32
27
  config.expect_with :rspec do |expectations|
33
- # This option will default to `true` in RSpec 4. It makes the `description`
34
- # and `failure_message` of custom matchers include text for helper methods
35
- # defined using `chain`, e.g.:
36
- # be_bigger_than(2).and_smaller_than(4).description
37
- # # => "be bigger than 2 and smaller than 4"
38
- # ...rather than:
39
- # # => "be bigger than 2"
40
28
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
41
29
  end
42
30
 
43
- # rspec-mocks config goes here. You can use an alternate test double
44
- # library (such as bogus or mocha) by changing the `mock_with` option here.
45
- config.mock_with :rspec do |mocks|
46
- # Prevents you from mocking or stubbing a method that does not exist on
47
- # a real object. This is generally recommended, and will default to
48
- # `true` in RSpec 4.
49
- mocks.verify_partial_doubles = true
50
- end
51
-
52
- # These two settings work together to allow you to limit a spec run
53
- # to individual examples or groups you care about by tagging them with
54
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
55
- # get run.
56
- config.filter_run :focus
57
- config.run_all_when_everything_filtered = true
58
-
59
- # Limits the available syntax to the non-monkey patched syntax that is recommended.
60
- # For more details, see:
61
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
62
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
63
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
64
- config.disable_monkey_patching!
65
-
66
- # This setting enables warnings. It's recommended, but in some cases may
67
- # be too noisy due to issues in dependencies.
68
- # config.warnings = true
69
-
70
- # Many RSpec users commonly either run the entire suite or an individual
71
- # file, and it's useful to allow more verbose output when running an
72
- # individual spec file.
73
- if config.files_to_run.one?
74
- # Use the documentation formatter for detailed output,
75
- # unless a formatter has already been configured
76
- # (e.g. via a command-line flag).
77
- config.default_formatter = "doc"
78
- end
79
-
80
- # Print the 10 slowest examples and example groups at the
81
- # end of the spec run, to help surface which specs are running
82
- # particularly slow.
83
- config.profile_examples = 10
31
+ # # Print the 10 slowest examples and example groups
32
+ # config.profile_examples = 10
84
33
 
85
34
  # Run specs in random order to surface order dependencies. If you find an
86
35
  # order dependency and want to debug it, you can fix the order by providing
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contracts-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
- - Aditya Bhargava
7
+ - Aditya Bhargava, Ruslan Gatyatov, Roman Heinrich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-22 00:00:00.000000000 Z
11
+ date: 2017-01-09 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,6 +18,7 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - ".codeclimate.yml"
21
22
  - ".gitignore"
22
23
  - ".rspec"
23
24
  - ".rubocop.yml"
@@ -26,17 +27,25 @@ files:
26
27
  - Gemfile
27
28
  - LICENSE
28
29
  - README.md
29
- - TODO.markdown
30
+ - Rakefile
30
31
  - TUTORIAL.md
31
32
  - benchmarks/bench.rb
32
33
  - benchmarks/hash.rb
33
34
  - benchmarks/invariants.rb
34
35
  - benchmarks/io.rb
35
36
  - benchmarks/wrap_test.rb
37
+ - bin/console
38
+ - bin/rubocop
36
39
  - contracts.gemspec
40
+ - docs/_config.yml
41
+ - docs/index.md
37
42
  - lib/contracts.rb
43
+ - lib/contracts/args_validator.rb
38
44
  - lib/contracts/builtin_contracts.rb
39
- - lib/contracts/call_with.rb
45
+ - lib/contracts/contract.rb
46
+ - lib/contracts/contract/call_with.rb
47
+ - lib/contracts/contract/failure_callback.rb
48
+ - lib/contracts/contract/validators.rb
40
49
  - lib/contracts/core.rb
41
50
  - lib/contracts/decorators.rb
42
51
  - lib/contracts/engine.rb
@@ -50,9 +59,7 @@ files:
50
59
  - lib/contracts/method_handler.rb
51
60
  - lib/contracts/method_reference.rb
52
61
  - lib/contracts/support.rb
53
- - lib/contracts/validators.rb
54
62
  - lib/contracts/version.rb
55
- - script/rubocop
56
63
  - spec/builtin_contracts_spec.rb
57
64
  - spec/contracts_spec.rb
58
65
  - spec/error_formatter_spec.rb
@@ -87,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
94
  version: '0'
88
95
  requirements: []
89
96
  rubyforge_project:
90
- rubygems_version: 2.5.1
97
+ rubygems_version: 2.4.5.1
91
98
  signing_key:
92
99
  specification_version: 4
93
100
  summary: Contracts for Ruby. (fork)
@@ -1,6 +0,0 @@
1
- - maybe make some screencasts
2
-
3
- - you can now do something like Haskell's quickcheck. Every contract has a method 'test_data' or something. You can use that data to automatically check methods with contracts to make sure they are correct.
4
- - http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html
5
- - for stuff like the Not contract, should I make a standard set of classes to check those functions with? Would that be useful at all?
6
- - also write specs for this stuff
@@ -1,97 +0,0 @@
1
- module Contracts
2
- module CallWith
3
- def call_with(this, *args, &blk)
4
- args << blk if blk
5
-
6
- # Explicitly append blk=nil if nil != Proc contract violation anticipated
7
- nil_block_appended = maybe_append_block!(args, blk)
8
-
9
- # Explicitly append options={} if Hash contract is present
10
- maybe_append_options!(args, blk)
11
-
12
- # Loop forward validating the arguments up to the splat (if there is one)
13
- (@args_contract_index || args.size).times do |i|
14
- contract = args_contracts[i]
15
- arg = args[i]
16
- validator = @args_validators[i]
17
-
18
- unless validator && validator[arg]
19
- return unless Contract.failure_callback(:arg => arg,
20
- :contract => contract,
21
- :class => klass,
22
- :method => method,
23
- :contracts => self,
24
- :arg_pos => i+1,
25
- :total_args => args.size,
26
- :return_value => false)
27
- end
28
-
29
- if contract.is_a?(Contracts::Func)
30
- args[i] = Contract.new(klass, arg, *contract.contracts)
31
- end
32
- end
33
-
34
- # If there is a splat loop backwards to the lower index of the splat
35
- # Once we hit the splat in this direction set its upper index
36
- # Keep validating but use this upper index to get the splat validator.
37
- if @args_contract_index
38
- splat_upper_index = @args_contract_index
39
- (args.size - @args_contract_index).times do |i|
40
- arg = args[args.size - 1 - i]
41
-
42
- if args_contracts[args_contracts.size - 1 - i].is_a?(Contracts::Args)
43
- splat_upper_index = i
44
- end
45
-
46
- # Each arg after the spat is found must use the splat validator
47
- j = i < splat_upper_index ? i : splat_upper_index
48
- contract = args_contracts[args_contracts.size - 1 - j]
49
- validator = @args_validators[args_contracts.size - 1 - j]
50
-
51
- unless validator && validator[arg]
52
- return unless Contract.failure_callback(:arg => arg,
53
- :contract => contract,
54
- :class => klass,
55
- :method => method,
56
- :contracts => self,
57
- :arg_pos => i-1,
58
- :total_args => args.size,
59
- :return_value => false)
60
- end
61
-
62
- if contract.is_a?(Contracts::Func)
63
- args[args.size - 1 - i] = Contract.new(klass, arg, *contract.contracts)
64
- end
65
- end
66
- end
67
-
68
- # If we put the block into args for validating, restore the args
69
- # OR if we added a fake nil at the end because a block wasn't passed in.
70
- args.slice!(-1) if blk || nil_block_appended
71
- result = if method.respond_to?(:call)
72
- # proc, block, lambda, etc
73
- method.call(*args, &blk)
74
- else
75
- # original method name referrence
76
- method.send_to(this, *args, &blk)
77
- end
78
-
79
- unless @ret_validator[result]
80
- Contract.failure_callback(:arg => result,
81
- :contract => ret_contract,
82
- :class => klass,
83
- :method => method,
84
- :contracts => self,
85
- :return_value => true)
86
- end
87
-
88
- this.verify_invariants!(method) if this.respond_to?(:verify_invariants!)
89
-
90
- if ret_contract.is_a?(Contracts::Func)
91
- result = Contract.new(klass, result, *ret_contract.contracts)
92
- end
93
-
94
- result
95
- end
96
- end
97
- end