google / yapf

A formatter for Python files
Apache License 2.0
13.76k stars 890 forks source link

Settings for forcing/prefering single/double quotes for strings #399

Open ghost opened 7 years ago

ghost commented 7 years ago

Just a setting so quoting style can be unified across a codebase.

e.g.

for the three strings abc, a'c, a"c

prefer_single_quotes -> 'abc', "a'c", 'a"c' prefer_double_quotes -> "abc", "a'c", 'a"c'

force_single_quotes -> 'abc', 'a\'c', 'a"c' force_double_quotes -> "abc", "a'c", "a\"c"

humitos commented 7 years ago

As a useful reference, I use this tool for exactly this: https://github.com/myint/unify

kxxoling commented 6 years ago

I'm always preferring single quote while writing JavaScript, and eslint works well with it.

mscheper commented 6 years ago

YAPF doesn't seem to replace triple single quotes with triple double quotes, even though PEP 8 specifies triple double quotes: https://www.python.org/dev/peps/pep-0008/#string-quotes

samuela commented 5 years ago

Is this feature on the roadmap at all? This really seems like a huge source of inconsistency. Even google internally forces quote symbol rules.

radude commented 5 years ago

Would be really useful. Any progress on this?

loganknecht commented 5 years ago

Hello!

I would like to communicate that this is also relevant to my interests!

Please implement this!

ianyepan commented 4 years ago

Thanks for opening this thread. I'm also looking forward to this being implemented.

willfish commented 4 years ago

Bump

fanninpm commented 4 years ago

This is one aspect in which black is superior to yapf. From the relevant portion of the docs:

Black prefers double quotes (" and """) over single quotes (' and '''). It will replace the latter with the former as long as it does not result in more backslash escapes than before. (emphasis added)

It goes further:

Black also standardizes string prefixes, making them always lowercase. On top of that, if your code is already Python 3.6+ only or it's using the unicode_literals future import, Black will remove u from the string prefix as it is meaningless in those scenarios.

kamahen commented 4 years ago

Yapf has a philosophy of not changing the source at all, except for whitespace.

You could always format your code with black, then re-format it with yapf. ;) This would also change some backslashes to parenthesized expressions, I think.

PS: pylint looks for the most common type of quotes and then complains when the other is used (except for cases like "'" and '"' which would otherwise be '\'' or "\"").

ianyepan commented 4 years ago

You could always format your code with black, then re-format it with yapf. ;)

Well, to be fair that's not at all a bad idea.

fanninpm commented 4 years ago

Yapf has a philosophy of not changing the source at all

[YAPF] takes the code and reformats it to the best formatting that conforms to the style guide, even if the original code didn't violate the style guide. (from the README)

@kamahen How are these two statements in concord? Does the README need to be changed?

Anyway, I normally use black instead of yapf, but one certain project I'm looking at contributing to has a style guide that dictates the usage of "single quotes for strings, or a double quote if the the string contains a single quote." This is where YAPF can help — by providing a means to specify a certain quote style in a project and to have that style automatically be applied.

ianyepan commented 4 years ago

From my experiences, black is superior. But I really really love 2-space indentation and black for-the-life-of-me refuse to include that option. Sad.

kamahen commented 4 years ago

@fanninpm "How are these two statements in concord? Does the README need to be changed?"

No. Yapf only changes whitespace. It doesn't change quotes; it doesn't reformat comments; it doesn't add/remove backslash; it doesn't insert/remove parentheses.

(I would love it if yapf had some options for doing these things; but I don't have time to do any of them, and Emacs will reformat comments for me.)

Black is fine as long as you don't want any options. I've used pretty-printers like that in the past (Plus), and there are worse things (the Plus pretty-printer was great because my input was on punched cards, so minor edits to the code were much easier if I didn't have to worry about reformatting). I think (but can't remember for sure) that someone wrote a reformatter for BNR Protel; I do remember that we all agreed on a standard format and henceforth there was no religious arguing over code layout standards.

bwendling commented 4 years ago

Yapf has a philosophy of not changing the source at all

[YAPF] takes the code and reformats it to the best formatting that conforms to the style guide, even if the original code didn't violate the style guide. (from the README)

@kamahen How are these two statements in concord? Does the README need to be changed?

We don't allow changes to the token stream. So we don't add, remove, or modify the tokens. This is why we don't allow adding a \-newline or rearranging imports, etc.

Anyway, I normally use black instead of yapf, but one certain project I'm looking at contributing to has a style guide that dictates the usage of "single quotes for strings, or a double quote if the the string contains a single quote." This is where YAPF can help — by providing a means to specify a certain quote style in a project and to have that style automatically be applied.

I've considered adding a feature where people could run their own transforms over the code. Similar to how lib2to3 does it with "fixes". (In fact, it would be exactly like that, because that's what we'll use.) That will allow them to use these transforms, but the onus is on the programmer to ensure it's safe to perform the transformations.

kamahen commented 4 years ago

lib2to3 is going away; don't know if any of the potential successors will have a transformation library. All I've seen so far is that there are a couple of potential successors for parsing.

See https://bugs.python.org/issue40360: lib2to3 is now deprecated and may not be able to fully parse Python 3.10+. CPython encourages using https://libcst.readthedocs.io/ or https://parso.readthedocs.io/

https://github.com/pyga/awpa https://github.com/Instagram/LibCST

LibCST builds on parso. Comparing stars on GitHub:

https://github.com/PyCQA/redbaron : 457 LibCST: 423 parso: 296 awpa: 10

https://bugs.python.org/issue40360#msg367726 and https://bugs.python.org/issue40360#msg367730

bwendling commented 4 years ago

See if 521d61770aa51cc362c679bdd08f46699d243713 helps you with the quotes issue.

you-n-g commented 3 years ago

When will this be merged into master and released?

ThiefMaster commented 3 years ago

Yeah, what's the state of this? This commit doesn't seem to be in master...

You could always format your code with black, then re-format it with yapf. ;)

