Beispiel #1
0
    def __call__(self, *args, tag=None, **kwargs):

        # If args/kwargs form a complete binding with no AbstractParameters
        # then return a simple call to the underlying function.
        try:
            funcsig = Signature.from_callable(self.func)
            binding = funcsig.bind(*args, **kwargs)
            kwargs = binding.arguments

            is_abstract_parameter = [
                isinstance(v, AbstractParameter) for v in kwargs.values()
            ]
            if not any(is_abstract_parameter):
                return self.func(**kwargs)
        except TypeError:
            pass

        # If no arguments are supplied then return the derived Parameter.
        if not any([args, kwargs, tag]):
            return self.derive()

        # Otherwise return a new Derivative with an updated binding.
        new_kwargs = self.kwargs.copy()
        funcsig = Signature.from_callable(self.func)
        binding = funcsig.bind_partial(*args, **kwargs)
        new_kwargs.update(binding.arguments)

        tag = self.tag if tag is None else tag
        return Derivative(self.func, self.method, tag, **new_kwargs)
Beispiel #2
0
def composite_outer_arguments(outer,inner,*args,**kwargs):
    if callable(outer) and callable(inner):
        def comp(*iargs,**ikwargs):
            return outer(inner(*iargs,**ikwargs),*args,**ikwargs)

    comp.__signature__ = Signature.from_callable(inner).replace(return_annotation=Signature.from_callable(outer).return_annotation)
    return comp
    else:
Beispiel #3
0
def test_register_signature():
    signature = Signature.from_callable(registry.register)

    with not_raises(TypeError):
        signature.bind(object(), object())
        signature.bind(object(), wrapper=object())
        signature.bind(expression=object(), wrapper=object())

    # register can behave as a decorator too
    returned_decorator = registry.register(object)
    signature = Signature.from_callable(returned_decorator)

    with not_raises(TypeError):
        signature.bind(object())
Beispiel #4
0
def composite(outer,inner,*args):
    comp = None
    if callable(outer) and callable(inner):
        def temp(*args, **kwargs):
            return outer(inner(*args,**kwargs))
        comp = temp
    else:
        raise TypeError("the outer and inner functions you provide have to be callable")
    comp.__signature__ = Signature.from_callable(inner).replace(return_annotation=Signature.from_callable(outer).return_annotation)
    if len(args)!=0:
        if all(callable, args):
            return composite(comp,args[0],*args)
        else:
            raise TypeError("all functions provided need to be callable in order to be composited")
    return comp
Beispiel #5
0
    def test___prepare_call_args_from_dict__exceptions(self):
        sample = SampleRpcObject(10)
        signature = Signature.from_callable(
            sample.pos_or_kw__var_pos__kw_only__kwargs)
        processor = RpcRequestProcessor(sample)

        with pytest.raises(TypeError, message='`get_patterns` must be a list'):
            processor._prepare_call_args_from_dict(signature, {
                'key': 'lol',
                'get_patterns': 1
            })

        with pytest.raises(TypeError,
                           message='You must specify `key` argument'):
            processor._prepare_call_args_from_dict(signature, {})

        with pytest.raises(
                TypeError,
                message=
                'Keyword arguments passed in the variable `kwargs` must be a dict'
        ):
            processor._prepare_call_args_from_dict(signature, {
                'key': 1,
                'kwargs': 'qwe'
            })
Beispiel #6
0
    def test___prepare_call_args_from_dict(self):
        sample = SampleRpcObject(10)
        signature = Signature.from_callable(
            sample.pos_or_kw__var_pos__kw_only__kwargs)
        processor = RpcRequestProcessor(sample)
        params = {
            'key': 'lol',
            'get_patterns': [1, 2, 3],
            'additional_kw': 2,
            'by': 'qwe',  # positional only
            'kwargs': {
                'trash': 1
            }
        }
        res = processor._prepare_call_args_from_dict(signature, params)
        assert res == (('lol', 1, 2, 3), {
            'by': 'qwe',
            'trash': 1,
            'additional_kw': 2
        })

        # can deal with empty *get_patterns
        params = {'key': 'lol'}
        res = processor._prepare_call_args_from_dict(signature, params)
        assert res == (('lol', ), {'by': None})
 def submit(self, func, *args, **kwargs):
     self.ran_dummy_executor = True
     sig = Signature.from_callable(func)
     assert sig.bind(*args, **kwargs).arguments["ref_input"] == refinp
     dummy_future = concurrent.futures.Future()
     dummy_future.set_result(None)
     return dummy_future
