Skip to content

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

Closed
wants to merge 13 commits into from
Closed

bpo-15987: Add ast.AST class richcompare methods #1368

wants to merge 13 commits into from

Conversation

louisom
Copy link
Contributor

@louisom louisom commented May 1, 2017

This will not compare with attributes, but fields and types.

https://bugs.python.org/issue15987

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a 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
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this recursive?

Copy link
Contributor Author

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]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not getattr?

Copy link
Contributor Author

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
Copy link
Member

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)
Copy link
Member

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

Copy link
Contributor Author

@louisom louisom May 2, 2017

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.

Copy link
Contributor Author

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
Copy link
Member

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
Copy link
Member

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?

Copy link
Contributor Author

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))]
Copy link
Member

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.

Copy link
Contributor Author

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(
Copy link
Member

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(
Copy link
Member

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().

@brettcannon brettcannon added the type-feature A feature request or enhancement label May 1, 2017
@louisom
Copy link
Contributor Author

louisom commented May 2, 2017

I'm not sure why travis failed on clang and gcc, my local build run pass the test.

@louisom
Copy link
Contributor Author

louisom commented May 2, 2017

@Haypo point out that I shouldn't change Python/Python-ast.c, it should be generated by asdl_c.py

@louisom louisom changed the title bpo-15987: Add AST nodes eq & ne compare methods bpo-15987: Add ast.AST class richcompare methods May 2, 2017
@tonybaloney
Copy link
Contributor

hi, this PR has been open for some time and the discussion in https://bugs.python.org/issue15987 is inconclusive.
Please can the team review this BPO

@vstinner
Copy link
Member

cc @methane

@vstinner
Copy link
Member

@louisom: Can you rebase this PR on master?

@tonybaloney
Copy link
Contributor

@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.

@vstinner
Copy link
Member

@vstinner the original branch no longer exists, GH shows it as "unknown repository", but it means the branch or the user no longer exist.

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:
https://patch-diff.githubusercontent.com/raw/python/cpython/pull/1368.patch

Is there someone interested to convert this old PR into a newer PR?

@flavianh
Copy link

flavianh commented Jul 20, 2019

@vstinner I can try!

@flavianh
Copy link

@vstinner Recreated at #14970

@csabella
Copy link
Contributor

Closing this pull request as it has been recreated under a different pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants