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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +30 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rubocop.yml +131 -0
- data/.travis.yml +22 -0
- data/Gemfile +8 -4
- data/README.md +13 -3
- data/Rakefile +1 -0
- data/TUTORIAL.md +6 -6
- data/bin/console +11 -0
- data/{script → bin}/rubocop +1 -2
- data/contracts.gemspec +1 -1
- data/docs/_config.yml +1 -0
- data/docs/index.md +112 -0
- data/lib/contracts.rb +8 -210
- data/lib/contracts/args_validator.rb +96 -0
- data/lib/contracts/builtin_contracts.rb +42 -35
- data/lib/contracts/contract.rb +136 -0
- data/lib/contracts/contract/call_with.rb +119 -0
- data/lib/contracts/contract/failure_callback.rb +61 -0
- data/lib/contracts/{validators.rb → contract/validators.rb} +9 -14
- data/lib/contracts/core.rb +4 -25
- data/lib/contracts/decorators.rb +1 -1
- data/lib/contracts/engine/base.rb +4 -5
- data/lib/contracts/engine/eigenclass.rb +3 -4
- data/lib/contracts/engine/target.rb +1 -3
- data/lib/contracts/error_formatter.rb +6 -6
- data/lib/contracts/errors.rb +2 -2
- data/lib/contracts/formatters.rb +20 -21
- data/lib/contracts/invariants.rb +10 -6
- data/lib/contracts/method_handler.rb +26 -31
- data/lib/contracts/method_reference.rb +13 -14
- data/lib/contracts/support.rb +2 -16
- data/lib/contracts/version.rb +1 -1
- data/spec/contracts_spec.rb +25 -6
- data/spec/error_formatter_spec.rb +0 -1
- data/spec/fixtures/fixtures.rb +5 -5
- data/spec/ruby_version_specific/contracts_spec_1.9.rb +17 -1
- data/spec/ruby_version_specific/contracts_spec_2.0.rb +1 -1
- data/spec/ruby_version_specific/contracts_spec_2.1.rb +1 -1
- data/spec/spec_helper.rb +17 -68
- metadata +15 -8
- data/TODO.markdown +0 -6
- data/lib/contracts/call_with.rb +0 -97
data/spec/fixtures/fixtures.rb
CHANGED
@@ -161,20 +161,20 @@ class GenericExample
|
|
161
161
|
block.call
|
162
162
|
end
|
163
163
|
|
164
|
-
Contract C::
|
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::
|
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::
|
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::
|
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::
|
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::
|
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 String, C::Bool, C::
|
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]
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
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
|
-
#
|
44
|
-
#
|
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.
|
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:
|
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
|
-
-
|
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/
|
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)
|
data/TODO.markdown
DELETED
@@ -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
|
data/lib/contracts/call_with.rb
DELETED
@@ -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
|