Beispiel #8
0
    def connect(self, slot: Callable) -> None:
        """Connects the signal to callable that will receive the signal when emitted.

        Arguments:
            slot: Callable with signature that match the signature defined for signal.

        Raises:
            ValueError: When callable signature does not match the signature of signal.
        """
        if not callable(slot):
            raise ValueError(f"Connection to non-callable '{slot.__class__.__name__}' object failed")
        # Verify signatures
        sig = Signature.from_callable(slot).replace(return_annotation=Signature.empty)
        if str(sig) != str(self._sig):
            # Check if the difference is only in keyword arguments with defaults.
            if not self._kw_test(sig):
                raise ValueError("Callable signature does not match the signal signature")
        if isinstance(slot, partial) or slot.__name__ == '<lambda>':
            # If it's a partial, a Signal or a lambda.
            if slot not in self._slots:
                self._slots.append(slot)
        elif ismethod(slot):
            # Check if it's an instance method and store it with the instance as the key
            self._islots[slot.__self__] = slot.__func__
        else:
            # If it's just a function then just store it as a weakref.
            newSlotRef = ref(slot)
            if newSlotRef not in self._slots:
                self._slots.append(newSlotRef)
Beispiel #9
0
def test_invalid_signatures(method) -> None:
    with pytest.raises(TypeError) as e:
        check(method.__name__)(method)

    sig = Signature.from_callable(method)
    message = f'invalid check handler "{method.__name__}": incompatible return type annotation in signature {repr(sig)}, expected to match <Signature () -> Union[bool, str, Tuple[bool, str], NoneType]>'
    assert str(e.value) == message
Beispiel #10
0
    def register_factory(
        self,
        factory: Callable,
        return_type: Optional[Type],
        life_style: ServiceLifeStyle,
    ) -> None:
        if not callable(factory):
            raise InvalidFactory(return_type)

        sign = Signature.from_callable(factory)
        if return_type is None:
            if sign.return_annotation is _empty:
                raise MissingTypeException()
            return_type = sign.return_annotation

            if isinstance(return_type, str):  # pragma: no cover
                # Python 3.10
                annotations = _get_factory_annotations_or_throw(factory)
                return_type = annotations["return"]

        self._bind(
            return_type,
            FactoryResolver(return_type,
                            self._check_factory(factory, sign, return_type),
                            life_style),
        )
Beispiel #11
0
    def get_executor(self, method: Callable) -> Callable:
        sig = Signature.from_callable(method)
        params = {
            key: Dependency(key, value.annotation)
            for key, value in sig.parameters.items()
        }

        if sys.version_info >= (3, 10):  # pragma: no cover
            # Python 3.10
            annotations = _get_factory_annotations_or_throw(method)
            for key, value in params.items():
                if key in annotations:
                    value.annotation = annotations[key]

        fns = []

        for key, value in params.items():
            fns.append(self._get_getter(key, value))

        if iscoroutinefunction(method):

            async def async_executor(scoped: Optional[Dict[Type, Any]] = None):
                with GetServiceContext(self, scoped) as context:
                    return await method(*[fn(context) for fn in fns])

            return async_executor

        def executor(scoped: Optional[Dict[Type, Any]] = None):
            with GetServiceContext(self, scoped) as context:
                return method(*[fn(context) for fn in fns])

        return executor
Beispiel #12
0
    def create_parser(self, doc=""):
        """

        :param doc:
        :return:
        """
        # I have a feeling this will ve changed but for the time being it's kinda cool
        sig = Signature.from_callable(self.execute)
        parameter_types = self.execute.__annotations__
        if len(sig.parameters) != len(parameter_types):
            raise ValueError(
                "All parameters definied in 'execute' must have types specified. See https://docs.python.org/3/library/typing.html for more"
            )
        parser = argparse.ArgumentParser(description=doc)
        for parameter in sig.parameters.values():
            parameter_type = parameter_types[parameter.name]
            if parameter.default != Parameter.empty and parameter_type is bool:
                # if the default is specified as false then we want to store true, otherwise the opposite
                arg_options = {
                    "action":
                    "store_true" if not parameter.default else "store_false"
                }
            elif parameter.default != Parameter.empty:
                arg_options = {
                    "default": parameter.default,
                    "required": False,
                    "type": parameter_type
                }
            else:
                arg_options = {"required": True}
            parser.add_argument(
                '--{}'.format(parameter.name.replace("_", "-")), **arg_options)
        return parser
