Skip to content

fix: bug#15089 - Removing leading indentation #15110

Merged
Carreau merged 2 commits into
ipython:mainfrom
marcoscoladev:bug/remove-leading-indentation
Feb 2, 2026
Merged

fix: bug#15089 - Removing leading indentation #15110
Carreau merged 2 commits into
ipython:mainfrom
marcoscoladev:bug/remove-leading-indentation

Conversation

@marcoscoladev

@marcoscoladev marcoscoladev commented Dec 26, 2025

Copy link
Copy Markdown

Fix doctest paste: strip prompts and dedent (#15089)

Summary

This PR improves how IPython handles pasting doctest and xdoctest code snippets. When pasting code like:

>>>     print(1)

IPython now strips the >>> prompt and also removes the extra indentation, so the result is:

print(1)

Previously, the result would have been:

    print(1)

which can cause an IndentationError at top-level.

What changed

  • inputtransformer2.py
    • Enhanced PromptStripper to:
      • Detect doctest-style pastes when any line matches ^\s*>>>.
      • In doctest-mode, strip ^\s*>>>\s? and ^\s*\.\.\.\s? (continuation).
      • After stripping, apply textwrap.dedent() to the joined block, then return dedented lines.
      • Only apply dedent when doctest prompts were actually stripped (to avoid changing non-doctest pastes).
      • Only treat ... as a continuation prompt when a >>> is present in the same block (avoids confusing Python Ellipsis with doctest continuation).
  • test_inputtransformer2_line.py
    • Added/updated tests covering single-line doctest, indented >>>, multi-line >>> + ... doctest, and standalone ... (unchanged when no >>>).

Description of changes

  • Update IPython/core/inputtransformer2.py to enhance the PromptStripper:
    • Detect doctest-mode for a pasted block when any line matches ^\s*>>>.
    • In doctest-mode, strip indented doctest prompts:
      • ^\s*>>>\s? (primary prompt)
      • ^\s*\.\.\.\s? (continuation prompt)
    • After stripping doctest prompts, apply textwrap.dedent() to the joined block and return the dedented lines.
    • Only apply dedent() when doctest prompts were actually stripped to avoid changing normal paste semantics.
  • Update/add tests in tests/test_inputtransformer2_line.py for the new behavior.

Motivation and context

Users often copy doctest examples from documentation or tools that show doctest prompts and indentation (for example, xdoctest-style indented examples). Previously IPython removed the >>> prompt but preserved the remaining indentation, which could turn a pasted, single-line doctest into an indented top-level statement and raise IndentationError. This PR makes doctest pastes behave as users expect: prompts are removed and the code block is normalized by dedenting.

Examples (Before → After)

Single-line doctest

Input:

>>>     print(1)

Before:

    print(1)

After:

print(1)

Indented xdoctest-style prompt

Input:

    >>>     print(1)

After:

print(1)

Multi-line doctest with continuation

Input:

>>> for i in range(2):
...     print(i)

After:

for i in range(2):
    print(i)

Standalone continuation prompt (unchanged)

Input:

...     print(1)

After (unchanged because no >>> present):

...     print(1)

Implementation notes

  • dedent() is applied only after doctest prompts were detected and stripped. This avoids affecting normal paste behavior for non-doctest code, and prevents accidental removal of meaningful indentation in user-pasted code.
  • ... is considered a continuation prompt only when the pasted block contains at least one >>>, to avoid confusing Python's Ellipsis literal with doctest continuations.
  • Regexes used are tolerant of leading whitespace to support indented >>> prompts (xdoctest-style).

Related issues

Testing performed

  • Added and updated tests in tests/test_inputtransformer2_line.py to cover:
    • Single-line doctest with extra indentation: ">>> print(1)\n" -> "print(1)\n"
    • Leading whitespace before >>>: " >>> print(1)\n" -> "print(1)\n"
    • Multiline doctest using >>> and ... continuation lines.
    • Standalone ... only lines remain unchanged.

Doc

Contribution by Gittensor, see my contribution statistics at https://gittensor.io/miners/details?githubId=191372963

@marcoscoladev

Copy link
Copy Markdown
Author

Hi @krassowski,

All required checks are passing.
This PR implements the fix described in “Removing leading indentation when pasting in a doctest snippet” (#15089).
When you have a moment, could you please review it and merge if everything looks good?

Thank you very much for your time and for maintaining IPython.

@krassowski

krassowski commented Dec 29, 2025

Copy link
Copy Markdown
Member

What happens when pasting into a docstring? Does it distinguish these cases?

@marcoscoladev

Copy link
Copy Markdown
Author

Good point — preserving doctest prompts inside docstrings makes sense.

I’ll update this so that when the paste occurs inside a triple-quoted string (docstring), we skip doctest stripping and dedenting, and only apply the transformation in normal code contexts.

I’ll add a targeted test case covering pasting doctest snippets inside a docstring to ensure the prompts remain intact.

@marcoscoladev

Copy link
Copy Markdown
Author

@krassowski I’ve pushed an update that preserves doctest prompts when pasting inside triple-quoted strings and added a targeted test covering this case.

@Carreau Carreau added this to the 9.9 milestone Feb 2, 2026
@Carreau Carreau merged commit 8a5b3bf into ipython:main Feb 2, 2026
20 checks passed
@Carreau

Carreau commented Feb 2, 2026

Copy link
Copy Markdown
Member

Thanks, let's try it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Removing leading indentation when pasting in a doctest snippet

3 participants