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

Add option to force color output #7771

Closed
chadrik opened this issue Oct 22, 2019 · 16 comments
Closed

Add option to force color output #7771

chadrik opened this issue Oct 22, 2019 · 16 comments

Comments

@chadrik
Copy link
Contributor

chadrik commented Oct 22, 2019

mypy ignores color_output=true if there is no tty, but in a CI context color is often supported and desired even though there's no tty. pytest solves this with a tri-state flag: --color=yes/no/auto, where color=auto is equivalent to mypy's color_output=true, and color=yes forces color on.

chad$ pytest --help | grep color
  --color=color         color terminal output (yes/no/auto).

I'm happy to submit a PR for this if you think it makes sense.

There is the issue of backward compatibility. We have a few options

  • introduce a new flag --color=yes/no/auto and deprecate the old boolean one. This would let us maintain backward compatibility for a few versions while people switch over
  • change the type of --color-output/--no-color-output to enum string. This would break backward compatibility, at least for the CLI. We might be able to hack something to work for config files.
@msullivan
Copy link
Collaborator

There is an undocumented environment variable MYPY_FORCE_COLOR that will force color.

At the very least that should get documented but probably we should do the true/false/auto thing.

Probably I'd want to maintain compatibility at least for a few versions..
Hm, is it possible with argparse to support both --color and --color=yes syntaxes?

@chadrik
Copy link
Contributor Author

chadrik commented Oct 22, 2019

There is an undocumented environment variable MYPY_FORCE_COLOR that will force color.

Thanks for the heads up!

Probably I'd want to maintain compatibility at least for a few versions..
Hm, is it possible with argparse to support both --color and --color=yes syntaxes?

I don't think there's anything natively supported for it, so it's probably a question of how difficult it is to hack.

@ilevkivskyi
Copy link
Member

ilevkivskyi commented Oct 22, 2019

I agree the three-state (with default set to auto) will be better than two state plus an env variable.

About backwards compatibility, it is unlikely that many people use --color-output right now because it is a default. It is more likely that they use --no-color-output.

Another thing that I didn't try but might work is to have four valid choices for --color-output: 'yes', 'no', 'auto', and '' (empty string). Maybe it is possible in argparse, and then we can make '' an alias to 'auto', and --no-color-output an alias to --color-output=no?

@ilevkivskyi
Copy link
Member

(edit: fixed current flag name)

@wkschwartz
Copy link
Contributor

Workaround for those arriving here because they're looking for color output from Mypy when run via Tox: setting passenv = TERM solved it for me.

@PhilippSelenium
Copy link

Any updates on this?

When I run mypy with tox I get no colour output regardless of which environment variables I pass:

passenv =
    MYPY_FORCE_COLOR
    PY_COLORS

@wkschwartz passenv = TERM had some unwanted side effects in my case.

@yowsa
Copy link

yowsa commented Nov 5, 2020

Any news on this? Color is working perfectly when I run mypy manually in PyCharm but doesn't show up in my pre-commit hooks when using iTerm. I tried setting MYPY_FORCE_COLOR=1 but it had no effect.

@abravalheri
Copy link

On #7771 (comment)

... passenv = TERM had some unwanted side effects in my case.

Hi @PhilippSelenium, in my setup tox seems to be working with passenv, but I am still unsure if I should include this workaround in the CI environment or not... Would you mind to share which unwanted side effects were you facing?

@PhilippSelenium
Copy link

@abravalheri I cannot remember. I just updated tox and mypy and added TERM and had no problems ...

@b0g3r
Copy link

b0g3r commented Apr 18, 2021

@yowsa in my case it fixed with explicit TERM=xterm-color as environment variable in pycharm run configuration

driazati added a commit to pytorch/pytorch that referenced this issue Jul 7, 2021
Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

[ghstack-poisoned]
driazati added a commit to pytorch/pytorch that referenced this issue Jul 8, 2021
Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

[ghstack-poisoned]
driazati added a commit to pytorch/pytorch that referenced this issue Jul 8, 2021
Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

[ghstack-poisoned]
driazati added a commit to pytorch/pytorch that referenced this issue Jul 8, 2021
Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

[ghstack-poisoned]
@domdfcoding
Copy link
Contributor

I have done a bit of digging and found that despite MYPY_FORCE_COLOR=1 the coloured output is prevented by an exception in util.py when calling curses.setupterm:

mypy/mypy/util.py

Lines 551 to 564 in eb1c525