Beispiel #13
0
def easy_init(cls):
    if hasattr(cls, '__init__') and type(
            cls.__init__).__name__ == 'function' and callable(cls.__init__):
        sig = Signature.from_callable(cls.__init__)
        sig = sig.replace(parameters=list(
            map(lambda val: val[1],
                filter(lambda val: val[0] != 'self', sig.parameters.items()))))
        init_func = cls.__init__
    elif hasattr(cls, '_fields') and type(cls._fields) is list:
        sig = Signature([
            Parameter(name, Parameter.POSITIONAL_OR_KEYWORD)
            for name in cls._fields
        ])
        init_func = lambda self, /, *args, **kwargs: None
        #print(sig)
    def new_init(self, *args, **kwargs):
        #print(self,file=sys.stderr)
        #print(*args,'\n',**kwargs)
        print(sig)
        bound = sig.bind(*args, **kwargs)
        for name, val in bound.arguments.items():
            print(name)
            setattr(self, name, val)
        return init_func(self, *args, **kwargs)

    new_init.__signature__ = sig
    setattr(cls, '__init__', new_init)
    return cls
Beispiel #14
0
def normalize_handler(
        route: Route,
        services: Services) -> Callable[[Request], Awaitable[Response]]:
    method = route.handler

    sig = Signature.from_callable(method)
    params = sig.parameters
    params_len = len(params)

    if any(
            str(param).startswith("*")
            or param.kind.value == _ParameterKind.KEYWORD_ONLY
            for param in params.values()):
        raise UnsupportedSignatureError(method)

    if inspect.iscoroutinefunction(method):
        normalized = get_async_wrapper(services, route, method, params,
                                       params_len)
    else:
        normalized = get_sync_wrapper(services, route, method, params,
                                      params_len)

    if normalized is not method:
        copy_special_attributes(method, normalized)
        _copy_name_and_docstring(method, normalized)

    return normalized
Beispiel #15
0
 def test_update_self_ignore_existing_anno(self):
     """Don't annotate first arg of instance methods if asked to ignore"""
     sig = Signature.from_callable(UpdateSignatureHelper.an_instance_method)
     sig = update_signature_args(sig, {'self': UpdateSignatureHelper}, has_self=True,
                                 existing_annotation_strategy=ExistingAnnotationStrategy.IGNORE)
     expected = Signature(parameters=[Parameter('self', Parameter.POSITIONAL_OR_KEYWORD)])
     assert sig == expected
Beispiel #16
0
 def test_update_yield_none_and_return(self):
     sig = Signature.from_callable(UpdateSignatureHelper.a_class_method)
     sig = update_signature_return(sig,
                                   return_type=str,
                                   yield_type=NoneType)
     assert sig == Signature(return_annotation=Generator[NoneType, NoneType,
                                                         str])
Beispiel #17
0
 def test_update_self(self):
     """Don't annotate first arg of instance methods"""
     sig = Signature.from_callable(UpdateSignatureHelper.an_instance_method)
     sig = update_signature_args(sig, {'self': UpdateSignatureHelper}, True)
     expected = Signature(
         parameters=[Parameter('self', Parameter.POSITIONAL_OR_KEYWORD)])
     assert sig == expected
Beispiel #18
0
 def proxy_func():
     n = name
     f = lambda *args, _async=False, **kwargs: self._pp_issue_tn(
         'call', n, *args, async=_async, **kwargs)
     f.__signature__ = Signature.from_callable(func)
     f.__doc__ = func.__doc__
     return f
Beispiel #19
0
 def test_nonetype_annotation(self):
     """NoneType should always be rendered as None"""
     sig = Signature.from_callable(UpdateSignatureHelper.has_annos)
     sig = update_signature_args(sig, {'a': Dict[str, NoneType]}, has_self=False,
                                 existing_annotation_strategy=ExistingAnnotationStrategy.IGNORE)
     stub = FunctionStub('test', sig, FunctionKind.MODULE)
     expected = 'def test(a: Dict[str, None], b) -> int: ...'
     assert stub.render() == expected
Beispiel #20
0
    def __init__(self, func, method, tag, *args, **kwargs):
        self.func = func
        self.method = method
        self.tag = tag

        funcsig = Signature.from_callable(func)
        binding = funcsig.bind_partial(*args, **kwargs)
        self.kwargs = binding.arguments
Beispiel #21
0
 def __init__(self, project, analysis_cls):
     self._project = project
     self._analysis_cls = analysis_cls
     self.__doc__ = ''
     self.__doc__ += analysis_cls.__doc__ or ''
     self.__doc__ += analysis_cls.__init__.__doc__ or ''
     self.__call__.__func__.__signature__ = Signature.from_callable(
         analysis_cls.__init__)
