def proxy_for_class(typ: Type, varname: str, meet_class_invariants: bool) -> object: # if the class has data members, we attempt to create a concrete instance with # symbolic members; otherwise, we'll create an object proxy that emulates it. obj = proxy_class_as_concrete(typ, varname) if obj is _MISSING: debug('Creating', typ, 'as an independent proxy class') obj = make_fake_object(typ, varname) else: debug('Creating', typ, 'with symbolic attribute assignments') class_conditions = _CALLTREE_PARSER.get().get_class_conditions(typ) # symbolic custom classes may assume their invariants: if meet_class_invariants and class_conditions is not None: for inv_condition in class_conditions.inv: if inv_condition.evaluate is None: continue isok = False with ExceptionFilter() as efilter: isok = inv_condition.evaluate({'self': obj}) if efilter.user_exc: raise IgnoreAttempt( f'Class proxy could not meet invariant "{inv_condition.expr_source}" on ' f'{varname} (proxy of {typ}) because it raised: {repr(efilter.user_exc[0])}' ) else: if efilter.ignore or not isok: raise IgnoreAttempt('Class proxy did not meet invariant ', inv_condition.expr_source) return obj
def check_deferred_assumptions(self, exc: Optional[Exception] = None) -> None: if isinstance(exc, NotDeterministic): # We won't be able to check deferred assumptions if our search tree isn't # stable. return for description, checker in self._deferred_assumptions: if not prefer_true(checker()): raise IgnoreAttempt("deferred assumption failed: " + description)
def describe_behavior( fn: Callable, args: inspect.BoundArguments) -> Tuple[object, Optional[Exception]]: with ExceptionFilter() as efilter: ret = fn(*args.args, **args.kwargs) return (ret, None) if efilter.user_exc is not None: debug('user-level exception found', *efilter.user_exc) return (None, efilter.user_exc[0]) if efilter.ignore: return (None, IgnoreAttempt()) assert False
def detach_path(self, exc: Optional[Exception] = None) -> None: """ Mark the current path exhausted. Also verifies all deferred assumptions. After detaching, the space may continue to be used (for example, to print realized symbolics). """ if isinstance(exc, NotDeterministic): # NotDeterministic is a user-reportable error, but it isn't valid to try # and use the statespace after it's detected return for description, checker in self._deferred_assumptions: if not prefer_true(checker()): raise IgnoreAttempt("deferred assumption failed: " + description) with NoTracing(): assert self._search_position.is_stem() node = self._search_position.grow_into(DeatchedPathNode()) assert node.child.is_stem() self.choices_made.append(node) self._search_position = node.child
def check_deferred_assumptions(self) -> None: for description, checker in self._deferred_assumptions: if not checker(): raise IgnoreAttempt('deferred assumption failed: ' + description)
def check_deferred_assumptions(self) -> None: for description, checker in self._deferred_assumptions: if not prefer_true(checker()): raise IgnoreAttempt("deferred assumption failed: " + description)