コード例 #1
0
ファイル: stubs.py プロジェクト: tamarbuata/MonkeyType
def update_signature_return(
    sig: inspect.Signature,
    return_type: type = None,
    yield_type: type = None,
    existing_annotation_strategy: ExistingAnnotationStrategy = ExistingAnnotationStrategy.REPLICATE,
) -> inspect.Signature:
    """Update return annotation with the supplied types"""
    anno = sig.return_annotation
    if anno is not inspect.Signature.empty:
        # If generating a stub to apply and there's already a return type
        # annotation, generate a stub with no return type annotation, to avoid
        # the possibility of "incompatible annotation" errors.
        if existing_annotation_strategy == ExistingAnnotationStrategy.OMIT:
            return sig.replace(return_annotation=inspect.Signature.empty)
        # Don't change pre-existing annotations unless asked to
        if existing_annotation_strategy == ExistingAnnotationStrategy.REPLICATE:
            return sig
    # NB: We cannot distinguish between functions that explicitly only
    # return None and those that do so implicitly. In the case of generator
    # functions both are typed as Iterator[<yield_type>]
    if (yield_type is not None) and ((return_type is None) or (return_type == NoneType)):
        anno = make_iterator(yield_type)
    elif (yield_type is not None) and (return_type is not None):
        anno = make_generator(yield_type, NoneType, return_type)
    elif return_type is not None:
        anno = return_type
    return sig.replace(return_annotation=anno)
コード例 #2
0
    def process_overload_signature(self, overload: Signature) -> Signature:
        """
		Processes the signature of the given overloaded implementation.

		:param overload:
		"""

        parameters = []
        non_overload_sig = inspect.signature(self.object)

        for param, non_overload_param in zip(
                overload.parameters.values(),
                non_overload_sig.parameters.values()):
            default = param.default

            if default is not Parameter.empty:
                for check, preprocessor in default_preprocessors:
                    if check(default):
                        default = preprocessor(default)
                        break

            if param.annotation is non_overload_param.annotation:
                annotation = Parameter.empty
            else:
                annotation = param.annotation
            parameters.append(
                param.replace(default=default, annotation=annotation))

        if non_overload_sig.return_annotation is overload.return_annotation:
            overload = overload.replace(parameters=parameters,
                                        return_annotation=Parameter.empty)
        else:
            overload = overload.replace(parameters=parameters)

        return overload
コード例 #3
0
ファイル: stubs.py プロジェクト: sobolevn/MonkeyType
def update_signature_args(
    sig: inspect.Signature,
    arg_types: Dict[str, type],
    has_self: bool,
    existing_annotation_strategy:
    ExistingAnnotationStrategy = ExistingAnnotationStrategy.REPLICATE,
) -> inspect.Signature:
    """Update argument annotations with the supplied types"""
    params = []
    for arg_idx, name in enumerate(sig.parameters):
        param = sig.parameters[name]
        typ = arg_types.get(name)
        typ = inspect.Parameter.empty if typ is None else typ
        is_self = (has_self and arg_idx == 0)
        annotated = param.annotation is not inspect.Parameter.empty
        if annotated and existing_annotation_strategy == ExistingAnnotationStrategy.OMIT:
            # generate no annotation for already-annotated args when generating
            # a stub to apply, avoiding the possibility of "incompatible
            # annotation" errors
            param = param.replace(annotation=inspect.Parameter.empty)
        # Don't touch existing annotations unless asked to ignore them
        if not is_self and (
            (existing_annotation_strategy == ExistingAnnotationStrategy.IGNORE)
                or not annotated):
            param = param.replace(annotation=typ)
        params.append(param)
    return sig.replace(parameters=params)
コード例 #4
0
 def replace_param(sig: inspect.Signature, param: inspect.Parameter,
                   type_: Type[Any]) -> inspect.Signature:
     new_param = param.replace(annotation=type_)
     return sig.replace(parameters=[
         new_param if p is param else p
         for p in sig.parameters.values()
     ])
コード例 #5
0
ファイル: test_abc.py プロジェクト: boeddeker/lazy_dataset
 def remove_annotation(sig: inspect.Signature):
     p: inspect.Parameter
     return sig.replace(
         parameters=[p.replace(annotation=inspect.Parameter.empty)
                     for p in sig.parameters.values()],
         return_annotation=inspect.Signature.empty,
     )
