Skip to content
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

[BUG] Invalid markup in a ProgressBar causes the entire Python script to exit abnormally. #2291

Closed
fmillion opened this issue May 24, 2022 · 1 comment · Fixed by #2305
Closed
Assignees
Labels
bug Something isn't working

Comments

@fmillion
Copy link

fmillion commented May 24, 2022

Describe the bug

NOTE: I found some more details on this. The issue isn't that an exception isn't raised, it's that you can't ever see any console output from that exception. Alternate screen issue? See EDIT below. Original bug report follows.

If you try to create a ProgressBar object, and within your fields you have some invalid markup (example: a closing [/color] tag without a corresponding opening tag), starting the progress bar with start() will cause the entire Python interpreter to exit with return code 1.

No error message is printed. Wrapping the code in a try/except block does not trap the error, the entire script still exits.

The following is a minimal working example illustrating the bug.

from rich.progress import (
    BarColumn,
    Progress,
    TaskID,
    TextColumn,
    TimeRemainingColumn,
)

import time

def test():

    print("I will now make Rich fail horribly...")

    pbar = Progress(
        "[green]Status",
        TimeRemainingColumn(),
        "Running[/red]" # THIS LINE HAS INVALID MARKUP. IT WILL CAUSE THE SCRIPT TO CRASH WITH NO ERROR.
    )

    task_id = pbar.add_task("test",start=False, total=10)

    # PROGRAM EXECUTION ABORTS HERE WITH NO ERROR MESSAGES.
    # Python interpreter returns code 1.
    pbar.start()

    print("We should make it here, but we don't.")

    for _ in range(10):
        time.sleep()
        pbar.update(task_id, advance=1)

    pbar.stop()

if __name__ == "__main__":

    # Even wrapping the test in a try/catch block does not prevent Python from exiting!
    try:
        test()
    except Exception as e:
        print(f"I caught an exception! {e}") # This is NOT called, NO exception is raised.

    print("I made it through the test!") # This is also NEVER reached. The script EXITS when pbar.start() is called.

Example run (Not much to see...):

dev@devbox:~$ python3 richbug.py
dev@devbox:~$ echo $?
1
dev@devbox:~$

Note that I have not tested this further to determine if it happens in other areas of Rich, but I know for sure it happens with ProgressBar.

What should happen?

If there's invalid markup, a normal exception should get thrown somewhere.

Even if for some reason the app needs to fully exit, printing an error message would still be useful. I spent over an hour tracking down what I thought was a bug or a forgotten exit() call in my own code before realizing the exact line where things failed was pbar.start().

I have a suspicion that this might have to do with the alternate screen - perhaps an exception is printed but it's done on the alternate screen so you never see it? I haven't spent much time looking at Rich's code, but I'd imagine perhaps wrapping code in try blocks with code to exit the alternate screen followed by re-raising the exception might work?

One more point: after the code exits, the cursor is missing - I have to use reset to bring it back. Again, suggests that we're switching into the alternate screen, crashing and then not getting back out to print errors.

EDIT: I discovered this is indeed the case. If I add the line open("exception.txt","w").write(str(e)) to the except block, the exception does get printed and indeed does include the correct markup error. So therefore this bug should perhaps be named "App does not exit alternate screen before crashing"?

Platform

dev@devbox:~$ python -m rich.diagnose

    ╭───────────────────────── <class 'rich.console.Console'> ─────────────────────────╮
    │ A high level console interface.                                                  │
    │                                                                                  │
    │ ╭──────────────────────────────────────────────────────────────────────────────╮ │
    │ │ <console width=148 ColorSystem.STANDARD>                                     │ │
    │ ╰──────────────────────────────────────────────────────────────────────────────╯ │
    │                                                                                  │
    │     color_system = 'standard'                                                    │
    │         encoding = 'utf-8'                                                       │
    │             file = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'> │
    │           height = 30                                                            │
    │    is_alt_screen = False                                                         │
    │ is_dumb_terminal = False                                                         │
    │   is_interactive = True                                                          │
    │       is_jupyter = False                                                         │
    │      is_terminal = True                                                          │
    │   legacy_windows = False                                                         │
    │         no_color = False                                                         │
    │          options = ConsoleOptions(                                               │
    │                        size=ConsoleDimensions(width=148, height=30),             │
    │                        legacy_windows=False,                                     │
    │                        min_width=1,                                              │
    │                        max_width=148,                                            │
    │                        is_terminal=True,                                         │
    │                        encoding='utf-8',                                         │
    │                        max_height=30,                                            │
    │                        justify=None,                                             │
    │                        overflow=None,                                            │
    │                        no_wrap=False,                                            │
    │                        highlight=None,                                           │
    │                        markup=None,                                              │
    │                        height=None                                               │
    │                    )                                                             │
    │            quiet = False                                                         │
    │           record = False                                                         │
    │         safe_box = True                                                          │
    │             size = ConsoleDimensions(width=148, height=30)                       │
    │        soft_wrap = False                                                         │
    │           stderr = False                                                         │
    │            style = None                                                          │
    │         tab_size = 8                                                             │
    │            width = 148                                                           │
    ╰──────────────────────────────────────────────────────────────────────────────────╯
    ╭─── <class 'rich._windows.WindowsConsoleFeatures'> ────╮
    │ Windows features available.                           │
    │                                                       │
    │ ╭───────────────────────────────────────────────────╮ │
    │ │ WindowsConsoleFeatures(vt=False, truecolor=False) │ │
    │ ╰───────────────────────────────────────────────────╯ │
    │                                                       │
    │ truecolor = False                                     │
    │        vt = False                                     │
    ╰───────────────────────────────────────────────────────╯
    ╭────── Environment Variables ───────╮
    │ {                                  │
    │     'TERM': 'screen',              │
    │     'COLORTERM': None,             │
    │     'CLICOLOR': None,              │
    │     'NO_COLOR': None,              │
    │     'TERM_PROGRAM': None,          │
    │     'COLUMNS': None,               │
    │     'LINES': None,                 │
    │     'JPY_PARENT_PID': None,        │
    │     'VSCODE_VERBOSE_LOGGING': None │
    │ }                                  │
    ╰────────────────────────────────────╯
    platform="Linux"

dev@devbox:~$ pip freeze | grep rich
rich==12.4.4

The above was run while SSH'ed into the devbox from Windows terminal. Same issue will occur no matter what client is being used though. Happens no matter how I run the code, whether it be on a local terminal, via SSH, etc.

Devbox is running Ubuntu Linux 22.04.

@github-actions
Copy link

Did I solve your problem?

Why not buy the devs a coffee to say thanks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants