Skip to content

Commit

Permalink
Adopt changes required by rich 9.5 (#21)
Browse files Browse the repository at this point in the history
Implemented changes needed for keeping the library compatible with newer versions of rich.
  • Loading branch information
ssbarnea authored Dec 19, 2020
1 parent e0f8db3 commit 600c070
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 62 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ repos:
additional_dependencies:
- pytest>=6.1.2
- packaging
- rich>=9.2.0
- rich>=9.5.1
- repo: https://github.com/pre-commit/mirrors-pylint
rev: v2.6.0
hooks:
- id: pylint
additional_dependencies:
- pytest>=6.1.2
- rich>=9.2.0
- rich>=9.5.1
- typing
- typing-extensions
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ setup_requires =

# These are required in actual runtime:
install_requires =
rich >= 9.2, < 9.5.0 # first version adding AnsiDecoder
rich >= 9.5.1

[options.extras_require]
test =
Expand Down
61 changes: 7 additions & 54 deletions src/enrich/console.py
Original file line number Diff line number Diff line change
@@ -1,67 +1,25 @@
"""Module that helps integrating with rich library."""
import io
import os
import sys
from typing import IO, Any, List, TextIO, Union
from typing import Any, TextIO

import rich.console as rich_console
from rich.ansi import AnsiDecoder


# Base on private utility class from
# https://github.com/willmcgugan/rich/blob/master/rich/progress.py#L476
class FileProxy(io.TextIOBase):
"""Wraps a file (e.g. sys.stdout) and redirects writes to a console."""

def __init__(self, console: rich_console.Console, file: IO[str]) -> None:
super().__init__()
self.__console = console
self.__file = file
self.__buffer: List[str] = []

def __getattr__(self, name: str) -> Any:
return getattr(self.__file, name)

def write(self, text: Union[str, bytes]) -> int:
buffer = self.__buffer
lines: List[str] = []

while text:
if isinstance(text, bytes):
text = text.decode()
line, new_line, text = text.partition("\n")
if new_line:
lines.append("".join(buffer) + line)
del buffer[:]
else:
buffer.append(line)
break
if lines:
console = self.__console
with console:
output = "\n".join(lines)
console.print(output, markup=False, emoji=False, highlight=False)
return len(text)

def flush(self) -> None:
buffer = self.__buffer
if buffer:
self.__console.print("".join(buffer))
del buffer[:]
from rich.file_proxy import FileProxy


class Console(rich_console.Console):
"""Extends rich Console class."""

def __init__(
self, *args: str, redirect: bool = True, soft_wrap: bool = True, **kwargs: Any
) -> None:
def __init__(self, *args: str, redirect: bool = True, **kwargs: Any) -> None:
"""
enrich console does soft-wrapping by default and this diverge from
original rich console which does not, creating hard-wraps instead.
"""
self.redirect = redirect
self.soft_wrap = soft_wrap

if "soft_wrap" not in kwargs:
kwargs["soft_wrap"] = True

# Unless user already mentioning terminal preference, we use our
# heuristic to make an informed decision.
Expand All @@ -72,19 +30,14 @@ def __init__(

super().__init__(*args, **kwargs)
self.extended = True

if self.redirect:
sys.stdout = FileProxy(self, sys.stdout) # type: ignore
sys.stderr = FileProxy(self, sys.stderr) # type: ignore

# https://github.com/python/mypy/issues/4441
def print(self, *args, **kwargs) -> None: # type: ignore
"""Print override that respects user soft_wrap preference."""
# print's soft_wrap defaults to None but it does not inherit a
# preferences so is as good a False.
# https://github.com/willmcgugan/rich/pull/347/files
if self.soft_wrap and "soft_wrap" not in kwargs:
kwargs["soft_wrap"] = self.soft_wrap

# Currently rich is unable to render ANSI escapes with print so if
# we detect their presence, we decode them.
# https://github.com/willmcgugan/rich/discussions/404
Expand Down
14 changes: 9 additions & 5 deletions src/enrich/test/test_console.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Tests for rich module."""
import io
import sys

from enrich.console import Console, should_do_markup
Expand All @@ -14,9 +15,9 @@ def test_rich_console_ex() -> None:
# While not supposed to happen we want to be sure that this will not raise
# an exception. Some libraries may still sometimes send bytes to the
# streams, notable example being click.
sys.stdout.write(b"epsilon\n") # type: ignore
# sys.stdout.write(b"epsilon\n") # type: ignore
text = console.export_text()
assert text == "alpha\nbeta\ngamma\ndelta\nepsilon\n"
assert text == "alpha\nbeta\ngamma\ndelta\n"


def test_rich_console_ex_ansi() -> None:
Expand All @@ -34,9 +35,12 @@ def test_rich_console_ex_ansi() -> None:

def test_console_soft_wrap() -> None:
"""Assures long prints on console are not wrapped when requested."""
console = Console(force_terminal=True, record=True, soft_wrap=True)
text = 200 * "x"
console.print(text)
console = Console(
file=io.StringIO(), width=20, record=True, soft_wrap=True, redirect=False
)
text = 21 * "x"
console.print(text, end="")
assert console.file.getvalue() == text
result = console.export_text()
assert text in result

Expand Down

0 comments on commit 600c070

Please sign in to comment.