Sorry, something went wrong.
|
The initial condition was based on tok->multi_line_start but then revisiting PEP701 I noticed that the example: >>> f'''A complex trick: {
... bag['bag'] # recursive bags!
... }'''
contained the opening curly bracket on the same level, so it was failing, but all the other cases were not. My goal was to skip that error condition, but I couldn't make a difference from the following cases: f"something {#
and f"""something {# some lines ahead
...
so I decided not to accept comments on the first line. Ideas are welcome :) |
Sorry, something went wrong.
|
@lysnikolaou @isidentical @mgmacias95 thoughts? |
Sorry, something went wrong.
|
Well, I'm not sure I like the idea of disallowing comments in the first line. One of the main points of 701 was that explaining f-string features would be much easier and this goes in the opposite direction. "You can add comments in f-string expressions" is much easier to remember than "You can add comments in f-string expressions, but not the first line". And this already comes on top of only allowing them in multi-line f-strings. This is not a very strong opinion and I'd obviously be okay to go with it, if working around it is very difficult and there's consensus that this is okay. |
Sorry, something went wrong.
|
Another option we could have, is start iterating on the rest of the line characters, and if I find a '}' I know we are on the same line and it's not valid, and if we find a '\n' we know it's a multi-line expression. Meaning: >>> f"nope {#}"
File "<stdin>", line 1
f"nope {#}"
^
SyntaxError: f-string expression part cannot include '#'
>>> f""" yep { # something
... 1 + 2 # math!
... }"""
' yep 3'
>>>
Can update the PR, but the code will look like this: if (INSIDE_FSTRING(tok) && (tok->lineno == 1)) {
while (c != '\n') {
c = tok_nextc(tok);
if (c == '}')
return MAKE_TOKEN(syntaxerror(tok, "f-string expression part cannot include '#'"));
}
}
Do you think something like this would make more sense @lysnikolaou ? If people gets creative I we will have problems as well with cases like: >>> f"meh {# I really like the } character
File "<stdin>", line 1
f"meh {# I really like the } character
^
SyntaxError: f-string expression part cannot include '#'
edit: if tok>lineno == 1 doesn't look too good, we could also condition it wrt the quote size, so we could have current_tok->f_string_quote_size == 1 instead. After all, we could detect if we are on a possible multi-line string. >>> f"""{#}"""
... 42}"""
'42'
but maybe it's better? |
Sorry, something went wrong.
|
edit: if tok>lineno == 1 doesn't look too good, we could also condition it wrt the quote size, so we could have current_tok->f_string_quote_size == 1 instead. After all, we could detect if we are on a possible multi-line string. This is the way to go in my opinion. The snippet you showed, while a bit tricky to parse for a human at first, should be okay, since this is also the case outside of f-strings: a_set = (#{
{
1, 2, 3, 4#}
}
)
|
Sorry, something went wrong.
|
This is the way to go in my opinion. I agree with this 👍 I think that the simpler the rules the easier to explain, specially since most syntax highlighters will do the right thing and show the comment in a darker shade |
Sorry, something went wrong.
|
Thanks for your feedback 🎉 |
Sorry, something went wrong.
| if (INSIDE_FSTRING(tok) && (current_tok->f_string_quote_size == 1)) { | ||
| while (c != '\n') { | ||
| c = tok_nextc(tok); | ||
| if (c == '}') |
There was a problem hiding this comment.
This may raise "false positives". What if for instance the text contains sone dictionary literal inside the expression or escaped }} or anything similar?
Sorry, something went wrong.
There was a problem hiding this comment.
I tried to play around with more cases, but I couldn't find a false-positive:
Maybe you have something else in mind? 🤔
Perhaps you were thinking of using INSIDE_FSTRING_EXPR(current_tok) as well?
Sorry, something went wrong.
There was a problem hiding this comment.
Example (check the location of the error caret):
Sorry, something went wrong.
There was a problem hiding this comment.
Another example:
Sorry, something went wrong.
There was a problem hiding this comment.
Another example:
Sorry, something went wrong.
There was a problem hiding this comment.
I think we may just want to drop this check because IIRC the error you will get is that there is a { that is never closed and it should point correctly to the one that's not closed
Sorry, something went wrong.
There was a problem hiding this comment.
yeah, also then we would need to define if we close the expression the moment we find a '}' or we agreed on something else, because something like:
should work by that condition, but things like:
will not. And the only solution I think could be possible, would be to either allow the '}}' escape pattern, so it could be valid with:
or we simply don't allow having { or } in the comments while being inside a f-string expression.
Not sure if we have another workaround.
Sorry, something went wrong.
There was a problem hiding this comment.
Nah I think the approach here is that a comment is a comment and we should not try to be clever about this. Let allow any comment inside and let's try to focus on the fact that the error message makes sort of sense (I expect that most of them would be unclosed brackets).
Sorry, something went wrong.
| if (INSIDE_FSTRING(tok) && (current_tok->f_string_quote_size == 1)) { | ||
| while (c != '\n') { | ||
| c = tok_nextc(tok); | ||
| if (c == '}') |
There was a problem hiding this comment.
Nit: Add braces per PEP 7
Sorry, something went wrong.
|
Hey @cmaureir, any progress on this? Will you get some time to address the comments so that we can merge this? |
Sorry, something went wrong.
|
Hey @cmaureir, any progress on this? Will you get some time to address the comments so that we can merge this? Hey, I got lost in the corner-cases, and I got distracted afterwards. >>> f"{1 # look some weird escaped }}
+
1
}"
So I'd need some input if f"something {1 # this is a comment } { no matter what is around on the rest of the line...
... }"
or f"something {1 # this is a comment } <- the expr and comment ended there, the rest is just a str"
With (1), we simple remove the error from the tokenizer, and we would expect behavior like this (from Pablo's comments): >>> a = 1
>>> f"{a # {1,2,3,4} }"
... }"
'1'
>>> f"{a # {1,2,3,4}
... }"
'1'
>>> f"{1 # look some weird escaped }}
... +
... 1
... }"
'2'
What do you think @lysnikolaou would what be enough? |
Sorry, something went wrong.
|
Yeah, let's go with (1). |
Sorry, something went wrong.
|
For that behavior, then it should be simpler, and only removing the error condition will be enough. If more test cases are required, please let me know. |
Sorry, something went wrong.
There was a problem hiding this comment.
Looks good!
Sorry, something went wrong.
|
Btw, let's add some more tests, at least covering comments in single-quoted f-string as well, in a different PR. |
Sorry, something went wrong.
|
Btw, let's add some more tests, at least covering comments in single-quoted f-string as well, in a different PR. Understood. Thanks for your time on this :) |
Sorry, something went wrong.
Enabling comments only on multi-line f-strings, but starting from the second line of it.