From 637a6a1cbcc5db668dc93a561f104cbea319bd11 Mon Sep 17 00:00:00 2001 From: indivar Date: Sun, 8 Jan 2023 00:37:47 +0530 Subject: [PATCH 01/17] add `pretty_exceptions_width` to DeveloperExceptionConfig adding new attribute in DeveloperExceptionConfig to allow setting width for rick traceback. --- typer/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/typer/models.py b/typer/models.py index 9bbe2a36d2..bfd03e7bf7 100644 --- a/typer/models.py +++ b/typer/models.py @@ -513,7 +513,9 @@ def __init__( pretty_exceptions_enable: bool = True, pretty_exceptions_show_locals: bool = True, pretty_exceptions_short: bool = True, + pretty_exceptions_width: int = 100, ) -> None: self.pretty_exceptions_enable = pretty_exceptions_enable self.pretty_exceptions_show_locals = pretty_exceptions_show_locals self.pretty_exceptions_short = pretty_exceptions_short + self.pretty_exceptions_width = pretty_exceptions_width From f4b44a4ac13a00680c874a776e1d429f800e4938 Mon Sep 17 00:00:00 2001 From: indivar Date: Sun, 8 Jan 2023 00:39:18 +0530 Subject: [PATCH 02/17] add `pretty_exceptions_width` in Typer class add `pretty_exceptions_width` in typer class to be used by `DeveloperConfigException` to allow setting width of traceback boxes. --- typer/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/typer/main.py b/typer/main.py index ccf9f0956c..a8a0e994f7 100644 --- a/typer/main.py +++ b/typer/main.py @@ -75,6 +75,7 @@ def except_hook( exc.__traceback__, show_locals=exception_config.pretty_exceptions_show_locals, suppress=supress_internal_dir_names, + width=exception_config.pretty_exceptions_width, ) console_stderr.print(rich_tb) return @@ -137,6 +138,7 @@ def __init__( pretty_exceptions_enable: bool = True, pretty_exceptions_show_locals: bool = True, pretty_exceptions_short: bool = True, + pretty_exceptions_width: int = 100, ): self._add_completion = add_completion self.rich_markup_mode: MarkupMode = rich_markup_mode @@ -144,6 +146,7 @@ def __init__( self.pretty_exceptions_enable = pretty_exceptions_enable self.pretty_exceptions_show_locals = pretty_exceptions_show_locals self.pretty_exceptions_short = pretty_exceptions_short + self.pretty_exceptions_width = pretty_exceptions_width self.info = TyperInfo( name=name, cls=cls, @@ -321,6 +324,7 @@ def __call__(self, *args: Any, **kwargs: Any) -> Any: pretty_exceptions_enable=self.pretty_exceptions_enable, pretty_exceptions_show_locals=self.pretty_exceptions_show_locals, pretty_exceptions_short=self.pretty_exceptions_short, + pretty_exceptions_width=self.pretty_exceptions_width, ), ) raise e From 0d209d84517819b684412e25f705a234694d3543 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:01:43 +0200 Subject: [PATCH 03/17] add tutorial 005 to showcase pretty_exceptions_width --- docs/tutorial/exceptions.md | 11 +++++++++ docs_src/exceptions/tutorial005.py | 37 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 docs_src/exceptions/tutorial005.py diff --git a/docs/tutorial/exceptions.md b/docs/tutorial/exceptions.md index 84dbac602c..ba17fc6f58 100644 --- a/docs/tutorial/exceptions.md +++ b/docs/tutorial/exceptions.md @@ -202,6 +202,17 @@ $ python main.py + +## Set Output Width + +If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to an integer: + +```Python hl_lines="3" +{!../docs_src/exceptions/tutorial005.py!} +``` + +This prevents artificial line breaks in cases where there is sufficient horizontal space on the console. + ## Disable Pretty Exceptions You can also entirely disable pretty exceptions with the parameter `pretty_exceptions_enable=False`: diff --git a/docs_src/exceptions/tutorial005.py b/docs_src/exceptions/tutorial005.py new file mode 100644 index 0000000000..3d0cd1f8fa --- /dev/null +++ b/docs_src/exceptions/tutorial005.py @@ -0,0 +1,37 @@ +import typer + +app = typer.Typer(pretty_exceptions_width=120) + + +@app.command() +def main(name: str = "morty"): + deep_dict_or_json = { + "this_is_a_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "this_is_the_next_long_key": { + "and_once_again_a_very_long_key": { + "but_this_is_not_the_end": {"end": True} + } + } + } + } + } + } + } + } + } + } + } + } + print(name + 3) + + +if __name__ == "__main__": + app() From 0460e47b61caf1325027bf9b7f8fb642b0c2c928 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:01:51 +0000 Subject: [PATCH 04/17] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs_src/exceptions/tutorial005.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs_src/exceptions/tutorial005.py b/docs_src/exceptions/tutorial005.py index 3d0cd1f8fa..b9b4ffec28 100644 --- a/docs_src/exceptions/tutorial005.py +++ b/docs_src/exceptions/tutorial005.py @@ -17,7 +17,9 @@ def main(name: str = "morty"): "this_is_the_next_long_key": { "this_is_the_next_long_key": { "and_once_again_a_very_long_key": { - "but_this_is_not_the_end": {"end": True} + "but_this_is_not_the_end": { + "end": True + } } } } From 3e81d23a16b9d934050aa7865f3ae69f17ccd2d8 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:07:17 +0200 Subject: [PATCH 05/17] add comment about default value --- docs/tutorial/exceptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/exceptions.md b/docs/tutorial/exceptions.md index ba17fc6f58..fe555a6902 100644 --- a/docs/tutorial/exceptions.md +++ b/docs/tutorial/exceptions.md @@ -205,7 +205,7 @@ $ python main.py ## Set Output Width -If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to an integer: +If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to a specific integer (it's 100 by default): ```Python hl_lines="3" {!../docs_src/exceptions/tutorial005.py!} From cb05984e813beb9578999a867d9547afd08c0adc Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:10:26 +0200 Subject: [PATCH 06/17] avoid F841 error --- docs_src/exceptions/tutorial005.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs_src/exceptions/tutorial005.py b/docs_src/exceptions/tutorial005.py index b9b4ffec28..702569a254 100644 --- a/docs_src/exceptions/tutorial005.py +++ b/docs_src/exceptions/tutorial005.py @@ -33,6 +33,7 @@ def main(name: str = "morty"): } } print(name + 3) + print(deep_dict_or_json) if __name__ == "__main__": From 45e9736fe3b78f351f6bd935d36f10a75a3d527f Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:15:21 +0200 Subject: [PATCH 07/17] add test case for new tutorial file --- .../test_exceptions/test_tutorial005.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/test_tutorial/test_exceptions/test_tutorial005.py diff --git a/tests/test_tutorial/test_exceptions/test_tutorial005.py b/tests/test_tutorial/test_exceptions/test_tutorial005.py new file mode 100644 index 0000000000..99a2147dcc --- /dev/null +++ b/tests/test_tutorial/test_exceptions/test_tutorial005.py @@ -0,0 +1,34 @@ +import os +import subprocess +import sys +from pathlib import Path + +from typer.testing import CliRunner + +from docs_src.exceptions import tutorial005 as mod + +runner = CliRunner() + + +def test_traceback_rich_pretty_width(): + file_path = Path(mod.__file__) + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", str(file_path)], + capture_output=True, + encoding="utf-8", + env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, + ) + print(result.stderr) + + assert "print(name + 3)" in result.stderr + assert 'TypeError: can only concatenate str (not "int") to str' in result.stderr + assert "name = 'morty'" in result.stderr + + +def test_script(): + result = subprocess.run( + [sys.executable, "-m", "coverage", "run", mod.__file__, "--help"], + capture_output=True, + encoding="utf-8", + ) + assert "Usage" in result.stdout From b9d9fc040e01abe5bd5ccb73d78ccc695f6e79b2 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:23:31 +0200 Subject: [PATCH 08/17] fix coverage and unused var warnings --- docs_src/exceptions/tutorial005.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs_src/exceptions/tutorial005.py b/docs_src/exceptions/tutorial005.py index 702569a254..759791c937 100644 --- a/docs_src/exceptions/tutorial005.py +++ b/docs_src/exceptions/tutorial005.py @@ -32,8 +32,7 @@ def main(name: str = "morty"): } } } - print(name + 3) - print(deep_dict_or_json) + print(name + deep_dict_or_json + 3) if __name__ == "__main__": From ea2d47586df5e565c91ad418aed7c757a2e7e68a Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 18 Apr 2024 11:26:12 +0200 Subject: [PATCH 09/17] fix test --- tests/test_tutorial/test_exceptions/test_tutorial005.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tutorial/test_exceptions/test_tutorial005.py b/tests/test_tutorial/test_exceptions/test_tutorial005.py index 99a2147dcc..203e52d37b 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial005.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial005.py @@ -20,8 +20,8 @@ def test_traceback_rich_pretty_width(): ) print(result.stderr) - assert "print(name + 3)" in result.stderr - assert 'TypeError: can only concatenate str (not "int") to str' in result.stderr + assert "print(name + deep_dict_or_json + 3)" in result.stderr + assert 'TypeError: can only concatenate str (not "dict") to str' in result.stderr assert "name = 'morty'" in result.stderr From f037896779f5dd2c09061696bdf13e704002f685 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 9 Aug 2024 11:56:15 +0200 Subject: [PATCH 10/17] add PYTHONIOENCODING to env settings --- tests/test_tutorial/test_exceptions/test_tutorial005.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tutorial/test_exceptions/test_tutorial005.py b/tests/test_tutorial/test_exceptions/test_tutorial005.py index 203e52d37b..bab19eb8d3 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial005.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial005.py @@ -16,7 +16,7 @@ def test_traceback_rich_pretty_width(): [sys.executable, "-m", "coverage", "run", str(file_path)], capture_output=True, encoding="utf-8", - env={**os.environ, "_TYPER_STANDARD_TRACEBACK": ""}, + env={**os.environ, "_TYPER_STANDARD_TRACEBACK": "", "PYTHONIOENCODING": "utf-8"}, ) print(result.stderr) From 96c0b5e530e0fec12f5b44c19de75c6ca5ab33e3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:56:23 +0000 Subject: [PATCH 11/17] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_tutorial/test_exceptions/test_tutorial005.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_tutorial/test_exceptions/test_tutorial005.py b/tests/test_tutorial/test_exceptions/test_tutorial005.py index bab19eb8d3..f3c12f72a6 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial005.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial005.py @@ -16,7 +16,11 @@ def test_traceback_rich_pretty_width(): [sys.executable, "-m", "coverage", "run", str(file_path)], capture_output=True, encoding="utf-8", - env={**os.environ, "_TYPER_STANDARD_TRACEBACK": "", "PYTHONIOENCODING": "utf-8"}, + env={ + **os.environ, + "_TYPER_STANDARD_TRACEBACK": "", + "PYTHONIOENCODING": "utf-8", + }, ) print(result.stderr) From fc4f3a68a40810993017fd536e3dc2097e1646b9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:13:58 +0000 Subject: [PATCH 12/17] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- typer/main.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/typer/main.py b/typer/main.py index aa00ad8e93..7ce36b4546 100644 --- a/typer/main.py +++ b/typer/main.py @@ -78,8 +78,6 @@ def except_hook( supress_internal_dir_names = [typer_path, click_path] exc = exc_value if rich: - from .rich_utils import MAX_WIDTH - rich_tb = Traceback.from_exception( type(exc), exc, From 7b0679b9198bf670e2969af6a128ddcfd4cf2636 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 27 Aug 2024 14:20:21 +0200 Subject: [PATCH 13/17] use MAX_WIDTH as default for Typer init --- docs/tutorial/exceptions.md | 3 ++- typer/main.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/exceptions.md b/docs/tutorial/exceptions.md index fe555a6902..2823717fbc 100644 --- a/docs/tutorial/exceptions.md +++ b/docs/tutorial/exceptions.md @@ -205,7 +205,8 @@ $ python main.py ## Set Output Width -If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to a specific integer (it's 100 by default): +If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to a specific integer +(by default it's the maximum console width if it can be determined, or otherwise 100): ```Python hl_lines="3" {!../docs_src/exceptions/tutorial005.py!} diff --git a/typer/main.py b/typer/main.py index 7ce36b4546..42ba6332b7 100644 --- a/typer/main.py +++ b/typer/main.py @@ -50,10 +50,13 @@ from . import rich_utils + DEFAULT_WIDTH = rich_utils.MAX_WIDTH or 100 + console_stderr = rich_utils._get_rich_console(stderr=True) except ImportError: # pragma: no cover rich = None # type: ignore + DEFAULT_WIDTH = 100 _original_except_hook = sys.excepthook _typer_developer_exception_attr_name = "__typer_developer_exception__" @@ -147,7 +150,7 @@ def __init__( pretty_exceptions_enable: bool = True, pretty_exceptions_show_locals: bool = True, pretty_exceptions_short: bool = True, - pretty_exceptions_width: int = 100, + pretty_exceptions_width: int = DEFAULT_WIDTH, ): self._add_completion = add_completion self.rich_markup_mode: MarkupMode = rich_markup_mode From 5914d786843066e6aba183bf1db160d54af51079 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:20:30 +0000 Subject: [PATCH 14/17] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tutorial/exceptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/exceptions.md b/docs/tutorial/exceptions.md index 2823717fbc..654e0dfb57 100644 --- a/docs/tutorial/exceptions.md +++ b/docs/tutorial/exceptions.md @@ -205,7 +205,7 @@ $ python main.py ## Set Output Width -If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to a specific integer +If you want to control the width of the yellow and red Rich exception borders, you can set the parameter `pretty_exceptions_width` to a specific integer (by default it's the maximum console width if it can be determined, or otherwise 100): ```Python hl_lines="3" From e1eec6d356dc019c30e0dc5c832cccd85b59762c Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 27 Aug 2024 14:38:24 +0200 Subject: [PATCH 15/17] fix --- typer/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typer/main.py b/typer/main.py index 42ba6332b7..2047998d34 100644 --- a/typer/main.py +++ b/typer/main.py @@ -50,7 +50,7 @@ from . import rich_utils - DEFAULT_WIDTH = rich_utils.MAX_WIDTH or 100 + DEFAULT_WIDTH = rich_utils.MAX_WIDTH console_stderr = rich_utils._get_rich_console(stderr=True) From 887282210c6825fa6eb686c6a1f6d4fc69bf5fef Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 27 Aug 2024 14:47:30 +0200 Subject: [PATCH 16/17] allow None as width --- typer/main.py | 2 +- typer/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/typer/main.py b/typer/main.py index 2047998d34..11737f7c9e 100644 --- a/typer/main.py +++ b/typer/main.py @@ -150,7 +150,7 @@ def __init__( pretty_exceptions_enable: bool = True, pretty_exceptions_show_locals: bool = True, pretty_exceptions_short: bool = True, - pretty_exceptions_width: int = DEFAULT_WIDTH, + pretty_exceptions_width: Union[int, None] = DEFAULT_WIDTH, ): self._add_completion = add_completion self.rich_markup_mode: MarkupMode = rich_markup_mode diff --git a/typer/models.py b/typer/models.py index bfd03e7bf7..7d4f9e110e 100644 --- a/typer/models.py +++ b/typer/models.py @@ -513,7 +513,7 @@ def __init__( pretty_exceptions_enable: bool = True, pretty_exceptions_show_locals: bool = True, pretty_exceptions_short: bool = True, - pretty_exceptions_width: int = 100, + pretty_exceptions_width: Union[int, None] = 100, ) -> None: self.pretty_exceptions_enable = pretty_exceptions_enable self.pretty_exceptions_show_locals = pretty_exceptions_show_locals From be5183983e6e37b3b08f8f9c96914457fd8c8482 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Tue, 27 Aug 2024 14:54:35 +0200 Subject: [PATCH 17/17] remove print statement --- tests/test_tutorial/test_exceptions/test_tutorial005.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_tutorial/test_exceptions/test_tutorial005.py b/tests/test_tutorial/test_exceptions/test_tutorial005.py index f3c12f72a6..0e700e491d 100644 --- a/tests/test_tutorial/test_exceptions/test_tutorial005.py +++ b/tests/test_tutorial/test_exceptions/test_tutorial005.py @@ -22,7 +22,6 @@ def test_traceback_rich_pretty_width(): "PYTHONIOENCODING": "utf-8", }, ) - print(result.stderr) assert "print(name + deep_dict_or_json + 3)" in result.stderr assert 'TypeError: can only concatenate str (not "dict") to str' in result.stderr