Skip to content

Commit

Permalink
readme and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Feb 22, 2020
1 parent 2dd136b commit e33afdd
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 15 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ from rich import print
print("Hello, [bold magenta]World[/bold magenta]!", ":vampire:", locals())
```

![Hello World](./imgs/print.png)

## Console Printing

For more control over rich terminal content, import and construct a `Console` object.
Expand All @@ -32,15 +34,13 @@ from rich.console import Console
console = Console()
```

Most applications will require one `Console` instance. The easiest way to manage your console would be to construct an instance at the module level and import it where needed.

The Console object has a `print` method which has an intentionally similar interface to the builtin `print` function. Here's an example of use:

```python
console.print("Hello", "World!")
```

As you might expect, this will print `"Hello World!"` to the terminal. Note that unlike the `print` function, Rich will word-wrap your text to fit within the terminal width.
As you might expect, this will print `"Hello World!"` to the terminal. Note that unlike the builtin `print` function, Rich will word-wrap your text to fit within the terminal width.

There are a few ways of adding color and style to your output. You can set a style for the entire output by adding a `style` keyword argument. Here's an example:

Expand Down Expand Up @@ -201,3 +201,11 @@ Note that console markup is rendered in the same was as `print()` and `log()`. I
The `Table` class is smart enough to resize columns to fit the available width of the terminal, wrapping text as required. Here's the same example, with the terminal made smaller than the table above:

![table2](./imgs/table2.png)

## Tracebacks

Rich can render beautiful tracebacks which are easier to read and show more code than standard Python tracebacks.

![traceback](./imgs/traceback.png)

![traceback_windows](./imgs/traceback_windows.png)
224 changes: 224 additions & 0 deletions color.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Welcome to Rich's documentation!
markdown.rst
syntax.rst
text.rst
traceback
protocol.rst

reference.rst
Expand Down
1 change: 1 addition & 0 deletions docs/source/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ Reference
reference/syntax.rst
reference/table.rst
reference/text.rst
reference/traceback.rst
6 changes: 6 additions & 0 deletions docs/source/reference/traceback.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rich.traceback
==============

.. automodule:: rich.traceback
:members: Traceback, install

24 changes: 24 additions & 0 deletions docs/source/traceback.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Traceback
=========

Rich can render Python tracebacks with syntax highlighting and formatting. Rich tracebacks are easier to read, and show more code, than standard Python tracebacks.


Printing tracebacks
-------------------

The :meth:`~rich.console.Console.print_exception` method will print a traceback for the current exception being handled.

try:
do_something()
except:
console.print_exception()


Traceback handler
-----------------

Rich can be installed as the default traceback handler so that all uncaught exceptions will be rendered with highlighting. Here's how::

from rich.traceback import install
install()
Binary file added imgs/print.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/traceback.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/traceback_windows.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 28 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ pprintpp = "^0.4.0"
typing-extensions = "^3.7.4"
dataclasses = {version="^0.7", python = "~3.6"}
colorama = "^0.4.3"
pygments = "^2.5.0"
commonmark = "^0.9.0"


[tool.poetry.dev-dependencies]

