gruns / icecream

🍦 Never use print() to debug again.
MIT License
9.07k stars 184 forks source link

Broken coloring for boolean in command prompt #35

Open offchan42 opened 5 years ago

offchan42 commented 5 years ago

image As you see in the image, the background color is broken after True keyword appears. How do I get around this problem?

gruns commented 5 years ago

Thanks for the Issue!

In which terminal are you experiencing this behavior so I may attempt to reproduce?

offchan42 commented 5 years ago

@gruns It's the default windows 10 command prompt. Try the following code:

from icecream import ic

ic(True)
print('hello')

image

KyleKing commented 5 years ago

I have the same issue on Windows where in, None, False, and True are highlighted along with any trailing output

KyleKing commented 4 years ago

I had a moment to troubleshoot this and created a minimal working example with a simplified formatted The problem appears to be from colorama converting the ANSI escape sequences for Win32

from pygments import highlight
from pygments.formatters import Terminal256Formatter
from pygments.lexers import Python3Lexer as Py3Lexer
from pygments.style import Style
from pygments.token import (
    Text, Name, Error, Other, String, Number, Keyword, Generic, Literal,
    Comment, Operator, Whitespace, Punctuation)

# Solarized: https://ethanschoonover.com/solarized/
class MinSolarizedDark(Style):

    GREEN   = '#859900' # noqa

    styles = {
        Keyword:                GREEN,
        Keyword.Constant:       GREEN,
        Keyword.Declaration:    GREEN,
        Keyword.Reserved:       GREEN,
        Keyword.Type:           GREEN,
    }

lexer = Py3Lexer(ensurenl=False)
formatter = Terminal256Formatter(style=MinSolarizedDark)

import colorama
from colorama import Style as colorama_style
colorama.init()

code = {'this': None, 'that': True}
result = highlight(str(code), lexer, formatter)
print(result.encode())
print(result)
print('\n---\nstill white background' + colorama_style.RESET_ALL)
print('now cleared')

colorama.deinit()

print('\n---\n')
print(result)

Output:

output

Without the colorama.init()/colorama.deinit(), I don't have any issues with Windows command prompt or powershell One easy solution might be to make colorama optional (or as an extra) and if the user installs colorama, they would have the win32 conversion, but it not, they wouldn't see the white background highlighting. I modified my local icecream.py in my .venv and seems to be working on my end

try:
    raise ImportError('HACK: Test if colorama were not installed')
    import colorama
except ImportError:
    colorama = None

@contextmanager
def supportTerminalColorsInWindows():
    # Filter and replace ANSI escape sequences on Windows with equivalent Win32
    # API calls. This code does nothing on non-Windows systems.
    if colorama:
        colorama.init()
    yield
    if colorama:
        colorama.deinit()

I'll add some notes to PR #40 later today/this weekend

~Update: I started working on a simple fork: https://github.com/KyleKing/icecream (Will revisit if prepping a PR and not just commenting on #40)~ (Fork is now deleted)

Update 2: the quick fix of making colorama optional won't work. PyTest has a dependency on colorama, so colorama would likely be installed for most users. An alternative could be to make the colorma toggleable through an ic.configure argument, but still not ideal

Update 3: the above snippet should be useful to resume troubleshooting, but I wasn't able to resolve the issue in a meaningful way

DavidLafond commented 3 years ago

Same for me, after an "in" everything get a background colour. Anyways to fix that?

alexmojaki commented 3 years ago

Same problem is also mentioned in https://github.com/gruns/icecream/issues/52#issuecomment-816225510, clearly this is bothering a lot of people.

This seems to essentially be a colorama bug. I don't have Windows to test on but https://github.com/tartley/colorama/issues/200 and https://github.com/tartley/colorama/issues/218 sound like likely candidates. icecream doesn't actually specify any background colors at all, and @KyleKing's example shows nicely that just asking for a green foreground causes the grey background.

colorama is hardly maintained these days, see https://github.com/tartley/colorama/issues/300 . Commits have slowed down and there are many open issues and PRs. The above issues are over 2 years old. icecream needs to not rely on colorama too much.

https://github.com/gruns/icecream/pull/40 would be helpful so that users can simply uninstall colorama to disable it.

You can disable color right now with https://github.com/gruns/icecream/issues/67#issuecomment-812449158 but as I said this needs to be easier and more obvious, something like ic.configureOutput(color=False) as mentioned in https://github.com/gruns/icecream/issues/31.

rafaelruizv commented 3 years ago

is there any update on this issue? this is very bothering... or at least any way to disable background color and keep the foreground color? This is issue is happening to me after the word "in" in windows VSCode

gruns commented 3 years ago

@rafaelruizv i dont have the time to tackle this right now, nor ready access to a windows machine to reproduce and debug

in the mean time, you can disable coloring by setting the outputFunction to just print to stderr print(..., file=sys.stderr)

import sys
from icecream import ic

ic.configureOutput(outputFunction=lambda *a: print(*a, file=sys.stderr))

this bypasses icecream's coloring functionality

char101 commented 2 years ago

Colorama does not support 256 colors so escape code like \x1b[38;5;100m is interpreted as command m with 3 parameters: 38 (no match), 5 (no match), and 100 (this match colorama.ansi.AnsiBack.LIGHTBLACK_EX which is the gray background color you see).

So one way to deal with this issue is to add this code

colorama.ansi.AnsiBack.LIGHTBLACK_EX = 999

somewhere in your code.

Since Windows 10 terminal supports native 256 ansi colors (with registry hack or using ctypes), a better solution is

import icecream
icecream.ic.configureOutput(outputFunction=lambda s: print(icecream.colorize(s), file=sys.stderr))