try:
# setupterm wants a fd to potentially write an "initialization sequence".
# We override sys.stdout for the daemon API so if stdout doesn't have an fd,
# just give it /dev/null.
try:
fd = sys.stdout.fileno()
except io.UnsupportedOperation:
with open("/dev/null", "rb") as f:
curses.setupterm(fd=f.fileno())
else:
curses.setupterm(fd=fd)
except curses.error:
# Most likely terminfo not found.
return False

Traceback (most recent call last):
  File "venv/bin/mypy", line 10, in <module>
    sys.exit(console_entry())
  File "venv/lib/python3.6/site-packages/mypy/__main__.py", line 11, in console_entry
    main(None, sys.stdout, sys.stderr)
  File "venv/lib/python3.6/site-packages/mypy/main.py", line 71, in main
    formatter = util.FancyFormatter(stdout, stderr, options.show_error_codes)
  File "venv/lib/python3.6/site-packages/mypy/util.py", line 502, in __init__
    self.dummy_term = not self.initialize_unix_colors()
  File "venv/lib/python3.6/site-packages/mypy/util.py", line 554, in initialize_unix_colors
    curses.setupterm(fd=fd)
_curses.error: setupterm: could not find terminfo database

I would expect a force option to, well, force the colours, even if the terminal doesn't support them.

Something like this should do it for Unix:

diff --git a/mypy/util.py b/mypy/util.py
index bae4821cd..95708f32b 100644
--- a/mypy/util.py
+++ b/mypy/util.py
@@ -504,15 +504,15 @@ class FancyFormatter:
             self.dummy_term = True
             return
         if sys.platform == 'win32':
-            self.dummy_term = not self.initialize_win_colors()
+            self.dummy_term = not self.initialize_win_colors(force_color)
         else:
-            self.dummy_term = not self.initialize_unix_colors()
+            self.dummy_term = not self.initialize_unix_colors(force_color)
         if not self.dummy_term:
             self.colors = {'red': self.RED, 'green': self.GREEN,
                            'blue': self.BLUE, 'yellow': self.YELLOW,
                            'none': ''}
 
-    def initialize_win_colors(self) -> bool:
+    def initialize_win_colors(self, force_color: bool = False) -> bool:
         """Return True if initialization was successful and we can use colors, False otherwise"""
         # Windows ANSI escape sequences are only supported on Threshold 2 and above.
         # we check with an assert at runtime and an if check for mypy, as asserts do not
@@ -544,10 +544,20 @@ class FancyFormatter:
             return True
         return False
 
-    def initialize_unix_colors(self) -> bool:
+    def initialize_unix_colors(self, force_color: bool = False) -> bool:
         """Return True if initialization was successful and we can use colors, False otherwise"""
+        if force_color:
+            self.NORMAL = '\033[22m'
+            self.BOLD = '\033[1m'
+            self.UNDER = '\033[4m'
+            self.DIM = '\033[2m'
+            self.BLUE = '\033[34m'
+            self.GREEN = '\033[32m'
+            self.RED = '\033[31m'
+            self.YELLOW = '\033[33m'
+
         if not CURSES_ENABLED:
-            return False
+            return force_color
         try:
             # setupterm wants a fd to potentially write an "initialization sequence".
             # We override sys.stdout for the daemon API so if stdout doesn't have an fd,
@@ -561,14 +571,15 @@ class FancyFormatter:
                 curses.setupterm(fd=fd)
         except curses.error:
             # Most likely terminfo not found.
-            return False
+            return force_color
+
         bold = curses.tigetstr('bold')
         under = curses.tigetstr('smul')
         set_color = curses.tigetstr('setaf')
         set_eseq = curses.tigetstr('cup')
 
         if not (bold and under and set_color and set_eseq):
-            return False
+            return force_color
 
         self.NORMAL = curses.tigetstr('sgr0').decode()
         self.BOLD = bold.decode()

facebook-github-bot pushed a commit to pytorch/pytorch that referenced this issue Jul 8, 2021
Summary:
Pull Request resolved: #61391

Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

Test Plan: Imported from OSS

Reviewed By: walterddr

Differential Revision: D29602686

Pulled By: driazati

