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 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 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])