lib/contracts/builtin_contracts.rb in contracts-lite-0.14.0 vs lib/contracts/builtin_contracts.rb in contracts-lite-0.15.0
- old
+ new
@@ -1,9 +1,5 @@
-require "contracts/formatters"
-require "set"
-
-# rdoc
# This module contains all the builtin contracts.
# If you want to use them, first:
#
# import Contracts
#
@@ -20,60 +16,60 @@
# That says that the +add+ function takes two numbers and returns a number.
module Contracts
module Builtin
# Check that an argument is +Numeric+.
class Num
- def self.valid? val
+ def self.valid?(val)
val.is_a? Numeric
end
end
# Check that an argument is a positive number.
class Pos
- def self.valid? val
+ def self.valid?(val)
val && val.is_a?(Numeric) && val > 0
end
end
# Check that an argument is a negative number.
class Neg
- def self.valid? val
+ def self.valid?(val)
val && val.is_a?(Numeric) && val < 0
end
end
# Check that an argument is an +Integer+.
class Int
- def self.valid? val
+ def self.valid?(val)
val && val.is_a?(Integer)
end
end
# Check that an argument is a natural number (includes zero).
class Nat
- def self.valid? val
+ def self.valid?(val)
val && val.is_a?(Integer) && val >= 0
end
end
# Check that an argument is a positive natural number (excludes zero).
class NatPos
- def self.valid? val
+ def self.valid?(val)
val && val.is_a?(Integer) && val > 0
end
end
# Passes for any argument.
class Any
- def self.valid? val
+ def self.valid?(val)
true
end
end
# Fails for any argument.
class None
- def self.valid? val
+ def self.valid?(val)
false
end
end
# Use this when you are writing your own contract classes.
@@ -89,29 +85,36 @@
def self.[](*vals)
new(*vals)
end
end
+ class EnumInspector
+ include ::Contracts::Formatters
+ def self.inspect(vals, last_join_word)
+ vals[0, vals.size-1].map do |x|
+ InspectWrapper.create(x)
+ end.join(", ") + " #{last_join_word} " + InspectWrapper.create(vals[-1]).to_s
+ end
+ end
+
# Takes a variable number of contracts.
# The contract passes if any of the contracts pass.
# Example: <tt>Or[Fixnum, Float]</tt>
class Or < CallableClass
def initialize(*vals)
@vals = vals
end
def valid?(val)
@vals.any? do |contract|
- res, _ = Contract.valid?(val, contract)
+ res, = Contract.valid?(val, contract)
res
end
end
def to_s
- @vals[0, @vals.size-1].map do |x|
- InspectWrapper.create(x)
- end.join(", ") + " or " + InspectWrapper.create(@vals[-1]).to_s
+ EnumInspector.inspect(@vals, "or")
end
end
# Takes a variable number of contracts.
# The contract passes if exactly one of those contracts pass.
@@ -121,20 +124,18 @@
@vals = vals
end
def valid?(val)
results = @vals.map do |contract|
- res, _ = Contract.valid?(val, contract)
+ res, = Contract.valid?(val, contract)
res
end
results.count(true) == 1
end
def to_s
- @vals[0, @vals.size-1].map do |x|
- InspectWrapper.create(x)
- end.join(", ") + " xor " + InspectWrapper.create(@vals[-1]).to_s
+ EnumInspector.inspect(@vals, "xor")
end
end
# Takes a variable number of contracts.
# The contract passes if all contracts pass.
@@ -144,19 +145,17 @@
@vals = vals
end
def valid?(val)
@vals.all? do |contract|
- res, _ = Contract.valid?(val, contract)
+ res, = Contract.valid?(val, contract)
res
end
end
def to_s
- @vals[0, @vals.size-1].map do |x|
- InspectWrapper.create(x)
- end.join(", ") + " and " + InspectWrapper.create(@vals[-1]).to_s
+ EnumInspector.inspect(@vals, "and")
end
end
# Takes a variable number of method names as symbols.
# The contract passes if the argument responds to all
@@ -255,11 +254,11 @@
@vals = vals
end
def valid?(val)
@vals.all? do |contract|
- res, _ = Contract.valid?(val, contract)
+ res, = Contract.valid?(val, contract)
!res
end
end
def to_s
@@ -280,11 +279,11 @@
end
def valid?(vals)
return false unless vals.is_a?(@collection_class)
vals.all? do |val|
- res, _ = Contract.valid?(val, @contract)
+ res, = Contract.valid?(val, @contract)
res
end
end
def to_s
@@ -300,11 +299,11 @@
def new(contract)
@before_new && @before_new.call
CollectionOf.new(@collection_class, contract)
end
- alias_method :[], :new
+ alias [] new
end
end
# Takes a contract. The related argument must be an array.
# Checks the contract against every element of the array.
@@ -319,24 +318,32 @@
SetOf = CollectionOf::Factory.new(Set)
# Used for <tt>*args</tt> (variadic functions). Takes a contract
# and uses it to validate every element passed in
# through <tt>*args</tt>.
- # Example: <tt>Args[Or[String, Num]]</tt>
- class Args < CallableClass
+ # Example: <tt>SplatArgs[Or[String, Num]]</tt>
+ class SplatArgs < CallableClass
attr_reader :contract
def initialize(contract)
@contract = contract
end
def to_s
- "Args[#{@contract}]"
+ "SplatArgs[#{@contract}]"
end
end
+ # for compatibility
+ class Args < SplatArgs
+ def initialize(contract)
+ puts "DEPRECATION WARNING: \nContract::Args was renamed to Contract::SplatArgs, please update your before the next major version"
+ @contract = contract
+ end
+ end
+
class Bool
- def self.valid? val
+ def self.valid?(val)
val.is_a?(TrueClass) || val.is_a?(FalseClass)
end
end
# Use this to specify a Range object of a particular datatype.
@@ -359,11 +366,11 @@
# Use this to specify the Hash characteristics. Takes two contracts,
# one for hash keys and one for hash values.
# Example: <tt>HashOf[Symbol, String]</tt>
class HashOf < CallableClass
- INVALID_KEY_VALUE_PAIR = "You should provide only one key-value pair to HashOf contract"
+ INVALID_KEY_VALUE_PAIR = "You should provide only one key-value pair to HashOf contract".freeze
def initialize(key, value = nil)
if value
@key = key
@value = value
@@ -387,11 +394,11 @@
end
private
def validate_hash(hash)
- fail ArgumentError, INVALID_KEY_VALUE_PAIR unless hash.count == 1
+ raise ArgumentError, INVALID_KEY_VALUE_PAIR unless hash.count == 1
end
end
# Use this to specify the Hash characteristics. This contracts fails
# if there are any extra keys that don't have contracts on them.
@@ -466,11 +473,11 @@
# Use this for specifying optional keyword argument
# Example: <tt>Optional[Num]</tt>
class Optional < CallableClass
UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH =
- "Unable to use Optional contract outside of KeywordArgs contract"
+ "Unable to use Optional contract outside of KeywordArgs contract".freeze
def self._valid?(hash, key, contract)
return Contract.valid?(hash[key], contract) unless contract.is_a?(Optional)
contract.within_opt_hash!
!hash.key?(key) || Contract.valid?(hash[key], contract)
@@ -503,10 +510,10 @@
attr_reader :contract, :within_opt_hash
def ensure_within_opt_hash
return if within_opt_hash
- fail ArgumentError, UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH
+ raise ArgumentError, UNABLE_TO_USE_OUTSIDE_OF_OPT_HASH
end
def formatted_contract
Formatters::InspectWrapper.create(contract)
end