pycroscope.signature¶
The Signature object and associated functionality. This
provides a way to represent rich callable objects and type check
calls.
- class pycroscope.signature.MaximumPositionalArgs(value: T, applicable_to: tuple[str, ...] = (), from_command_line: bool = False, priority: int = 0)¶
If calls have more than this many positional arguments, attempt to turn them into keyword arguments.
- exception pycroscope.signature.InvalidSignature¶
Raised when an invalid signature is encountered.
- class pycroscope.signature.CheckCallContext(*, visitor: 'pycroscope.name_check_visitor.NameCheckVisitor | None', can_assign_ctx: pycroscope.value.CanAssignContext, node: ast.AST | None = None, callee: pycroscope.value.Value | None = None, use_partial_call: bool = False)¶
- class pycroscope.signature.CallReturn(return_value: Value, sig: ForwardRef('Signature'), is_error: bool = False, used_any_for_match: bool = False, remaining_arguments: ActualArguments | None = None)¶
Return value of a preprocessed call.
This returns data that is useful for overload resolution.
- class pycroscope.signature.ImplReturn(return_value: Value, constraint: AbstractConstraint = NullConstraint(), no_return_unless: AbstractConstraint = NullConstraint())¶
Return value of impl functions.
These functions return either a single
pycroscope.value.Valueobject, indicating what the function returns, or an instance of this class.- constraint: AbstractConstraint¶
A
pycroscope.stacked_scopes.Constraintindicating things that are true if the function returns a truthy value.
- no_return_unless: AbstractConstraint¶
A
pycroscope.stacked_scopes.Constraintindicating things that are true unless the function does not return.
- class pycroscope.signature.CallContext(vars: dict[str, Value], visitor: NameCheckVisitor, composites: dict[str, Composite], node: AST | None, sig: Signature, inferred_return_value: Value)¶
The context passed to an impl function.
- visitor: NameCheckVisitor¶
Using the visitor can allow various kinds of advanced logic in impl functions.
- varname_for_arg(arg: str) VarnameWithOrigin | None¶
Return a varname corresponding to the given function argument.
This is useful for creating a
pycroscope.stacked_scopes.Constraintreferencing the argument.
- show_error(message: str, error_code: Error = Error(name='incompatible_call', description='Incompatible arguments to a function call.'), *, arg: str | None = None, node: AST | None = None, detail: str | None = None) None¶
Show an error.
If the arg parameter is given, we attempt to find the AST for that argument to the function and point the error to it.
- class pycroscope.signature.ParameterKind(*values)¶
Kinds of parameters.
- ELLIPSIS = 6¶
Special kind for Callable[…, T]. Such callables are compatible with any other callable. There can only be one ELLIPSIS parameter and it must be the last one.
- class pycroscope.signature.SigParameter(name: str, kind: ~pycroscope.signature.ParameterKind = ParameterKind.POSITIONAL_OR_KEYWORD, default: ~pycroscope.value.Value | None = None, annotation: ~pycroscope.value.Value = AnyValue(source=<AnySource.unannotated: 6>))¶
Represents a single parameter to a callable.
- kind: ParameterKind = 1¶
How the parameter can be passed.
- class pycroscope.signature.Signature(parameters: dict[str, ~pycroscope.signature.SigParameter], return_value: ~pycroscope.value.Value, impl: ~collections.abc.Callable[[~pycroscope.signature.CallContext], ~pycroscope.value.Value | ~pycroscope.signature.ImplReturn] | None = None, callable: object | None = None, is_asynq: bool = False, has_return_annotation: bool = True, allow_call: bool = False, allow_partial_call: bool = False, evaluator: ~pycroscope.type_evaluation.Evaluator | None = None, deprecated: str | None = None, bound_receiver_param_name: str | None = None, bound_receiver_composite: ~pycroscope.stacked_scopes.Composite | None = None, inferable_typevars: set[~pycroscope.value.TypeVarParam | ~pycroscope.value.ParamSpecParam | ~pycroscope.value.TypeVarTupleParam] = <factory>, use_default_inferable_typevars: bool = True, self_param: ~pycroscope.value.TypeVarParam | None = None)¶
Represents the signature of a Python callable.
This is used to type check function calls and it powers the
pycroscope.value.CallableValueclass.- parameters: dict[str, SigParameter]¶
An ordered mapping of the signature’s parameters.
- impl: Callable[[CallContext], Value | ImplReturn] | None = None¶
impl function for this signature.
- allow_call: bool = False¶
Whether type checking can call the actual function to retrieve a precise return value.
- allow_partial_call: bool = False¶
Whether the type checker should create a PartialCallValue if not all arguments are fully known.
- bind_arguments(actual_args: ActualArguments, ctx: CheckCallContext) dict[str, tuple[int | str | <DEFAULT> | <ARGS> | <KWARGS> | <UNKNOWN>, ~pycroscope.stacked_scopes.Composite]] | None¶
Attempt to bind the parameters in the signature to the arguments actually passed in.
Nomenclature: - parameters: the formal parameters of the callable - arguments: the arguments passed in in this call - bound arguments: the mapping of parameter names to values produced by this call
- check_call(args: ~collections.abc.Iterable[tuple[~pycroscope.stacked_scopes.Composite, None | str | ~pycroscope.signature.PossibleArg | <ARGS> | <KWARGS> | <ELLIPSIS> | ~pycroscope.value.ParamSpecParam]], ctx: ~pycroscope.signature.CheckCallContext) Value¶
Type check a call to this Signature with the given arguments.
This may call the impl function or the underlying callable, but normally just uses
inspect.Signature.bind().
- maybe_show_too_many_pos_args_error(*, args: ~collections.abc.Sequence[tuple[~pycroscope.stacked_scopes.Composite, None | str | ~pycroscope.signature.PossibleArg | <ARGS> | <KWARGS> | <ELLIPSIS> | ~pycroscope.value.ParamSpecParam]], bound_args: dict[str, tuple[int | str | <DEFAULT> | <ARGS> | <KWARGS> | <UNKNOWN>, ~pycroscope.stacked_scopes.Composite]], ctx: ~pycroscope.signature.CheckCallContext) None¶
Show an error if the call to this Signature has too many positional arguments.
- can_assign(other: Signature | OverloadedSignature, ctx: CanAssignContext) Mapping[ExternalType(type_path='pycroscope.value.TypeParam'), Sequence[ExternalType(type_path='pycroscope.value.Bound')]] | CanAssignError¶
Equivalent of
pycroscope.value.Value.can_assign(). Checks whether anotherSignatureis compatible with thisSignature.
- get_asynq_value() Signature¶
Return the
Signaturefor the .asynq attribute of anpycroscope.extensions.AsynqCallable.
- classmethod make(parameters: Iterable[SigParameter], return_annotation: Value | None = None, *, impl: Callable[[CallContext], Value | ImplReturn] | None = None, callable: object | None = None, has_return_annotation: bool = True, is_asynq: bool = False, allow_call: bool = False, allow_partial_call: bool = False, evaluator: Evaluator | None = None, deprecated: str | None = None, self_param: TypeVarParam | None = None, bound_receiver_param_name: str | None = None, bound_receiver_composite: Composite | None = None) Signature¶
Create a
Signatureobject.This is more convenient to use than the constructor because it abstracts away the creation of the underlying
inspect.Signature.
- pycroscope.signature.ANY_SIGNATURE = Signature(parameters={'...': SigParameter(name='...', kind=<ParameterKind.ELLIPSIS: 6>, default=None, annotation=AnyValue(source=<AnySource.unannotated: 6>))}, return_value=AnyValue(source=<AnySource.explicit: 2>), impl=None, callable=None, is_asynq=False, has_return_annotation=True, allow_call=False, allow_partial_call=False, evaluator=None, deprecated=None)¶
Signaturethat should be compatible with any otherSignature.
- pycroscope.signature.preprocess_args(args: ~collections.abc.Iterable[tuple[~pycroscope.stacked_scopes.Composite, None | str | ~pycroscope.signature.PossibleArg | <ARGS> | <KWARGS> | <ELLIPSIS> | ~pycroscope.value.ParamSpecParam]], ctx: ~pycroscope.signature.CheckCallContext) ActualArguments | None¶
Preprocess the argument list. Produces an ActualArguments object.
- class pycroscope.signature.OverloadedSignature(sigs: Sequence[Signature])¶
Represent an overloaded function.
- check_call(args: ~collections.abc.Iterable[tuple[~pycroscope.stacked_scopes.Composite, None | str | ~pycroscope.signature.PossibleArg | <ARGS> | <KWARGS> | <ELLIPSIS> | ~pycroscope.value.ParamSpecParam]], ctx: ~pycroscope.signature.CheckCallContext) Value¶
Check a call to an overloaded function.
The way overloads are handled is not well specified in any PEPs. Useful resources include:
Michael Lee’s specification of mypy’s behavior.
Eric Traut’s discussion of pyright’s behavior.
The documentation for pyright’s behavior.
Our behavior is closer to mypy. The general rule is to pick the first overload that matches and return an error otherwise, but there are two twists:
Anyand unions.Before we do a full check, we first check only whether the argument names and numbers match by calling
Signature.bind_arguments()(a trick we picked up from pyright). This makes for better error messages.If an overload matched only due to
Any, we continue looking for more overloads. If there are other matching overloads, we returnAny(withAnySource.multiple_overload_matches). This is different from pyright’s behavior: pyright picks the first overload regardless ofAny, which is unsafe in general. Returning aUnionwould be more precise, but may lead to false positives according to experience from other type checkers. A match “due toAny” is defined as a check that succeeded becauseAnywas on the right-hand side but not the left-hand side of a typecheck.This is implemented by setting a flag on the
pycroscope.value.CanAssignContextwhen a type check succeeds due toAny. This flag gets propagated toImplReturn.used_any_for_match.If an overload does not match, but one of the arguments passed was a
Union, we try all the components of theUnionseparately. If some of them match, we subtract them from theUnionand try the remaining overloads with a narrowerUnion. In this case, we return aUnionof the return values of all the matching overloads on success.The decomposition happens in the private
_check_param_type_compatibilitymethod ofSignature. When we perform decomposition, this method returns apycroscope.value.Valuerepresenting the remaining union members. This value is then used to construct a newActualArgumentsobject, which ends up inImplReturn.remaining_arguments.An overload that matches without requiring use of
Anyor union decomposition is called a “clean match”.
- class pycroscope.signature.BoundMethodSignature(signature: Signature | OverloadedSignature, self_composite: Composite, return_override: Value | None = None)¶
Signature for a method bound to a particular value.
- pycroscope.signature.mark_ellipsis_style_any_tail_parameters(params: Sequence[SigParameter]) list[SigParameter]¶
Mark
*args: Any, **kwargs: Anytails as gradual-call tails.We encode this with
AnySource.ellipsis_callableso it remains distinct from tails that becomeAnyonly after TypeVar substitution.