コード例 #6
0
ファイル: signal.py プロジェクト: FirebirdSQL/python3-base
    def __init__(self, signature: Signature):
        """
        Arguments:
            signature: Signature for slots.

        Important:
            Only slots that match the signature could be connected to signal. The check is
            performed only on parameters, and not on return value type (as signals does
            not have/ignore return values).

            The match must be exact, including type annotations, parameter names, order,
            parameter type etc. The sole exception to this rule are excess slot keyword
            arguments with default values.

        Note:
            Signal functions with signatures different from signal could be adapted using
            `functools.partial`. However, you can "mask" only keyword arguments (without
            default) and leading positional arguments (as any positional argument binded
            by name will not mask-out parameter from signature introspection).
        """
        self._sig: Signature = signature.replace(parameters=[p for p in signature.parameters.values()
                                                             if p.name != 'self'],
                                                 return_annotation=Signature.empty)
        #: Toggle to block / unblock signal transmission
        self.block: bool = False
        self._slots: List[Callable] = []
        self._islots: WeakKeyDictionary = WeakKeyDictionary()
コード例 #7
0
ファイル: inspect.py プロジェクト: nstarman/utilipy
def insert_parameter(sig: Signature, index: int,
                     param: Parameter) -> Signature:
    """Insert a new Parameter.

    Similar to .replace, but more convenient for adding a single parameter
    Parameters are immutable, so will create a new Signature object

    Parameters
    ----------
    sig:  Signature
        Signature object
    index: int
        index into Signature.parameters at which to insert new parameter
    param: Parameter
        param to insert at index

    Returns
    -------
    Signature:
        a new Signature object with the inserted parameter

    """
    parameters = list(sig.parameters.values())
    parameters.insert(index, param)

    return sig.replace(parameters=parameters)
コード例 #8
0
ファイル: inspect.py プロジェクト: nstarman/utilipy
def modify_parameter(
    sig: Signature,
    param: T.Union[str, int],
    name: T.Union[str, _empty] = _empty,
    kind: T.Any = _empty,
    default: T.Any = _empty,
    annotation: T.Any = _empty,
) -> Signature:
    """Modify a Parameter.

    Similar to `.replace,` but more convenient for modifying a single parameter
    Parameters are immutable, so will create a new `Signature` object

    Parameters
    ----------
    sig:  Signature
        Signature object
    param: int or str
        the parameter index (or name) in `self.parameters`
    name: str
        new parameter name, defaults to old parameter name
        **default: None**
    kind: type
        new parameter kind, defaults to old parameter kind
        **default: None**
    default: any
        new parameter default, defaults to old parameter default
        **default: None**
    annotation: any
        new parameter annotation, defaults to old parameter annotation
        **default: None**

    Returns
    -------
    Signature
        a new Signature object with the replaced parameter

    """
    # identify parameter to modify
    if isinstance(param, int):
        index = param
    else:
        index = list(sig.parameters.keys()).index(param)
    # get the parameters, and the specific param
    params = list(sig.parameters.values())
    _param = params[index]

    # replacements
    name = _param.name if name is _empty else name
    kind = _param.kind if kind is _empty else kind
    default = _param.default if default is _empty else default
    annotation = _param.annotation if annotation is _empty else annotation

    # adjust parameter list
    params[index] = _param.replace(name=name,
                                   kind=kind,
                                   default=default,
                                   annotation=annotation)

    return sig.replace(parameters=params)
コード例 #9
0
def resolve_annotations(cls_or_callable: Union[Type[object], Callable],
                        sig: inspect.Signature):
    """Resolve all type-hints in the signature for the class or callable.

    Parameters
    ----------
    cls_or_callable
        A class or callable object.
    sig
        The signature of the object.

    Returns
    -------
    A new signature with all annotations resolved, unless a NameError is raised.
    """
    parameters = dict(sig.parameters)
    to_resolve = {x: y for x, y in parameters.items() if _should_resolve(y)}
    if to_resolve:  # nocover
        hints = get_type_hints(cls_or_callable)
        resolved = {
            x: y.replace(annotation=hints[x])
            for x, y in to_resolve.items()
        }
        parameters.update(resolved)
        return sig.replace(parameters=parameters.values())
    return sig
コード例 #10
0
ファイル: utils.py プロジェクト: astropenguin/azely
    def update(sig: Signature, defaults: StrKeyDict) -> Signature:
        params = []

        for param in sig.parameters.values():
            try:
                default = defaults[param.name]
                params.append(param.replace(default=default))
            except (KeyError, ValueError):
                params.append(param.replace())

        return sig.replace(parameters=params)
コード例 #11
0
ファイル: _utils.py プロジェクト: QuentinSoubeyran/pheres
def _sig_without(sig: inspect.Signature, param: Union[int, str]) -> inspect.Signature:
    """Removes a parameter from a Signature object

    If param is an int, remove the parameter at that position, else
    remove any paramater with that name
    """
    if isinstance(param, int):
        params = list(sig.parameters.values())
        params.pop(param)
    else:
        params = [p for name, p in sig.parameters.items() if name != param]
    return sig.replace(parameters=params)
コード例 #12
0
def update_signature_args(sig: inspect.Signature, arg_types: Dict[str, type],
                          has_self: bool) -> inspect.Signature:
    """Update argument annotations with the supplied types"""
    params = []
    for arg_idx, name in enumerate(sig.parameters):
        param = sig.parameters[name]
        typ = arg_types.get(name)
        # Don't touch pre-existing annotations and leave self un-annotated
        if (typ is not None) and \
           (param.annotation is inspect.Parameter.empty) and \
           ((not has_self) or (arg_idx != 0)):
            param = param.replace(annotation=typ)
        params.append(param)
    return sig.replace(parameters=params)
コード例 #13
0
	def process_overload_signature(self, overload: Signature) -> Signature:
		"""
		Processes the signature of the given overloaded implementation.

		:param overload:
		"""

		__globals__ = safe_getattr(self.object, "__globals__", {})
		overload = evaluate_signature(overload, __globals__)

		if not inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
			overload = overload.replace(parameters=list(overload.parameters.values())[1:])

		return super().process_overload_signature(overload)
コード例 #14
0
ファイル: inspect.py プロジェクト: sukumarsat/sphinx
def evaluate_signature(sig: inspect.Signature,
                       globalns: Dict = None,
                       localns: Dict = None) -> inspect.Signature:
    """Evaluate unresolved type annotations in a signature object."""
    def evaluate_forwardref(ref: ForwardRef, globalns: Dict,
                            localns: Dict) -> Any:
        """Evaluate a forward reference."""
        if sys.version_info > (3, 9):
            return ref._evaluate(globalns, localns, frozenset())
        else:
            return ref._evaluate(globalns, localns)

    def evaluate(annotation: Any, globalns: Dict, localns: Dict) -> Any:
        """Evaluate unresolved type annotation."""
        try:
            if isinstance(annotation, str):
                ref = ForwardRef(annotation, True)
                annotation = evaluate_forwardref(ref, globalns, localns)

                if isinstance(annotation, ForwardRef):
                    annotation = evaluate_forwardref(ref, globalns, localns)
                elif isinstance(annotation, str):
                    # might be a ForwardRef'ed annotation in overloaded functions
                    ref = ForwardRef(annotation, True)
                    annotation = evaluate_forwardref(ref, globalns, localns)
        except (NameError, TypeError):
            # failed to evaluate type. skipped.
            pass

        return annotation

    if globalns is None:
        globalns = {}
    if localns is None:
        localns = globalns

    parameters = list(sig.parameters.values())
    for i, param in enumerate(parameters):
        if param.annotation:
            annotation = evaluate(param.annotation, globalns, localns)
            parameters[i] = param.replace(annotation=annotation)

    return_annotation = sig.return_annotation
    if return_annotation:
        return_annotation = evaluate(return_annotation, globalns, localns)

    return sig.replace(parameters=parameters,
                       return_annotation=return_annotation)
コード例 #15
0
ファイル: stubs.py プロジェクト: wind1239/MonkeyType
def update_signature_args(
        sig: inspect.Signature,
        arg_types: Dict[str, type],
        has_self: bool,
        ignore_existing_annotations: bool = False) -> inspect.Signature:
    """Update argument annotations with the supplied types"""
    params = []
    for arg_idx, name in enumerate(sig.parameters):
        param = sig.parameters[name]
        typ = arg_types.get(name)
        typ = inspect.Parameter.empty if typ is None else typ
        is_self = (has_self and arg_idx == 0)
        annotated = param.annotation is not inspect.Parameter.empty
        # Don't touch existing annotations unless ignore_existing_annotations
        if not is_self and (ignore_existing_annotations or not annotated):
            param = param.replace(annotation=typ)
        params.append(param)
    return sig.replace(parameters=params)
コード例 #16
0
def update_signature_return(sig: inspect.Signature,
                            return_type: type = None,
                            yield_type: type = None) -> inspect.Signature:
    """Update return annotation with the supplied types"""
    anno = sig.return_annotation
    # Dont' touch pre-existing annotations
    if anno is not inspect.Signature.empty:
        return sig
    # NB: We cannot distinguish between functions that explicitly only
    # return None and those that do so implicitly. In the case of generator
    # functions both are typed as Iterator[<yield_type>]
    if (yield_type is not None) and ((return_type is None) or
                                     (return_type == NoneType)):
        anno = make_iterator(yield_type)
    elif (yield_type is not None) and (return_type is not None):
        anno = make_generator(yield_type, NoneType, return_type)
    elif return_type is not None:
        anno = return_type
    return sig.replace(return_annotation=anno)
