-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add "preserve" quote-style to mimic Black's skip-string-normalization #8822
Conversation
b8130e1
to
8793f8d
Compare
|
I have based this commit on: - ruff-pre-commit README.md | Using Ruff with pre-commit https://github.com/astral-sh/ruff-pre-commit/blob/main/README.md - The Ruff Formatter | Conflicting lint rules https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules Support for the ruff formatter was added in pytest-ruff by commits from October 2023, released the same day as versions 0.2 and 0.2.1. Hence, it makes sense to require pytest-ruff ≥ 0.2.1 now that we use the ruff formatter. I cannot find in ruff the equivalent for `skip-string-normalization` in black. This is currently an open issue in ruff: astral-sh/ruff#7305 astral-sh/ruff#7525 astral-sh/ruff#8822 I have settled on single quotes, for now.
I have based this commit on: - ruff-pre-commit README.md | Using Ruff with pre-commit https://github.com/astral-sh/ruff-pre-commit/blob/main/README.md - The Ruff Formatter | Conflicting lint rules https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules Support for the ruff formatter was added in pytest-ruff by commits from October 2023, released the same day as versions 0.2 and 0.2.1. Hence, it makes sense to require pytest-ruff ≥ 0.2.1 now that we use the ruff formatter. I cannot find in ruff the equivalent for `skip-string-normalization` in black. This is currently an open issue, in progress: astral-sh/ruff#7305 astral-sh/ruff#7525 astral-sh/ruff#8822 I have settled on single quotes, for now.
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.
Nice one! +1
Thanks for implementing this new option. It is a good signal on how important this functionality is for the community. I haven't looked at the code yet and have some more catch-up work to do before I'll find the time for the review. I'm overall okay with adding this new option but I want to make sure that it removes the need for |
Awesome, thanks @sciyoshi, great to see you back on the repo :) I have basically the same reaction: I support adding this, though it'd be nice if doing so could definitively preclude us from adding |
Thanks :) I think there's three cases to think about for the
Black's behavior with |
8793f8d
to
8fe698a
Compare
To make sure I understand you correctly. This PR
In other words, using |
Correct, that's the current behavior of this PR: --- example.py
+++ example.py
@@ -6,12 +6,12 @@
R"double"
-B'single'
+b'single'
-B"double"
+b"double"
-"\' escape"
+"' escape"
-'''single triple'''
+"""single triple"""
"""double triple""" |
The "preserve" quote style looks like a step in the right direction. What would this PR do about this? s = '''
"""
Example docstring
"""
''' Or this? return('''
"""
Example docstring
"""
'''
) Are you sure you know what an "unnecessary" escape is? What about? pattern = re.compile('''
whatever
''') Or this? pattern = re.compile(fr"""
whatever
""") Finally, what about backslash-newlines? s = textwrap.dedent("""\
unit test data
""") Removing the trailing backslash would break some of Leo's unit tests. |
@edreamleo the result for your examples would be import re
import textwrap
s = '''"""
Example docstring
"""
'''
def foo():
return('''
"""
Example docstring
"""
'''
)
pattern = re.compile('''
whatever
''')
pattern = re.compile(fr"""
whatever
""")
s = textwrap.dedent("""\
unit test data
""") --- example.py
+++ example.py
@@ -6,22 +6,29 @@
"""
'''
+
def foo():
- return('''
+ return '''
"""
Example docstring
"""
'''
- )
-pattern = re.compile('''
+
+pattern = re.compile(
+ """
whatever
-''')
+"""
+)
-pattern = re.compile(fr"""
+pattern = re.compile(
+ rf"""
whatever
-""")
+"""
+)
-s = textwrap.dedent("""\
+s = textwrap.dedent(
+ """\
unit test data
-""")
+"""
+) This happens to be identical to the formatting without the |
@zanieb Thanks for your comment! My only remaining concern is the backslash-newline question. By "whatever" I meant various cases containing escapes that might be considered "unnecessary". Perhaps this PR has no effect on that question. |
8fe698a
to
40dca18
Compare
I've added an argument to Backslash-newlines will be preserved, as will other escape sequences. From my testing I think it is only unnecessarily-escaped quotes that are changed. If @MichaReiser and @charliermarsh are OK with it, I think this could probably be merged as-is. Nothing precludes us from changing the behavior of |
40dca18
to
54bc011
Compare
We've intentionally omitted any other options than
Any other semantic than what we've defined in this PR would be confusing in my view, because the scope of the
In that case, I would prefer having a dedicated
That would be great. You can probably even use an existing test and add an |
54bc011
to
0e722dd
Compare
No problem, I've now removed those.
I don't quite follow, are you saying that the issue is with the name I don't think Ruff will need to add a separate
Thanks for the tip - I added some simple tests to this PR. Let me know if there's other cases we should be checking. |
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 made a few changes to the code and introduced a QuoteChar
to avoid having to handle Preserve
in situations where Preserve
isn't a valid variant (and there's no good way of e.g. implementing invert
).
I also extended your tests by a few docstring examples and noticed that single-quoted docstrings remain unchanged (see failing tests). This isn't specific to preserve
, the docstring quotes also remain unchanged when using quote-style: single
.
@charliermarsh I belive you changed the formatter to enforce double quotes for all docstrings and triple quoted strings. Was it an intentional decision to handle single quoted docstrings the same as inline strings or do you think this should be changed?
Implementation note: The string formatting should know that it is a docstring by check its layout.
Signed-off-by: Micha Reiser <micha@reiser.io>
Signed-off-by: Micha Reiser <micha@reiser.io>
310358d
to
36a17e9
Compare
I rebased the changes, updated the documentation, and gated the new option behind the Something I noticed when updating the documentation is that The reason for gating this behind preview is that we had some internal discussions and @charliermarsh brought up this valid concern:
We gate this behind preview because we want to ship the functionality that allows users to preserve their quote style, but we need to gather more feedback if configuring this using @charliermarsh or @BurntSushi would appreciate if you could review the changes that I made to this PR. |
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.
Nice!
One other thought here is whether it makes sense to document the nooks and crannies of the preserve
option. That is, its impact (or not) on docstring quoting and how it interacts with escaping and what not.
|
||
|
||
def docstring_single(): | ||
"single" |
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.
Just to clarify here (given what @charliermarsh said), we are starting with normalizing docstring using single quotes to double quotes (even with preserve=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.
Correct, that's the current behavior of this PR. Like @charliermarsh this is probably unexpected behavior, but can be changed later if we hear feedback about 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.
SGTM!
I agree with this, although like I mentioned this can be relaxed in a followup without breaking compatibility.
I think adding a separate option for this would be a mistake - |
This is my feeling as well.
(Just to clarify, I was referring here to the confusion that |
I continue to feel conflicted about this. The documentation for The other challenge is that we wouldn't be able to support enforcing double quotes for triple quoted strings and docstrings but preserve the other quotes. Anyway, I think this is something we can re-visit when we get more feedback. This looks good to me. Thanks for pushing us to revisit adding this option by creating the PR. |
https://code.visualstudio.com/updates/v1_85 Commented out portions of Python config will work when Ruff cuts a new release astral-sh/ruff#8822
I was trying out the "preserve" quote-style on a code base formatted with black using "skip-string-normalization" and was surprised to see non-docstring multiline strings using
Just a little feedback. |
Thanks for the feedback. Does this behavior prevent you from adopting ruff or are okay with the changes that it introduces? |
I wouldn't say the behavior prevents adoption, but it does add a little friction. If there were only a small number of changes between black and ruff on our code base, I'd just open a pull request to switch to ruff and expect my team to be happy that formatting is faster. Without "preserve" there are hundreds of files changed. Since "preserve" is only currently available with the preview setting and that changes other things, using it also results in many files reformatted. I'm personally fine normalizing all quotes, and I imagine my teammates probably are too, but it becomes a point of discussion when lots of files change and cause merge conflicts with their outstanding pull requests. Edit: I do notice that PEP 8 says:
So the behavior seems good. |
Just like @genericmoniker I also expected |
Summary
Adds a new option to the
quote-style
formatter configuration called "preserve":In other words, using
preserve
leaves the quotes of inline-strings as is, but performs all other normalisation, the same as forsingle
ordouble
.Fixes #7525
Test Plan
Added tests. Tested that
quote-style="preserve
without--preview
fails with an error.Edited by @MichaReiser: I expanded the summary to be explicit about what
preserve
does and updated the test plan.