diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ddfb9f5..3cd045e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [9.5.0] - Unreleased + +### Changed + +- If file is not specified on Console then the Console.file will return the current sys.stdout + +### Added + +- Added stderr parameter to Console +- Added rich.reconfigure + ## [9.4.0] - 2020-12-12 ### Added diff --git a/examples/spinners.py b/examples/spinners.py index 68585b00..9daf847c 100644 --- a/examples/spinners.py +++ b/examples/spinners.py @@ -9,7 +9,7 @@ from rich.spinner import Spinner, SPINNERS all_spinners = Columns( [ Spinner(spinner_name, text=Text(repr(spinner_name), style="green")) - for spinner_name in sorted(SPINNERS.keys()) + for spinner_name in sorted(SPINNERS) ], column_first=True, expand=True, diff --git a/rich/__init__.py b/rich/__init__.py index dbb9da61..acf068e8 100644 --- a/rich/__init__.py +++ b/rich/__init__.py @@ -25,6 +25,18 @@ def get_console() -> "Console": return _console +def reconfigure(*args, **kwargs) -> None: + """Reconfigures the global console bu replacing it with another. + + Args: + console (Console): Replacement console instance. + """ + from rich.console import Console + + new_console = Console(*args, **kwargs) + _console.__dict__ = new_console.__dict__ + + def print(*objects: Any, sep=" ", end="\n", file: IO[str] = None, flush: bool = False): r"""Print object(s) supplied via positional arguments. This function has an identical signature to the built-in print. diff --git a/rich/console.py b/rich/console.py index 481f597d..1fd87ebd 100644 --- a/rich/console.py +++ b/rich/console.py @@ -391,6 +391,7 @@ class Console: force_terminal (Optional[bool], optional): Enable/disable terminal control codes, or None to auto-detect terminal. Defaults to None. force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None. theme (Theme, optional): An optional style theme object, or ``None`` for default theme. + stderr (bool, optional): User stderr rather than stdout if ``file `` is not specified. Defaults to False. file (IO, optional): A file object where the console should write to. Defaults to stdout. width (int, optional): The width of the terminal. Leave as default to auto-detect width. height (int, optional): The height of the terminal. Leave as default to auto-detect height. @@ -419,6 +420,7 @@ class Console: force_terminal: bool = None, force_jupyter: bool = None, theme: Theme = None, + stderr: bool = False, file: IO[str] = None, width: int = None, height: int = None, @@ -459,7 +461,8 @@ class Console: self._color_system: Optional[ColorSystem] self._force_terminal = force_terminal - self.file = file or sys.stdout + self._file = file + self.stderr = stderr if color_system is None: self._color_system = None @@ -478,6 +481,7 @@ class Console: self.safe_box = safe_box self.get_datetime = get_datetime or datetime.now self.get_time = get_time or monotonic + self.stderr = stderr self._record_buffer_lock = threading.RLock() self._thread_locals = ConsoleThreadLocals( @@ -489,6 +493,18 @@ class Console: def __repr__(self) -> str: return f"" + @property + def file(self) -> IO[str]: + """Get the file object to write to.""" + file = self._file or (sys.stderr if self.stderr else sys.stdout) + file = getattr(file, "rich_proxied_file", file) + return file + + @file.setter + def file(self, new_file: IO[str]) -> None: + """Set a new file object.""" + self._file = new_file + @property def _buffer(self) -> List[Segment]: """Get a thread local buffer.""" diff --git a/rich/file_proxy.py b/rich/file_proxy.py index b0aa0ba2..98911806 100644 --- a/rich/file_proxy.py +++ b/rich/file_proxy.py @@ -17,6 +17,11 @@ class FileProxy(io.TextIOBase): self.__buffer: List[str] = [] self.__ansi_decoder = AnsiDecoder() + @property + def rich_proxied_file(self) -> IO[str]: + """Get proxied file.""" + return self.__file + def __getattr__(self, name: str) -> Any: return getattr(self.__file, name) diff --git a/tests/test_rich_print.py b/tests/test_rich_print.py index 9fc611e2..18467c6b 100644 --- a/tests/test_rich_print.py +++ b/tests/test_rich_print.py @@ -9,6 +9,11 @@ def test_get_console(): assert isinstance(console, Console) +def test_reconfigure_console(): + rich.reconfigure(width=100) + assert rich.get_console().width == 100 + + def test_rich_print(): console = rich.get_console() output = io.StringIO()