Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check against invalid Signature objects and prepare for refactoring Signature compatibility logic #390

Merged
merged 14 commits into from
Jan 9, 2022
Merged
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Check against invalid `Signature` objects and prepare
for refactoring `Signature` compatibility logic (#390)
- Treat `int` and `float` as compatible with `complex`,
as specified in PEP 484 (#389)
- Do not error on boolean operations on values typed
Expand Down
33 changes: 26 additions & 7 deletions pyanalyze/arg_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,17 @@
import inspect
import sys
from types import FunctionType, ModuleType
from typing import Any, Callable, Iterator, Sequence, Generic, Mapping, Optional, Union
from typing import (
Any,
Callable,
Iterator,
Sequence,
Generic,
Mapping,
Optional,
Tuple,
Union,
)
import typing_inspect
from unittest import mock

Expand Down Expand Up @@ -352,11 +362,15 @@ def from_signature(

parameters = []
for i, parameter in enumerate(sig.parameters.values()):
parameters.append(
self._make_sig_parameter(
parameter, func_globals, function_object, is_wrapped, i
)
param, make_everything_pos_only = self._make_sig_parameter(
parameter, func_globals, function_object, is_wrapped, i
)
if make_everything_pos_only:
parameters = [
replace(param, kind=ParameterKind.POSITIONAL_ONLY)
for param in parameters
]
parameters.append(param)

return Signature.make(
parameters,
Expand All @@ -376,7 +390,7 @@ def _make_sig_parameter(
function_object: Optional[object],
is_wrapped: bool,
index: int,
) -> SigParameter:
) -> Tuple[SigParameter, bool]:
"""Given an inspect.Parameter, returns a Parameter object."""
if is_wrapped:
typ = AnyValue(AnySource.inference)
Expand All @@ -395,9 +409,14 @@ def _make_sig_parameter(
)
):
kind = ParameterKind.POSITIONAL_ONLY
make_everything_pos_only = True
else:
kind = ParameterKind(parameter.kind)
return SigParameter(parameter.name, kind, default=default, annotation=typ)
make_everything_pos_only = False
return (
SigParameter(parameter.name, kind, default=default, annotation=typ),
make_everything_pos_only,
)

def _get_type_for_parameter(
self,
Expand Down
17 changes: 11 additions & 6 deletions pyanalyze/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,19 @@ def compute_parameters(

posonly_args = getattr(node.args, "posonlyargs", [])
num_without_defaults = len(node.args.args) + len(posonly_args) - len(defaults)
defaults = [*[None] * num_without_defaults, *defaults, *kw_defaults]
args: List[Tuple[ParameterKind, ast.arg]] = (
[(ParameterKind.POSITIONAL_ONLY, arg) for arg in posonly_args]
+ [(ParameterKind.POSITIONAL_OR_KEYWORD, arg) for arg in node.args.args]
+ [(ParameterKind.KEYWORD_ONLY, arg) for arg in node.args.kwonlyargs]
)
vararg_defaults = [None] if node.args.vararg is not None else []
defaults = [
*[None] * num_without_defaults,
*defaults,
*vararg_defaults,
*kw_defaults,
]
args: List[Tuple[ParameterKind, ast.arg]] = [
(ParameterKind.POSITIONAL_ONLY, arg) for arg in posonly_args
] + [(ParameterKind.POSITIONAL_OR_KEYWORD, arg) for arg in node.args.args]
if node.args.vararg is not None:
args.append((ParameterKind.VAR_POSITIONAL, node.args.vararg))
args += [(ParameterKind.KEYWORD_ONLY, arg) for arg in node.args.kwonlyargs]
if node.args.kwarg is not None:
args.append((ParameterKind.VAR_KEYWORD, node.args.kwarg))
params = []
Expand Down
Loading