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

Cache prevents re-enabling ANSI support when a subprocess has disabled it #59

Open
SnoopJ opened this issue Jan 29, 2022 · 0 comments
Open

Comments

@SnoopJ
Copy link

SnoopJ commented Jan 29, 2022

Problem description

Using subprocess on Windows can break the colored output of coloredlogs if the new process modifies the console mode. Unfortunately, this seems to happen quite a lot, and the caching applied to enable_ansi_support() prevents the end-user from turning it back on using this function. The cache is effectively invalid after every subprocess.Popen because of this.

Reproduction program given below.

Possible fix

Python 3.8 adds audit hooks that would allow this cache to be invalidated whenever subprocess is being used on Windows. If the relevant ANSI functionality in humanfriendly called enable_ansi_support() before producing output, the reenable_ansi() function defined in the program below could be installed as an audit hook to automatically resolve the problem. Whether or not that's something humanfriendly would want to do is up to the maintainer(s), but if so I would be happy to submit a PR to do this. If not, hopefully this trick helps out any users who stub their toe on the same bug 🙂

import sys

if sys.version_info > (3, 8):
    def reenable_ansi_hook(event, args):
        if event == "subprocess.Popen":
            reenable_ansi()  # defined below

    sys.addaudithook(reenable_ansi_hook)

Reproduction program

import logging
import subprocess

import coloredlogs


logger = logging.getLogger(__name__)
coloredlogs.install()

logger.info(f"This line should have working ANSI")
subprocess.check_output(["echo"])  # changes the console mode on Windows 10

logger.info(f"This line should have broken ANSI")
subprocess.check_output(["echo"])

coloredlogs.enable_ansi_support()  # does NOT enable ANSI support because the cache is now invalid
logger.info(f"This line should have working ANSI again")


def reenable_ansi():
    try:
        # invalidate the cache, if necessary
        del coloredlogs.enable_ansi_support.cached_results
    except NameError:
        pass
    coloredlogs.enable_ansi_support()


subprocess.check_output(["echo"])
reenable_ansi()
logger.info(f"This line should have working ANSI again")

Screenshot of Win10 output

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

No branches or pull requests

1 participant