File: rich_formatted_exceptions.rst

package info (click to toggle)
python-cyclopts 3.12.0-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,288 kB
  • sloc: python: 11,445; makefile: 24
file content (104 lines) | stat: -rw-r--r-- 4,831 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
=========================
Rich Formatted Exceptions
=========================
Tracebacks of uncaught exceptions provide valuable feedback for debugging. This guide demonstrates how to enhance your error messages using rich formatting.

-------------------------
Standard Python Traceback
-------------------------
Consider the following example:

.. code-block:: python

    from cyclopts import App

    app = App()

    @app.default
    def main(name: str):
        print(name + 3)

    if __name__ == "__main__":
        app()

Running this script will produce a standard Python traceback:

.. code-block:: console

   $ python my-script.py foo
   Traceback (most recent call last):
     File "/cyclopts/my-script.py", line 12, in <module>
       app()
     File "/cyclopts/cyclopts/core.py", line 903, in __call__
       return command(*bound.args, **bound.kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     File "/cyclopts/my-script.py", line 8, in main
       print(name + 3)
             ~~~~~^~~
   TypeError: can only concatenate str (not "int") to str

------------------------
Rich Formatted Traceback
------------------------
To create a more visually appealing and informative traceback, you can use the `Rich library's traceback handler`_. Here's how to modify your script:

.. code-block:: python

    import sys
    from cyclopts import App
    from rich.console import Console

    console = Console()
    app = App(console=console)  # Use same Console object for Cyclopts operations.

    @app.default
    def main(name: str):
        print(name + 3)

    if __name__ == "__main__":
        try:
            app()
        except Exception:
            console.print_exception()
            sys.exit(1)

Now, running the updated script will display a rich-formatted traceback:

.. code-block:: console

   $ python my-script.py foo
   ╭──────────────── Traceback (most recent call last) ─────────────────╮
   │ /cyclopts/my-script.py:16 in <module>                              │
   │                                                                    │
   │   13                                                               │
   │   14 if __name__ == "__main__":                                    │
   │   15 │   try:                                                      │
   │ ❱ 16 │   │   app()                                                 │
   │   17 │   except Exception:                                         │
   │   18 │   │   console.print_exception(width=70)                     │
   │   19                                                               │
   │                                                                    │
   │ /cyclopts/cyclopts/core.py:903 in __call__                         │
   │                                                                    │
   │    900 │   │   │   │                                               │
   │    901 │   │   │   │   return asyncio.run(command(*bound.args, **b │
   │    902 │   │   │   else:                                           │
   │ ❱  903 │   │   │   │   return command(*bound.args, **bound.kwargs) │
   │    904 │   │   except Exception as e:                              │
   │    905 │   │   │   try:                                            │
   │    906 │   │   │   │   from pydantic import ValidationError as Pyd │
   │                                                                    │
   │ /cyclopts/my-script.py:11 in main                                  │
   │                                                                    │
   │    8                                                               │
   │    9 @app.default                                                  │
   │   10 def main(name: str):                                          │
   │ ❱ 11 │   print(name + 3)                                           │
   │   12                                                               │
   │   13                                                               │
   │   14 if __name__ == "__main__":                                    │
   ╰────────────────────────────────────────────────────────────────────╯

This rich-formatted traceback provides a more readable and visually appealing representation of the error, but may make copy/pasting for sharing a bit more cumbersome.

.. _Rich library's traceback handler: https://rich.readthedocs.io/en/stable/traceback.html#printing-tracebacks