def test_callable(self): bindings = collections.ChainMap() self.assertTrue(unify(Callable[[Iterable], bool], Callable[[List], bool], bindings)) self.assertFalse(unify(Callable[[List], bool], Callable[[Iterable], bool], bindings)) self.assertTrue(unify(Callable[[int, _T], List[int]], Callable[[int, str], _U], bindings)) self.assertEqual(realize(Callable[[_U], _T], bindings), Callable[[List[int]], str])
def find_key_in_heap( self, ref: z3.ExprRef, typ: Type, proxy_generator: Callable[[Type], object], snapshot: SnapshotRef = SnapshotRef(-1) ) -> object: with self.framework(): for (curref, curtyp, curval) in itertools.chain(*self.heaps[snapshot:]): could_match = dynamic_typing.unify(curtyp, typ) if not could_match: continue if self.smt_fork(curref == ref): debug('HEAP key lookup ', ref, ': Found existing. ', 'type:', name_of_type(type(curval)), 'id:', id(curval) % 1000) return curval ret = proxy_generator(typ) debug('HEAP key lookup ', ref, ': Created new. ', 'type:', name_of_type(type(ret)), 'id:', id(ret) % 1000) #assert dynamic_typing.unify(python_type(ret), typ), 'proxy type was {} and type required was {}'.format(type(ret), typ) self.add_value_to_heaps(ref, typ, ret) return ret
def wrapper(*a: object, **kw: Dict[str, object]) -> object: #debug('short circuit wrapper ', original) space = optional_context_statespace() if (not self.engaged) or (not space) or space.running_framework_code: return original(*a, **kw) # We *heavily* bias towards concrete execution, because it's often the case # that a single short-circuit will render the path useless. TODO: consider # decaying short-crcuit probability over time. use_short_circuit = space.fork_with_confirm_or_else(0.95) if not use_short_circuit: #debug('short circuit: Choosing not to intercept', original) return original(*a, **kw) try: self.engaged = False debug('short circuit: Short circuiting over a call to ', original) self.intercepted = True return_type = sig.return_annotation # Deduce type vars if necessary if len(typing_inspect.get_parameters(sig.return_annotation)) > 0 or typing_inspect.is_typevar(sig.return_annotation): typevar_bindings: typing.ChainMap[object, type] = collections.ChainMap( ) bound = sig.bind(*a, **kw) bound.apply_defaults() for param in sig.parameters.values(): argval = bound.arguments[param.name] value_type = python_type(argval) #debug('unify', value_type, param.annotation) if not dynamic_typing.unify(value_type, param.annotation, typevar_bindings): debug( 'aborting intercept due to signature unification failure') return original(*a, **kw) #debug('unify bindings', typevar_bindings) return_type = dynamic_typing.realize( sig.return_annotation, typevar_bindings) debug('short circuit: Deduced return type was ', return_type) # adjust arguments that may have been mutated assert subconditions is not None bound = sig.bind(*a, **kw) mutable_args = subconditions.mutable_args for argname, arg in bound.arguments.items(): if mutable_args is None or argname in mutable_args: forget_contents(arg) if return_type is type(None): return None # note that the enforcement wrapper ensures postconditions for us, so we # can just return a free variable here. return proxy_for_type(return_type, 'proxyreturn' + space.uniq()) finally: self.engaged = True
def find_key_in_heap( self, ref: z3.ExprRef, typ: Type, proxy_generator: Callable[[Type], object], snapshot: SnapshotRef = SnapshotRef(-1), ) -> object: with NoTracing(): for (curref, curtyp, curval) in itertools.chain(*self.heaps[snapshot:]): could_match = dynamic_typing.unify(curtyp, typ) if not could_match: continue if self.smt_fork(curref == ref): debug( "HEAP key lookup ", ref, ": Found existing. ", "type:", name_of_type(type(curval)), "id:", id(curval) % 1000, ) return curval ret = proxy_generator(typ) debug( "HEAP key lookup ", ref, ": Created new. ", "type:", name_of_type(type(ret)), "id:", id(ret) % 1000, ) self.add_value_to_heaps(ref, typ, ret) return ret
def test_nested_union(self): bindings = collections.ChainMap() self.assertTrue(unify(List[str], Sequence[Union[str, int]], bindings))
def test_union_into_union(self): bindings = collections.ChainMap() self.assertTrue( unify(Union[str, int], Union[str, int, float], bindings)) self.assertFalse( unify(Union[str, int, float], Union[str, int], bindings))
def test_union_ok(self): bindings = collections.ChainMap() self.assertTrue(unify(int, Union[str, int], bindings)) self.assertTrue( unify(Tuple[int, ...], Union[int, Iterable[_T]], bindings)) self.assertEqual(bindings[_T], int)
def test_union_fail(self): bindings = collections.ChainMap() self.assertFalse( unify(Iterable[int], Union[int, Dict[str, _T]], bindings))
def test_tuple(self): bindings = collections.ChainMap() self.assertFalse(unify(tuple, Tuple[int, str], bindings))
def test_uniform_tuple(self): bindings = collections.ChainMap() self.assertTrue(unify(Tuple[int, int], Tuple[_T, ...], bindings)) self.assertEqual(bindings[_T], int) self.assertFalse(unify(Tuple[int, str], Tuple[_T, ...], bindings))
def test_plain_callable(self): bindings = collections.ChainMap() self.assertTrue( unify(Callable[[int, str], List[int]], Callable, bindings))
def test_zero_type_args_ok(self): bindings = collections.ChainMap() self.assertTrue(unify(map, Iterable[_T])) self.assertFalse(unify(map, Iterable[int]))
def test_bound_vtypears(self): bindings = collections.ChainMap() self.assertTrue(unify(Dict[str, int], Dict[_T, _U])) self.assertFalse(unify(Dict[str, int], Dict[_T, _T]))
def test_typevars(self): bindings = collections.ChainMap() self.assertTrue( unify(Tuple[int, str, List[int]], Tuple[int, _T, _U], bindings)) self.assertEqual(realize(Mapping[_U, _T], bindings), Mapping[List[int], str])
def test_raw_tuple(self): bindings = collections.ChainMap() self.assertTrue(unify(tuple, Iterable[_T], bindings))