better dedent
It's like textwrap.dedent, but with added t-string support.
The problem: interpolating before dedenting
Have you ever used textwrap.dedent with an f-string that has newline characters in a replacement field?
For example, given this code string (which has newlines in it):
code = r"""
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
""".strip("\n")
Using textwrap.dedent with an f-string that uses code in a replacement field results in very strange indentation:
>>> print(dedent(f"""\
... Example function:
... {code}
...
... That function was NOT indented properly!"""))
Example function:
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
The problem is that f-strings immediately interpolate their replacement fields.
That code string is injected into the new string before dedent has a chance to even look at the string.
By the time textwrap.dedent does its dedenting, the weirdness has already happened.
The solution: interpolating after dedenting
Passing a t-string to the better_dedent.dedent function allows the replacement fields to maintain their original indentation level.
Using the same code string as before:
code = r"""
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
""".strip("\n")
The better_dedent.dedent function will dedent the t-string and then inject the replacement field, resulting in much more sensible indentation:
>>> print(dedent(t"""\
... Example function:
... {code}
...
... That function was indented properly!""")
...
Example function:
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
That function was indented properly!
Using a t-string allows for dedenting the whole string before the replacement fields are inserted and then inserting the replacement fields.
Note that if an f-string is passed to better_dedent.dedent, it will simply delegate to textwrap.dedent.
undent
This package also includes an undent function, which will strip a leading newline (note the lack of \ after t"""):
>>> print(undent(t"""
... Example function:
... {code}
... That function was indented properly!"""))
Example function:
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
That function was indented properly!
The undent function will also strips a trailing newline by default:
>>> print(undent(t"""
... Example function:
... {code}
... That function was indented properly!
... """))
Example function:
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
That function was indented properly!
>>> print("Note that there's no blank line above this prompt")
Note that there's no blank line above this prompt
Passing strip_trailing=False to undent will suppress trailing newline removal.
Installation
pip install better-dedent
Or if you have uv installed and you'd like to play with it right now:
uvx --with better-dedent python
You can then import dedent and undent like this:
from better_dedent import dedent, undent
And try them out:
code = r"""
def strip_each(lines):
new_lines = []
for line in lines:
new_lines.append(line.rstrip("\n"))
return new_lines
""".strip("\n")
text = undent(t"""
Here is some example code:
{code}
That indentation worked out nicely!
""")
print(text)
License
better-dedent is distributed under the terms of the MIT license.
Release files for better-dedent 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| better_dedent-0.0.3.tar.gz | 6.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| better_dedent-0.0.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 11.0 kB
Release files / better_dedent-0.0.3.tar.gz
| Download URL | better_dedent-0.0.3.tar.gz |
|---|---|
| Size | 6.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
eebcc59241687ad04435140b49af3d70a7245e0403fe9fb70bb76ec4eb20c3d1
|
|
BLAKE2b-256 checksum How to use checksums |
c755d08e7981b74c0b2d457479140c198d61b4f05edc5c3b3436528a22dd1d4b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.28.1
|
Release files / better_dedent-0.0.3-py3-none-any.whl
| Download URL | better_dedent-0.0.3-py3-none-any.whl |
|---|---|
| Size | 4.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff6d34bcf91c98c9b32ef2f26da7eca1c579d8d234c41e4277e6d041042189c5
|
|
BLAKE2b-256 checksum How to use checksums |
0a5e4506ed4770e0d005bc9c3829c39f05fee425facce2ff16095a77f7412205
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
python-httpx/0.28.1
|