# Pre-PEP: d-string / Dedented Multiline Strings with Optional Language Hinting

**URL:** <https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988>\
**Category:** Ideas\
**Created:** [May 6, 2025, 5:00pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988 "2025-05-06T17:00:30Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [May 19, 2025, 12:42am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/41 "2025-05-19T00:42:44Z")

</div>

In the previous thread, Serhiy proposed ` __future__ ` import and I am +1 on it.

But Guido was -1 on ` __future__ `:

> [@D-string vs str.dedent()](https://discuss.python.org/t/d-string-vs-str-dedent/35907/16):
>
> Please don’t. I think using `d"..."` is fine. I’m not too keen on a ` __future__ import`. (I maintain some tests that happen to require

I think tools like pyupgrade or 2to3 will reduce maintenance cost of existing code.

---

<div class="post-metadata">

**Author:** ![tstefan](https://avatars.discourse-cdn.com/v4/letter/t/f475e1/32.png) [@tstefan](https://discuss.python.org/u/tstefan)\
**Post date:** [May 19, 2025, 3:33pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/42 "2025-05-19T15:33:37Z")

</div>

The proposal looks nice. If a new syntax is introduced (like `d'''...'''`), the d-strings should not be a just a short-hand for `textwrap.dedent`, but it should be done _the right way_.

The most important extensions of d-strings compared to `textwrap.dedent` should be a compatibility with f-strings and t-strings, moreover it should support line continuation, so

```python
foo = d'''
       abc\
       def
       '''

```

should remove not only the newline, bu also all spaces before `d`. JEP 378 would be a good starting point, but I am not particularly happy that JEP 378 allows the closing quotes to be indented more than the text (with the superfluous spaces been ignored).

---

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [May 19, 2025, 6:07pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/43 "2025-05-19T18:07:32Z")

</div>

Here is a tiny suggestion for an optional dedent adjustment. The number specifies indentation of the result in characters. By default it is 0 (max. dedent possible).

There is an [update](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/56) about `str.dedent`being more suitable for this.

```python
        html = d:4"""\
            <div> <!-- leading whitespace trimmed to 4 whitespace chars -->
                Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            </div>
            """

```

An indentation could be even inserted (with space characters):

```python
DEFAULT_HTML = d:4"""\
<div> <!-- four leading spaces inserted-->
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
"""

```

---

<div class="post-metadata">

**Author:** ![malemburg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/malemburg/32/50_2.png) [@malemburg](https://discuss.python.org/u/malemburg)\
**Post date:** [May 19, 2025, 8:17pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/44 "2025-05-19T20:17:42Z")

</div>

I don’t think that proliferation of string modifiers is a good idea.

Can’t we just have some operator added to f-strings, which then takes care of the dedent ?  
E.g.

```python
f"""{#!dedent}
   Some text
   More text
"""

```

The compiler could take care of the conversion at compile time, if possible (some of the formatting in the f-string may prevent determining the right dedent to use), or defer this to runtime by using `textwrap.dedent()`.

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [May 19, 2025, 8:28pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/45 "2025-05-19T20:28:13Z")

</div>

I think that’d be a pretty major change to f-strings (a magic keyword that modifies the _rest_ of the string?). I’d rather have a separate modifier\[1\].

* * *

1. that I can ignore if I don’t want to use it

---

<div class="post-metadata">

**Author:** ![malemburg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/malemburg/32/50_2.png) [@malemburg](https://discuss.python.org/u/malemburg)\
**Post date:** [May 19, 2025, 8:56pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/46 "2025-05-19T20:56:28Z")

</div>

Think of it as a shebang: the whole formatted string gets passed to a _dedent_ function, very much like a Python script that is read from disk and then run using Python.

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [May 19, 2025, 9:10pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/47 "2025-05-19T21:10:44Z")

</div>

I mean I get it. I just think it’s a really big change to f-strings. My mental model of an f-string is “expressions inside of {}, and a literal string outside of {}”. This format would change that.

It’s not insurmountable, but I don’t think such a change is simpler\[1\] than introducing a different prefix.

* * *

1. in terms of teaching it, reading it, etc

---

<div class="post-metadata">

**Author:** ![malemburg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/malemburg/32/50_2.png) [@malemburg](https://discuss.python.org/u/malemburg)\
**Post date:** [May 19, 2025, 9:46pm UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/48 "2025-05-19T21:46:09Z")

</div>

I mentioned this idea, because it will allow to add more such “interpret this string in some special way” kind of semantics without having to change Python’s syntax every time (there have been numerous such suggestions in the past and the d-string one is another new variant).

But yeah, I don’t want to hijack the discussion with a new proposal. Just suggesting that we may be better off, considering these things in a broader sense.

---

<div class="post-metadata">

**Author:** ![AA-Turner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aa-turner/32/4979_2.png) [@AA-Turner](https://discuss.python.org/u/AA-Turner)\
**Post date:** [May 20, 2025, 2:58am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/49 "2025-05-20T02:58:49Z")

</div>

I would still advocate for the simpler alternative of `str.dedent()`, where we can do the dedenting at compile time.

It doesn’t cover the more esoteric cases mentioned in this thread, but it also doesn’t have the drawbacks of more syntax or combinatorial explosion of string prefixes.

A

---

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [May 20, 2025, 4:10am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/50 "2025-05-20T04:10:02Z")

</div>

In terms of user convenience, the following order would be better

1. both of d-string and str.dedent()
2. d-string only
3. str.dedent() only
4. status quo

But we need to balance the costs and benefits of Python’s language specification and implementation complexity. My concern is that adding str.dedent() will negate the introduction of an additional d-string and ultimately make it less convenient for the user than if d-string were introduced.

Therefore, I am prioritizing the d-string discussion ahead of the str.dedent() discussion, and since there is still a year until Python 3.15 is in beta, there is no need to rush the str.dedent() discussion.

---

<div class="post-metadata">

**Author:** ![AA-Turner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aa-turner/32/4979_2.png) [@AA-Turner](https://discuss.python.org/u/AA-Turner)\
**Post date:** [May 20, 2025, 4:50am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/52 "2025-05-20T04:50:57Z")

</div>

@methane please could you edit the message to be specific about what the ` __future__ ` import would change? I scrolled back several messages but I don’t think I’ve seen a concrete explanation.

Two more poll suggestions: make it multiple choice, and add a ‘do nothing’ option (/and maybe also a ‘add `str.dedent()`’ option). Currently I can’t vote in the poll: I would vote ‘no’ on d-prefix and I don’t know what the future import entails so I would also vote ‘no’, but there’s no option for this!

A

---

<div class="post-metadata">

**Author:** ![AA-Turner](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aa-turner/32/4979_2.png) [@AA-Turner](https://discuss.python.org/u/AA-Turner)\
**Post date:** [May 20, 2025, 4:53am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/53 "2025-05-20T04:53:23Z")

</div>

> [@methane](#):
>
> My concern is that adding str.dedent() will negate the introduction of an additional d-string and ultimately make it less convenient for the user than if d-string were introduced.

Thanks for the rationale, this is a fair point.

---

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [May 20, 2025, 5:31am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/54 "2025-05-20T05:31:15Z")

</div>

I cannot the vote because of time limit. So I repost it.

I want to poll about d-string vs ` __future__ ` import.  
` __future__ ` import changes syntax of triple quote string literal like proposed d-string.

- d-string makes string prefix more complex.
  - E.g. `d/D/df/dF/DF/Df/fd/fD/FD/Fd/dt/dT/DT/Dt/td/tD/TD/Td/ud/...`
  - But it doesn’t break backward compatibility in the future.

- ` __future__ ` import doesn’t need new prefix.
  - It changes all triple quote literals.
  - It will break backward compatibility in the future. But it will make language simple.
  - Tools like pyupgrade would help the transition.

- `str.dedent()` is the most simple option.
  - But it cannot work nicely with t/f-string.
    - People want to use t-string for HTML or SQL. And they want to dedent it too.

  - It cannot work nicely with line continuation too.
  - Vote to d-string or ` __future__ ` import if you want both of dedenting literal and `str.dedent()`
    - Because we are discussing about literal improvement is necessary or not.

_Poll ([view on site](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/54))_

---

<div class="post-metadata">

**Author:** ![tstefan](https://avatars.discourse-cdn.com/v4/letter/t/f475e1/32.png) [@tstefan](https://discuss.python.org/u/tstefan)\
**Post date:** [May 20, 2025, 6:35am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/55 "2025-05-20T06:35:51Z")

</div>

I think the choice d-string prefix versus member function depends very much on the mental model and thus on the precise semantics.

I voted in favor of the d-string prefix since [I would prefer](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/42) sematics that goes beyond what a function could do, similar to JEP 378. A prefix can only be applied to string literals (including f- and t-strings).

But if dedention similar to `textwrap.dedent` was intrduced to Python, i.e., something that can be applied after the fact to any string object, I would actually prefer `str.dedent()`. If the core developers decide that application of `str.dedent()` to a string literal would be cmputed at compile-time, I would see this as a kind of an optimization, like constant folding.

---

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [May 20, 2025, 7:10am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/56 "2025-05-20T07:10:58Z")

</div>

I will vote for the `str.dedent`, because it is a function (method) and as such it can take arguments.

Inspired by the baseline idea, I made a proposal about optional adjustments to dedent. I posted examples for d-strings, but I will prefer this one (just a short example without going into details):

```python
    if cond:
        html = """\
            <div>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            </div>
            """.dedent(4) # leave 4 whitespace leading chars when dedenting

```

Regardless of my proposal, other ideas for `.dedent` fine control may appear and the d-string syntax is not suitable for that.

---

<div class="post-metadata">

**Author:** ![blhsing](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/blhsing/32/25812_2.png) [@blhsing](https://discuss.python.org/u/blhsing)\
**Post date:** [May 20, 2025, 7:29am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/57 "2025-05-20T07:29:06Z")

</div>

> [@xitop](#):
>
> ```python
> if cond:
> html = """\
> <div>
> Lorem ipsum dolor sit amet, consectetur adipiscing elit.
> </div>
> """.dedent(4) # leave 4 whitespace leading chars when dedenting
> 
> ```

Spelling out the literal number of spaces of indentation looks rather inelegant compared to the visual cue provided by the indentation of the closing quote as I suggested, which turns out to be also the solution adopted by JEP 378:

```python
    if cond:
        html = d"""\
            <div>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            </div>
        """ # leave 4 whitespace leading chars when dedenting

```

Also, `str.dedent` won’t help preserve line continuation markers and make them meaningful to dedentation in a string literal, and won’t help indent interpolated values in an f/t-string, which are features that can only be helped with a new type of string literal.

---

<div class="post-metadata">

**Author:** ![xitop](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xitop/32/13242_2.png) [@xitop](https://discuss.python.org/u/xitop)\
**Post date:** [May 20, 2025, 8:18am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/58 "2025-05-20T08:18:50Z")

</div>

> [@blhsing](#):
>
> Spelling out the literal number of spaces of indentation looks rather inelegant compared to the visual clue provided by the indentation of the closing quote as I suggested, which turns out to be also the solution adopted by JEP 378

Thank you for your reply. I’m afraid I got somehow lost in the discussion regarding which ideas and sub-ideas are currently in favour and which were not.

You find the explicitly set indentation inelegant. Yes, it might look so, but it is more capable than the visual clue. It could also indent, not only dedent (let’s ignore naming for now). And it could replace tabs with spaces or vice versa - if there will be any demand for such feature, of course.

```python
HTML1 = """\
<div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
""".dedent(4)

```

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [May 20, 2025, 9:08am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/59 "2025-05-20T09:08:01Z")

</div>

I voted for dedent, but I disagree that it forever prevents the introduction of d-strings. Yes, it makes it harder to justify adding them, but not impossible.

---

<div class="post-metadata">

**Author:** ![methane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/methane/32/43_2.png) [@methane](https://discuss.python.org/u/methane)\
**Post date:** [May 20, 2025, 9:36am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/60 "2025-05-20T09:36:07Z")

</div>

I don’t mean str.dedent() makes d-string impossible forever.  
As I explained [in this comment](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/50), introducing `str.dedent()` will make d-string harder.

Since this thread is about improving multiline string literal, we need to focus on it.  
So please vote to `str.dedent()` if (and only if) you are against improving literal because of you think `str.dedent()` is enough for Python users.

Adding `str.dedent()` or not will be discussed _after_ we decide to improve literal or not.  
If you are +/- 0 on literal improvement, please skip this vote and discuss about `str.dedent()` later.

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [May 20, 2025, 10:41am UTC](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988/61 "2025-05-20T10:41:26Z")

</div>

> [@methane](#):
>
> So please vote to `str.dedent()` if (and only if) you are against improving literal because of you think `str.dedent()` is enough for Python users.

OK. The only use cases that I’ve seen which can’t be handled by `str.dedent()` are f-strings where interpolated values contain newlines. These aren’t literals, so I’ll stick with my vote. I’m happy to discuss the f-string case separately.

[Previous page](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988.md?page=2)

[Next page](https://discuss.python.org/t/pre-pep-d-string-dedented-multiline-strings-with-optional-language-hinting/90988.md?page=4)
