-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
string_processing: Use explicit string concatenation #2553
Comments
Yeah I still think this is the way to go. |
I don't have a strong preference between this (explicit str concat) and parens (#3159). There are some cases I think parens have better readability, e.g. some_list = [
(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
" incididunt ut labore et dolore magna aliqua Ut enim ad minim"
),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
] some_list = [
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
] Parens make it more clear that it's a two element list. However, during the implementation of #3159, we realized adding parens (thus another level of indentation) can result in significant changes to the code, which could be off putting. --- a/django:django/db/backends/mysql/features.py
+++ b/django:django/db/backends/mysql/features.py
@@ -122,12 +132,14 @@
skips.update(
{
"https://jira.mariadb.org/browse/MDEV-19598": {
- "schema.tests.SchemaTests."
- "test_alter_not_unique_field_to_primary_key",
+ (
+ "schema.tests.SchemaTests."
+ "test_alter_not_unique_field_to_primary_key"
+ ),
},
}
) v.s. --- a/django:django/db/backends/mysql/features.py
+++ b/django:django/db/backends/mysql/features.py
@@ -122,12 +132,14 @@
skips.update(
{
"https://jira.mariadb.org/browse/MDEV-19598": {
"schema.tests.SchemaTests."
- "test_alter_not_unique_field_to_primary_key",
+ + "test_alter_not_unique_field_to_primary_key",
},
}
) This is the reason in #3159 we decided to limit parens to only list/tuple/set literals, and exclude function calls. IMO we should still do something to function calls, maybe explicit str concatenation is the answer. If so, then we can choose explicit str concatenation over parens for list/tuple/set literals too. |
It would feel a bit off to use parens in other places and explicit concatenation in others in my opinion. |
Agreed that we should try to use the same formatting in function calls v.s. list/tuple/set literals. I don't think there exists a clear call that either explicit-str-concat or use-parens would be better. Then how about this approach: Black takes existing parens (in unformatted code) into account and decides which format to use?
# before
function_call(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
# after
function_call(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
# before
function_call(
(" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim"),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
(" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim"),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
# after
function_call(
(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
" incididunt ut labore et dolore magna aliqua Ut enim ad minim"
),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
" incididunt ut labore et dolore magna aliqua Ut enim ad minim"
),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
] Then, we are able to use either of them as we see fit depending on the local context. I understand that this will add another exception to Previous formatting is taken into account as little as possible, with rare exceptions like the magic trailing comma., but IMHO this is a good trade-off. WDYT? @felix-hilden @JelleZijlstra |
I see your point, but we do really want to minimise the effect of the code itself to our formatting choices for consistency. If there isn't a clear winner but we want to format consistently, then I guess the decision has to be more or less arbitrary. Much like string prefixes or other minor details. |
Hmm, focusing on existing parens here, this actually fits Black's paren management here:
These parens are inner parens that you might want to have for clarity or further code organization. Following this rule, the existing parens in these cases should not be removed, i.e. we should implement #3260. With above implemented, we can then take a look at whether we want to use explicit str concatenations, or force adding parens + implicit str concatenations. If this is a more or less arbitrary decision, I think we can chose explicit str concatenations here as it produces less diffs than force adding parens. The examples below illustrate above decisions: # before
function_call(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
function_call(
(" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim"),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
(" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim"),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
# after
function_call(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim",
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
]
function_call(
(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim"
),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
)
some_list = [
(
" lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor"
+ " incididunt ut labore et dolore magna aliqua Ut enim ad minim"
),
" veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo",
] |
Alright, turns out that in terms of a cohesive parens policy, we're not really there 😅 I'm not sure how each case was decided, but we definitely don't preserve all "organising" parens. Perhaps we should consider the bigger picture first. |
@felix-hilden hmm, I think we draw a different line between "organising" and "non-organising" parens. The purpose of them is to (significantly) increase readability, so maybe we should really call them readability-parens.
|
Bump for this one. I think the parens argument (now resolved) was not related, and muddied this thread. I would still love to see explicit concatenation replace implicit concatenation in all cases, for the reasons mentioned at the top:
|
As an additional data point, |
It may be worth mentioning that starlark (and google internal linters) explicitly bans implicit python string concatenation. Guido himself has mentioned that implicit string concat only exists because of backwards compatibility: https://mail.python.org/pipermail/python-ideas/2013-May/020557.html My own first experience of black adding implicit concat somewhere was complete surprise and confusion at this being a language feature, so while I do not have a strong opinion about black adding + operators, I am very strongly against black introducing implicit string concat anywhere where it was not there before, since that also sort of blocks most linters from having a lint rule against it that is enabled by default. |
Describe the style change
I suggest to use explicit string concatenation, instead of implicit concatenation, for (currently experimental) string processing, with whitespace pushed to the end of each line.
Examples in the current Black style
Desired style
Additional context
Advantages of this method:
Worth noting that Guido & the Python community have considered removing implicit concatenation for these reasons, but ran into complications (here's an article about this). However, the reasons why they left it in the language (
%
precedence, etc.) don't apply to whether Black uses the feature (for the%
precedence issue, it doesn't apply at least because the multiline strings are wrapped in parentheses), so I think that Black ought to use the explicit version.The text was updated successfully, but these errors were encountered: