Detect quote style ignoring docstrings (#3306)

Currently the quote style of the first string in a file is used for autodetecting what to use when rewriting code for fixes. This is an okay heuristic, but often the first line in a file is a docstring, rather than a string constant, and it's not uncommon for pre-Black code to have different quoting styles for those.

For example, in the Google style guide:
https://google.github.io/styleguide/pyguide.html
> Be consistent with your choice of string quote character within a file. Pick ' or " and stick with it. ... Docstrings must use """ regardless.

This branch adjusts the logic to instead skip over any `"""` triple doublequote string tokens. The default, if there are no single quoted strings, is still to use double quote as the style.
This commit is contained in:
Martin Packman 2023-03-03 04:59:33 +00:00 committed by GitHub
parent a03fa93c3a
commit 98209be8aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -180,7 +180,9 @@ fn detect_quote(contents: &str, locator: &Locator) -> Option<Quote> {
if let Tok::String { .. } = tok {
let content = locator.slice(&Range::new(start, end));
if let Some(pattern) = leading_quote(content) {
if pattern.contains('\'') {
if pattern.contains("\"\"\"") {
continue;
} else if pattern.contains('\'') {
return Some(Quote::Single);
} else if pattern.contains('"') {
return Some(Quote::Double);
@ -276,13 +278,27 @@ x = (
let locator = Locator::new(contents);
assert_eq!(detect_quote(contents, &locator), Some(Quote::Double));
let contents = r#"s = "It's done.""#;
let locator = Locator::new(contents);
assert_eq!(detect_quote(contents, &locator), Some(Quote::Double));
// No style if only double quoted docstring (will take default Double)
let contents = r#"
def f():
"""Docstring."""
pass
"#;
let locator = Locator::new(contents);
assert_eq!(detect_quote(contents, &locator), Some(Quote::Double));
assert_eq!(detect_quote(contents, &locator), None);
// Detect from string literal appearing after docstring
let contents = r#"
"""Module docstring."""
a = 'v'
"#;
let locator = Locator::new(contents);
assert_eq!(detect_quote(contents, &locator), Some(Quote::Single));
}
#[test]