Expand Down
10 changes: 7 additions & 3 deletions rich/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,17 +744,21 @@ def print(
extend(render(renderable, render_options))

def print_exception(
self, code_width: Optional[int] = 88, extra_lines: int = 2
self,
width: Optional[int] = 88,
extra_lines: int = 3,
theme: Optional[str] = None,
) -> None:
"""Prints a rich render of the last exception and traceback.
Args:
code_width (Optional[int], optional): Number of characters used to render code. Defaults to 88.
extra_lines (int, optional): Additional lines of code to render. Defaults to 2.
extra_lines (int, optional): Additional lines of code to render. Defaults to 3.
theme (str, optional): Override pygments theme used in traceback
"""
from .traceback import Traceback

traceback = Traceback(code_width=code_width, extra_lines=extra_lines)
traceback = Traceback(width=width, extra_lines=extra_lines, theme=theme)
self.print(traceback)

def log(
Expand Down
50 changes: 42 additions & 8 deletions rich/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,20 @@
WINDOWS = platform.system() == "Windows"


def install(width: Optional[int] = 100, extra_lines: int = 2) -> None:
def install(
width: Optional[int] = 100, extra_lines: int = 3, theme: Optional[str] = None
) -> None:
"""Install a rich traceback handler.
Once installed, any tracebacks will be printed with syntax highlighting and rich formatting.
Args:
width (Optional[int], optional): Width (in characters) of traceback. Defaults to 100.
extra_lines (int, optional): Extra lines of code. Defaults to 2.
extra_lines (int, optional): Extra lines of code. Defaults to 3.
theme (str, optional) Pygments theme to use in traceback. Defaults to ``None`` which will pick
a theme appropriate for the platform.
"""
console = Console(file=sys.stderr)

Expand All @@ -46,7 +51,12 @@ def excepthook(
) -> None:
console.print(
Traceback.from_exception(
type_, value, traceback, width=width, extra_lines=extra_lines
type_,
value,
traceback,
width=width,
extra_lines=extra_lines,
theme=theme,
)
)

Expand Down Expand Up @@ -89,7 +99,11 @@ class PathHighlighter(RegexHighlighter):

class Traceback:
def __init__(
self, trace: Trace = None, width: Optional[int] = 88, extra_lines: int = 3,
self,
trace: Trace = None,
width: Optional[int] = 88,
extra_lines: int = 3,
theme: Optional[str] = None,
):
"""A Console renderable that renders a traceback.
Expand All @@ -98,12 +112,19 @@ def __init__(
the last exception.
width (Optional[int], optional): Number of characters used to traceback. Defaults to 100.
extra_lines (int, optional): Additional lines of code to render. Defaults to 3.
theme (str, optional): Override pygments theme used in traceback.
"""
if trace is None:
trace = self.extract(*sys.exc_info())
exc_type, exc_value, traceback = sys.exc_info()
if exc_type is None or exc_value is None or traceback is None:
raise ValueError(
"Value for 'trace' required if not called in except: block"
)
trace = self.extract(exc_type, exc_value, traceback)
self.trace = trace
self.width = width
self.extra_lines = extra_lines
self.theme = theme

@classmethod
def from_exception(
Expand All @@ -112,10 +133,13 @@ def from_exception(
exc_value: BaseException,
traceback: TracebackType,
width: Optional[int] = 100,
extra_lines: int = 2,
extra_lines: int = 3,
theme: Optional[str] = None,
):
rich_traceback = cls.extract(exc_type, exc_value, traceback)
return Traceback(rich_traceback, width=width, extra_lines=extra_lines)
return Traceback(
rich_traceback, width=width, extra_lines=extra_lines, theme=theme
)

@classmethod
def extract(
Expand All @@ -124,6 +148,16 @@ def extract(
exc_value: BaseException,
traceback: TracebackType,
) -> Trace:
"""Extrace traceback information.
Args:
exc_type (Type[BaseException]): Exception type.
exc_value (BaseException): Exception value.
traceback (TracebackType): Python Traceback object.
Returns:
Trace: A Trace instance which you can use to construct a `Traceback`.
"""
stacks: List[Stack] = []
while True:
stack = Stack(exc_type=str(exc_type.__name__), exc_value=str(exc_value))
Expand Down Expand Up @@ -210,7 +244,7 @@ def _render_syntax_error(self, syntax_error: _SyntaxError) -> RenderResult:
@render_group()
def _render_stack(self, stack: Stack) -> RenderResult:
path_highlighter = PathHighlighter()
theme = "fruity" if WINDOWS else "monokai"
theme = self.theme or ("fruity" if WINDOWS else "monokai")
for frame in stack.frames:
text = Text.assemble(
(" File ", "traceback.text"),
Expand Down

0 comments on commit e33afdd

Please sign in to comment.