-
-
Notifications
You must be signed in to change notification settings - Fork 276
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 typing to NodeNG.nodes_of_class
#1168
Conversation
This uses overloads to type the ``nodes_of_class`` function
As said in the description: would like some help figuring out why EDIT: I have done some additional investigations. The problem is that Pdb) self
<FunctionDef.nodes_of_class l.504 at 0x109915e80>
(Pdb) [i for i in self.get_children()]
[<Decorators l.503 at 0x1094b9580>, <Arguments l.505 at 0x1094b97c0>, <Subscript l.508 at 0x1094b9640>, <Expr l.509 at 0x1094b9220>] L509 is the EDIT2: Looks like #1015 has already indicated 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.
Thanks for starting the work on this one! It was long overdue.
I left a few comments. Basically, all current overloads are redundant and can be removed.
--
One area we still need to take a look at is the annotation for klass
. As this can be a tuple as well, it complicates things. An idea:
T_Nodes = TypeVar("T_Nodes", bound="NodeNG")
T_Nodes2 = TypeVar("T_Nodes2", bound="NodeNG")
T_Nodes3 = TypeVar("T_Nodes3", bound="NodeNG")
SkipKlassT = Union[None, Type["NodeNG"], Tuple[Type["NodeNG"], ...]]
class NodeNG:
@overload
def nodes_of_class(
self,
klass: Type[T_Nodes],
skip_klass: SkipKlassT = None,
) -> Iterator[T_Nodes]:
...
@overload
def nodes_of_class(
self,
klass: Tuple[Type[T_Nodes], Type[T_Nodes2]],
skip_klass: SkipKlassT = None,
) -> Union[Iterator[T_Nodes], Iterator[T_Nodes2]]:
...
@overload
def nodes_of_class(
self,
klass: Tuple[Type[T_Nodes], Type[T_Nodes2], Type[T_Nodes3]],
skip_klass: SkipKlassT = None,
) -> Union[Iterator[T_Nodes], Iterator[T_Nodes2], Iterator[T_Nodes3]]:
...
# Technically any number of additional overloads with a different number of
# items for 'klass' could be added. However, 3 should cover most cases
# Use the last overload as fallback.
# Unfortunately, this doesn't work in 'mypy'. Probably because of a bug.
@overload
def nodes_of_class(
self,
klass: Tuple[Type[T_Nodes], ...],
skip_klass: SkipKlassT = None,
) -> Iterator[T_Nodes]:
...
def nodes_of_class(
self,
klass: Union[
Type[T_Nodes],
Tuple[Type[T_Nodes], Type[T_Nodes2]],
Tuple[Type[T_Nodes], Type[T_Nodes2], Type[T_Nodes3]],
Tuple[Type[T_Nodes], ...], # related to the 'mypy' bug. Needs to be excluded as well
],
skip_klass: SkipKlassT = None,
) -> Union[Iterator[T_Nodes], Iterator[T_Nodes2], Iterator[T_Nodes3]]:
# implementation
pass
--
Regarding the pylint
issue. I would think this is a bug. Need to take a look at it sometime. For now, I would recommend to use # pylint: ignore
and link the issue.
Wow, this is a much cleaner solution! I did not know |
astroid/nodes/scoped_nodes.py
Outdated
for yield_ in self.nodes_of_class(node_classes.Yield): | ||
for ( | ||
yield_ | ||
) in self.nodes_of_class( # pylint: disable=not-an-iterable # See https://github.com/PyCQA/astroid/issues/1015 |
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.
Just realized that we would need to add this to every call in pylint
as well 😕
The issue should probably be fixed before we can merge it.
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 a pip install -e local_astroid_folder
and succeeded in running the pre-commit to test for this. (in my local pylint folder of course)
The problem comes from overload
s where the ...
is on a separate line (I think).
We don't have those in pylint (yet), so I think for the time-being we are fine.
You might want to check this though by doing pip -e
as well, just to be sure!
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.
Just tested it as well and you're right. At the moment pylint
doesn't complain. The reason however isn't that we don't use overloads
. It's actually that node
in visit_xxx(self, node)
cannot be inferred and thus no error is emitted. In contrast, just doing something like this will easily produce one:
def func():
node = nodes.For()
for n in node.nodes_of_class(nodes.Name): # not-an-iterable
pass
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.
Didn't we just add typing to all visit_xxx(self, node)
calls in pylint
? Or is that not enough to help mypy
?
I saw you just assigned somebody to #1015. I think we should block this until that issue has been fixed, right?
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.
Except from some corner cases, type annotations aren't used to infer values in pylint. That is different in mypy
.
I think we should block this until that issue has been fixed, right?
Since this doesn't actually cause any issues with pylint
, I would say we can merge it now. It doesn't necessarily need to wait for #1015.
I spend most of the time dealing with type checker issues to be honest. The one I mentioned for
We should be able to remove a few |
@DanielNoord Would you like to work on a follow up PR for |
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 good 🚀
Thanks @DanielNoord!
Yes! You can assign that (imaginary) issue to me 😄 |
Steps
Description
This uses overloads to type the
nodes_of_class
function.For some reason
pylint
doesn't pick up on the iterable context correctly. Some help would be appreciated! This is not shown in the CI but does show up locally.Type of Changes
Related Issue