fbshipit-source-id: e8f4cd71572cc068927e6719534e64773cb16c7f
QYP-842653 pushed a commit to QYP-842653/Pytorch that referenced this issue Jul 27, 2021
Both the [GitHub Actions log viewer](https://github.saobby.my.eu.orgmunity/t/ansi-color-output-in-webview/17621) and the HUD PR page log viewer support ANSI color codes so turn those on via this [secret env variable](python/mypy#7771)

ghstack-source-id: 77b47d6e1e449f69a44e24a5095c4980f92a383f
Pull Request resolved: pytorch/pytorch#61391
cjolowicz added a commit to cjolowicz/cookiecutter-hypermodern-python-instance that referenced this issue Nov 19, 2021
Unfortunately, this does not actually work on GitHub Actions, see [1].

[1] python/mypy#7771 (comment)
@eggplants
Copy link
Contributor

eggplants commented Mar 2, 2022

$ MYPY_FORCE_COLOR=1 mypy ... is worked.

Environment

  • macOS 12
  • Python 3.9
  • mypy 0.931

Screenshot

image

@miron
Copy link

miron commented Apr 13, 2022

$ MYPY_FORCE_COLOR=1 mypy ... is worked.

Environment

  • macOS 12
  • Python 3.9
  • mypy 0.931

Screenshot

image

How you can accept this as a working solution, you can't see half of the output. I have the option to disable colors in mypy.ini with:

[mypy]
color_output = False

but that doesn't work i.e. with:

python -m mypy.stubtest library

A better theme for black consoles would be great, which should be the majority of people i guess, nobody else is bothered by this?

stuhood pushed a commit to pantsbuild/pants that referenced this issue Sep 9, 2022
This fixes #16451 by continuing the color half of #16488 (terminal width).

It does this by forcing mypy to always include color escapes, and then stripping them out in pants, based on the [GLOBAL].colors setting.

This seems to only be possible via an undocumented environment variable: `MYPY_FORCE_COLOR`: python/mypy#7771, https://github.com/python/mypy/blob/03638dd670373db0b8f00cc3bcec256d09729d06/mypy/util.py#L543

Doing this also requires setting `TERM=linux` so that curses can find appropriate info in the terminfo database.

[ci skip-rust]
[ci skip-build-wheels]
stuhood pushed a commit to stuhood/pants that referenced this issue Sep 9, 2022
…build#16586)

This fixes pantsbuild#16451 by continuing the color half of pantsbuild#16488 (terminal width).

It does this by forcing mypy to always include color escapes, and then stripping them out in pants, based on the [GLOBAL].colors setting.

This seems to only be possible via an undocumented environment variable: `MYPY_FORCE_COLOR`: python/mypy#7771, https://github.com/python/mypy/blob/03638dd670373db0b8f00cc3bcec256d09729d06/mypy/util.py#L543

Doing this also requires setting `TERM=linux` so that curses can find appropriate info in the terminfo database.

[ci skip-rust]
[ci skip-build-wheels]
stuhood added a commit to pantsbuild/pants that referenced this issue Sep 9, 2022
…y-pick of #16586) (#16808)

This fixes #16451 by continuing the color half of #16488 (terminal width).

It does this by forcing mypy to always include color escapes, and then stripping them out in pants, based on the [GLOBAL].colors setting.

This seems to only be possible via an undocumented environment variable: `MYPY_FORCE_COLOR`: python/mypy#7771, https://github.com/python/mypy/blob/03638dd670373db0b8f00cc3bcec256d09729d06/mypy/util.py#L543

Doing this also requires setting `TERM=linux` so that curses can find appropriate info in the terminfo database.

[ci skip-rust]
[ci skip-build-wheels]
ilevkivskyi pushed a commit that referenced this issue Dec 7, 2022
Last time i checked it wasn't the 1960's. So I think the CI could be
colorized.

Configured pytest, tox, mypy(#7771) and pip¹ (I already already
colorized black and isort when I initially added them)


1: Pip doesn't work yet pypa/pip#10909, so
this is just a placedholder for when it (hopefully) soon will.

Co-authored-by: KotlinIsland <kotlinisland@users.noreply.github.com>
@intgr
Copy link
Contributor

intgr commented Feb 28, 2023

Unfortunately MYPY_FORCE_COLOR is ignored by dmypy daemon.

EDIT: My bad, I was missing TERM environment variable. Adding TERM=ansi env fixed it.

@intgr
Copy link
Contributor

intgr commented Feb 28, 2023

@miron This issue is about a way to force color output, your comment is offtopic for this issue. Feel free to open a separate issue. Also don't quote previous comments in full -- if you want to quote, only keep the relevant parts.

@hauntsaninja
Copy link
Collaborator

Use the MYPY_FORCE_COLOR or FORCE_COLOR environment variables. #13815 is for documenting this better

jvilders added a commit to jvilders/python-project-setup that referenced this issue May 25, 2024
Based on: python/mypy#7771, now using
a currently undocumented environment variable that forces mypy
to emit colored output even in non-interactive sessions, such as
running mypy through python's subprocess.run.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests