Skip to content
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

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

Open
ghost opened this issue Apr 28, 2017 · 29 comments
Open

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

ghost opened this issue Apr 28, 2017 · 29 comments

Comments

@ghost
Copy link

ghost commented Apr 28, 2017

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

humitos commented Jun 9, 2017

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

@kxxoling
Copy link

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

@mscheper
Copy link

mscheper commented Oct 11, 2018

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

samuela commented Mar 14, 2019

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

radude commented Jun 30, 2019

Would be really useful. Any progress on this?

@loganknecht
Copy link

Hello!

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

Please implement this!

@ianyepan
Copy link

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

@willfish
Copy link

Bump

@fanninpm
Copy link

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

kamahen commented Jun 18, 2020

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

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

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

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

kamahen commented Jun 19, 2020

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

bwendling commented Jun 19, 2020

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

kamahen commented Jun 20, 2020

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

See if 521d617 helps you with the quotes issue.

@you-n-g
Copy link

you-n-g commented Oct 30, 2020

When will this be merged into master and released?

@ThiefMaster
Copy link

ThiefMaster commented Mar 17, 2021

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

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

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

Erotemic commented Sep 8, 2021

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

  • Docstrings that will be assigned to a __doc__ attribute should be triple double quoted: e.g.
def func():
    """
    I want my docstrings to look like this
    """
   ...
  • Existing triple quotes that are assigned to a variable or passed to a function as an argument should be converted to triple single quotes. e.g.
import ubelt
text = ubelt.codeblock(
    '''
    This text is meant to be used problematically, so distinguish it from documentation
    ''')
  • Unless the text has a quote character embedded inside it. In that case leave it be. The programmer probably knows what they are doing there.
import ubelt
text = ubelt.codeblock(
    """
    I know what I'm doing here. Please don't escape my single quotes. It would make this ugly!
    """)
  • For regular quotes, similar rules apply. If it is assigned or used it should be single quoted unless there are already quotes in the string.
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
  • For string that are not docstrings, but also not assigned to an attribute or used, double quotes is probably better.

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

kamahen commented Sep 8, 2021

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

Erotemic commented Sep 8, 2021

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

@mscheper
Copy link

mscheper commented Dec 2, 2021

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

@kamahen
Copy link
Contributor

kamahen commented Dec 2, 2021

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

dhensen commented Jan 16, 2023

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:

  • black does it, but is too opinionated
  • yapf is very nice, configurable, but doesn't want to touch the token stream, so no double quotes among others. IMO this is also an opinion. Which is fine, but make it configurable with a default conforming to your philosophy.

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

@kamahen
Copy link
Contributor

kamahen commented Jan 16, 2023

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests