Yes! `textwrap.dedent` is great. On further reflection `wrap` is actually more useful for this kludge (see below). But my point is that that's a whole import for a kludge. Compare the f-string ideal (by my standards):
raise ValueError("File exists, not uploading: "
f"{filename} -> {bucket}, {key}")
...which is short enough that it's readable, and it's clear where exactly each variable is going. It's the single obvious solution, so much so that I don't spend a second thinking about it (very Pythonic!). Compare it to using `str.format` with the same continued indentation:
raise ValueError(("File exists, not uploading: {filename} -> "
"{bucket}, {key}").format(filename=filename,
bucket=bucket,
key=key))
Even this minimal example looks terrible! Remember that a lot of exceptions are raised within multiply-nested blocks, and then format pushes things farther to the right (while also ruining your automated string-literal concatenation, hence the extra parentheses), leaving very little room for the format arguments. You can use a more self-consistent and readable indentation strategy:
raise ValueError(
(
"File exists, not uploading: {filename} -> "
"{bucket}, {key}"
).format(filename, bucket, key)
)
This is unquestionably more pleasant to read than the former, but it's
3 times longer than the simple f-string solution, and I would argue it is not any more readable than the f-string for this simple example. My point with having a `str.wrap` builtin is that at
least you could use the docstring convention of terminating multi-line strings on a newline, which would get rid of the string concatenation issues while leaving you a consistent (albeit diminished by the "wrap" call) amount of rightward room for the `format` args:
raise ValueError("""File exists, not uploading: {filename} ->
{bucket}, {key}
""".dedent().format(filename=filename,
bucket=bucket, key=key))
Maybe a little bit better than the first one, especially if you're writing a longer docstring and don't want to think about string concatenation. But still a kludge. You can use positional formatting to shorten things up, but the fundamental weakness of `str.format` remains.