Skip to content

IDLE displays ANSI sequences in tracebacks when sys.excepthook is customized #127060

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

Closed
vstinner opened this issue Nov 20, 2024 · 13 comments
Closed
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes stdlib Python modules in the Lib dir topic-IDLE type-bug An unexpected behavior, bug, or error

Comments

@vstinner
Copy link
Member

vstinner commented Nov 20, 2024

Error on Python 3.13 and newer.

Reproducer

  • Run IDLE
  • Set a custom sys.excepthook:
import sys
def hook(*args): return sys.__excepthook__(*args)
sys.excepthook=hook
  • Trigger an error which display a traceback, such as accessing a variable which doesn't exist.

Output

>>> os
Traceback (most recent call last):
  File �[35m"/home/vstinner/python/3.13/Lib/idlelib/run.py"�[0m, line �[35m590�[0m, in �[35mruncode�[0m
    �[31mexec�[0m�[1;31m(code, self.locals)�[0m
    �[31m~~~~�[0m�[1;31m^^^^^^^^^^^^^^^^^^^�[0m
  File �[35m"<pyshell#12>"�[0m, line �[35m1�[0m, in �[35m<module>�[0m
�[1;35mNameError�[0m: �[35mname 'os' is not defined. Did you forget to import 'os'?�[0m

ANSI sequences to colorize the output are unexpected and makes the output hard to read.

Expected output

>>> os
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    os
NameError: name 'os' is not defined. Did you forget to import 'os'?

Explanation

In the normal case:

  • IDLE replaces sys.stderr with io.StringIO() to call the "excepthook".
  • _colorize.can_colorize() returns False.
  • It works as expected.

If sys.excepthook is overridden:

  • IDLE replaces sys.stderr with a idlelib.run.StdOutputFile object at startup.
  • _colorize.can_colorize() returns True because StdOutputFile.isatty() always return True.

Linked PRs

@vstinner vstinner added topic-IDLE 3.13 bugs and security fixes 3.14 bugs and security fixes labels Nov 20, 2024
vstinner added a commit to vstinner/cpython that referenced this issue Nov 20, 2024
IDLE StdOutputFile.isatty() now returns False instead of True.
@terryjreedy terryjreedy changed the title [IDLE] IDLE displays ANSI sequences in tracebacks when sys.excepthook is customized IDLE displays ANSI sequences in tracebacks when sys.excepthook is customized Nov 20, 2024
@terryjreedy
Copy link
Member

terryjreedy commented Nov 20, 2024

On Windows, 3.14.0a1 install or fresh build, I do not see this when running from editor.

Traceback (most recent call last):
  File "f:\dev\3x\Lib\idlelib\run.py", line 590, in runcode
    exec(code, self.locals)
    ~~~~^^^^^^^^^^^^^^^^^^^
  File "F:\dev\tem\tem.py", line 4, in <module>
    os
NameError: name 'os' is not defined. Did you forget to import 'os'?

After entering at prompt, the only differences are that the file is <pyshell#3> and os is missing. In CommandPrompt, the escape code highlighting (and the OS line) is present.

I do see the code on macOS, so I presume you are using mac or linux.

IDLE normally calls print_exception, which call a function to rid tracebacks of IDLE artifacts. When sys.excepthook is changed from sys.__excepthook__, the custom hook has to do this if desired. hook does not, hence the extra lines.

The absence of interactive code lines, such as os was part of the default sys.__excepthook__ before 3.13. Python does not cache them. IDLE normally adds them and the new REPL does also.

I have thought about converting ~/^ to highlights. Since those lines might eventually go away when duplicated by inline markup, I have recently also thought of using the latter instead. It would be disappointing if that were not available on Windows.

IDLE always replaces the run process stderr with StdOutputfile. Normally, print_exception is called. After printing the traceback created by python while stderr is bound to an StdOutput file, it calls get_message_line to get SomeException: <message line>. For Attribute and Name errors, it temporarily replaces stderr to get the 'Did you mean' hints. (When hints are added for other exception classes, they should be added to the list.) This temporary replacement cannot affect the presence of color codes in the traceback itself.

The sys.stdxxx bindings are visible to user code. Changing an attribute might break the intended behavior of existing code.

@picnixz picnixz added type-bug An unexpected behavior, bug, or error stdlib Python modules in the Lib dir labels Nov 21, 2024
@vstinner
Copy link
Member Author

I do see the code on macOS, so I presume you are using mac or linux.

Right, I'm on Linux. I expected the behavior to be the same on Windows.

On Fedora, the ABRT service installs a custom sys.excepthook using a PTH file (.pth) to catch Python unhandled exceptions and report them to Bugzilla bug tracker.

So this IDLE bug is always reproduced on Fedora without having to install a custom excepthook manually, see: https://bugzilla.redhat.com/show_bug.cgi?id=2325502

@vstinner
Copy link
Member Author

vstinner commented Nov 21, 2024

I expected the behavior to be the same on Windows.

Oh, I forgot that on Windows Python doesn't use ANSI sequences, but control directly the console using the Windows API. So right, Windows is not affected by this issue.

@vstinner
Copy link
Member Author

The sys.stdxxx bindings are visible to user code. Changing an attribute might break the intended behavior of existing code.

What's the purpose of pretending that sys.stdout and sys.stderr are TTY, whereas they are not?

@vstinner
Copy link
Member Author

cc @serhiy-storchaka

@vstinner
Copy link
Member Author

@terryjreedy: So you don't like my simple #127061 approach? It does fix the issue for me. Do you have access to Linux or macOS to reproduce the issue?

@terryjreedy
Copy link
Member

terryjreedy commented Dec 17, 2024

I will try to test on my Mac tomorrow. And maybe get setup to do so on Ubuntu. (I have it on a partition on Windows, which my daughter used, but have not yet done anything with it myself.) I need to be able to create and download/run PRs on both other systems.

@terryjreedy
Copy link
Member

I am a bit worried that changing isatty could break something. I can grep idlelib to check locally, but 3rd party code might be accessing sys.stdxxx.isatty. As I said above, this seems like a public interface.

Besides this, I would like to revise IDLE to recognize the code and add highlights. This would require switching back. Now that Hugh made it (supposedly, not yet tested) possible to request color codes on Windows, I will be more motivated to do so.

A different temporary fix would by to filter out color codes. If I can get them on Windows, I can work on that immediately on my Windows machine. (This would be the first step in using them anyway.) Besides familiarily, my main Windows machine is by far the best ergonomically.

@terryjreedy
Copy link
Member

isatty()

Return True if the stream is interactive (i.e., connected to a terminal/tty device).

To me, this means that one can use s = input("Prompt: ") and expect someone to read the prompt and respond. This is true when connected to IDLE's shell, so I consider the current code to be correct, and hence prefer a different solution.

@terryjreedy
Copy link
Member

terryjreedy commented Dec 17, 2024

Since Hugo has started adding color codes to other output (unittest and something else so far), perhaps all stderr output should be filtered, not just Tracebacks. I would not want to filter stdout, as users might want to test sending ansi codes. It might be better to change the environment setting on startup, as long as this only affects IDLE and its subprocesses.

@serhiy-storchaka
Copy link
Member

Why not simply set the TERM environment variable to "idle" or whatever? Not all terminals support ANSI sequences, IDLE is the one that does not support.

Later we can implement support of ANSI sequences in IDLE.

vstinner added a commit to vstinner/cpython that referenced this issue Dec 17, 2024
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.
vstinner added a commit to vstinner/cpython that referenced this issue Dec 17, 2024
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.
@vstinner
Copy link
Member Author

Why not simply set the TERM environment variable to "idle" or whatever?

Good idea: I wrote PR gh-128028 to fix this issue.

@terryjreedy
Copy link
Member

TERM is set in pyshell line 427. Should move to init when do other cleanups. Can easily change if needed.

@terryjreedy terryjreedy moved this to In Progress in IDLE Issues Dec 18, 2024
terryjreedy pushed a commit that referenced this issue Dec 18, 2024
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Dec 18, 2024
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.
(cherry picked from commit 559b0e7)

Co-authored-by: Victor Stinner <[email protected]>
terryjreedy pushed a commit that referenced this issue Dec 18, 2024
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.

(cherry picked from commit 559b0e7)

Co-authored-by: Victor Stinner <[email protected]>
@github-project-automation github-project-automation bot moved this from In Progress to Done in IDLE Issues Dec 18, 2024
srinivasreddy pushed a commit to srinivasreddy/cpython that referenced this issue Jan 8, 2025
Set TERM environment variable to "dumb" to disable traceback colors
in IDLE, since IDLE doesn't understand ANSI escape sequences.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.13 bugs and security fixes 3.14 bugs and security fixes stdlib Python modules in the Lib dir topic-IDLE type-bug An unexpected behavior, bug, or error
Projects
Status: Done
Development

No branches or pull requests

4 participants