Module textual.devtools.renderables
Expand source code
from __future__ import annotations
import sys
from datetime import datetime
from pathlib import Path
from typing import Iterable
from importlib_metadata import version
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal
from rich.align import Align
from rich.console import Console, ConsoleOptions, RenderResult
from rich.markup import escape
from rich.rule import Rule
from rich.segment import Segment, Segments
from rich.style import Style
from rich.styled import Styled
from rich.table import Table
from rich.text import Text
from textual._log import LogGroup
DevConsoleMessageLevel = Literal["info", "warning", "error"]
class DevConsoleHeader:
def __init__(self, verbose: bool = False) -> None:
self.verbose = verbose
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
preamble = Text.from_markup(
f"[bold]Textual Development Console [magenta]v{version('textual')}\n"
"[magenta]Run a Textual app with [reverse]textual run --dev my_app.py[/] to connect.\n"
"[magenta]Press [reverse]Ctrl+C[/] to quit."
)
if self.verbose:
preamble.append(Text.from_markup("\n[cyan]Verbose logs enabled"))
render_options = options.update(width=options.max_width - 4)
lines = console.render_lines(preamble, render_options)
new_line = Segment.line()
padding = Segment("▌", Style.parse("bright_magenta"))
for line in lines:
yield padding
yield from line
yield new_line
class DevConsoleLog:
"""Renderable representing a single log message
Args:
segments (Iterable[Segment]): The segments to display
path (str): The path of the file on the client that the log call was made from
line_number (int): The line number of the file on the client the log call was made from
unix_timestamp (int): Seconds since January 1st 1970
"""
def __init__(
self,
segments: Iterable[Segment],
path: str,
line_number: int,
unix_timestamp: int,
group: int,
verbosity: int,
severity: int,
) -> None:
self.segments = segments
self.path = path
self.line_number = line_number
self.unix_timestamp = unix_timestamp
self.group = group
self.verbosity = verbosity
self.severity = severity
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
local_time = datetime.fromtimestamp(self.unix_timestamp)
table = Table.grid(expand=True)
file_link = escape(f"file://{Path(self.path).absolute()}")
file_and_line = escape(f"{Path(self.path).name}:{self.line_number}")
group = LogGroup(self.group).name
time = local_time.time()
group_text = Text(group)
if group == "WARNING":
group_text.stylize("bold yellow reverse")
elif group == "ERROR":
group_text.stylize("bold red reverse")
else:
group_text.stylize("dim")
log_message = Text.assemble((f"[{time}]", "dim"), " ", group_text)
table.add_row(
log_message,
Align.right(
Text(f"{file_and_line}", style=Style(dim=True, link=file_link))
),
)
yield table
if group == "PRINT":
yield Styled(Segments(self.segments), "bold")
else:
yield from self.segments
class DevConsoleNotice:
"""Renderable for messages written by the devtools console itself
Args:
message (str): The message to display
level (DevtoolsMessageLevel): The message level ("info", "warning", or "error").
Determines colors used to render the message and the perceived importance.
"""
def __init__(self, message: str, *, level: DevConsoleMessageLevel = "info") -> None:
self.message = message
self.level = level
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
level_to_style = {
"info": "dim",
"warning": "yellow",
"error": "red",
}
yield Rule(self.message, style=level_to_style.get(self.level, "dim"))
Classes
class DevConsoleHeader (verbose: bool = False)
-
Expand source code
class DevConsoleHeader: def __init__(self, verbose: bool = False) -> None: self.verbose = verbose def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: preamble = Text.from_markup( f"[bold]Textual Development Console [magenta]v{version('textual')}\n" "[magenta]Run a Textual app with [reverse]textual run --dev my_app.py[/] to connect.\n" "[magenta]Press [reverse]Ctrl+C[/] to quit." ) if self.verbose: preamble.append(Text.from_markup("\n[cyan]Verbose logs enabled")) render_options = options.update(width=options.max_width - 4) lines = console.render_lines(preamble, render_options) new_line = Segment.line() padding = Segment("▌", Style.parse("bright_magenta")) for line in lines: yield padding yield from line yield new_line
class DevConsoleLog (segments: Iterable[Segment], path: str, line_number: int, unix_timestamp: int, group: int, verbosity: int, severity: int)
-
Renderable representing a single log message
Args
segments
:Iterable[Segment]
- The segments to display
path
:str
- The path of the file on the client that the log call was made from
line_number
:int
- The line number of the file on the client the log call was made from
unix_timestamp
:int
- Seconds since January 1st 1970
Expand source code
class DevConsoleLog: """Renderable representing a single log message Args: segments (Iterable[Segment]): The segments to display path (str): The path of the file on the client that the log call was made from line_number (int): The line number of the file on the client the log call was made from unix_timestamp (int): Seconds since January 1st 1970 """ def __init__( self, segments: Iterable[Segment], path: str, line_number: int, unix_timestamp: int, group: int, verbosity: int, severity: int, ) -> None: self.segments = segments self.path = path self.line_number = line_number self.unix_timestamp = unix_timestamp self.group = group self.verbosity = verbosity self.severity = severity def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: local_time = datetime.fromtimestamp(self.unix_timestamp) table = Table.grid(expand=True) file_link = escape(f"file://{Path(self.path).absolute()}") file_and_line = escape(f"{Path(self.path).name}:{self.line_number}") group = LogGroup(self.group).name time = local_time.time() group_text = Text(group) if group == "WARNING": group_text.stylize("bold yellow reverse") elif group == "ERROR": group_text.stylize("bold red reverse") else: group_text.stylize("dim") log_message = Text.assemble((f"[{time}]", "dim"), " ", group_text) table.add_row( log_message, Align.right( Text(f"{file_and_line}", style=Style(dim=True, link=file_link)) ), ) yield table if group == "PRINT": yield Styled(Segments(self.segments), "bold") else: yield from self.segments
class DevConsoleNotice (message: str, *, level: DevConsoleMessageLevel = 'info')
-
Renderable for messages written by the devtools console itself
Args
message
:str
- The message to display
level
:DevtoolsMessageLevel
- The message level ("info", "warning", or "error"). Determines colors used to render the message and the perceived importance.
Expand source code
class DevConsoleNotice: """Renderable for messages written by the devtools console itself Args: message (str): The message to display level (DevtoolsMessageLevel): The message level ("info", "warning", or "error"). Determines colors used to render the message and the perceived importance. """ def __init__(self, message: str, *, level: DevConsoleMessageLevel = "info") -> None: self.message = message self.level = level def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: level_to_style = { "info": "dim", "warning": "yellow", "error": "red", } yield Rule(self.message, style=level_to_style.get(self.level, "dim"))