-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-15987: Add ast.AST class richcompare methods #1368
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
Conversation
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 don't know whether it is good idea to implement the comparison of AST nodes, but added technical comments to the implementation.
Lib/ast.py
Outdated
|
||
def ast_eq_compare(a, b): | ||
if type(a) != type(b): | ||
return False |
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.
return NotImplemented
This will allow other classes implement the comparison with AST nodes.
Lib/ast.py
Outdated
if type(a) != type(b): | ||
return False | ||
if type(a) not in _NODES: | ||
return a == b |
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.
Isn't this recursive?
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 may recursive to a builtin-type value, then can return compare fast.
Lib/ast.py
Outdated
|
||
ret = True | ||
for field in a._fields: | ||
af = vars(a)[field] |
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 not getattr?
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 point out.
Lib/ast.py
Outdated
if type(a) not in _NODES: | ||
return a == b | ||
|
||
ret = True |
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.
Actually this isn't needed. See below.
Lib/ast.py
Outdated
if len(af) != len(bf): | ||
return False | ||
for i, j in zip(af, bf): | ||
ret &= ast_eq_compare(i, j) |
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.
Fail fast.
if i != j:
return False
But stop, why not compare just lists?
if af != bf:
return False
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.
No, you can't simply compare these, _ast.KEYWORDS's fields value will be builtin-type
or [_ast.KEYWORDS]
(e.g. [<_ast.Expr object at 0x7f06659c8468>]
), since the compare method doesn't hook up yet, you can't simply compare a list with _ast.KEYWORDS.
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.
Thus we will need to recursively to compare the items.
Lib/ast.py
Outdated
|
||
for n in _NODES: | ||
n.__eq__ = ast_eq_compare | ||
n.__ne__ = ast_ne_compare |
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 isn't needed. The default implementation falls back to __eq__
Lib/ast.py
Outdated
|
||
|
||
for n in _NODES: | ||
n.__eq__ = ast_eq_compare |
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 not patch just the base class?
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.
@serhiy-storchaka You are right, I thought is was difficult or not possible when implementing a top-down richcompare, but I'm wrong.
re-implement the richcompare inside the AST_type
Lib/ast.py
Outdated
from _ast import * | ||
|
||
|
||
# Add EQ and NE compare to _ast Nodes | ||
_NODES = [vars(_ast)[k] for k in filter( | ||
lambda x: not x.startswith('_') and x not in ('AST' 'PyCF_ONLY_AST'), vars(_ast))] |
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.
'ASTPyCF_ONLY_AST' is the single literal.
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.
Change to ('AST', 'PyCF_ONLY_AST')
Lib/ast.py
Outdated
from _ast import * | ||
|
||
|
||
# Add EQ and NE compare to _ast Nodes | ||
_NODES = [vars(_ast)[k] for k in filter( |
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.
Don't use filter
and lambda
. Use just if
in the list comprehension.
Lib/ast.py
Outdated
from _ast import * | ||
|
||
|
||
# Add EQ and NE compare to _ast Nodes | ||
_NODES = [vars(_ast)[k] for k in filter( |
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.
Rather than calling vars()
multiple times just iterate vars(_ast).items()
.
I'm not sure why travis failed on clang and gcc, my local build run pass the test. |
@Haypo point out that I shouldn't change |
hi, this PR has been open for some time and the discussion in https://bugs.python.org/issue15987 is inconclusive. |
cc @methane |
@louisom: Can you rebase this PR on master? |
@vstinner the original branch no longer exists, GH shows it as "unknown repository", but it means the branch or the user no longer exist. The only way to merge this would be to recreate the patch elsewhere. |
https://github.com/louisom user still exists. I understand that he deleted its fork of CPython. It's possible to download this PR as a patch using the URL: Is there someone interested to convert this old PR into a newer PR? |
@vstinner I can try! |
Closing this pull request as it has been recreated under a different pull request. |
This will not compare with attributes, but fields and types.
https://bugs.python.org/issue15987