-
-
Notifications
You must be signed in to change notification settings - Fork 267
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
Add some inference annotations #1887
Add some inference annotations #1887
Conversation
Pull Request Test Coverage Report for Build 3700007049
💛 - Coveralls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial pass!
astroid/decorators.py
Outdated
@@ -89,15 +89,17 @@ def __get__(self, inst, objtype=None): | |||
return val | |||
|
|||
|
|||
def path_wrapper(func): | |||
def path_wrapper(func: Callable) -> Callable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a Typevar
or even a ParamSpec
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain more? I haven't used those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the PEP introducing ParamSpec
is quite clear:
https://peps.python.org/pep-0612/
It explains its uses and those can be applied here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds out of scope for this PR. I can undo this change if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let's revert then
astroid/inference.py
Outdated
def _infer_sequence_helper(node, context: InferenceContext | None = None): | ||
def _infer_sequence_helper( | ||
node: _BaseContainerT, context: InferenceContext | None = None | ||
) -> list[nodes.NodeNG]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is node.elts
correctly typed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BaseContainer
has self.elts: list[NodeNG] = []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm that sounds weird. I need to investigate this but I'm fairly certain that it could be Instance
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked and this is likely incorrect. In the construction of Lists
in DictModel.attr_values
we use the keys
of a Dict.items
. Those are SuccessfulInferenceResults
.
So elts
is indeed incorrectly typed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this change be undone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you change it to SuccessfulInferenceResult
?
astroid/inference.py
Outdated
def _populate_context_lookup(call, context): | ||
def _populate_context_lookup( | ||
call: nodes.Call, context: InferenceContext | None | ||
) -> dict[nodes.NodeNG, InferenceContext]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like it should be InferenceResult
or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nodes.NodeNG
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did another pass! Thanks for taking the time to do this, I know how difficult it is to get these right and PRs like this are really helpful to at least get the discussion and project going 😄
astroid/decorators.py
Outdated
def wrapped(node, context: InferenceContext | None = None, _func=func, **kwargs): | ||
def wrapped( | ||
node, context: InferenceContext | None = None, _func=func, **kwargs | ||
) -> Iterator: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use Generator
, since this function has return
statements.
astroid/helpers.py
Outdated
@@ -219,7 +219,7 @@ def is_supertype(type1, type2) -> bool: | |||
return _type_check(type1, type2) | |||
|
|||
|
|||
def class_instance_as_index(node): | |||
def class_instance_as_index(node) -> nodes.Const | None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def class_instance_as_index(node) -> nodes.Const | None: | |
def class_instance_as_index(node: bases.Instance) -> nodes.Const | None: |
I did a quick check and this should work 😄
astroid/inference.py
Outdated
def _infer_sequence_helper(node, context: InferenceContext | None = None): | ||
def _infer_sequence_helper( | ||
node: _BaseContainerT, context: InferenceContext | None = None | ||
) -> list[nodes.NodeNG]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked and this is likely incorrect. In the construction of Lists
in DictModel.attr_values
we use the keys
of a Dict.items
. Those are SuccessfulInferenceResults
.
So elts
is indeed incorrectly typed.
astroid/inference.py
Outdated
@@ -216,7 +218,7 @@ def _higher_function_scope(node: nodes.NodeNG) -> nodes.FunctionDef | None: | |||
while current.parent and not isinstance(current.parent, nodes.FunctionDef): | |||
current = current.parent | |||
if current and current.parent: | |||
return current.parent # type: ignore[return-value] | |||
return current.parent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This causes an additional message.
astroid/inference.py
Outdated
@@ -743,7 +745,9 @@ def _bin_op( | |||
) | |||
|
|||
|
|||
def _get_binop_contexts(context, left, right): | |||
def _get_binop_contexts( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do this in my BinOp
PRs. I'll prepare those somewhere this week.
@@ -759,7 +763,7 @@ def _get_binop_contexts(context, left, right): | |||
yield new_context | |||
|
|||
|
|||
def _same_type(type1, type2): | |||
def _same_type(type1, type2) -> bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting as adding annotations to type1
will cause a type error... Hmm, we should probably investigate this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is used twice. In both cases, the inputs can be InferenceResult | None
, but this function assumes that it will be InferenceResult
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proxy
is involved too. Messy!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😅
astroid/protocols.py
Outdated
@@ -349,7 +349,9 @@ def assend_assigned_stmts( | |||
nodes.AssignAttr.assigned_stmts = assend_assigned_stmts | |||
|
|||
|
|||
def _arguments_infer_argname(self, name, context): | |||
def _arguments_infer_argname( | |||
self, name: str, context: InferenceContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name
can be None
, see code down below.
astroid/decorators.py
Outdated
@@ -89,15 +89,17 @@ def __get__(self, inst, objtype=None): | |||
return val | |||
|
|||
|
|||
def path_wrapper(func): | |||
def path_wrapper(func: Callable) -> Callable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, let's revert then
astroid/inference.py
Outdated
def _infer_sequence_helper(node, context: InferenceContext | None = None): | ||
def _infer_sequence_helper( | ||
node: _BaseContainerT, context: InferenceContext | None = None | ||
) -> list[nodes.NodeNG]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you change it to SuccessfulInferenceResult
?
@@ -759,7 +763,7 @@ def _get_binop_contexts(context, left, right): | |||
yield new_context | |||
|
|||
|
|||
def _same_type(type1, type2): | |||
def _same_type(type1, type2) -> bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😅
astroid/inference.py
Outdated
def _populate_context_lookup(call, context): | ||
def _populate_context_lookup( | ||
call: nodes.Call, context: InferenceContext | None | ||
) -> dict[InferenceResult, InferenceContext]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you actually checked that this is InferenceResult
and not SuccesfulInferenceResult
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, there are a lot of fixes. I would be in favor of merging. We definitely need to activate mypy to be able to tell if something regressed without having to check locally by comparing the output before and after (I didn't do that so the approve is based on trust and the fact that actually verifying would take a lot of time.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did verify this last time and all comments have been resolved! Thanks!
Type of Changes