Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
assert inspect.isfunction(value) or isinstance(value, (staticmethod, classmethod))
# Determine the function to be decorated
if inspect.isfunction(value):
func = value
elif isinstance(value, (staticmethod, classmethod)):
func = value.__func__
else:
raise NotImplementedError("Unexpected value for a function: {}".format(value))
# Collect preconditions and postconditions of the function
preconditions = [] # type: List[List[Contract]]
snapshots = [] # type: List[Snapshot]
postconditions = [] # type: List[Contract]
contract_checker = icontract._checkers.find_checker(func=func)
if contract_checker is not None:
preconditions = contract_checker.__preconditions__
snapshots = contract_checker.__postcondition_snapshots__
postconditions = contract_checker.__postconditions__
# Collect the preconditions and postconditions from bases.
#
# Preconditions and postconditions of __init__ of base classes are deliberately ignored (and not collapsed) since
# initialization is an operation specific to the concrete class and does not relate to the class hierarchy.
if key not in ['__init__']:
base_preconditions = [] # type: List[List[Contract]]
base_snapshots = [] # type: List[Snapshot]
base_postconditions = [] # type: List[Contract]
bases_have_func = False
for base in bases:
# Check if there is a checker function in the base class
base_contract_checker = icontract._checkers.find_checker(func=base_func)
# Ignore functions which don't have preconditions or postconditions
if base_contract_checker is not None:
base_preconditions.extend(base_contract_checker.__preconditions__)
base_snapshots.extend(base_contract_checker.__postcondition_snapshots__)
base_postconditions.extend(base_contract_checker.__postconditions__)
# Add preconditions and postconditions of the function
preconditions = [] # type: List[List[Contract]]
snapshots = [] # type: List[Snapshot]
postconditions = [] # type: List[Contract]
contract_checker = icontract._checkers.find_checker(func=func)
if contract_checker is not None:
preconditions = contract_checker.__preconditions__
snapshots = contract_checker.__postcondition_snapshots__
postconditions = contract_checker.__postconditions__
preconditions = _collapse_preconditions(
base_preconditions=base_preconditions,
bases_have_func=bases_have_func,
preconditions=preconditions,
func=func)
snapshots = _collapse_snapshots(base_snapshots=base_snapshots, snapshots=snapshots)
postconditions = _collapse_postconditions(
base_postconditions=base_postconditions, postconditions=postconditions)
if func == value.fget:
base_func = getattr(base, key).fget
elif func == value.fset:
base_func = getattr(base, key).fset
elif func == value.fdel:
base_func = getattr(base, key).fdel
else:
raise NotImplementedError("Unhandled case: func neither value.fget, value.fset nor value.fdel")
if base_func is None:
continue
bases_have_func = True
# Check if there is a checker function in the base class
base_contract_checker = icontract._checkers.find_checker(func=base_func)
# Ignore functions which don't have preconditions or postconditions
if base_contract_checker is not None:
base_preconditions.extend(base_contract_checker.__preconditions__)
base_snapshots.extend(base_contract_checker.__postcondition_snapshots__)
base_postconditions.extend(base_contract_checker.__postconditions__)
# Add preconditions and postconditions of the function
preconditions = [] # type: List[List[Contract]]
snapshots = [] # type: List[Snapshot]
postconditions = [] # type: List[Contract]
contract_checker = icontract._checkers.find_checker(func=func)
if contract_checker is not None:
preconditions = contract_checker.__preconditions__
snapshots = contract_checker.__postcondition_snapshots__
#
# Preconditions and postconditions of __init__ of base classes are deliberately ignored (and not collapsed) since
# initialization is an operation specific to the concrete class and does not relate to the class hierarchy.
if key not in ['__init__']:
base_preconditions = [] # type: List[List[Contract]]
base_snapshots = [] # type: List[Snapshot]
base_postconditions = [] # type: List[Contract]
bases_have_func = False
for base in bases:
if hasattr(base, key):
bases_have_func = True
# Check if there is a checker function in the base class
base_func = getattr(base, key)
base_contract_checker = icontract._checkers.find_checker(func=base_func)
# Ignore functions which don't have preconditions or postconditions
if base_contract_checker is not None:
base_preconditions.extend(base_contract_checker.__preconditions__)
base_snapshots.extend(base_contract_checker.__postcondition_snapshots__)
base_postconditions.extend(base_contract_checker.__postconditions__)
# Collapse preconditions and postconditions from the bases with the the function's own ones
preconditions = _collapse_preconditions(
base_preconditions=base_preconditions,
bases_have_func=bases_have_func,
preconditions=preconditions,
func=func)
snapshots = _collapse_snapshots(base_snapshots=base_snapshots, snapshots=snapshots)
def __call__(self, func: CallableT) -> CallableT:
"""
Add the postcondition to the list of postconditions of the function ``func``.
The function ``func`` is decorated with a contract checker if there is no contract checker in
the decorator stack.
:param func: function to be wrapped
:return: contract checker around ``func`` if no contract checker on the decorator stack, or ``func`` otherwise
"""
if not self.enabled:
return func
# Find a contract checker
contract_checker = icontract._checkers.find_checker(func=func)
if contract_checker is not None:
# Do not add an additional wrapper since the function has been already wrapped with a contract checker
result = func
else:
# Wrap the function with a contract checker
contract_checker = icontract._checkers.decorate_with_checker(func=func)
result = contract_checker
# Add the postcondition to the list of postconditions stored at the checker
assert hasattr(contract_checker, "__postconditions__")
assert isinstance(getattr(contract_checker, "__postconditions__"), list)
getattr(contract_checker, "__postconditions__").append(self._contract)
return result