Skip to content

Commit

Permalink
Clean up terminal width handling (#9143)
Browse files Browse the repository at this point in the history
* Remove fixed_terminal_width from utils.colorize docstring

This was added by 91adf61, yet colorize()
doesn't actually have a fixed_terminal_width argument.

* Move MYPY_FORCE_TERMINAL_WIDTH handling into get_terminal_width()

Those two callers are the only two, and both check MYPY_FORCE_TERMINAL_WIDTH
before calling get_terminal_width().

* Use shutil.get_terminal_size()

The documentation for Python's os.get_terminal_size() says:

    shutil.get_terminal_size() is the high-level function which should normally
    be used, os.get_terminal_size is the low-level implementation.

https://docs.python.org/3/library/os.html#os.get_terminal_size

shutil.get_terminal_size() already takes care of various corner cases such as:

- Providing a fallback (to 80 columns, like the current DEFAULT_COLUMNS)
- Returning that fallback if os.get_terminal_size() raises OSError
- Doing the same if it returns a size of 0

In addition to that:

- It takes care of some more corner cases ("stdout is None, closed, detached, or
  not a terminal, or os.get_terminal_size() is unsupported")
- It adds support for the COLUMNS environment variable (rather than the
  non-standard MYPY_FORCE_TERMINAL_WIDTH)

https://github.com/python/cpython/blob/v3.8.3/Lib/shutil.py#L1298-L1341
  • Loading branch information
The-Compiler committed Jul 22, 2020
1 parent 03815d6 commit 0a8967c
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 18 deletions.
3 changes: 1 addition & 2 deletions mypy/dmypy/client.py
Expand Up @@ -475,8 +475,7 @@ def request(status_file: str, command: str, *, timeout: Optional[int] = None,
# Tell the server whether this request was initiated from a human-facing terminal,
# so that it can format the type checking output accordingly.
args['is_tty'] = sys.stdout.isatty() or int(os.getenv('MYPY_FORCE_COLOR', '0')) > 0
args['terminal_width'] = (int(os.getenv('MYPY_FORCE_TERMINAL_WIDTH', '0')) or
get_terminal_width())
args['terminal_width'] = get_terminal_width()
bdata = json.dumps(args).encode('utf8')
_, name = get_status(status_file)
try:
Expand Down
20 changes: 4 additions & 16 deletions mypy/util.py
Expand Up @@ -7,6 +7,7 @@
import sys
import hashlib
import io
import shutil

from typing import (
TypeVar, List, Tuple, Optional, Dict, Sequence, Iterable, Container, IO, Callable
Expand Down Expand Up @@ -34,7 +35,6 @@
PLAIN_ANSI_DIM = '\x1b[2m' # type: Final

DEFAULT_SOURCE_OFFSET = 4 # type: Final
DEFAULT_COLUMNS = 80 # type: Final

# At least this number of columns will be shown on each side of
# error location when printing source code snippet.
Expand Down Expand Up @@ -424,14 +424,7 @@ def split_words(msg: str) -> List[str]:

def get_terminal_width() -> int:
"""Get current terminal width if possible, otherwise return the default one."""
try:
cols, _ = os.get_terminal_size()
except OSError:
return DEFAULT_COLUMNS
else:
if cols == 0:
return DEFAULT_COLUMNS
return cols
return int(os.getenv('MYPY_FORCE_TERMINAL_WIDTH', '0')) or shutil.get_terminal_size().columns


def soft_wrap(msg: str, max_len: int, first_offset: int,
Expand Down Expand Up @@ -594,8 +587,7 @@ def style(self, text: str, color: Literal['red', 'green', 'blue', 'yellow', 'non
def fit_in_terminal(self, messages: List[str],
fixed_terminal_width: Optional[int] = None) -> List[str]:
"""Improve readability by wrapping error messages and trimming source code."""
width = (fixed_terminal_width or int(os.getenv('MYPY_FORCE_TERMINAL_WIDTH', '0')) or
get_terminal_width())
width = fixed_terminal_width or get_terminal_width()
new_messages = messages.copy()
for i, error in enumerate(messages):
if ': error:' in error:
Expand All @@ -619,11 +611,7 @@ def fit_in_terminal(self, messages: List[str],
return new_messages

def colorize(self, error: str) -> str:
"""Colorize an output line by highlighting the status and error code.
If fixed_terminal_width is given, use it instead of calling get_terminal_width()
(used by the daemon).
"""
"""Colorize an output line by highlighting the status and error code."""
if ': error:' in error:
loc, msg = error.split('error:', maxsplit=1)
if not self.show_error_codes:
Expand Down

0 comments on commit 0a8967c

Please sign in to comment.