def get_fn_conditions(self, ctxfn: FunctionInfo) -> Optional[Conditions]: fn_and_sig = ctxfn.get_callable() if fn_and_sig is None: return None (fn, sig) = fn_and_sig filename, first_line, _lines = sourcelines(fn) if isinstance(fn, types.BuiltinFunctionType): return Conditions(fn, fn, [], [], frozenset(), sig, frozenset(), []) lines = list(get_doc_lines(fn)) parse = parse_sections(lines, ("pre", "post", "raises"), filename) pre: List[ConditionExpr] = [] raises: Set[Type[BaseException]] = set() post_conditions: List[ConditionExpr] = [] mutable_args: Optional[FrozenSet[str]] = None if parse.mutable_expr is not None: mutable_args = frozenset(expr.strip().split(".")[0] for expr in parse.mutable_expr.split(",") if expr != "") for line_num, expr in parse.sections["pre"]: pre.append( condition_from_source_text(filename, line_num, expr, fn_globals(fn))) for line_num, expr in parse.sections["raises"]: if "#" in expr: expr = expr.split("#")[0] for exc_source in expr.split(","): try: exc_type = eval(exc_source) except: e = sys.exc_info()[1] parse.syntax_messages.append( ConditionSyntaxMessage(filename, line_num, str(e))) continue if not issubclass(exc_type, BaseException): parse.syntax_messages.append( ConditionSyntaxMessage( filename, line_num, f'"{exc_type}" is not an exception class', )) continue raises.add(exc_type) for line_num, expr in parse.sections["post"]: post_conditions.append( condition_from_source_text(filename, line_num, expr, fn_globals(fn))) return Conditions( fn, fn, pre, post_conditions, frozenset(raises), sig, mutable_args, parse.syntax_messages, )
def get_fn_conditions(self, ctxfn: FunctionInfo) -> Optional[Conditions]: fn_and_sig = ctxfn.get_callable() if fn_and_sig is None: return None (fn, sig) = fn_and_sig # TODO replace this guard with package-level configuration? if (getattr(fn, "__module__", False) and fn.__module__.startswith("crosshair.") and not fn.__module__.endswith("_test")): return None try: first_body_line = AssertsParser.get_first_body_line(fn) except OSError: return None if first_body_line is None: return None filename, first_line, _lines = sourcelines(fn) @wraps(fn) def wrappedfn(*a, **kw): try: return NoEnforce(fn)(*a, **kw) except AssertionError as e: # TODO: check that this isn't failing at an early line in a different # file? _, lineno = frame_summary_for_fn( fn, traceback.extract_tb(e.__traceback__)) if lineno >= first_body_line: raise post = [ ConditionExpr( POSTCONDIITON, lambda _: True, filename, first_line, "", ) ] return Conditions( wrappedfn, fn, [], # (pre) post, raises=frozenset(parse_sphinx_raises(fn)), sig=sig, mutable_args=None, fn_syntax_messages=[], )
def get_fn_conditions(self, ctxfn: FunctionInfo) -> Optional[Conditions]: fn_and_sig = ctxfn.get_callable() if fn_and_sig is None: return None (fn, sig) = fn_and_sig if not getattr(fn, "is_hypothesis_test", False): return None fuzz_one = getattr(getattr(fn, "hypothesis", None), "fuzz_one_input", None) if fuzz_one is None: return None filename, first_line, _lines = sourcelines(fn) post = [ ConditionExpr( POSTCONDIITON, lambda _: True, filename, first_line, "", ) ] sig = inspect.Signature(parameters=[ inspect.Parameter( "payload", inspect.Parameter.POSITIONAL_ONLY, annotation=bytes) ]) return Conditions( fuzz_one, fn, [], # (pre) post, raises=frozenset(), sig=sig, mutable_args=None, fn_syntax_messages=[], counterexample_description_maker=partial( self._format_counterexample, fn), )
def get_fn_conditions(self, ctxfn: FunctionInfo) -> Optional[Conditions]: if icontract is None: return None fn_and_sig = ctxfn.get_callable() if fn_and_sig is None: return None (fn, sig) = fn_and_sig checker = icontract._checkers.find_checker(func=fn) # type: ignore contractless_fn = fn # type: ignore while (hasattr(contractless_fn, "__is_invariant_check__") or hasattr(contractless_fn, "__preconditions__") or hasattr(contractless_fn, "__postconditions__")): contractless_fn = contractless_fn.__wrapped__ # type: ignore if checker is None: return Conditions(contractless_fn, contractless_fn, [], [], frozenset(), sig, None, []) pre: List[ConditionExpr] = [] post: List[ConditionExpr] = [] def eval_contract(contract, kwargs): condition_kwargs = icontract._checkers.select_condition_kwargs( contract=contract, resolved_kwargs=kwargs) return contract.condition(**condition_kwargs) disjunction = checker.__preconditions__ # type: ignore if len(disjunction) == 0: pass elif len(disjunction) == 1: for contract in disjunction[0]: evalfn = functools.partial(eval_contract, contract) filename, line_num, _lines = sourcelines(contract.condition) pre.append( ConditionExpr(evalfn, filename, line_num, self.contract_text(contract))) else: def eval_disjunction(disjunction, kwargs) -> bool: for conjunction in disjunction: ok = True for contract in conjunction: if not eval_contract(contract, kwargs): ok = False break if ok: return True return False evalfn = functools.partial(eval_disjunction, disjunction) filename, line_num, _lines = sourcelines(contractless_fn) source = ("(" + ") or (".join([ " and ".join([self.contract_text(c) for c in conj]) for conj in disjunction ]) + ")") pre.append(ConditionExpr(evalfn, filename, line_num, source)) snapshots = checker.__postcondition_snapshots__ # type: ignore def take_snapshots(**kwargs): old_as_mapping: MutableMapping[str, Any] = {} for snap in snapshots: snap_kwargs = icontract._checkers.select_capture_kwargs( a_snapshot=snap, resolved_kwargs=kwargs) old_as_mapping[snap.name] = snap.capture(**snap_kwargs) return icontract._checkers.Old(mapping=old_as_mapping) def post_eval(contract, kwargs): _old = kwargs.pop("__old__") kwargs["OLD"] = take_snapshots(**_old.__dict__) kwargs["result"] = kwargs.pop("__return__") del kwargs["_"] condition_kwargs = icontract._checkers.select_condition_kwargs( contract=contract, resolved_kwargs=kwargs) return contract.condition(**condition_kwargs) for postcondition in checker.__postconditions__: # type: ignore evalfn = functools.partial(post_eval, postcondition) filename, line_num, _lines = sourcelines(postcondition.condition) post.append( ConditionExpr(evalfn, filename, line_num, self.contract_text(postcondition))) return Conditions( contractless_fn, contractless_fn, pre, post, raises=frozenset(parse_sphinx_raises(fn)), sig=sig, mutable_args=None, fn_syntax_messages=[], )