Beispiel #22
0
 def test_update_yield(self):
     sig = Signature.from_callable(UpdateSignatureHelper.a_class_method)
     sig = update_signature_return(sig, yield_type=int)
     assert sig == Signature(return_annotation=Iterator[int])
     sig = update_signature_return(sig,
                                   return_type=NoneType,
                                   yield_type=int)
     assert sig == Signature(return_annotation=Iterator[int])
    def decorator(wrapper_func: WrapperAcceptingBoundArgs):
        original_signature = Signature.from_callable(original_func)

        @wraps(original_func)
        def from_args_to_bound_args_obj(*args, **kwargs):
            arguments = original_signature.bind(*args, **kwargs)
            return wrapper_func(arguments)

        return from_args_to_bound_args_obj
Beispiel #24
0
 def test_update_class(self):
     """Don't annotate the first arg of classmethods"""
     sig = Signature.from_callable(
         UpdateSignatureHelper.a_class_method.__func__)
     sig = update_signature_args(sig, {'cls': Type[UpdateSignatureHelper]},
                                 True)
     expected = Signature(
         parameters=[Parameter('cls', Parameter.POSITIONAL_OR_KEYWORD)])
     assert sig == expected
Beispiel #25
0
 def test_update_arg_ignore_existing_anno(self):
     """Update stubs only bases on traces."""
     sig = Signature.from_callable(UpdateSignatureHelper.has_annos)
     sig = update_signature_args(sig, {'a': str, 'b': bool}, has_self=False, ignore_existing_annotations=True)
     params = [
         Parameter('a', Parameter.POSITIONAL_OR_KEYWORD, annotation=str),
         Parameter('b', Parameter.POSITIONAL_OR_KEYWORD, annotation=bool),
     ]
     assert sig == Signature(parameters=params, return_annotation=int)
Beispiel #26
0
 def test_update_arg(self):
     """Update arg annotations from types"""
     sig = Signature.from_callable(UpdateSignatureHelper.has_annos)
     sig = update_signature_args(sig, {'b': int}, False)
     params = [
         Parameter('a', Parameter.POSITIONAL_OR_KEYWORD, annotation=int),
         Parameter('b', Parameter.POSITIONAL_OR_KEYWORD, annotation=int),
     ]
     assert sig == Signature(parameters=params, return_annotation=int)
    def __init__(self, concrete_type, services, lifestyle):
        assert isclass(concrete_type)
        assert not isabstract(concrete_type)

        self.concrete_type = concrete_type
        self.services = services
        sig = Signature.from_callable(concrete_type.__init__)
        self.params = sig.parameters
        self.lifestyle = lifestyle
Beispiel #28
0
def normalize_handler(services, method):
    sig = Signature.from_callable(method)
    params = sig.parameters
    params_len = len(params)

    if inspect.iscoroutinefunction(method):
        return get_async_wrapper(services, method, params, params_len)

    return get_sync_wrapper(services, method, params, params_len)
Beispiel #29
0
def has_method(obj, method_name, signature=None):
    for member in inspect.getmembers(obj, predicate=inspect.ismethod):
        member_method_name = member[0]
        member_method = member[1]
        if member_method_name == method_name:
            if signature is not None:
                return Signature.from_callable(member_method) == signature
            return True
    return False
Beispiel #30
0
 def test_update_arg_ignore_existing_anno_None(self):
     """Update arg annotations from types"""
     sig = Signature.from_callable(UpdateSignatureHelper.has_annos)
     sig = update_signature_args(sig, {'a': None, 'b': int}, has_self=False, ignore_existing_annotations=True)
     params = [
         Parameter('a', Parameter.POSITIONAL_OR_KEYWORD, annotation=inspect.Parameter.empty),
         Parameter('b', Parameter.POSITIONAL_OR_KEYWORD, annotation=int),
     ]
     assert sig == Signature(parameters=params, return_annotation=int)
Beispiel #31
0
def required_args(attrs):
    """Extract the required arguments from a class's attrs.

    Arguments:
      attrs (:py:class:`dict`) :The attributes of a class.

    Returns:
      :py:class:`set`: The required arguments.

    """
    init_args = attr_args = set()
    if '__init__' in attrs:
        sig = Signature.from_callable(attrs['__init__'])
        init_args = set(
            name
            for name, param in sig.parameters.items()
            if param.kind == Parameter.KEYWORD_ONLY
            and param.default is Signature.empty
        )
    if 'REQUIRED' in attrs:
        attr_args = attrs['REQUIRED']
    return set.union(attr_args, init_args)