From b80ed71b1fc54c4041c38d2df17970a2714b19bd Mon Sep 17 00:00:00 2001 From: Bartek Sokorski Date: Tue, 12 Jul 2022 23:58:25 +0200 Subject: [PATCH 1/2] Replace class with stdlib solution --- cleo/application.py | 4 +- cleo/io/outputs/section_output.py | 6 +- cleo/terminal.py | 142 ------------------------------ cleo/ui/progress_bar.py | 8 +- pyproject.toml | 1 - 5 files changed, 9 insertions(+), 152 deletions(-) delete mode 100644 cleo/terminal.py diff --git a/cleo/application.py b/cleo/application.py index 9228c961..3fbce938 100644 --- a/cleo/application.py +++ b/cleo/application.py @@ -2,6 +2,7 @@ import os import re +import shutil import sys from contextlib import suppress @@ -29,7 +30,6 @@ from cleo.io.io import IO from cleo.io.outputs.output import Verbosity from cleo.io.outputs.stream_output import StreamOutput -from cleo.terminal import Terminal from cleo.ui.ui import UI @@ -61,7 +61,7 @@ def __init__(self, name: str = "console", version: str = "") -> None: self._name = name self._version = version self._display_name: str | None = None - self._terminal = Terminal() + self._terminal = shutil.get_terminal_size() self._default_command = "list" self._single_command = False self._commands: dict[str, Command] = {} diff --git a/cleo/io/outputs/section_output.py b/cleo/io/outputs/section_output.py index ea99fc55..ad286e79 100644 --- a/cleo/io/outputs/section_output.py +++ b/cleo/io/outputs/section_output.py @@ -1,13 +1,13 @@ from __future__ import annotations import math +import shutil from typing import TYPE_CHECKING from typing import TextIO from cleo.io.outputs.output import Verbosity from cleo.io.outputs.stream_output import StreamOutput -from cleo.terminal import Terminal if TYPE_CHECKING: @@ -31,7 +31,7 @@ def __init__( self._lines = 0 sections.insert(0, self) self._sections = sections - self._terminal = Terminal() + self._terminal = shutil.get_terminal_size() @property def content(self) -> str: @@ -67,7 +67,7 @@ def add_content(self, content: str) -> None: self._lines += ( math.ceil( len(self.remove_format(line_content).replace("\t", " ")) - / self._terminal.width + / self._terminal.columns ) or 1 ) diff --git a/cleo/terminal.py b/cleo/terminal.py deleted file mode 100644 index 49a7cfca..00000000 --- a/cleo/terminal.py +++ /dev/null @@ -1,142 +0,0 @@ -from __future__ import annotations - -import os -import platform -import shlex -import struct -import subprocess - - -class Terminal: - """ - Represents the current terminal. - """ - - _width = None - _height = None - - @property - def width(self) -> int: - width = os.getenv("COLUMNS", "").strip() - if width: - return int(width) - - if self.__class__._width is None: - self._init_dimensions() - - return self.__class__._width - - @property - def height(self) -> int: - height = os.getenv("LINES", "").strip() - if height: - return int(height) - - if self.__class__._height is None: - self._init_dimensions() - - return self.__class__._height - - @classmethod - def _init_dimensions(cls) -> None: - current_os = platform.system().lower() - dimensions = None - - if current_os.lower() == "windows": - dimensions = cls._get_terminal_size_windows() - if dimensions is None: - dimensions = cls._get_terminal_size_tput() - elif current_os.lower() in ["linux", "darwin"] or current_os.startswith( - "cygwin" - ): - dimensions = cls._get_terminal_size_linux() - - if dimensions is None: - dimensions = 80, 25 - - # Ensure we have a valid width - if dimensions[0] <= 0: - dimensions = 80, dimensions[1] - - cls._width, cls._height = dimensions - - @classmethod - def _get_terminal_size_windows(cls) -> tuple[int, int] | None: - try: - from ctypes import create_string_buffer - from ctypes import windll - - # stdin handle is -10 - # stdout handle is -11 - # stderr handle is -12 - h = windll.kernel32.GetStdHandle(-12) - csbi = create_string_buffer(22) - res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) - if res: - ( - bufx, - bufy, - curx, - cury, - wattr, - left, - top, - right, - bottom, - maxx, - maxy, - ) = struct.unpack("hhhhHhhhhhh", csbi.raw) - sizex = right - left + 1 - sizey = bottom - top + 1 - return sizex, sizey - except Exception: - return - - @classmethod - def _get_terminal_size_tput(cls) -> tuple[int, int] | None: - # get terminal width - # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window # noqa: E501 - try: - cols = int( - subprocess.check_output( - shlex.split("tput cols"), stderr=subprocess.STDOUT - ) - ) - rows = int( - subprocess.check_output( - shlex.split("tput lines"), stderr=subprocess.STDOUT - ) - ) - - return cols, rows - except Exception: - pass - - @classmethod - def _get_terminal_size_linux(cls) -> tuple[int, int] | None: - def ioctl_GWINSZ(fd): # noqa: N802 - try: - import fcntl - import termios - - cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234")) - return cr - except Exception: - pass - - cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - cr = ioctl_GWINSZ(fd) - os.close(fd) - except Exception: - pass - - if not cr: - try: - cr = (os.environ["LINES"], os.environ["COLUMNS"]) - except Exception: - return - - return int(cr[1]), int(cr[0]) diff --git a/cleo/ui/progress_bar.py b/cleo/ui/progress_bar.py index 45b0e5dd..ecf29254 100644 --- a/cleo/ui/progress_bar.py +++ b/cleo/ui/progress_bar.py @@ -2,6 +2,7 @@ import math import re +import shutil import time from typing import TYPE_CHECKING @@ -11,7 +12,6 @@ from cleo.cursor import Cursor from cleo.io.io import IO from cleo.io.outputs.section_output import SectionOutput -from cleo.terminal import Terminal from cleo.ui.component import Component @@ -57,7 +57,7 @@ def __init__( io = io.error_output self._io = io - self._terminal = Terminal() + self._terminal = shutil.get_terminal_size() self._max = 0 self._step_width = None self._set_max_steps(max) @@ -317,7 +317,7 @@ def _overwrite(self, message: str) -> None: int( math.floor( len(self._io.remove_format(message)) - / self._terminal.width + / self._terminal.columns ) ) + self._format_line_count @@ -443,7 +443,7 @@ def _build_line(self) -> str: lines_width = max(lines_length) - terminal_width = self._terminal.width + terminal_width = self._terminal.columns if lines_width <= terminal_width: return line diff --git a/pyproject.toml b/pyproject.toml index 4ed1f82f..926c0a9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,6 @@ module = [ "cleo.io.inputs.token_parser", "cleo.io.outputs.stream_output", "cleo.parser", - "cleo.terminal", "cleo.testers.application_tester", "cleo.testers.command_tester", "cleo.ui.choice_question", From c9147ecec2fd39f6edb6ed4e59b7ff78d36e99a2 Mon Sep 17 00:00:00 2001 From: Bartek Sokorski Date: Wed, 13 Jul 2022 00:04:00 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33db3fcf..3dd19cba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [1.0.0] - UNRELEASED + +- Replaced `Terminal` class with `shutil.get_terminal_size()` from standard library +[#175](https://github.com/python-poetry/cleo/pull/175). + + ## [0.8.1] - 2020-04-17 ### Changed