Skip to content

Commit

Permalink
themed tracebacks
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Oct 3, 2020
1 parent 2634553 commit ebb4eaa
Show file tree
Hide file tree
Showing 15 changed files with 193 additions and 107 deletions.
2 changes: 1 addition & 1 deletion docs/source/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ If you intend to use Rich with Jupyter then there are some additional dependenci
Quick Start
-----------

The quickest way to get up and running with Rich is to import the alternative ``print`` function which may be used as a drop-in replacement for Python's built in function. Here's how you would do that::
The quickest way to get up and running with Rich is to import the alternative ``print`` function which takes the same arguments as the built-in ``print`` and may be used as a drop-in replacement. Here's how you would do that::

from rich import print

Expand Down
22 changes: 14 additions & 8 deletions rich/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,9 @@ def end_capture(self) -> str:
self._exit_buffer()
return render_result

def push_theme(self, theme: Theme, inherit: bool = True) -> None:
"""Push a new theme on to the top of the stack, overwriting the styles from the previous theme.
Generally speaking, you call :meth:`~rich.console.Console.theme` to get a context manager, rather
def push_theme(self, theme: Theme, *, inherit: bool = True) -> None:
"""Push a new theme on to the top of the stack, replacing the styles from the previous theme.
Generally speaking, you should call :meth:`~rich.console.Console.use_theme` to get a context manager, rather
than calling this method directly.
Args:
Expand All @@ -529,12 +529,12 @@ def pop_theme(self) -> None:
"""Remove theme from top of stack, restoring previous theme."""
self._theme_stack.pop_theme()

