-
Notifications
You must be signed in to change notification settings - Fork 21
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
Fix bug in assignments #68
Fix bug in assignments #68
Conversation
'x -> ()']) | ||
|
||
def test_call_assignment(self): | ||
code = "NameError().name = 't'" |
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.
Here the ast.Call instance will never be analyzed because it's not part of the supported nodes for assignments.
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, it's not bound to any identifier... We could create temporary identifier for unbound expression that get assigned, but let's keep that for another patch.
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.
But it won't be visited at all, so the ast.Call instance uses won't be part of the chains at all, even if we could argue that it's still a user of NameError, the same manner NameError won't be added to the uses of the builtins NameError symbol. This is why I think we should unconditionally visit this part.
beniget/beniget.py
Outdated
elif isinstance(elt, (ast.Subscript, ast.Attribute)): | ||
self.visit(elt) |
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.
We could remove these isinstance checks and simply call visit() for all other node types?
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 like the conservative checks we are currently doing. That way if another case pop ups we don't have a default (and maybe unexpected) behavior.
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.
See my other comment about the node being completely ignored if we don’t include a catch all case
@paugier , maybe you have a moment to look at the pending PRs ? Thanks a lot, |
beniget/beniget.py
Outdated
elif isinstance(elt, (ast.Subscript, ast.Attribute)): | ||
self.visit(elt) |
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 like the conservative checks we are currently doing. That way if another case pop ups we don't have a default (and maybe unexpected) behavior.
beniget/beniget.py
Outdated
self.visit(elt) | ||
elif isinstance(elt, ast.Starred) and isinstance(elt.value, ast.Name): |
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.
group that with if isinstance(elt, ast.Name):
above as it's the same body?
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.
It's not exactly the same code, though.
tests/test_chains.py
Outdated
break | ||
''' | ||
self.checkChains(code, ['curr -> (curr -> (), curr -> (Call -> ()))', | ||
'parts -> (Starred -> (), parts -> (), parts -> ())']*2) |
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'm a bit puzzled by the Starred
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.
Can you develop ?
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.
Why is the Starred in the def-use chain? It's not a user, 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.
OK, I dive a bit and I now understand the situation a bit better. When we use *
to expand a container as part of an argument call, the Starred
is clearly a user. And it' has a Load
context. When it's used to unpack a tuple, it has a Store
context and it's just used to specify the nature of the operation. It is debatable whether that's a use or not... I'd rather see that as a property of the def, but we don't have that concept. I don't see it as a new Def either. Let me submit a new PR for that particular behavior
'x -> ()']) | ||
|
||
def test_call_assignment(self): | ||
code = "NameError().name = 't'" |
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, it's not bound to any identifier... We could create temporary identifier for unbound expression that get assigned, but let's keep that for another patch.
Can you rebase that one on the |
Fixes #66