コード例 #17
0
ファイル: test_all.py プロジェクト: ConradBailey/funcgen
def test_all_valid_sigs_content(all_valid_signatures_set, make_param_combos):
    annotations = [None, Parameter.empty]
    defaults = [None, Parameter.empty]
    arg1_combos = make_param_combos(['arg1'], Parameter.POSITIONAL_OR_KEYWORD,
                                    annotations, defaults)
    arg2_combos = make_param_combos(['arg2'], Parameter.POSITIONAL_OR_KEYWORD,
                                    annotations, defaults)
    kwarg1_combos = make_param_combos(['kwarg1'], Parameter.KEYWORD_ONLY,
                                      annotations, defaults)
    kwarg2_combos = make_param_combos(['kwarg2'], Parameter.KEYWORD_ONLY,
                                      annotations, defaults)
    defaults = [Parameter.empty]
    args_combos = make_param_combos(['args'], Parameter.VAR_POSITIONAL,
                                    annotations, defaults)
    kwargs_combos = make_param_combos(['kwargs'], Parameter.VAR_KEYWORD,
                                      annotations, defaults)

    for params in product(arg1_combos, arg2_combos, args_combos, kwarg1_combos,
                          kwarg2_combos, kwargs_combos):
        params = filter(None, params)
        try:
            sig = Signature(params)
            sig_return = sig.replace(return_annotation=None)
        except ValueError:  # invalid signature
            continue

        if (('arg2' in sig.parameters and not 'arg1' in sig.parameters) or
            ('kwarg2' in sig.parameters and not 'kwarg1' in sig.parameters)):
            assert sig not in all_valid_signatures_set
            assert sig_return not in all_valid_signatures_set
            continue

        assert sig in all_valid_signatures_set
        all_valid_signatures_set.remove(sig)
        assert sig_return in all_valid_signatures_set
        all_valid_signatures_set.remove(sig_return)

    assert len(all_valid_signatures_set) == 0
コード例 #18
0
ファイル: inspect.py プロジェクト: nstarman/utilipy
def drop_parameter(sig: Signature, param: T.Union[str, int, Parameter,
                                                  None]) -> Signature:
    """Drop a Parameter.

    Parameters
    ----------
    sig : Signature
        Signature object
    param: str, int, Parameter
        the parameter to drop in self.parameters
        identified by either the name (str) or index (int)
        (Parameter type calls name)
        If None, does not drop anything

    Returns
    -------
    Signature:
        a new Signature object with the replaced parameter

    """
    if param is None:
        return sig
    elif isinstance(param, int):  # convert index to name
        index = param
    elif isinstance(param, str):
        index = list(sig.parameters.keys()).index(param)
    elif isinstance(param, Parameter):
        index = list(sig.parameters.keys()).index(param.name)
    else:
        raise TypeError
    # setup
    parameters = list(sig.parameters.values())

    # drop
    del parameters[index]

    return sig.replace(parameters=parameters)
コード例 #19
0
 def __update_signature_from_docs(sig: inspect.Signature, docs: list) -> inspect.Signature:
     """:type docs: list[str]"""
     rtype = next((l[8:] for l in docs if l.startswith(':rtype')), None)
     ptypes = {t[0]: t[1] for t in [p.split(': ') for p in [l[6:] for l in docs if l.startswith(':type')]]}
     parameters = [p.replace(annotation=ptypes.get(n, p.annotation)) for n, p in sig.parameters.items()]
     return sig.replace(parameters=parameters, return_annotation=rtype if rtype else sig.return_annotation)
コード例 #20
0
ファイル: fixture.py プロジェクト: NorthIsUp/we-love-fixture
def _insert_param(sig: Signature, param: Parameter, index=0) -> Signature:
    params = list(sig.parameters.values())
    params.insert(index, param)
    return sig.replace(parameters=params)
コード例 #21
0
ファイル: plugin.py プロジェクト: eriknw/metagraph-1
def normalize_signature(sig: inspect.Signature):
    """Return normalized signature with bare type classes instantiated"""
    new_params = [normalize_parameter(p) for p in sig.parameters.values()]
    new_return = normalize_type(sig.return_annotation)
    return sig.replace(parameters=new_params, return_annotation=new_return)