def theme(self, theme: Theme, inherit: bool = True) -> ThemeContext:
"""Use a new temporary theme for the duration of the context manager.
def use_theme(self, theme: Theme, *, inherit: bool = True) -> ThemeContext:
"""Use a different theme for the duration of the context manager.
Args:
theme (Theme): Theme instance to user.
inherit (bool, optional): Inherit existing styles. Defaults to True.
inherit (bool, optional): Inherit existing console styles. Defaults to True.
Returns:
ThemeContext: [description]
Expand Down Expand Up @@ -1023,10 +1023,11 @@ def print(
def print_exception(
self,
*,
width: Optional[int] = 88,
width: Optional[int] = 100,
extra_lines: int = 3,
theme: Optional[str] = None,
word_wrap: bool = False,
show_locals: bool = False,
) -> None:
"""Prints a rich render of the last exception and traceback.
Expand All @@ -1035,11 +1036,16 @@ def print_exception(
extra_lines (int, optional): Additional lines of code to render. Defaults to 3.
theme (str, optional): Override pygments theme used in traceback
word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False.
show_locals (bool, optional): Enable display of local variables. Defaults to False.
"""
from .traceback import Traceback

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

Expand Down
19 changes: 10 additions & 9 deletions rich/default_styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .style import Style

DEFAULT_STYLES: Dict[str, Style] = {
"none": Style(),
"none": Style.null(),
"reset": Style(
color="default",
bgcolor="default",
Expand Down Expand Up @@ -51,9 +51,9 @@
"logging.level.warning": Style(color="red"),
"logging.level.error": Style(color="red", bold=True),
"logging.level.critical": Style(color="red", bold=True, reverse=True),
"log.level": Style(),
"log.level": Style.null(),
"log.time": Style(color="cyan", dim=True),
"log.message": Style(),
"log.message": Style.null(),
"log.path": Style(dim=True),
"repr.error": Style(color="red", bold=True),
"repr.str": Style(color="green", italic=False, bold=False),
Expand All @@ -75,12 +75,13 @@
"repr.url": Style(underline=True, color="bright_blue", italic=False, bold=False),
"repr.uuid": Style(color="bright_yellow", bold=False),
"rule.line": Style(color="bright_green"),
"rule.text": Style(),
"prompt": Style(),
"rule.text": Style.null(),
"prompt": Style.null(),
"prompt.choices": Style(color="magenta", bold=True),
"prompt.default": Style(color="cyan", bold=True),
"prompt.invalid": Style(color="red"),
"prompt.invalid.choice": Style(color="red"),
"pretty": Style.null(),
"scope.border": Style(color="blue"),
"scope.key": Style(color="yellow", italic=True),
"scope.key.special": Style(color="yellow", italic=True, dim=True),
Expand All @@ -89,21 +90,21 @@
"repr.filename": Style(color="bright_magenta"),
"table.header": Style(bold=True),
"table.footer": Style(bold=True),
"table.cell": Style(),
"table.cell": Style.null(),
"table.title": Style(italic=True),
"table.caption": Style(italic=True, dim=True),
"traceback.border.syntax_error": Style(color="bright_red"),
"traceback.border": Style(color="red"),
"traceback.text": Style(),
"traceback.text": Style.null(),
"traceback.title": Style(color="red", bold=True),
"traceback.exc_type": Style(color="bright_red", bold=True),
"traceback.exc_value": Style(),
"traceback.exc_value": Style.null(),
"traceback.offset": Style(color="bright_red", bold=True),
"bar.back": Style(color="grey23"),
"bar.complete": Style(color="rgb(249,38,114)"),
"bar.finished": Style(color="rgb(114,156,31)"),
"bar.pulse": Style(color="rgb(249,38,114)"),
"progress.description": Style(),
"progress.description": Style.null(),
"progress.filesize": Style(color="green"),
"progress.filesize.total": Style(color="green"),
"progress.download": Style(color="green"),
Expand Down
4 changes: 2 additions & 2 deletions rich/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class RichHandler(Handler):
highlighter (Highlighter, optional): Highlighter to style log messages, or None to use ReprHighlighter. Defaults to None.
markup (bool, optional): Enable console markup in log messages. Defaults to False.
rich_tracebacks (bool, optional): Enable rich tracebacks with syntax highlighting and formatting. Defaults to False.
tracebacks_width (Optional[int], optional): Number of characters used to render tracebacks code. Defaults to 88.
tracebacks_width (Optional[int], optional): Number of characters used to render tracebacks, or None for full width. Defaults to None.
tracebacks_extra_lines (int, optional): Additional lines of code to render tracebacks, or None for full width. Defaults to None.
tracebacks_theme (str, optional): Override pygments theme used in traceback.
tracebacks_word_wrap (bool, optional): Enable word wrapping of long tracebacks lines. Defaults to False.
Expand Down Expand Up @@ -62,7 +62,7 @@ def __init__(
highlighter: Highlighter = None,
markup: bool = False,
rich_tracebacks: bool = False,
tracebacks_width: Optional[int] = 88,
tracebacks_width: Optional[int] = None,
tracebacks_extra_lines: int = 3,
tracebacks_theme: Optional[str] = None,
tracebacks_word_wrap: bool = True,
Expand Down
17 changes: 8 additions & 9 deletions rich/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,14 @@ def __rich_console__(

def __rich_measure__(self, console: "Console", max_width: int) -> "Measurement":
_title = self._title
if _title is None:
width = Measurement.get(console, self.renderable, max_width - 2).maximum + 2
else:
width = (
measure_renderables(
console, [self.renderable, _title], max_width
).maximum
+ 4
)
_, right, _, left = Padding.unpack(self.padding)
padding = left + right
renderables = [self.renderable, _title] if _title else [self.renderable]
width = (
measure_renderables(console, renderables, max_width - padding - 2).maximum
+ padding
+ 2
)
return Measurement(width, width)


Expand Down
1 change: 1 addition & 0 deletions rich/pretty.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ def __rich_console__(
justify=self.justify or options.justify,
overflow=self.overflow or options.overflow,
no_wrap=pick_bool(self.no_wrap, options.no_wrap),
style="pretty",
)
pretty_text = self.highlighter(pretty_text)
yield pretty_text
Expand Down
2 changes: 1 addition & 1 deletion rich/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ def process_renderables(

syntax = Syntax(
'''def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]:
"""Iterate and generate a tup`le with a flag for last value."""
"""Iterate and generate a tuple with a flag for last value."""
iter_values = iter(values)
try:
previous_value = next(iter_values)
Expand Down
39 changes: 22 additions & 17 deletions rich/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,6 @@ def _make_color(color: Union[Color, str]) -> Color:

self._color = None if color is None else _make_color(color)
self._bgcolor = None if bgcolor is None else _make_color(bgcolor)
self._attributes = sum(
(
bold and 1 or 0,
dim and 2 or 0,
italic and 4 or 0,
underline and 8 or 0,
blink and 16 or 0,
blink2 and 32 or 0,
reverse and 64 or 0,
conceal and 128 or 0,
strike and 256 or 0,
underline2 and 512 or 0,
frame and 1024 or 0,
encircle and 2048 or 0,
overline and 4096 or 0,
)
)
self._set_attributes = sum(
(
bold is not None,
Expand All @@ -152,6 +135,28 @@ def _make_color(color: Union[Color, str]) -> Color:
overline is not None and 4096,
)
)
self._attributes = (
sum(
(
bold and 1 or 0,
dim and 2 or 0,
italic and 4 or 0,
underline and 8 or 0,
blink and 16 or 0,
blink2 and 32 or 0,
reverse and 64 or 0,
conceal and 128 or 0,
strike and 256 or 0,
underline2 and 512 or 0,
frame and 1024 or 0,
encircle and 2048 or 0,
overline and 4096 or 0,
)
)
if self._set_attributes
else 0
)

self._link = link
self._link_id = f"{time()}-{randint(0, 999999)}" if link else ""
self._hash = hash(
Expand Down
9 changes: 4 additions & 5 deletions rich/syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ class SyntaxTheme(ABC):
@abstractmethod
def get_style_for_token(self, token_type: TokenType) -> Style:
"""Get a style for a given Pygments token."""
raise NotImplementedError
raise NotImplementedError # pragma: no cover

@abstractmethod
def get_background_style(self) -> Style:
"""Get the background color."""
raise NotImplementedError
raise NotImplementedError # pragma: no cover


class PygmentsSyntaxTheme(SyntaxTheme):
Expand Down Expand Up @@ -302,8 +302,7 @@ def from_path(

if lexer is None:
try:
lexer = guess_lexer_for_filename(path, code)
lexer_name = lexer.name
lexer_name = guess_lexer_for_filename(path, code).name
except ClassNotFound:
pass

Expand Down Expand Up @@ -494,7 +493,7 @@ def __rich_console__(
if first:
line_column = str(line_no).rjust(numbers_column_width - 2) + " "
if highlight_line(line_no):
yield _Segment(line_pointer, number_style)
yield _Segment(line_pointer, Style(color="red"))
yield _Segment(line_column, highlight_number_style)
else:
yield _Segment(" ", highlight_number_style)
Expand Down
14 changes: 9 additions & 5 deletions rich/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,19 +241,23 @@ def __rich_measure__(self, console: "Console", max_width: int) -> Measurement:
if self.width is not None:
max_width = self.width

if self.box:
max_width -= len(self.columns) - 1
if self.show_edge:
max_width -= 2
# if self.box:
# max_width -= len(self.columns) - 1
# if self.show_edge:
# max_width -= 2

if max_width < 0:
return Measurement(0, 0)

extra_width = self._extra_width

max_width = sum(self._calculate_column_widths(console, max_width))

_measure_column = self._measure_column

measurements = [
_measure_column(console, column, max_width) for column in self.columns
_measure_column(console, column, max_width - extra_width)
for column in self.columns
]
minimum_width = (
sum(measurement.minimum for measurement in measurements) + extra_width
Expand Down
7 changes: 3 additions & 4 deletions rich/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,9 @@ def push_theme(self, theme: Theme, inherit: bool = True) -> None:
inherit (boolean, optional): Inherit styles from current top of stack.
"""
styles: Dict[str, Style]
if inherit:
styles = {**self._entries[-1], **theme.styles}
else:
styles = theme.styles.copy()
styles = (
{**self._entries[-1], **theme.styles} if inherit else theme.styles.copy()
)
self._entries.append(styles)
self.get = self._entries[-1].get

Expand Down
Loading

0 comments on commit ebb4eaa

Please sign in to comment.