Well, to be fair that's not at all a bad idea.

It is a bad idea: Editors can usually call black or yapf for formatting, but not both...

ianyepan commented 3 years ago

It is a bad idea: Editors can usually call black or yapf for formatting, but not both...

I beg to differ. I believe it's not impossible to set up a sequence of formatters with specific orders -- I know for a fact Emacs can do this in a breeze.

mscheper commented 3 years ago

Yapf has a philosophy of not changing the source at all

This is a well-intentioned philosophy, but YAPF would be a far more useful tool if the philosophy was for this to merely be the default behaviour. I've seen hundreds of hours wasted by devs not being able to find code because of these things, and the resulting formatting arguments. The more that can be enforced by code, saving devs from having to worry about it, the better, IMHO.

Erotemic commented 3 years ago

There just needs to be a simple script that follows these rules:

def func():
    """
    I want my docstrings to look like this
    """
   ...
import ubelt
text = ubelt.codeblock(
    '''
    This text is meant to be used problematically, so distinguish it from documentation
    ''')
import ubelt
text = ubelt.codeblock(
    """
    I know what I'm doing here. Please don't escape my single quotes. It would make this ugly!
    """)
x = 'mode1'                          # Due to my RSA, it can hurt to type. Single quotes are easier on my hands. I know its a small thing, but I do use them a lot. Extra shift presses add up. 
y = f'"{string_payload}"'  # please don't reformat these

def foo(): """ my docstring # note - single lines are ok for short docstrings """ x = 1 """ This is a multi-line comment, probably containing some sort of ascii drawing, but not a docstring. Use double quotes to indicate it is a comment. """ return x + 1

Anyway, if anyone writes that tool let me know. I'll just run it after yapf. I really don't care if it is a part of it. I just want a configurable quote normalizing script. If someone writes it I can put it on pypi if they need help with that part. (I might write it if nobody else does, I imagine you can at least get 90% of the way there with a Concrete Syntax Tree, or a tool like redbaron, or even ast and some hueristics)

/rant

EDIT: I did write it myself: https://gist.github.com/Erotemic/75618ea970a2af49cd43db1bf61a8ac6

It's not the exact spec I wroteup, but its close, and it got the job done.

kamahen commented 3 years ago

Instead of text = ubelt.codeblock(...) why not use the standard Python library's textwrap.dedent()?

Anyway, you can run black or black -S (https://github.com/psf/black) to do some of the transformations that you want, and then run yapf to allow control over the the formatting that black doesn't allow.

Erotemic commented 3 years ago

@kamahen because I don't want to have to write .strip('\n') after it every time.

mscheper commented 2 years ago

@kamahen: Does your comment have anything to do with quotation marks?

kamahen commented 2 years ago

@mscheper - My comment has to do with transformation libraries - and changing between single and double quotes would be an example of a transformation. As noted elsewhere, yapf only changes whitespace and leaves everything else alone. Other tools, such as black can do other changes, such as changing the quotes or adding/removing backslashes/parentheses.

Any tool that depends on lib2to3 (both yapf and black currently depend on it) is subject to breakage with future changes to Python syntax. (Already we've seen problems with the "walrus" operator, for example)

dhensen commented 1 year ago

Please, just implement this, and make the default adhere to your philosophy. This way we can have amazing Yapf, but with double quotes.

The way I see it:

So can we ever have a formatter do exactly what we want?

kamahen commented 1 year ago

It seems to me that this is a fair bit of work (which nobody seems to be volunteering to do) and there's a simple work-around: use black to change the quote and then use yapf to make it format the way you want.

seele-vollerei-ai commented 9 months ago

I prefer to use single quotes, and you can use Eslint to configure whether to use single or double quotes by default during front-end development. But there doesn't seem to be a python formatter that can do that yet. Maybe it's a difference in philosophy, which is frustrating.