parent
7c150c5bc8
commit
9cb2b9b409
@ -1,387 +0,0 @@
|
|||||||
From 62ad3fb999287f1495273d4ef41ff6abc28fd278 Mon Sep 17 00:00:00 2001
|
|
||||||
From: PikachuEXE <pikachuexe@gmail.com>
|
|
||||||
Date: Tue, 26 Jan 2021 17:37:59 +0800
|
|
||||||
Subject: [PATCH 5/5] * Update implementation & spec to be 3.0 compatible
|
|
||||||
|
|
||||||
Mainly around the breaking behaviour change about keyword arguments
|
|
||||||
---
|
|
||||||
lib/contracts.rb | 14 ++++-----
|
|
||||||
lib/contracts/call_with.rb | 31 ++++++++++---------
|
|
||||||
lib/contracts/invariants.rb | 10 +++---
|
|
||||||
lib/contracts/method_handler.rb | 6 ++--
|
|
||||||
lib/contracts/method_reference.rb | 4 +--
|
|
||||||
spec/builtin_contracts_spec.rb | 20 +++++-------
|
|
||||||
spec/contracts_spec.rb | 21 +++++++------
|
|
||||||
spec/fixtures/fixtures.rb | 9 ++----
|
|
||||||
spec/override_validators_spec.rb | 6 ++--
|
|
||||||
.../contracts_spec_2.0.rb | 4 +--
|
|
||||||
spec/validators_spec.rb | 2 +-
|
|
||||||
11 files changed, 63 insertions(+), 64 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/lib/contracts.rb b/lib/contracts.rb
|
|
||||||
index baf2acf..f5ae75d 100644
|
|
||||||
--- a/lib/contracts.rb
|
|
||||||
+++ b/lib/contracts.rb
|
|
||||||
@@ -93,9 +93,9 @@ class Contract < Contracts::Decorator
|
|
||||||
last_contract = args_contracts.last
|
|
||||||
penultimate_contract = args_contracts[-2]
|
|
||||||
@has_options_contract = if @has_proc_contract
|
|
||||||
- penultimate_contract.is_a?(Hash) || penultimate_contract.is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
+ penultimate_contract.is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
else
|
|
||||||
- last_contract.is_a?(Hash) || last_contract.is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
+ last_contract.is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
end
|
|
||||||
# ===
|
|
||||||
|
|
||||||
@@ -214,12 +214,12 @@ class Contract < Contracts::Decorator
|
|
||||||
|
|
||||||
# Same thing for when we have named params but didn't pass any in.
|
|
||||||
# returns true if it appended nil
|
|
||||||
- def maybe_append_options! args, blk
|
|
||||||
+ def maybe_append_options! args, kargs, blk
|
|
||||||
return false unless @has_options_contract
|
|
||||||
- if @has_proc_contract && (args_contracts[-2].is_a?(Hash) || args_contracts[-2].is_a?(Contracts::Builtin::KeywordArgs)) && !args[-2].is_a?(Hash)
|
|
||||||
- args.insert(-2, {})
|
|
||||||
- elsif (args_contracts[-1].is_a?(Hash) || args_contracts[-1].is_a?(Contracts::Builtin::KeywordArgs)) && !args[-1].is_a?(Hash)
|
|
||||||
- args << {}
|
|
||||||
+ if @has_proc_contract && args_contracts[-2].is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
+ args.insert(-2, kargs)
|
|
||||||
+ elsif args_contracts[-1].is_a?(Contracts::Builtin::KeywordArgs)
|
|
||||||
+ args << kargs
|
|
||||||
end
|
|
||||||
true
|
|
||||||
end
|
|
||||||
diff --git a/lib/contracts/call_with.rb b/lib/contracts/call_with.rb
|
|
||||||
index 9252c79..224b357 100644
|
|
||||||
--- a/lib/contracts/call_with.rb
|
|
||||||
+++ b/lib/contracts/call_with.rb
|
|
||||||
@@ -1,17 +1,17 @@
|
|
||||||
module Contracts
|
|
||||||
module CallWith
|
|
||||||
- def call_with(this, *args, &blk)
|
|
||||||
- call_with_inner(false, this, *args, &blk)
|
|
||||||
+ def call_with(this, *args, **kargs, &blk)
|
|
||||||
+ call_with_inner(false, this, *args, **kargs, &blk)
|
|
||||||
end
|
|
||||||
|
|
||||||
- def call_with_inner(returns, this, *args, &blk)
|
|
||||||
+ def call_with_inner(returns, this, *args, **kargs, &blk)
|
|
||||||
args << blk if blk
|
|
||||||
|
|
||||||
# Explicitly append blk=nil if nil != Proc contract violation anticipated
|
|
||||||
nil_block_appended = maybe_append_block!(args, blk)
|
|
||||||
|
|
||||||
# Explicitly append options={} if Hash contract is present
|
|
||||||
- maybe_append_options!(args, blk)
|
|
||||||
+ kargs_appended = maybe_append_options!(args, kargs, blk)
|
|
||||||
|
|
||||||
# Loop forward validating the arguments up to the splat (if there is one)
|
|
||||||
(@args_contract_index || args.size).times do |i|
|
|
||||||
@@ -57,14 +57,16 @@ module Contracts
|
|
||||||
validator = @args_validators[args_contracts.size - 1 - j]
|
|
||||||
|
|
||||||
unless validator && validator[arg]
|
|
||||||
- return unless Contract.failure_callback(:arg => arg,
|
|
||||||
- :contract => contract,
|
|
||||||
- :class => klass,
|
|
||||||
- :method => method,
|
|
||||||
- :contracts => self,
|
|
||||||
- :arg_pos => i-1,
|
|
||||||
- :total_args => args.size,
|
|
||||||
- :return_value => false)
|
|
||||||
+ return unless Contract.failure_callback({
|
|
||||||
+ :arg => arg,
|
|
||||||
+ :contract => contract,
|
|
||||||
+ :class => klass,
|
|
||||||
+ :method => method,
|
|
||||||
+ :contracts => self,
|
|
||||||
+ :arg_pos => i - 1,
|
|
||||||
+ :total_args => args.size,
|
|
||||||
+ :return_value => false,
|
|
||||||
+ })
|
|
||||||
end
|
|
||||||
|
|
||||||
if contract.is_a?(Contracts::Func)
|
|
||||||
@@ -76,15 +78,16 @@ module Contracts
|
|
||||||
# If we put the block into args for validating, restore the args
|
|
||||||
# OR if we added a fake nil at the end because a block wasn't passed in.
|
|
||||||
args.slice!(-1) if blk || nil_block_appended
|
|
||||||
+ args.slice!(-1) if kargs_appended
|
|
||||||
result = if method.respond_to?(:call)
|
|
||||||
# proc, block, lambda, etc
|
|
||||||
- method.call(*args, &blk)
|
|
||||||
+ method.call(*args, **kargs, &blk)
|
|
||||||
else
|
|
||||||
# original method name reference
|
|
||||||
# Don't reassign blk, else Travis CI shows "stack level too deep".
|
|
||||||
target_blk = blk
|
|
||||||
target_blk = lambda { |*params| blk.call(*params) } if blk && blk.is_a?(Contract)
|
|
||||||
- method.send_to(this, *args, &target_blk)
|
|
||||||
+ method.send_to(this, *args, **kargs, &target_blk)
|
|
||||||
end
|
|
||||||
|
|
||||||
unless @ret_validator[result]
|
|
||||||
diff --git a/lib/contracts/invariants.rb b/lib/contracts/invariants.rb
|
|
||||||
index 56d2d82..215cb89 100644
|
|
||||||
--- a/lib/contracts/invariants.rb
|
|
||||||
+++ b/lib/contracts/invariants.rb
|
|
||||||
@@ -46,10 +46,12 @@ module Contracts
|
|
||||||
def check_on(target, method)
|
|
||||||
return if target.instance_eval(&@condition)
|
|
||||||
|
|
||||||
- self.class.failure_callback(:expected => expected,
|
|
||||||
- :actual => false,
|
|
||||||
- :target => target,
|
|
||||||
- :method => method)
|
|
||||||
+ self.class.failure_callback({
|
|
||||||
+ :expected => expected,
|
|
||||||
+ :actual => false,
|
|
||||||
+ :target => target,
|
|
||||||
+ :method => method,
|
|
||||||
+ })
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.failure_callback(data)
|
|
||||||
diff --git a/lib/contracts/method_handler.rb b/lib/contracts/method_handler.rb
|
|
||||||
index fe301cd..714e4e1 100644
|
|
||||||
--- a/lib/contracts/method_handler.rb
|
|
||||||
+++ b/lib/contracts/method_handler.rb
|
|
||||||
@@ -107,7 +107,7 @@ module Contracts
|
|
||||||
current_engine = engine
|
|
||||||
|
|
||||||
# We are gonna redefine original method here
|
|
||||||
- method_reference.make_definition(target) do |*args, &blk|
|
|
||||||
+ method_reference.make_definition(target) do |*args, **kargs, &blk|
|
|
||||||
engine = current_engine.nearest_decorated_ancestor
|
|
||||||
|
|
||||||
# If we weren't able to find any ancestor that has decorated methods
|
|
||||||
@@ -130,14 +130,14 @@ module Contracts
|
|
||||||
last_error = nil
|
|
||||||
|
|
||||||
decorated_methods.each do |decorated_method|
|
|
||||||
- result = decorated_method.call_with_inner(true, self, *args, &blk)
|
|
||||||
+ result = decorated_method.call_with_inner(true, self, *args, **kargs, &blk)
|
|
||||||
return result unless result.is_a?(ParamContractError)
|
|
||||||
last_error = result
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ::Contract.failure_callback(last_error.data, false)
|
|
||||||
- decorated_methods.last.call_with_inner(false, self, *args, &blk)
|
|
||||||
+ decorated_methods.last.call_with_inner(false, self, *args, **kargs, &blk)
|
|
||||||
end
|
|
||||||
rescue expected_error => final_error
|
|
||||||
raise final_error.to_contract_error
|
|
||||||
diff --git a/lib/contracts/method_reference.rb b/lib/contracts/method_reference.rb
|
|
||||||
index 0bc68f8..0c0c03f 100644
|
|
||||||
--- a/lib/contracts/method_reference.rb
|
|
||||||
+++ b/lib/contracts/method_reference.rb
|
|
||||||
@@ -39,8 +39,8 @@ module Contracts
|
|
||||||
|
|
||||||
# Calls original method on specified `this` argument with
|
|
||||||
# specified arguments `args` and block `&blk`.
|
|
||||||
- def send_to(this, *args, &blk)
|
|
||||||
- this.send(aliased_name, *args, &blk)
|
|
||||||
+ def send_to(this, *args, **kargs, &blk)
|
|
||||||
+ this.send(aliased_name, *args, **kargs, &blk)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
diff --git a/spec/builtin_contracts_spec.rb b/spec/builtin_contracts_spec.rb
|
|
||||||
index 00cf495..a9f7257 100644
|
|
||||||
--- a/spec/builtin_contracts_spec.rb
|
|
||||||
+++ b/spec/builtin_contracts_spec.rb
|
|
||||||
@@ -376,10 +376,6 @@ RSpec.describe "Contracts:" do
|
|
||||||
fails { @o.hash_keywordargs(:hash => nil) }
|
|
||||||
fails { @o.hash_keywordargs(:hash => 1) }
|
|
||||||
end
|
|
||||||
-
|
|
||||||
- it "should pass if a method is overloaded with non-KeywordArgs" do
|
|
||||||
- passes { @o.person_keywordargs("name", 10) }
|
|
||||||
- end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "Optional:" do
|
|
||||||
@@ -405,15 +401,15 @@ RSpec.describe "Contracts:" do
|
|
||||||
end
|
|
||||||
|
|
||||||
context "given a fulfilled contract" do
|
|
||||||
- it { expect(@o.gives_max_value(:panda => 1, :bamboo => 2)).to eq(2) }
|
|
||||||
- it { expect(@o.pretty_gives_max_value(:panda => 1, :bamboo => 2)).to eq(2) }
|
|
||||||
+ it { expect(@o.gives_max_value({ :panda => 1, :bamboo => 2 })).to eq(2) }
|
|
||||||
+ it { expect(@o.pretty_gives_max_value({ :panda => 1, :bamboo => 2 })).to eq(2) }
|
|
||||||
end
|
|
||||||
|
|
||||||
context "given an unfulfilled contract" do
|
|
||||||
- it { fails { @o.gives_max_value(:panda => "1", :bamboo => "2") } }
|
|
||||||
+ it { fails { @o.gives_max_value({ :panda => "1", :bamboo => "2" }) } }
|
|
||||||
it { fails { @o.gives_max_value(nil) } }
|
|
||||||
it { fails { @o.gives_max_value(1) } }
|
|
||||||
- it { fails { @o.pretty_gives_max_value(:panda => "1", :bamboo => "2") } }
|
|
||||||
+ it { fails { @o.pretty_gives_max_value({ :panda => "1", :bamboo => "2" }) } }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "#to_s" do
|
|
||||||
@@ -430,25 +426,25 @@ RSpec.describe "Contracts:" do
|
|
||||||
describe "StrictHash:" do
|
|
||||||
context "when given an exact correct input" do
|
|
||||||
it "does not raise an error" do
|
|
||||||
- passes { @o.strict_person(:name => "calvin", :age => 10) }
|
|
||||||
+ passes { @o.strict_person({ :name => "calvin", :age => 10 }) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when given an input with correct keys but wrong types" do
|
|
||||||
it "raises an error" do
|
|
||||||
- fails { @o.strict_person(:name => "calvin", :age => "10") }
|
|
||||||
+ fails { @o.strict_person({ :name => "calvin", :age => "10" }) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when given an input with missing keys" do
|
|
||||||
it "raises an error" do
|
|
||||||
- fails { @o.strict_person(:name => "calvin") }
|
|
||||||
+ fails { @o.strict_person({ :name => "calvin" }) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when given an input with extra keys" do
|
|
||||||
it "raises an error" do
|
|
||||||
- fails { @o.strict_person(:name => "calvin", :age => 10, :soft => true) }
|
|
||||||
+ fails { @o.strict_person({ :name => "calvin", :age => 10, :soft => true }) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
diff --git a/spec/contracts_spec.rb b/spec/contracts_spec.rb
|
|
||||||
index 72c8603..5586415 100644
|
|
||||||
--- a/spec/contracts_spec.rb
|
|
||||||
+++ b/spec/contracts_spec.rb
|
|
||||||
@@ -349,19 +349,19 @@ RSpec.describe "Contracts:" do
|
|
||||||
|
|
||||||
describe "Hashes" do
|
|
||||||
it "should pass for exact correct input" do
|
|
||||||
- expect { @o.person(:name => "calvin", :age => 10) }.to_not raise_error
|
|
||||||
+ expect { @o.person({ :name => "calvin", :age => 10 }) }.to_not raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should pass even if some keys don't have contracts" do
|
|
||||||
- expect { @o.person(:name => "calvin", :age => 10, :foo => "bar") }.to_not raise_error
|
|
||||||
+ expect { @o.person({ :name => "calvin", :age => 10, :foo => "bar" }) }.to_not raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should fail if a key with a contract on it isn't provided" do
|
|
||||||
- expect { @o.person(:name => "calvin") }.to raise_error(ContractError)
|
|
||||||
+ expect { @o.person({ :name => "calvin" }) }.to raise_error(ContractError)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should fail for incorrect input" do
|
|
||||||
- expect { @o.person(:name => 50, :age => 10) }.to raise_error(ContractError)
|
|
||||||
+ expect { @o.person({ :name => 50, :age => 10 }) }.to raise_error(ContractError)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@@ -612,16 +612,19 @@ RSpec.describe "Contracts:" do
|
|
||||||
|
|
||||||
it "should contain to_s representation within a Hash contract" do
|
|
||||||
expect do
|
|
||||||
- @o.hash_complex_contracts(:rigged => "bad")
|
|
||||||
+ @o.hash_complex_contracts({ :rigged => "bad" })
|
|
||||||
end.to raise_error(ContractError, not_s(delim "TrueClass or FalseClass"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should contain to_s representation within a nested Hash contract" do
|
|
||||||
expect do
|
|
||||||
- @o.nested_hash_complex_contracts(:rigged => true,
|
|
||||||
- :contents => {
|
|
||||||
- :kind => 0,
|
|
||||||
- :total => 42 })
|
|
||||||
+ @o.nested_hash_complex_contracts({
|
|
||||||
+ :rigged => true,
|
|
||||||
+ :contents => {
|
|
||||||
+ :kind => 0,
|
|
||||||
+ :total => 42,
|
|
||||||
+ },
|
|
||||||
+ })
|
|
||||||
end.to raise_error(ContractError, not_s(delim "String or Symbol"))
|
|
||||||
end
|
|
||||||
|
|
||||||
diff --git a/spec/fixtures/fixtures.rb b/spec/fixtures/fixtures.rb
|
|
||||||
index b6d2bea..c42722e 100644
|
|
||||||
--- a/spec/fixtures/fixtures.rb
|
|
||||||
+++ b/spec/fixtures/fixtures.rb
|
|
||||||
@@ -120,16 +120,11 @@ class GenericExample
|
|
||||||
end
|
|
||||||
|
|
||||||
Contract C::KeywordArgs[:name => String, :age => Fixnum] => nil
|
|
||||||
- def person_keywordargs(data)
|
|
||||||
- end
|
|
||||||
-
|
|
||||||
- # Testing overloaded method
|
|
||||||
- Contract String, Fixnum => nil
|
|
||||||
- def person_keywordargs(name, age)
|
|
||||||
+ def person_keywordargs(name: "name", age: 10)
|
|
||||||
end
|
|
||||||
|
|
||||||
Contract C::KeywordArgs[:hash => C::HashOf[Symbol, C::Num]] => nil
|
|
||||||
- def hash_keywordargs(data)
|
|
||||||
+ def hash_keywordargs(hash:)
|
|
||||||
end
|
|
||||||
|
|
||||||
Contract (/foo/) => nil
|
|
||||||
diff --git a/spec/override_validators_spec.rb b/spec/override_validators_spec.rb
|
|
||||||
index 293c84c..25af373 100644
|
|
||||||
--- a/spec/override_validators_spec.rb
|
|
||||||
+++ b/spec/override_validators_spec.rb
|
|
||||||
@@ -30,15 +30,15 @@ RSpec.describe Contract do
|
|
||||||
obj = klass.new
|
|
||||||
|
|
||||||
expect do
|
|
||||||
- obj.something(:a => 35, :b => "hello")
|
|
||||||
+ obj.something({ :a => 35, :b => "hello" })
|
|
||||||
end.to raise_error(ContractError)
|
|
||||||
|
|
||||||
expect do
|
|
||||||
- obj.something(
|
|
||||||
+ obj.something({
|
|
||||||
:a => 35,
|
|
||||||
:b => "hello",
|
|
||||||
:it_is_a_hash => true
|
|
||||||
- )
|
|
||||||
+ })
|
|
||||||
end.not_to raise_error
|
|
||||||
end
|
|
||||||
|
|
||||||
diff --git a/spec/ruby_version_specific/contracts_spec_2.0.rb b/spec/ruby_version_specific/contracts_spec_2.0.rb
|
|
||||||
index 78c5e69..c2b3d69 100644
|
|
||||||
--- a/spec/ruby_version_specific/contracts_spec_2.0.rb
|
|
||||||
+++ b/spec/ruby_version_specific/contracts_spec_2.0.rb
|
|
||||||
@@ -1,10 +1,10 @@
|
|
||||||
class GenericExample
|
|
||||||
- Contract C::Args[String], { repeat: C::Maybe[C::Num] } => C::ArrayOf[String]
|
|
||||||
+ Contract C::Args[String], C::KeywordArgs[ repeat: C::Maybe[C::Num] ] => C::ArrayOf[String]
|
|
||||||
def splat_then_optional_named(*vals, repeat: 2)
|
|
||||||
vals.map { |v| v * repeat }
|
|
||||||
end
|
|
||||||
|
|
||||||
- Contract ({foo: C::Nat}) => nil
|
|
||||||
+ Contract C::KeywordArgs[ foo: C::Nat ] => nil
|
|
||||||
def nat_test_with_kwarg(foo: 10)
|
|
||||||
end
|
|
||||||
|
|
||||||
diff --git a/spec/validators_spec.rb b/spec/validators_spec.rb
|
|
||||||
index 588580e..22dc2a9 100644
|
|
||||||
--- a/spec/validators_spec.rb
|
|
||||||
+++ b/spec/validators_spec.rb
|
|
||||||
@@ -34,7 +34,7 @@ RSpec.describe "Contract validators" do
|
|
||||||
|
|
||||||
describe "within a hash" do
|
|
||||||
it "should pass for a matching string" do
|
|
||||||
- expect { o.hash_containing_foo(:host => "foo.example.org") }.to_not raise_error
|
|
||||||
+ expect { o.hash_containing_foo({ :host => "foo.example.org" }) }.to_not raise_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
2.29.2
|
|
||||||
|
|
@ -1 +1 @@
|
|||||||
SHA512 (contracts-0.16.1.gem) = bc182431de9efbc6d23603c68a64eddcd3f27ea1ac8c2c9ff00840cf38d2f58ba595304127e6b43e504d3aa387559a5c1429b671dadac175d3a4ad2c02edbf6a
|
SHA512 (contracts-0.17.gem) = bce1417e7b505ec35b43917d53cbdb175995ff877da2a6122e08b3c7e537d557785987a0110006525dd079f09d574be3f5f4793154f99ac91c32f83662fa311b
|
||||||
|
Loading…
Reference in new issue