bpo-15987: Add ast.AST class richcompare methods#1368
bpo-15987: Add ast.AST class richcompare methods#1368louisom wants to merge 13 commits intopython:masterfrom louisom:bpo-15987-compare-ast-nodes
Conversation
serhiy-storchaka
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Why not patch just the base class?
There was a problem hiding this comment.
@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
|
|
||
| # 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.
'ASTPyCF_ONLY_AST' is the single literal.
There was a problem hiding this comment.
Change to ('AST', 'PyCF_ONLY_AST')
Lib/ast.py
Outdated
|
|
||
|
|
||
| # Add EQ and NE compare to _ast Nodes | ||
| _NODES = [vars(_ast)[k] for k in filter( |
There was a problem hiding this comment.
Don't use filter and lambda. Use just if in the list comprehension.
Lib/ast.py
Outdated
|
|
||
|
|
||
| # Add EQ and NE compare to _ast Nodes | ||
| _NODES = [vars(_ast)[k] for k in filter( |
There was a problem hiding this comment.
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