-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
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
gh-131421: fix ASDL grammar for Dict
to have an expr?*
keys field
#131419
base: main
Are you sure you want to change the base?
Conversation
In the `ast` documentation for Python: * https://docs.python.org/3/library/ast.html#ast.Dict it is made clear that: > When doing dictionary unpacking using dictionary literals the expression to be expanded goes in the values list, with a `None` at the corresponding position in `keys`. Hence, `keys` is really a `expr?*` and *not* a `expr*`.
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
Dict
variant to have an expr?*
keys field.Dict
variant to have an expr?*
keys field.
@@ -63,7 +63,7 @@ module Python | |||
| UnaryOp(unaryop op, expr operand) | |||
| Lambda(arguments args, expr body) | |||
| IfExp(expr test, expr body, expr orelse) | |||
| Dict(expr* keys, expr* values) | |||
| Dict(expr?* keys, expr* values) |
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 kind of change makes me wonder whether we should also add '+' to indicate 1 or more items. For instance nonlocal
requires at least one name, same for import
, global
and others.
Similarly, there is no explanation of what *
and ?
actually mean. While they can be inferred, I would expect a caption for them. WDYT @JelleZijlstra?
Dict
variant to have an expr?*
keys field.Dict
to have an expr?*
keys field
I don't think it's really worth changing the grammar here. |
Can we perhaps add a comment instead? because now that I think about it, for static analysis tools, we could be surprised (like, if we only focus on the ASDL and not on the documented entry itself). [I could be surprised in Sphinx though I don't think I've encountered an issue with this] |
It represents a point where it completely breaks expectation, where up until then, the ASDL (as far as I have observed) was being completely respected by the Would this be very difficult to parse / break a lot of handling? |
It's been like this for a long time and I don't recall any other reports of confusion about it, so there's a good argument to stick with the working code. That said, if you can provide a patch that parses this new syntax correctly and that compiles correctly, we can consider it. |
@JelleZijlstra I updated the Naturally, |
class Quantifier: | ||
class _Optional: pass | ||
class _Sequence: pass | ||
OPTIONAL = _Optional() | ||
SEQUENCE = _Sequence() |
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.
Could this just be an enum?
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.
Sure, I just prefer these to have unique/singleton values (as opposed to int
s or whatnot).
I can change it if its outside the expected coding style.
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.
If you wanted singletons you could also just do OPTIONAL = object()
but to be honest I think an Enum/StrEnum is a better choice here since it's more explicit.
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.
(one reason to do the class trick is to have a bit of a nicer repr(), but OTOH, I don't think we need to worry about importing enum
)
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.
Is it worth importing enum
? If you want to add your suggested change I can commit 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'm not sure if this is already the case or not, but can you quickly check that the tests for ast.parse('{}')
handle this case?
elif self.cur_token.kind == TokenKind.Question: | ||
is_opt = True | ||
quantifiers = [] | ||
while self.cur_token.kind in (TokenKind.Asterisk, TokenKind.Question): |
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.
Shouldn't we check that we don't have **
for instance or ??
?
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.
Maybe. But both ?? and ** are legitimate types, ** perhaps more legitimate than ?? is.
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.
Ah yes, actually the current parser doesn't care. I thought that it would have warned the user. And should T**
actually mean a list of list of T? is the obtained C code designed to handle this kind of grammar?
I have no strong opinion now on whether we should warn ??
.
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.
There is essentially no change to the C code at all at this point. I don't know how this was handled before, since expr?* was always there implicitly, but this didn't seem to matter.
class Field(AST): | ||
def __init__(self, type, name=None, seq=False, opt=False): | ||
def __init__(self, type, name=None, quantifiers=None): |
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.
Is there a need to support more than two qualifiers? and/or shouldn't we check the consistency of those qualifiers as well?
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.
Currently there are no more than two quantifiers on any type, as per my change to Python.asdl.
I'm just implementing the EBNF grammar described at the top of the asdl.py file. And I don't think this files does any amount of extra validation so far anyway.
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
In the
ast
documentation for Python:Hence,
keys
is really aexpr?*
and not aexpr*
.Python.asdl
type forkeys
inDict
literals #131421