contracts-lite 0.14.0 → 0.15.0

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