Merge branch 'main' of github.com:willmcgugan/textual into datatable-clear-cursor

This commit is contained in:
Darren Burns
2023-01-18 15:16:15 +00:00
98 changed files with 1741 additions and 1624 deletions

View File

@@ -31,7 +31,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `COMPONENT_CLASSES` are now inherited from base classes https://github.com/Textualize/textual/issues/1399
- Watch methods may now take no parameters
- Added `compute` parameter to reactive
- A `TypeError` raised during `compose` now carries the full traceback.
- A `TypeError` raised during `compose` now carries the full traceback
- Removed base class `NodeMessage` from which all node-related `Tree` events inherited
### Fixed
@@ -43,6 +44,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fixed `DataTable` cursors not resetting to origin on `clear()` https://github.com/Textualize/textual/pull/1601
- Fixed TextLog wrapping issue https://github.com/Textualize/textual/issues/1554
- Fixed issue with TextLog not writing anything before layout https://github.com/Textualize/textual/issues/1498
- Fixed an exception when populating a child class of `ListView` purely from `compose` https://github.com/Textualize/textual/issues/1588
## [0.9.1] - 2022-12-30

View File

@@ -222,6 +222,7 @@ theme:
- navigation.indexes
- navigation.tabs.sticky
- content.code.annotate
- content.code.copy
palette:
- media: "(prefers-color-scheme: light)"
scheme: default

View File

@@ -1,22 +1,34 @@
from __future__ import annotations
import inspect
from typing import Callable
import rich.repr
from rich.console import RenderableType
__all__ = ["log", "panic"]
from ._context import active_app
from ._log import LogGroup, LogVerbosity
from ._typing import TypeAlias
__all__ = ["log", "panic", "__version__"] # type: ignore
LogCallable: TypeAlias = "Callable"
def __getattr__(name: str) -> str:
"""Lazily get the version from whatever API is available."""
if name == "__version__":
try:
from importlib.metadata import version
except ImportError:
import pkg_resources
return pkg_resources.get_distribution("textual").version
else:
return version("textual")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
class LoggerError(Exception):
"""Raised when the logger failed."""
@@ -70,10 +82,10 @@ class Logger:
"""Get a new logger with selective verbosity.
Args:
verbose (bool): True to use HIGH verbosity, otherwise NORMAL.
verbose: True to use HIGH verbosity, otherwise NORMAL.
Returns:
Logger: New logger.
New logger.
"""
verbosity = LogVerbosity.HIGH if verbose else LogVerbosity.NORMAL
return Logger(self._log, self._group, verbosity)

View File

@@ -46,10 +46,10 @@ class Animation(ABC):
"""Call the animation, return a boolean indicating whether animation is in-progress or complete.
Args:
time (float): The current timestamp
time: The current timestamp
Returns:
bool: True if the animation has finished, otherwise False.
True if the animation has finished, otherwise False.
"""
raise NotImplementedError("")
@@ -135,14 +135,14 @@ class BoundAnimator:
"""Animate an attribute.
Args:
attribute (str): Name of the attribute to animate.
value (float | Animatable): The value to animate to.
final_value (object, optional): The final value of the animation. Defaults to `value` if not set.
duration (float | None, optional): The duration of the animate. Defaults to None.
speed (float | None, optional): The speed of the animation. Defaults to None.
delay (float, optional): A delay (in seconds) before the animation starts. Defaults to 0.0.
easing (EasingFunction | str, optional): An easing method. Defaults to "in_out_cubic".
on_complete (CallbackType | None, optional): A callable to invoke when the animation is finished. Defaults to None.
attribute: Name of the attribute to animate.
value: The value to animate to.
final_value: The final value of the animation. Defaults to `value` if not set.
duration: The duration of the animate. Defaults to None.
speed: The speed of the animation. Defaults to None.
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
easing: An easing method. Defaults to "in_out_cubic".
on_complete: A callable to invoke when the animation is finished. Defaults to None.
"""
start_value = getattr(self._obj, attribute)
@@ -215,15 +215,15 @@ class Animator:
"""Animate an attribute to a new value.
Args:
obj (object): The object containing the attribute.
attribute (str): The name of the attribute.
value (Any): The destination value of the attribute.
final_value (Any, optional): The final value, or ellipsis if it is the same as ``value``. Defaults to Ellipsis/
duration (float | None, optional): The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
speed (float | None, optional): The speed of the animation. Defaults to None.
easing (EasingFunction | str, optional): An easing function. Defaults to DEFAULT_EASING.
delay (float, optional): Number of seconds to delay the start of the animation by. Defaults to 0.
on_complete (CallbackType | None, optional): Callback to run after the animation completes.
obj: The object containing the attribute.
attribute: The name of the attribute.
value: The destination value of the attribute.
final_value: The final value, or ellipsis if it is the same as ``value``. Defaults to Ellipsis/
duration: The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
speed: The speed of the animation. Defaults to None.
easing: An easing function. Defaults to DEFAULT_EASING.
delay: Number of seconds to delay the start of the animation by. Defaults to 0.
on_complete: Callback to run after the animation completes.
"""
animate_callback = partial(
self._animate,
@@ -256,14 +256,14 @@ class Animator:
"""Animate an attribute to a new value.
Args:
obj (object): The object containing the attribute.
attribute (str): The name of the attribute.
value (Any): The destination value of the attribute.
final_value (Any, optional): The final value, or ellipsis if it is the same as ``value``. Defaults to ....
duration (float | None, optional): The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
speed (float | None, optional): The speed of the animation. Defaults to None.
easing (EasingFunction | str, optional): An easing function. Defaults to DEFAULT_EASING.
on_complete (CallbackType | None, optional): Callback to run after the animation completes.
obj: The object containing the attribute.
attribute: The name of the attribute.
value: The destination value of the attribute.
final_value: The final value, or ellipsis if it is the same as ``value``. Defaults to ....
duration: The duration of the animation, or ``None`` to use speed. Defaults to ``None``.
speed: The speed of the animation. Defaults to None.
easing: An easing function. Defaults to DEFAULT_EASING.
on_complete: Callback to run after the animation completes.
"""
if not hasattr(obj, attribute):
raise AttributeError(

View File

@@ -22,12 +22,12 @@ def arrange(
"""Arrange widgets by applying docks and calling layouts
Args:
widget (Widget): The parent (container) widget.
size (Size): The size of the available area.
viewport (Size): The size of the viewport (terminal).
widget: The parent (container) widget.
size: The size of the available area.
viewport: The size of the viewport (terminal).
Returns:
tuple[list[WidgetPlacement], set[Widget], Spacing]: Widget arrangement information.
Widget arrangement information.
"""
arrange_widgets: set[Widget] = set()

View File

@@ -82,13 +82,13 @@ def get_box(
"""Get segments used to render a box.
Args:
name (str): Name of the box type.
inner_style (Style): The inner style (widget background)
outer_style (Style): The outer style (parent background)
style (Style): Widget style
name: Name of the box type.
inner_style: The inner style (widget background)
outer_style: The outer style (parent background)
style: Widget style
Returns:
tuple: A tuple of 3 Segment triplets.
A tuple of 3 Segment triplets.
"""
_Segment = Segment
(
@@ -137,13 +137,13 @@ def render_row(
"""Render a top, or bottom border row.
Args:
box_row (tuple[Segment, Segment, Segment]): Corners and side segments.
width (int): Total width of resulting line.
left (bool): Render left corner.
right (bool): Render right corner.
box_row: Corners and side segments.
width: Total width of resulting line.
left: Render left corner.
right: Render right corner.
Returns:
list[Segment]: A list of segments.
A list of segments.
"""
box1, box2, box3 = box_row
if left and right:

View File

@@ -8,7 +8,7 @@ of subsequent keys.
Note that stdlib's @lru_cache is implemented in C and faster! It's best to use
@lru_cache where you are caching things that are fairly quick and called many times.
Use LRUCache where you want increased flexibility and you are caching slow operations
where the overhead of the cache is a small fraction of the total processing time.
where the overhead of the cache is a small fraction of the total processing time.
"""
@@ -80,7 +80,7 @@ class LRUCache(Generic[CacheKey, CacheValue]):
"""Grow the maximum size to at least `maxsize` elements.
Args:
maxsize (int): New maximum size.
maxsize: New maximum size.
"""
self.maxsize = max(self.maxsize, maxsize)
@@ -99,8 +99,8 @@ class LRUCache(Generic[CacheKey, CacheValue]):
"""Set a value.
Args:
key (CacheKey): Key.
value (CacheValue): Value.
key: Key.
value: Value.
"""
link = self._cache.get(key)
if link is None:
@@ -141,11 +141,11 @@ class LRUCache(Generic[CacheKey, CacheValue]):
"""Get a value from the cache, or return a default if the key is not present.
Args:
key (CacheKey): Key
default (Optional[DefaultValue], optional): Default to return if key is not present. Defaults to None.
key: Key
default: Default to return if key is not present. Defaults to None.
Returns:
Union[CacheValue, Optional[DefaultValue]]: Either the value or a default.
Either the value or a default.
"""
link = self._cache.get(key)
if link is None:
@@ -190,7 +190,7 @@ class FIFOCache(Generic[CacheKey, CacheValue]):
do many lookups.
Args:
maxsize (int): Maximum size of the cache.
maxsize: Maximum size of the cache.
"""
__slots__ = [
@@ -230,8 +230,8 @@ class FIFOCache(Generic[CacheKey, CacheValue]):
"""Set a value.
Args:
key (CacheKey): Key.
value (CacheValue): Value.
key: Key.
value: Value.
"""
if key not in self._cache and len(self._cache) >= self._maxsize:
for first_key in self._cache:
@@ -255,11 +255,11 @@ class FIFOCache(Generic[CacheKey, CacheValue]):
"""Get a value from the cache, or return a default if the key is not present.
Args:
key (CacheKey): Key
default (Optional[DefaultValue], optional): Default to return if key is not present. Defaults to None.
key: Key
default: Default to return if key is not present. Defaults to None.
Returns:
Union[CacheValue, Optional[DefaultValue]]: Either the value or a default.
Either the value or a default.
"""
try:
result = self._cache[key]

View File

@@ -16,10 +16,10 @@ async def invoke(callback: Callable, *params: object) -> Any:
"""Invoke a callback with an arbitrary number of parameters.
Args:
callback (Callable): [description]
callback: The callable to be invoked.
Returns:
Any: [description]
The return value of the invoked callable.
"""
_rich_traceback_guard = True
parameter_count = count_parameters(callback)

View File

@@ -5,7 +5,7 @@ from ._time import time
"""
A module that serves as the single source of truth for everything time-related in a Textual app.
Having this logic centralised makes it easier to simulate time in integration tests,
Having this logic centralised makes it easier to simulate time in integration tests,
by mocking the few functions exposed by this module.
"""
@@ -32,7 +32,7 @@ def get_time_no_wait() -> float:
Get the current wall clock time.
Returns:
float: the value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
The value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
"""
return _clock.get_time_no_wait()
@@ -43,7 +43,7 @@ async def get_time() -> float:
able to "do things" elsewhere right before we fetch the time.
Returns:
float: the value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
The value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
"""
return await _clock.get_time()
@@ -53,6 +53,6 @@ async def sleep(seconds: float) -> None:
Coroutine that completes after a given time (in seconds).
Args:
seconds (float): the duration we should wait for before unblocking the awaiter
seconds: The duration we should wait for before unblocking the awaiter
"""
return await _clock.sleep(seconds)

View File

@@ -99,9 +99,9 @@ class ChopsUpdate:
"""A renderable which updates chops (fragments of lines).
Args:
chops (list[dict[int, list[Segment] | None]]): A mapping of offsets to list of segments, per line.
crop (Region): Region to restrict update to.
chop_ends (list[list[int]]): A list of the end offsets for each line
chops: A mapping of offsets to list of segments, per line.
crop: Region to restrict update to.
chop_ends: A list of the end offsets for each line
"""
self.chops = chops
self.spans = spans
@@ -199,10 +199,10 @@ class Compositor:
or are contiguous to produce optimal non-overlapping spans.
Args:
regions (Iterable[Region]): An iterable of Regions.
regions: An iterable of Regions.
Returns:
Iterable[tuple[int, int, int]]: Yields tuples of (Y, X1, X2)
Yields tuples of (Y, X1, X2).
"""
inline_ranges: dict[int, list[tuple[int, int]]] = {}
setdefault = inline_ranges.setdefault
@@ -237,11 +237,11 @@ class Compositor:
"""Reflow (layout) widget and its children.
Args:
parent (Widget): The root widget.
size (Size): Size of the area to be filled.
parent: The root widget.
size: Size of the area to be filled.
Returns:
ReflowResult: Hidden shown and resized widgets
Hidden shown and resized widgets.
"""
self._cuts = None
self._layers = None
@@ -302,7 +302,7 @@ class Compositor:
"""Get a mapping of widgets on to region and clip.
Returns:
dict[Widget, tuple[Region, Region]]: visible widget mapping.
Visible widget mapping.
"""
if self._visible_widgets is None:
screen = self.size.region
@@ -327,10 +327,10 @@ class Compositor:
"""Arrange a widgets children based on its layout attribute.
Args:
root (Widget): Top level widget.
root: Top level widget.
Returns:
tuple[CompositorMap, set[Widget]]: Compositor map and set of widgets.
Compositor map and set of widgets.
"""
ORIGIN = NULL_OFFSET
@@ -352,10 +352,10 @@ class Compositor:
"""Called recursively to place a widget and its children in the map.
Args:
widget (Widget): The widget to add.
region (Region): The region the widget will occupy.
order (tuple[int, ...]): A tuple of ints to define the order.
clip (Region): The clipping region (i.e. the viewport which contains it).
widget: The widget to add.
region: The region the widget will occupy.
order: A tuple of ints to define the order.
clip: The clipping region (i.e. the viewport which contains it).
"""
visibility = widget.styles.get_rule("visibility")
if visibility is not None:
@@ -525,14 +525,14 @@ class Compositor:
"""Get the widget under a given coordinate.
Args:
x (int): X Coordinate.
y (int): Y Coordinate.
x: X Coordinate.
y: Y Coordinate.
Raises:
errors.NoWidget: If there is not widget underneath (x, y).
Returns:
tuple[Widget, Region]: A tuple of the widget and its region.
A tuple of the widget and its region.
"""
contains = Region.contains
@@ -546,11 +546,11 @@ class Compositor:
"""Get all widgets under a given coordinate.
Args:
x (int): X coordinate.
y (int): Y coordinate.
x: X coordinate.
y: Y coordinate.
Returns:
Iterable[tuple[Widget, Region]]: Sequence of (WIDGET, REGION) tuples.
Sequence of (WIDGET, REGION) tuples.
"""
contains = Region.contains
for widget, cropped_region, region in self.layers_visible[y]:
@@ -561,11 +561,11 @@ class Compositor:
"""Get the Style at the given cell or Style.null()
Args:
x (int): X position within the Layout
y (int): Y position within the Layout
x: X position within the Layout
y: Y position within the Layout
Returns:
Style: The Style at the cell (x, y) within the Layout
The Style at the cell (x, y) within the Layout
"""
try:
widget, region = self.get_widget_at(x, y)
@@ -592,13 +592,13 @@ class Compositor:
"""Get information regarding the relative position of a widget in the Compositor.
Args:
widget (Widget): The Widget in this layout you wish to know the Region of.
widget: The Widget in this layout you wish to know the Region of.
Raises:
NoWidget: If the Widget is not contained in this Layout.
Returns:
MapGeometry: Widget's composition information.
Widget's composition information.
"""
try:
@@ -615,7 +615,7 @@ class Compositor:
A cut is every point on a line where a widget starts or ends.
Returns:
list[list[int]]: A list of cuts for every line.
A list of cuts for every line.
"""
if self._cuts is not None:
return self._cuts
@@ -646,7 +646,7 @@ class Compositor:
"""Get rendered widgets (lists of segments) in the composition.
Returns:
Iterable[tuple[Region, Region, Strips]]: An iterable of <region>, <clip region>, and <strips>
An iterable of <region>, <clip region>, and <strips>
"""
# If a renderable throws an error while rendering, the user likely doesn't care about the traceback
# up to this point.
@@ -696,7 +696,7 @@ class Compositor:
"""Render a layout.
Returns:
SegmentLines: A renderable
A renderable
"""
width, height = self.size
@@ -784,8 +784,8 @@ class Compositor:
"""Update a given widget in the composition.
Args:
console (Console): Console instance.
widget (Widget): Widget to update.
console: Console instance.
widget: Widget to update.
"""
regions: list[Region] = []

View File

@@ -65,7 +65,7 @@ def take_svg_screenshot(
terminal_size: A pair of integers (rows, columns), representing terminal size.
Returns:
str: An SVG string, showing the content of the terminal window at the time
An SVG string, showing the content of the terminal window at the time
the screenshot was taken.
"""

View File

@@ -18,13 +18,13 @@ class DurationParseError(DurationError):
def _duration_as_seconds(duration: str) -> float:
"""
Args:
duration (str): A string of the form ``"2s"`` or ``"300ms"``, representing 2 seconds and
duration: A string of the form ``"2s"`` or ``"300ms"``, representing 2 seconds and
300 milliseconds respectively. If no unit is supplied, e.g. ``"2"``, then the duration is
assumed to be in seconds.
Raises:
DurationParseError: If the argument ``duration`` is not a valid duration string.
Returns:
float: The duration in seconds.
The duration in seconds.
"""
match = _match_duration(duration)

View File

@@ -32,10 +32,10 @@ class Monochrome(LineFilter):
"""Convert colors in a style to monochrome.
Args:
style (Style): A Rich Style.
style: A Rich Style.
Returns:
Style: A new Rich style.
A new Rich style.
"""
style_color = style.color
style_background = style.bgcolor

View File

@@ -14,7 +14,7 @@ class ImmutableSequenceView(Generic[T]):
"""Initialise the immutable sequence.
Args:
wrap (Sequence[T]): The sequence being wrapped.
wrap: The sequence being wrapped.
"""
self._wrap = wrap
@@ -52,12 +52,12 @@ class ImmutableSequenceView(Generic[T]):
"""Return the index of the given item.
Args:
item (T): The item to find in the sequence.
start (int, optional): Optional start location.
stop (int, optional): Optional stop location.
item: The item to find in the sequence.
start: Optional start location.
stop: Optional stop location.
Returns:
T: The index of the item in the sequence.
The index of the item in the sequence.
Raises:
ValueError: If the item is not in the sequence.

View File

@@ -20,10 +20,10 @@ def shebang_python(candidate: Path) -> bool:
"""Does the given file look like it's run with Python?
Args:
candidate (Path): The candidate file to check.
candidate: The candidate file to check.
Returns:
bool: ``True`` if it looks to #! python, ``False`` if not.
``True`` if it looks to #! python, ``False`` if not.
"""
try:
with candidate.open("rb") as source:
@@ -37,13 +37,13 @@ def import_app(import_name: str) -> App:
"""Import an app from a path or import name.
Args:
import_name (str): A name to import, such as `foo.bar`, or a path ending with .py.
import_name: A name to import, such as `foo.bar`, or a path ending with .py.
Raises:
AppFail: If the app could not be found for any reason.
Returns:
App: A Textual application
A Textual application
"""
import inspect

View File

@@ -38,23 +38,23 @@ class Layout(ABC):
"""Generate a layout map that defines where on the screen the widgets will be drawn.
Args:
parent (Widget): Parent widget.
size (Size): Size of container.
parent: Parent widget.
size: Size of container.
Returns:
Iterable[WidgetPlacement]: An iterable of widget location
An iterable of widget location
"""
def get_content_width(self, widget: Widget, container: Size, viewport: Size) -> int:
"""Get the optimal content width by arranging children.
Args:
widget (Widget): The container widget.
container (Size): The container size.
viewport (Size): The viewport size.
widget: The container widget.
container: The container size.
viewport: The viewport size.
Returns:
int: Width of the content.
Width of the content.
"""
if not widget.children:
width = 0
@@ -76,13 +76,13 @@ class Layout(ABC):
"""Get the content height.
Args:
widget (Widget): The container widget.
container (Size): The container size.
viewport (Size): The viewport.
width (int): The content width.
widget: The container widget.
container: The container size.
viewport: The viewport.
width: The content width.
Returns:
int: Content height (in lines).
Content height (in lines).
"""
if not widget.children:
height = 0

View File

@@ -40,11 +40,11 @@ def layout_resolve(total: int, edges: Sequence[EdgeProtocol]) -> list[int]:
clip the rows that would overflow the screen height.
Args:
total (int): Total number of characters.
edges (Sequence[Edge]): Edges within total space.
total: Total number of characters.
edges: Edges within total space.
Returns:
list[int]: Number of characters for each edge.
Number of characters for each edge.
"""
# Size of edge or None for yet to be determined
sizes = [(edge.size or None) for edge in edges]

View File

@@ -54,10 +54,10 @@ class NodeList(Sequence["Widget"]):
"""Return the index of the given widget.
Args:
widget (Widget): The widget to find in the node list.
widget: The widget to find in the node list.
Returns:
int: The index of the widget in the node list.
The index of the widget in the node list.
Raises:
ValueError: If the widget is not in the node list.
@@ -72,7 +72,7 @@ class NodeList(Sequence["Widget"]):
"""Append a Widget.
Args:
widget (Widget): A widget.
widget: A widget.
"""
if widget not in self._nodes_set:
self._nodes.append(widget)
@@ -87,7 +87,7 @@ class NodeList(Sequence["Widget"]):
"""Insert a Widget.
Args:
widget (Widget): A widget.
widget: A widget.
"""
if widget not in self._nodes_set:
self._nodes.insert(index, widget)
@@ -112,7 +112,7 @@ class NodeList(Sequence["Widget"]):
Removing a widget not in the list is a null-op.
Args:
widget (Widget): A Widget in the list.
widget: A Widget in the list.
"""
if widget in self._nodes_set:
del self._nodes[self._nodes.index(widget)]

View File

@@ -16,9 +16,9 @@ def _apply_opacity(
background colors applied.
Args:
segments (Iterable[Segment]): The segments in the foreground.
base_background (Color): The background color to blend foreground into.
opacity (float): The blending factor. A value of 1.0 means output segments will
segments: The segments in the foreground.
base_background: The background color to blend foreground into.
opacity: The blending factor. A value of 1.0 means output segments will
have identical foreground and background colors to input segments.
"""
_Segment = Segment

View File

@@ -13,11 +13,11 @@ def partition(
the values where the predicate is False, the second list will contain the remaining values.
Args:
pred (Callable[[T], object]): A callable that returns True or False for a given value.
iterable (Iterable[T]): In Iterable of values.
pred: A callable that returns True or False for a given value.
iterable: In Iterable of values.
Returns:
tuple[list[T], list[T]]: A list of values where the predicate is False, and a list
A list of values where the predicate is False, and a list
where the predicate is True.
"""

View File

@@ -10,11 +10,11 @@ def _make_path_object_relative(path: str | PurePath, obj: object) -> Path:
Used, for example, to return the path of a CSS file relative to a Textual App instance.
Args:
path (str | Path): A path.
obj (object): A Python object to resolve the path relative to.
path: A path.
obj: A Python object to resolve the path relative to.
Returns:
Path: A resolved Path object, relative to obj
A resolved Path object, relative to obj
"""
path = Path(path)

View File

@@ -29,14 +29,14 @@ def resolve(
"""Resolve a list of dimensions.
Args:
dimensions (Sequence[Scalar]): Scalars for column / row sizes.
total (int): Total space to divide.
gutter (int): Gutter between rows / columns.
size (Size): Size of container.
viewport (Size): Size of viewport.
dimensions: Scalars for column / row sizes.
total: Total space to divide.
gutter: Gutter between rows / columns.
size: Size of container.
viewport: Size of viewport.
Returns:
list[tuple[int, int]]: List of (<OFFSET>, <LENGTH>)
List of (<OFFSET>, <LENGTH>)
"""
resolved: list[tuple[Scalar, Fraction | None]] = [
@@ -94,14 +94,14 @@ def resolve_box_models(
"""Resolve box models for a list of dimensions
Args:
dimensions (list[Scalar | None]): A list of Scalars or Nones for each dimension.
widgets (list[Widget]): Widgets in resolve.
size (Size): size of container.
parent_size (Size): Size of parent.
dimensions (Literal["width", "height"]): Which dimension to resolve.
dimensions: A list of Scalars or Nones for each dimension.
widgets: Widgets in resolve.
size: Size of container.
parent_size: Size of parent.
dimensions: Which dimension to resolve.
Returns:
list[BoxModel]: List of resolved box models.
List of resolved box models.
"""
fraction_width = Fraction(size.width)

View File

@@ -24,11 +24,11 @@ def index_to_cell_position(segments: Iterable[Segment], index: int) -> int:
*before* the character at `index`.
Args:
segments (Iterable[Segment]): The segments to find the cell position within.
index (int): The index to convert into a cell position.
segments: The segments to find the cell position within.
index: The index to convert into a cell position.
Returns:
int: The cell position of the character at `index`.
The cell position of the character at `index`.
Raises:
NoCellPositionForIndex: If the supplied index doesn't fall within the given segments.
@@ -70,12 +70,12 @@ def line_crop(
"""Crops a list of segments between two cell offsets.
Args:
segments (list[Segment]): A list of Segments for a line.
start (int): Start offset (cells)
end (int): End offset (cells, exclusive)
total (int): Total cell length of segments.
segments: A list of Segments for a line.
start: Start offset (cells)
end: End offset (cells, exclusive)
total: Total cell length of segments.
Returns:
list[Segment]: A new shorter list of segments
A new shorter list of segments
"""
# This is essentially a specialized version of Segment.divide
# The following line has equivalent functionality (but a little slower)
@@ -121,12 +121,12 @@ def line_trim(segments: list[Segment], start: bool, end: bool) -> list[Segment]:
"""Optionally remove a cell from the start and / or end of a list of segments.
Args:
segments (list[Segment]): A line (list of Segments)
start (bool): Remove cell from start.
end (bool): Remove cell from end.
segments: A line (list of Segments)
start: Remove cell from start.
end: Remove cell from end.
Returns:
list[Segment]: A new list of segments.
A new list of segments.
"""
segments = segments.copy()
if segments and start:
@@ -151,13 +151,13 @@ def line_pad(
"""Adds padding to the left and / or right of a list of segments.
Args:
segments (Iterable[Segment]): A line of segments.
pad_left (int): Cells to pad on the left.
pad_right (int): Cells to pad on the right.
style (Style): Style of padded cells.
segments: A line of segments.
pad_left: Cells to pad on the left.
pad_right: Cells to pad on the right.
style: Style of padded cells.
Returns:
list[Segment]: A new line with padding.
A new line with padding.
"""
if pad_left and pad_right:
return [
@@ -188,14 +188,14 @@ def align_lines(
"""Align lines.
Args:
lines (Lines): A list of lines.
style (Style): Background style.
size (Size): Size of container.
horizontal (AlignHorizontal): Horizontal alignment.
vertical (AlignVertical): Vertical alignment
lines: A list of lines.
style: Background style.
size: Size of container.
horizontal: Horizontal alignment.
vertical: Vertical alignment
Returns:
Iterable[list[Segment]]: Aligned lines.
Aligned lines.
"""

View File

@@ -30,11 +30,11 @@ def make_blank(width, style: Style) -> Segment:
"""Make a blank segment.
Args:
width (_type_): Width of blank.
style (Style): Style of blank.
width: Width of blank.
style: Style of blank.
Returns:
Segment: A single segment
A single segment
"""
return Segment(intern(" " * width), style)
@@ -82,10 +82,10 @@ class StylesCache:
"""Check if a given line is dirty (needs to be rendered again).
Args:
y (int): Y coordinate of line.
y: Y coordinate of line.
Returns:
bool: True if line requires a render, False if can be cached.
True if line requires a render, False if can be cached.
"""
return y in self._dirty_lines
@@ -98,11 +98,11 @@ class StylesCache:
"""Render the content for a widget.
Args:
widget (Widget): A widget.
region (Region): A region of the widget to render.
widget: A widget.
region: A region of the widget to render.
Returns:
Lines: Rendered lines.
Rendered lines.
"""
base_background, background = widget.background_colors
styles = widget.styles
@@ -149,17 +149,17 @@ class StylesCache:
"""Render a widget content plus CSS styles.
Args:
styles (StylesBase): CSS Styles object.
size (Size): Size of widget.
base_background (Color): Background color beneath widget.
background (Color): Background color of widget.
render_content_line (RenderLineCallback): Callback to render content line.
content_size (Size | None, optional): Size of content or None to assume full size. Defaults to None.
padding (Spacing | None, optional): Override padding from Styles, or None to use styles.padding. Defaults to None.
crop (Region | None, optional): Region to crop to. Defaults to None.
styles: CSS Styles object.
size: Size of widget.
base_background: Background color beneath widget.
background: Background color of widget.
render_content_line: Callback to render content line.
content_size: Size of content or None to assume full size. Defaults to None.
padding: Override padding from Styles, or None to use styles.padding. Defaults to None.
crop: Region to crop to. Defaults to None.
Returns:
Lines: Rendered lines.
Rendered lines.
"""
if content_size is None:
content_size = size
@@ -217,17 +217,17 @@ class StylesCache:
"""Render a styled line.
Args:
styles (StylesBase): Styles object.
y (int): The y coordinate of the line (relative to widget screen offset).
size (Size): Size of the widget.
content_size (Size): Size of the content area.
padding (Spacing): Padding.
base_background (Color): Background color of widget beneath this line.
background (Color): Background color of widget.
render_content_line (RenderLineCallback): Callback to render a line of content.
styles: Styles object.
y: The y coordinate of the line (relative to widget screen offset).
size: Size of the widget.
content_size: Size of the content area.
padding: Padding.
base_background: Background color of widget beneath this line.
background: Background color of widget.
render_content_line: Callback to render a line of content.
Returns:
list[Segment]: A line of segments.
A line of segments.
"""
gutter = styles.gutter
@@ -259,10 +259,10 @@ class StylesCache:
"""Post process segments to apply opacity and tint.
Args:
segments (Iterable[Segment]): Iterable of segments.
segments: Iterable of segments.
Returns:
list[Segment]: New list of segments
New list of segments
"""
if styles.text_opacity != 1.0:
segments = TextOpacity.process_segments(segments, styles.text_opacity)

View File

@@ -14,7 +14,7 @@ class TextEditorBackend:
"""Set the content of the editor
Args:
text (str): The text to set as the content
text: The text to set as the content
"""
self.content = text
@@ -24,7 +24,7 @@ class TextEditorBackend:
return False.
Returns:
bool: True if the text content was modified. False otherwise.
True if the text content was modified. False otherwise.
"""
if self.cursor_index == 0:
return False
@@ -40,7 +40,7 @@ class TextEditorBackend:
"""Delete the character in front of the cursor without moving the cursor.
Returns:
bool: True if the text content was modified. False otherwise.
True if the text content was modified. False otherwise.
"""
if self.cursor_index == len(self.content):
return False
@@ -55,7 +55,7 @@ class TextEditorBackend:
"""Move the cursor 1 character left in the text. Is a noop if cursor is at start.
Returns:
bool: True if the cursor moved. False otherwise.
True if the cursor moved. False otherwise.
"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
@@ -66,7 +66,7 @@ class TextEditorBackend:
"""Move the cursor 1 character right in the text. Is a noop if the cursor is at end.
Returns:
bool: True if the cursor moved. False otherwise.
True if the cursor moved. False otherwise.
"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
@@ -77,7 +77,7 @@ class TextEditorBackend:
"""Check if the cursor can move 1 codepoint left in the text.
Returns:
bool: True if the cursor can move left. False otherwise.
True if the cursor can move left. False otherwise.
"""
previous_index = self.cursor_index
new_index = max(0, previous_index - 1)
@@ -89,7 +89,7 @@ class TextEditorBackend:
exist (e.g. we're at the end), then return None
Returns:
str: The codepoint to the right of the cursor if it exists, otherwise None.
The codepoint to the right of the cursor if it exists, otherwise None.
"""
previous_index = self.cursor_index
new_index = min(len(self.content), previous_index + 1)
@@ -103,7 +103,7 @@ class TextEditorBackend:
"""Move the cursor to the start of the text
Returns:
bool: True if the cursor moved. False otherwise.
True if the cursor moved. False otherwise.
"""
if self.cursor_index == 0:
return False
@@ -115,7 +115,7 @@ class TextEditorBackend:
"""Move the cursor to the end of the text
Returns:
bool: True if the cursor moved. False otherwise.
True if the cursor moved. False otherwise.
"""
text_length = len(self.content)
if self.cursor_index == text_length:
@@ -132,7 +132,7 @@ class TextEditorBackend:
text: The text to insert
Returns:
bool: Always returns True since text should be insertable regardless of cursor location
Always returns True since text should be insertable regardless of cursor location
"""
new_text = (
self.content[: self.cursor_index] + text + self.content[self.cursor_index :]
@@ -146,11 +146,11 @@ class TextEditorBackend:
a subset of the content e.g. scrollable single-line input fields
Args:
start (int): The starting index to return text from (inclusive)
end (int): The index to return text up to (exclusive)
start: The starting index to return text from (inclusive)
end: The index to return text up to (exclusive)
Returns:
str: The sliced string between start and end.
The sliced string between start and end.
"""
return self.content[start:end]

View File

@@ -24,7 +24,7 @@ if WINDOWS:
"""Sleep for a given number of seconds.
Args:
secs (float): Number of seconds to sleep for.
secs: Number of seconds to sleep for.
"""
await get_running_loop().run_in_executor(None, win_sleep, secs)
@@ -34,7 +34,7 @@ else:
"""Sleep for a given number of seconds.
Args:
secs (float): Number of seconds to sleep for.
secs: Number of seconds to sleep for.
"""
# From practical experiments, asyncio.sleep sleeps for at least half a millisecond too much
# Presumably there is overhead asyncio itself which accounts for this

View File

@@ -32,7 +32,7 @@ else:
specified time. This is generally not an issue for Textual's use case.
Args:
secs (float): Seconds to sleep for.
secs: Seconds to sleep for.
"""
# Subtract a millisecond to account for overhead

View File

@@ -239,10 +239,10 @@ class XTermParser(Parser[events.Event]):
"""Map a sequence of code points on to a sequence of keys.
Args:
sequence (str): Sequence of code points.
sequence: Sequence of code points.
Returns:
Iterable[events.Key]: keys
Keys
"""
keys = ANSI_SEQUENCES_KEYS.get(sequence)

View File

@@ -19,13 +19,13 @@ def parse(action: str) -> tuple[str, tuple[object, ...]]:
"""Parses an action string.
Args:
action (str): String containing action.
action: String containing action.
Raises:
ActionError: If the action has invalid syntax.
Returns:
tuple[str, tuple[object, ...]]: Action name and parameters
Action name and parameters
"""
params_match = re_action_params.match(action)
if params_match is not None:

View File

@@ -160,7 +160,7 @@ class _WriterThread(threading.Thread):
"""Write text. Text will be enqueued for writing.
Args:
text (str): Text to write to the file.
text: Text to write to the file.
"""
self._queue.put(text)
@@ -168,7 +168,7 @@ class _WriterThread(threading.Thread):
"""Pretend to be a terminal.
Returns:
bool: True if this is a tty.
True if this is a tty.
"""
return True
@@ -176,7 +176,7 @@ class _WriterThread(threading.Thread):
"""Get file handle number.
Returns:
int: File number of proxied file.
File number of proxied file.
"""
return self._file.fileno()
@@ -216,10 +216,10 @@ CallThreadReturnType = TypeVar("CallThreadReturnType")
class App(Generic[ReturnType], DOMNode):
"""The base class for Textual Applications.
Args:
driver_class (Type[Driver] | None, optional): Driver class or ``None`` to auto-detect. Defaults to None.
css_path (str | PurePath | list[str | PurePath] | None, optional): Path to CSS or ``None`` for no CSS file.
driver_class: Driver class or ``None`` to auto-detect. Defaults to None.
css_path: Path to CSS or ``None`` for no CSS file.
Defaults to None. To load multiple CSS files, pass a list of strings or paths which will be loaded in order.
watch_css (bool, optional): Watch CSS for changes. Defaults to False.
watch_css: Watch CSS for changes. Defaults to False.
Raises:
CssPathError: When the supplied CSS path(s) are an unexpected type.
@@ -419,14 +419,14 @@ class App(Generic[ReturnType], DOMNode):
"""Animate an attribute.
Args:
attribute (str): Name of the attribute to animate.
value (float | Animatable): The value to animate to.
final_value (object, optional): The final value of the animation. Defaults to `value` if not set.
duration (float | None, optional): The duration of the animate. Defaults to None.
speed (float | None, optional): The speed of the animation. Defaults to None.
delay (float, optional): A delay (in seconds) before the animation starts. Defaults to 0.0.
easing (EasingFunction | str, optional): An easing method. Defaults to "in_out_cubic".
on_complete (CallbackType | None, optional): A callable to invoke when the animation is finished. Defaults to None.
attribute: Name of the attribute to animate.
value: The value to animate to.
final_value: The final value of the animation. Defaults to `value` if not set.
duration: The duration of the animate. Defaults to None.
speed: The speed of the animation. Defaults to None.
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
easing: An easing method. Defaults to "in_out_cubic".
on_complete: A callable to invoke when the animation is finished. Defaults to None.
"""
self._animate(
@@ -461,8 +461,8 @@ class App(Generic[ReturnType], DOMNode):
"""Exit the app, and return the supplied result.
Args:
result (ReturnType | None, optional): Return value. Defaults to None.
message (RenderableType | None): Optional message to display on exit.
result: Return value. Defaults to None.
message: Optional message to display on exit.
"""
self._exit = True
self._return_value = result
@@ -500,7 +500,7 @@ class App(Generic[ReturnType], DOMNode):
"""Get a mapping of variables used to pre-populate CSS.
Returns:
dict[str, str]: A mapping of variable name to value.
A mapping of variable name to value.
"""
variables = self.design["dark" if self.dark else "light"].generate()
return variables
@@ -524,7 +524,7 @@ class App(Generic[ReturnType], DOMNode):
Called by the constructor.
Returns:
Driver: A Driver class which manages input and display.
A Driver class which manages input and display.
"""
driver_class: Type[Driver]
if WINDOWS:
@@ -603,7 +603,7 @@ class App(Generic[ReturnType], DOMNode):
```
Args:
verbosity (int, optional): Verbosity level 0-3. Defaults to 1.
verbosity: Verbosity level 0-3. Defaults to 1.
"""
devtools = self.devtools
@@ -651,7 +651,7 @@ class App(Generic[ReturnType], DOMNode):
This method will ensure that your code is ran within the correct context.
Args:
callback (Callable): A callable to run.
callback: A callable to run.
*args: Arguments to the callback.
**kwargs: Keyword arguments for the callback.
@@ -690,8 +690,8 @@ class App(Generic[ReturnType], DOMNode):
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
Args:
filename (str | None, optional): Filename of screenshot, or None to auto-generate. Defaults to None.
path (str, optional): Path to directory. Defaults to current working directory.
filename: Filename of screenshot, or None to auto-generate. Defaults to None.
path: Path to directory. Defaults to current working directory.
"""
self.save_screenshot(filename, path)
@@ -699,7 +699,7 @@ class App(Generic[ReturnType], DOMNode):
"""Export an SVG screenshot of the current screen.
Args:
title (str | None, optional): The title of the exported screenshot or None
title: The title of the exported screenshot or None
to use app title. Defaults to None.
"""
@@ -727,13 +727,13 @@ class App(Generic[ReturnType], DOMNode):
"""Save an SVG screenshot of the current screen.
Args:
filename (str | None, optional): Filename of SVG screenshot, or None to auto-generate
filename: Filename of SVG screenshot, or None to auto-generate
a filename with the date and time. Defaults to None.
path (str, optional): Path to directory for output. Defaults to current working directory.
time_format (str, optional): Time format to use if filename is None. Defaults to "%Y-%m-%d %X %f".
path: Path to directory for output. Defaults to current working directory.
time_format: Time format to use if filename is None. Defaults to "%Y-%m-%d %X %f".
Returns:
str: Filename of screenshot.
Filename of screenshot.
"""
if filename is None:
svg_filename = (
@@ -761,11 +761,11 @@ class App(Generic[ReturnType], DOMNode):
"""Bind a key to an action.
Args:
keys (str): A comma separated list of keys, i.e.
action (str): Action to bind to.
description (str, optional): Short description of action. Defaults to "".
show (bool, optional): Show key in UI. Defaults to True.
key_display (str, optional): Replacement text for key, or None to use default. Defaults to None.
keys: A comma separated list of keys, i.e.
action: Action to bind to.
description: Short description of action. Defaults to "".
show: Show key in UI. Defaults to True.
key_display: Replacement text for key, or None to use default. Defaults to None.
"""
self._bindings.bind(
keys, action, description, show=show, key_display=key_display
@@ -780,10 +780,10 @@ class App(Generic[ReturnType], DOMNode):
needing to add a key_display to every binding.
Args:
key (str): The binding key string.
key: The binding key string.
Returns:
str: The display string for the input key.
The display string for the input key.
"""
return _get_key_display(key)
@@ -837,8 +837,8 @@ class App(Generic[ReturnType], DOMNode):
"""An asynchronous context manager for testing app.
Args:
headless (bool, optional): Run in headless mode (no output or input). Defaults to True.
size (tuple[int, int] | None, optional): Force terminal size to `(WIDTH, HEIGHT)`,
headless: Run in headless mode (no output or input). Defaults to True.
size: Force terminal size to `(WIDTH, HEIGHT)`,
or None to auto-detect. Defaults to None.
"""
@@ -885,13 +885,13 @@ class App(Generic[ReturnType], DOMNode):
"""Run the app asynchronously.
Args:
headless (bool, optional): Run in headless mode (no output). Defaults to False.
size (tuple[int, int] | None, optional): Force terminal size to `(WIDTH, HEIGHT)`,
headless: Run in headless mode (no output). Defaults to False.
size: Force terminal size to `(WIDTH, HEIGHT)`,
or None to auto-detect. Defaults to None.
auto_pilot (AutopilotCallbackType): An auto pilot coroutine.
auto_pilot: An auto pilot coroutine.
Returns:
ReturnType | None: App return value.
App return value.
"""
from .pilot import Pilot
@@ -941,13 +941,13 @@ class App(Generic[ReturnType], DOMNode):
"""Run the app.
Args:
headless (bool, optional): Run in headless mode (no output). Defaults to False.
size (tuple[int, int] | None, optional): Force terminal size to `(WIDTH, HEIGHT)`,
headless: Run in headless mode (no output). Defaults to False.
size: Force terminal size to `(WIDTH, HEIGHT)`,
or None to auto-detect. Defaults to None.
auto_pilot (AutopilotCallbackType): An auto pilot coroutine.
auto_pilot: An auto pilot coroutine.
Returns:
ReturnType | None: App return value.
App return value.
"""
async def run_app() -> None:
@@ -1017,12 +1017,12 @@ class App(Generic[ReturnType], DOMNode):
with the given ID.
Args:
id (str): The ID of the node to search for.
expect_type (type | None, optional): Require the object be of the supplied type, or None for any type.
id: The ID of the node to search for.
expect_type: Require the object be of the supplied type, or None for any type.
Defaults to None.
Returns:
ExpectType | Widget: The first child of this node with the specified ID.
The first child of this node with the specified ID.
Raises:
NoMatches: if no children could be found for this ID
@@ -1053,12 +1053,12 @@ class App(Generic[ReturnType], DOMNode):
To get the screen, use `self.screen`.
Args:
id (str): The ID to search for in the subtree
expect_type (type | None, optional): Require the object be of the supplied type, or None for any type.
id: The ID to search for in the subtree
expect_type: Require the object be of the supplied type, or None for any type.
Defaults to None.
Returns:
ExpectType | Widget: The first descendant encountered with this ID.
The first descendant encountered with this ID.
Raises:
NoMatches: if no children could be found for this ID
@@ -1088,12 +1088,12 @@ class App(Generic[ReturnType], DOMNode):
"""Mount the given widgets relative to the app's screen.
Args:
*widgets (Widget): The widget(s) to mount.
before (int | str | Widget, optional): Optional location to mount before.
after (int | str | Widget, optional): Optional location to mount after.
*widgets: The widget(s) to mount.
before: Optional location to mount before.
after: Optional location to mount after.
Returns:
AwaitMount: An awaitable object that waits for widgets to be mounted.
An awaitable object that waits for widgets to be mounted.
Raises:
MountError: If there is a problem with the mount request.
@@ -1113,12 +1113,12 @@ class App(Generic[ReturnType], DOMNode):
"""Mount widgets from an iterable.
Args:
widgets (Iterable[Widget]): An iterable of widgets.
before (int | str | Widget, optional): Optional location to mount before.
after (int | str | Widget, optional): Optional location to mount after.
widgets: An iterable of widgets.
before: Optional location to mount before.
after: Optional location to mount after.
Returns:
AwaitMount: An awaitable object that waits for widgets to be mounted.
An awaitable object that waits for widgets to be mounted.
Raises:
MountError: If there is a problem with the mount request.
@@ -1133,10 +1133,10 @@ class App(Generic[ReturnType], DOMNode):
"""Check if a given screen has been installed.
Args:
screen (Screen | str): Either a Screen object or screen name (the `name` argument when installed).
screen: Either a Screen object or screen name (the `name` argument when installed).
Returns:
bool: True if the screen is currently installed,
True if the screen is currently installed,
"""
if isinstance(screen, str):
return screen in self._installed_screens
@@ -1147,13 +1147,13 @@ class App(Generic[ReturnType], DOMNode):
"""Get an installed screen.
Args:
screen (Screen | str): Either a Screen object or screen name (the `name` argument when installed).
screen: Either a Screen object or screen name (the `name` argument when installed).
Raises:
KeyError: If the named screen doesn't exist.
Returns:
Screen: A screen instance.
A screen instance.
"""
if isinstance(screen, str):
try:
@@ -1173,13 +1173,13 @@ class App(Generic[ReturnType], DOMNode):
If the screen isn't running, it will be registered before it is run.
Args:
screen (Screen | str): Either a Screen object or screen name (the `name` argument when installed).
screen: Either a Screen object or screen name (the `name` argument when installed).
Raises:
KeyError: If the named screen doesn't exist.
Returns:
tuple[Screen, AwaitMount]: A screen instance and an awaitable that awaits the children mounting.
A screen instance and an awaitable that awaits the children mounting.
"""
_screen = self.get_screen(screen)
@@ -1193,10 +1193,10 @@ class App(Generic[ReturnType], DOMNode):
"""Handle the replaced screen.
Args:
screen (Screen): A screen object.
screen: A screen object.
Returns:
Screen: The screen that was replaced.
The screen that was replaced.
"""
screen.post_message_no_wait(events.ScreenSuspend(self))
@@ -1210,7 +1210,7 @@ class App(Generic[ReturnType], DOMNode):
"""Push a new screen on the screen stack.
Args:
screen (Screen | str): A Screen instance or the name of an installed screen.
screen: A Screen instance or the name of an installed screen.
"""
next_screen, await_mount = self._get_screen(screen)
@@ -1223,7 +1223,7 @@ class App(Generic[ReturnType], DOMNode):
"""Switch to another screen by replacing the top of the screen stack with a new screen.
Args:
screen (Screen | str): Either a Screen object or screen name (the `name` argument when installed).
screen: Either a Screen object or screen name (the `name` argument when installed).
"""
if self.screen is not screen:
@@ -1239,15 +1239,15 @@ class App(Generic[ReturnType], DOMNode):
"""Install a screen.
Args:
screen (Screen): Screen to install.
name (str | None, optional): Unique name of screen or None to auto-generate.
screen: Screen to install.
name: Unique name of screen or None to auto-generate.
Defaults to None.
Raises:
ScreenError: If the screen can't be installed.
Returns:
AwaitMount: An awaitable that awaits the mounting of the screen and its children.
An awaitable that awaits the mounting of the screen and its children.
"""
if name is None:
name = nanoid.generate()
@@ -1267,10 +1267,10 @@ class App(Generic[ReturnType], DOMNode):
method is a null-op.
Args:
screen (Screen | str): The screen to uninstall or the name of a installed screen.
screen: The screen to uninstall or the name of a installed screen.
Returns:
str | None: The name of the screen that was uninstalled, or None if no screen was uninstalled.
The name of the screen that was uninstalled, or None if no screen was uninstalled.
"""
if isinstance(screen, str):
if screen not in self._installed_screens:
@@ -1295,7 +1295,7 @@ class App(Generic[ReturnType], DOMNode):
"""Pop the current screen from the stack, and switch to the previous screen.
Returns:
Screen: The screen that was replaced.
The screen that was replaced.
"""
screen_stack = self._screen_stack
if len(screen_stack) <= 1:
@@ -1312,8 +1312,8 @@ class App(Generic[ReturnType], DOMNode):
"""Focus (or unfocus) a widget. A focused widget will receive key events first.
Args:
widget (Widget): Widget to focus.
scroll_visible (bool, optional): Scroll widget in to view.
widget: Widget to focus.
scroll_visible: Scroll widget in to view.
"""
self.screen.set_focus(widget, scroll_visible)
@@ -1321,7 +1321,7 @@ class App(Generic[ReturnType], DOMNode):
"""Called when the mouse is over another widget.
Args:
widget (Widget | None): Widget under mouse, or None for no widgets.
widget: Widget under mouse, or None for no widgets.
"""
if widget is None:
if self.mouse_over is not None:
@@ -1343,7 +1343,7 @@ class App(Generic[ReturnType], DOMNode):
"""Send all mouse events to the given widget, disable mouse capture.
Args:
widget (Widget | None): If a widget, capture mouse event, or None to end mouse capture.
widget: If a widget, capture mouse event, or None to end mouse capture.
"""
if widget == self.mouse_captured:
return
@@ -1359,7 +1359,7 @@ class App(Generic[ReturnType], DOMNode):
"""Exits the app then displays a message.
Args:
*renderables (RenderableType, optional): Rich renderables to display on exit.
*renderables: Rich renderables to display on exit.
"""
assert all(
@@ -1379,7 +1379,7 @@ class App(Generic[ReturnType], DOMNode):
"""Called with an unhandled exception.
Args:
error (Exception): An exception instance.
error: An exception instance.
"""
if hasattr(error, "__rich__"):
@@ -1589,11 +1589,11 @@ class App(Generic[ReturnType], DOMNode):
"""Register a widget as a child of another.
Args:
parent (DOMNode): Parent node.
child (Widget): The child widget to register.
parent: Parent node.
child: The child widget to register.
widgets: The widget to register.
before (int, optional): A location to mount before.
after (int, option): A location to mount after.
before: A location to mount before.
after: A location to mount after.
"""
# Let's be 100% sure that we've not been asked to do a before and an
@@ -1640,12 +1640,12 @@ class App(Generic[ReturnType], DOMNode):
"""Register widget(s) so they may receive events.
Args:
parent (DOMNode): Parent node.
parent: Parent node.
*widgets: The widget(s) to register.
before (int, optional): A location to mount before.
after (int, option): A location to mount after.
before: A location to mount before.
after: A location to mount after.
Returns:
list[Widget]: List of modified widgets.
List of modified widgets.
"""
@@ -1674,7 +1674,7 @@ class App(Generic[ReturnType], DOMNode):
"""Unregister a widget.
Args:
widget (Widget): A Widget to unregister
widget: A Widget to unregister
"""
widget.reset_focus()
if isinstance(widget._parent, Widget):
@@ -1690,8 +1690,8 @@ class App(Generic[ReturnType], DOMNode):
"""Start a widget (run it's task) so that it can receive messages.
Args:
parent (Widget): The parent of the Widget.
widget (Widget): The Widget to start.
parent: The parent of the Widget.
widget: The Widget to start.
"""
widget._attach(parent)
@@ -1702,10 +1702,10 @@ class App(Generic[ReturnType], DOMNode):
"""Check if a widget is mounted.
Args:
widget (Widget): A widget.
widget: A widget.
Returns:
bool: True of the widget is mounted.
True of the widget is mounted.
"""
return widget in self._registry
@@ -1759,7 +1759,7 @@ class App(Generic[ReturnType], DOMNode):
"""Refresh CSS.
Args:
animate (bool, optional): Also execute CSS animations. Defaults to True.
animate: Also execute CSS animations. Defaults to True.
"""
stylesheet = self.app.stylesheet
stylesheet.set_variables(self.get_css_variables())
@@ -1771,8 +1771,8 @@ class App(Generic[ReturnType], DOMNode):
"""Display a renderable within a sync.
Args:
screen (Screen): Screen instance
renderable (RenderableType): A Rich renderable.
screen: Screen instance
renderable: A Rich renderable.
"""
try:
@@ -1800,11 +1800,11 @@ class App(Generic[ReturnType], DOMNode):
"""Get the widget under the given coordinates.
Args:
x (int): X Coordinate.
y (int): Y Coordinate.
x: X coordinate.
y: Y coordinate.
Returns:
tuple[Widget, Region]: The widget and the widget's screen region.
The widget and the widget's screen region.
"""
return self.screen.get_widget_at(x, y)
@@ -1818,7 +1818,7 @@ class App(Generic[ReturnType], DOMNode):
"""Get a chain of nodes and bindings to consider. If no widget is focused, returns the bindings from both the screen and the app level bindings. Otherwise, combines all the bindings from the currently focused node up the DOM to the root App.
Returns:
list[tuple[DOMNode, Bindings]]: List of DOM nodes and their bindings.
List of DOM nodes and their bindings.
"""
focused = self.focused
namespace_bindings: list[tuple[DOMNode, Bindings]]
@@ -1837,11 +1837,11 @@ class App(Generic[ReturnType], DOMNode):
"""Handle a key press.
Args:
key (str): A key.
priority (bool): If `True` check from `App` down, otherwise from focused up.
key: A key.
priority: If `True` check from `App` down, otherwise from focused up.
Returns:
bool: True if the key was handled by a binding, otherwise False
True if the key was handled by a binding, otherwise False
"""
for namespace, bindings in (
reversed(self._binding_chain) if priority else self._binding_chain
@@ -1887,12 +1887,12 @@ class App(Generic[ReturnType], DOMNode):
"""Perform an action.
Args:
action (str): Action encoded in a string.
default_namespace (object | None): Namespace to use if not provided in the action,
action: Action encoded in a string.
default_namespace: Namespace to use if not provided in the action,
or None to use app. Defaults to None.
Returns:
bool: True if the event has handled.
True if the event has handled.
"""
print("ACTION", action, default_namespace)
if isinstance(action, str):
@@ -1921,12 +1921,12 @@ class App(Generic[ReturnType], DOMNode):
"""Dispatch an action to an action method.
Args:
namespace (object): Namespace (object) of action.
action_name (str): Name of the action.
params (Any): Action parameters.
namespace: Namespace (object) of action.
action_name: Name of the action.
params: Action parameters.
Returns:
bool: True if handled, otherwise False.
True if handled, otherwise False.
"""
_rich_traceback_guard = True
@@ -1961,12 +1961,12 @@ class App(Generic[ReturnType], DOMNode):
"""Allow the app an opportunity to dispatch events to action system.
Args:
event_name (str): _description_
event (events.Event): An event object.
default_namespace (object | None): The default namespace, where one isn't supplied.
event_name: _description_
event: An event object.
default_namespace: The default namespace, where one isn't supplied.
Returns:
bool: True if an action was processed.
True if an action was processed.
"""
try:
style = getattr(event, "style")
@@ -2008,10 +2008,10 @@ class App(Generic[ReturnType], DOMNode):
"""Detach a list of widgets from the DOM.
Args:
widgets (list[Widget]): The list of widgets to detach from the DOM.
widgets: The list of widgets to detach from the DOM.
Returns:
list[Widget]: The list of widgets that should be pruned.
The list of widgets that should be pruned.
Note:
A side-effect of calling this function is that each parent of
@@ -2068,7 +2068,7 @@ class App(Generic[ReturnType], DOMNode):
"""Walk children depth first, generating widgets and a list of their siblings.
Returns:
Iterable[list[Widget]]: The child widgets of root.
The child widgets of root.
"""
stack: list[Widget] = [root]
@@ -2087,10 +2087,10 @@ class App(Generic[ReturnType], DOMNode):
"""Remove nodes from DOM, and return an awaitable that awaits cleanup.
Args:
widgets (list[Widget]): List of nodes to remvoe.
widgets: List of nodes to remvoe.
Returns:
AwaitRemove: Awaitable that returns when the nodes have been fully removed.
Awaitable that returns when the nodes have been fully removed.
"""
async def prune_widgets_task(
@@ -2099,8 +2099,8 @@ class App(Generic[ReturnType], DOMNode):
"""Prune widgets as a background task.
Args:
widgets (list[Widget]): Widgets to prune.
finished_event (asyncio.Event): Event to set when complete.
widgets: Widgets to prune.
finished_event: Event to set when complete.
"""
try:
await self._prune_nodes(widgets)
@@ -2119,7 +2119,7 @@ class App(Generic[ReturnType], DOMNode):
"""Remove nodes and children.
Args:
widgets (Widget): _description_
widgets: _description_
"""
async with self._dom_lock:
for widget in widgets:
@@ -2129,7 +2129,7 @@ class App(Generic[ReturnType], DOMNode):
"""Remove a node and its children. Children are removed before parents.
Args:
root (Widget): Node to remove.
root: Node to remove.
"""
# Pruning a node that has been removed is a no-op
if root not in self._registry:
@@ -2170,7 +2170,7 @@ class App(Generic[ReturnType], DOMNode):
"""Focus the given widget.
Args:
widget_id (str): ID of widget to focus.
widget_id: ID of widget to focus.
"""
try:
node = self.query(f"#{widget_id}").first()
@@ -2184,7 +2184,7 @@ class App(Generic[ReturnType], DOMNode):
"""Switches to another screen.
Args:
screen (str): Name of the screen.
screen: Name of the screen.
"""
self.switch_screen(screen)
@@ -2192,7 +2192,7 @@ class App(Generic[ReturnType], DOMNode):
"""Pushes a screen on to the screen stack and makes it active.
Args:
screen (str): Name of the screen.
screen: Name of the screen.
"""
self.push_screen(screen)

View File

@@ -11,7 +11,7 @@ class AwaitRemove:
"""Initialise the instance of ``AwaitRemove``.
Args:
finished_flag (asyncio.Event): The asyncio event to wait on.
finished_flag: The asyncio event to wait on.
"""
self.finished_flag = finished_flag

View File

@@ -52,7 +52,7 @@ class Bindings:
"""Initialise a collection of bindings.
Args:
bindings (Iterable[BindingType] | None, optional): An optional set of initial bindings.
bindings: An optional set of initial bindings.
Note:
The iterable of bindings can contain either a `Binding`
@@ -104,10 +104,10 @@ class Bindings:
"""Merge a bindings. Subsequent bound keys override initial keys.
Args:
bindings (Iterable[Bindings]): A number of bindings.
bindings: A number of bindings.
Returns:
Bindings: New bindings.
New bindings.
"""
keys: dict[str, Binding] = {}
for _bindings in bindings:
@@ -119,7 +119,7 @@ class Bindings:
"""A list of bindings for shown keys.
Returns:
list[Binding]: Shown bindings.
Shown bindings.
"""
keys = [binding for binding in self.keys.values() if binding.show]
return keys
@@ -136,12 +136,12 @@ class Bindings:
"""Bind keys to an action.
Args:
keys (str): The keys to bind. Can be a comma-separated list of keys.
action (str): The action to bind the keys to.
description (str, optional): An optional description for the binding.
show (bool, optional): A flag to say if the binding should appear in the footer.
key_display (str | None, optional): Optional string to display in the footer for the key.
priority (bool, optional): Is this a priority binding, checked form app down to focused widget?
keys: The keys to bind. Can be a comma-separated list of keys.
action: The action to bind the keys to.
description: An optional description for the binding.
show: A flag to say if the binding should appear in the footer.
key_display: Optional string to display in the footer for the key.
priority: Is this a priority binding, checked form app down to focused widget?
"""
all_keys = [key.strip() for key in keys.split(",")]
for key in all_keys:
@@ -158,13 +158,13 @@ class Bindings:
"""Get a binding if it exists.
Args:
key (str): Key to look up.
key: Key to look up.
Raises:
NoBinding: If the binding does not exist.
Returns:
Binding: A binding object for the key,
A binding object for the key,
"""
try:
return self.keys[key]

View File

@@ -28,16 +28,16 @@ def get_box_model(
"""Resolve the box model for this Styles.
Args:
styles (StylesBase): Styles object.
container (Size): The size of the widget container.
viewport (Size): The viewport size.
width_fraction (Fraction): A fraction used for 1 `fr` unit on the width dimension.
height_fraction (Fraction):A fraction used for 1 `fr` unit on the height dimension.
get_content_width (Callable[[Size, Size], int]): A callable which accepts container size and parent size and returns a width.
get_content_height (Callable[[Size, Size, int], int]): A callable which accepts container size and parent size and returns a height.
styles: Styles object.
container: The size of the widget container.
viewport: The viewport size.
width_fraction: A fraction used for 1 `fr` unit on the width dimension.
height_fraction: A fraction used for 1 `fr` unit on the height dimension.
get_content_width: A callable which accepts container size and parent size and returns a width.
get_content_height: A callable which accepts container size and parent size and returns a height.
Returns:
BoxModel: A tuple with the size of the content area and margin.
A tuple with the size of the content area and margin.
"""
_content_width, _content_height = container
content_width = Fraction(_content_width)

View File

@@ -9,10 +9,10 @@ def camel_to_snake(
"""Convert name from CamelCase to snake_case.
Args:
name (str): A symbol name, such as a class name.
name: A symbol name, such as a class name.
Returns:
str: Name in camel case.
Name in camel case.
"""
def repl(match: Match[str]) -> str:

View File

@@ -13,8 +13,8 @@ def _section(title: str, values: dict[str, str]) -> None:
"""Print a collection of named values within a titled section.
Args:
title (str): The title for the section.
values (dict[str, str]): The values to print out.
title: The title for the section.
values: The values to print out.
"""
max_name = max(map(len, values.keys()))
max_value = max(map(len, values.values()))
@@ -60,7 +60,7 @@ def _guess_term() -> str:
"""Try and guess which terminal is being used.
Returns:
str: The best guess at the name of the terminal.
The best guess at the name of the terminal.
"""
# First obvious place to look is in $TERM_PROGRAM.
@@ -95,10 +95,10 @@ def _env(var_name: str) -> str:
"""Get a representation of an environment variable.
Args:
var_name (str): The name of the variable to get.
var_name: The name of the variable to get.
Returns:
str: The value, or an indication that it isn't set.
The value, or an indication that it isn't set.
"""
return os.environ.get(var_name, "*Not set*")
@@ -122,10 +122,10 @@ def _str_rich(value: Any) -> str:
"""Convert a rich console option to a string.
Args:
value (Any): The value to convert to a string.
value: The value to convert to a string.
Returns:
str: The string version of the value for output
The string version of the value for output
"""
return str(value)

View File

@@ -125,8 +125,8 @@ class ColorParseError(Exception):
"""A color failed to parse.
Args:
message (str): the error message
suggested_color (str | None): a close color we can suggest. Defaults to None.
message: The error message
suggested_color: A close color we can suggest. Defaults to None.
"""
def __init__(self, message: str, suggested_color: str | None = None):
@@ -152,10 +152,10 @@ class Color(NamedTuple):
"""Create a new color from Rich's Color class.
Args:
rich_color (RichColor): An instance of rich.color.Color.
rich_color: An instance of rich.color.Color.
Returns:
Color: A new Color.
A new Color.
"""
r, g, b = rich_color.get_truecolor()
return cls(r, g, b)
@@ -165,12 +165,12 @@ class Color(NamedTuple):
"""Create a color from HLS components.
Args:
h (float): Hue.
l (float): Lightness.
s (float): Saturation.
h: Hue.
l: Lightness.
s: Saturation.
Returns:
Color: A new color.
A new color.
"""
r, g, b = hls_to_rgb(h, l, s)
return cls(int(r * 255 + 0.5), int(g * 255 + 0.5), int(b * 255 + 0.5))
@@ -195,7 +195,7 @@ class Color(NamedTuple):
"""Check if the color is transparent, i.e. has 0 alpha.
Returns:
bool: True if transparent, otherwise False.
True if transparent, otherwise False.
"""
return self.a == 0
@@ -205,7 +205,7 @@ class Color(NamedTuple):
"""Get a color with all components saturated to maximum and minimum values.
Returns:
Color: A color object.
A color object.
"""
r, g, b, a = self
@@ -223,7 +223,7 @@ class Color(NamedTuple):
"""This color encoded in Rich's Color class.
Returns:
RichColor: A color object as used by Rich.
A color object as used by Rich.
"""
r, g, b, _a = self
return RichColor(
@@ -235,7 +235,7 @@ class Color(NamedTuple):
"""A tuple of the color components normalized to between 0 and 1.
Returns:
tuple[float, float, float]: Normalized components.
Normalized components.
"""
r, g, b, _a = self
@@ -246,7 +246,7 @@ class Color(NamedTuple):
"""Get just the red, green, and blue components.
Returns:
tuple[int, int, int]: Color components
Color components
"""
r, g, b, _ = self
return (r, g, b)
@@ -256,7 +256,7 @@ class Color(NamedTuple):
"""Get the color as HSL.
Returns:
HSL: Color in HSL format.
Color in HSL format.
"""
r, g, b = self.normalized
h, l, s = rgb_to_hls(r, g, b)
@@ -267,7 +267,7 @@ class Color(NamedTuple):
"""Get the human perceptual brightness.
Returns:
float: Brightness value (0-1).
Brightness value (0-1).
"""
r, g, b = self.normalized
@@ -279,7 +279,7 @@ class Color(NamedTuple):
"""The color in CSS hex form, with 6 digits for RGB, and 8 digits for RGBA.
Returns:
str: A CSS hex-style color, e.g. `"#46b3de"` or `"#3342457f"`
A CSS hex-style color, e.g. `"#46b3de"` or `"#3342457f"`
"""
r, g, b, a = self.clamped
@@ -294,7 +294,7 @@ class Color(NamedTuple):
"""The color in CSS hex form, with 6 digits for RGB. Alpha is ignored.
Returns:
str: A CSS hex-style color, e.g. "#46b3de"
A CSS hex-style color, e.g. "#46b3de"
"""
r, g, b, a = self.clamped
@@ -305,7 +305,7 @@ class Color(NamedTuple):
"""The color in CSS rgb or rgba form.
Returns:
str: A CSS style color, e.g. `"rgb(10,20,30)"` or `"rgb(50,70,80,0.5)"`
A CSS style color, e.g. `"rgb(10,20,30)"` or `"rgb(50,70,80,0.5)"`
"""
r, g, b, a = self
@@ -316,7 +316,7 @@ class Color(NamedTuple):
"""Get a monochrome version of this color.
Returns:
Color: A new monochrome color.
A new monochrome color.
"""
r, g, b, a = self
gray = round(r * 0.2126 + g * 0.7152 + b * 0.0722)
@@ -333,10 +333,10 @@ class Color(NamedTuple):
"""Create a new color with the given alpha.
Args:
alpha (float): New value for alpha.
alpha: New value for alpha.
Returns:
Color: A new color.
A new color.
"""
r, g, b, _ = self
return Color(r, g, b, alpha)
@@ -347,12 +347,12 @@ class Color(NamedTuple):
"""Generate a new color between two colors.
Args:
destination (Color): Another color.
factor (float): A blend factor, 0 -> 1.
alpha (float | None): New alpha for result. Defaults to None.
destination: Another color.
factor: A blend factor, 0 -> 1.
alpha: New alpha for result. Defaults to None.
Returns:
Color: A new color.
A new color.
"""
if factor == 0:
return self
@@ -411,14 +411,14 @@ class Color(NamedTuple):
Any other formats will raise a `ColorParseError`.
Args:
color_text (str | Color): Text with a valid color format. Color objects will
color_text: Text with a valid color format. Color objects will
be returned unmodified.
Raises:
ColorParseError: If the color is not encoded correctly.
Returns:
Color: Instance encoding the color specified by the argument.
Instance encoding the color specified by the argument.
"""
if isinstance(color_text, Color):
return color_text
@@ -498,11 +498,11 @@ class Color(NamedTuple):
"""Darken the color by a given amount.
Args:
amount (float): Value between 0-1 to reduce luminance by.
alpha (float | None, optional): Alpha component for new color or None to copy alpha. Defaults to None.
amount: Value between 0-1 to reduce luminance by.
alpha: Alpha component for new color or None to copy alpha. Defaults to None.
Returns:
Color: New color.
New color.
"""
l, a, b = rgb_to_lab(self)
l -= amount * 100
@@ -512,11 +512,11 @@ class Color(NamedTuple):
"""Lighten the color by a given amount.
Args:
amount (float): Value between 0-1 to increase luminance by.
alpha (float | None, optional): Alpha component for new color or None to copy alpha. Defaults to None.
amount: Value between 0-1 to increase luminance by.
alpha: Alpha component for new color or None to copy alpha. Defaults to None.
Returns:
Color: New color.
New color.
"""
return self.darken(-amount, alpha)
@@ -525,11 +525,11 @@ class Color(NamedTuple):
"""Get a light or dark color that best contrasts this color, for use with text.
Args:
alpha (float, optional): An alpha value to adjust the pure white / black by.
alpha: An alpha value to adjust the pure white / black by.
Defaults to 0.95.
Returns:
Color: A new color, either an off-white or off-black
A new color, either an off-white or off-black
"""
brightness = self.brightness
white_contrast = abs(brightness - WHITE.brightness)

View File

@@ -13,7 +13,7 @@ class Coordinate(NamedTuple):
"""Get the coordinate to the left.
Returns:
Coordinate: The coordinate to the left.
The coordinate to the left.
"""
row, column = self
return Coordinate(row, column - 1)
@@ -22,7 +22,7 @@ class Coordinate(NamedTuple):
"""Get the coordinate to the right.
Returns:
Coordinate: The coordinate to the right.
The coordinate to the right.
"""
row, column = self
return Coordinate(row, column + 1)
@@ -31,7 +31,7 @@ class Coordinate(NamedTuple):
"""Get the coordinate above.
Returns:
Coordinate: The coordinate above.
The coordinate above.
"""
row, column = self
return Coordinate(row - 1, column)
@@ -40,7 +40,7 @@ class Coordinate(NamedTuple):
"""Get the coordinate below.
Returns:
Coordinate: The coordinate below.
The coordinate below.
"""
row, column = self
return Coordinate(row + 1, column)

View File

@@ -12,11 +12,11 @@ def friendly_list(
"'foo', 'bar', or 'baz'"
Args:
words (Iterable[str]): A list of words.
joiner (str, optional): The last joiner word. Defaults to "or".
words: A list of words.
joiner: The last joiner word. Defaults to "or".
Returns:
str: List as prose.
List as prose.
"""
words = [
repr(word) for word in sorted(words, key=str.lower) if word or not omit_empty

View File

@@ -17,10 +17,10 @@ def _markup_and_highlight(text: str) -> Text:
a styled Text object.
Args:
text (str): The text to highlight and markup.
text: The text to highlight and markup.
Returns:
Text: The Text, with highlighting and markup applied.
The Text, with highlighting and markup applied.
"""
return _highlighter(render(text))
@@ -30,11 +30,11 @@ class Example:
the help text.
Attributes:
markup (str): The markup to display for this example
markup: The markup to display for this example
"""
def __init__(self, markup: str) -> None:
self.markup = markup
self.markup: str = markup
def __rich_console__(
self, console: Console, options: ConsoleOptions
@@ -48,14 +48,14 @@ class Bullet:
pertaining to that information.
Attributes:
markup (str): The markup to display
examples (Iterable[Example] | None): An optional list of examples
markup: The markup to display
examples: An optional list of examples
to display below this bullet.
"""
def __init__(self, markup: str, examples: Iterable[Example] | None = None) -> None:
self.markup = markup
self.examples = [] if examples is None else examples
self.markup: str = markup
self.examples: Iterable[Example] | None = [] if examples is None else examples
def __rich_console__(
self, console: Console, options: ConsoleOptions
@@ -71,14 +71,14 @@ class HelpText:
value).
Attributes:
summary (str): A succinct summary of the issue.
bullets (Iterable[Bullet] | None): Bullet points which provide additional
summary: A succinct summary of the issue.
bullets: Bullet points which provide additional
context around the issue. These are rendered below the summary. Defaults to None.
"""
def __init__(self, summary: str, *, bullets: Iterable[Bullet] = None) -> None:
self.summary = summary
self.bullets = bullets or []
self.summary: str = summary
self.bullets: Iterable[Bullet] | None = bullets or []
def __str__(self) -> str:
return self.summary

View File

@@ -29,8 +29,8 @@ issue with inline styles."""
class ContextSpecificBullets:
"""
Args:
inline (Iterable[Bullet]): Information only relevant to users who are using inline styling.
css (Iterable[Bullet]): Information only relevant to users who are using CSS.
inline: Information only relevant to users who are using inline styling.
css: Information only relevant to users who are using CSS.
"""
inline: Sequence[Bullet]
@@ -40,7 +40,7 @@ class ContextSpecificBullets:
"""Get the information associated with the given context
Args:
context (StylingContext | None): The context to retrieve info for.
context: The context to retrieve info for.
"""
if context == "inline":
return list(self.inline)
@@ -52,10 +52,10 @@ def _python_name(property_name: str) -> str:
"""Convert a CSS property name to the corresponding Python attribute name
Args:
property_name (str): The CSS property name
property_name: The CSS property name
Returns:
str: The Python attribute name as found on the Styles object
The Python attribute name as found on the Styles object
"""
return property_name.replace("-", "_")
@@ -64,10 +64,10 @@ def _css_name(property_name: str) -> str:
"""Convert a Python style attribute name to the corresponding CSS property name
Args:
property_name (str): The Python property name
property_name: The Python property name
Returns:
str: The CSS property name
The CSS property name
"""
return property_name.replace("_", "-")
@@ -80,11 +80,11 @@ def _contextualize_property_name(
'-' with '_' or vice-versa
Args:
property_name (str): The name of the property
context (StylingContext): The context the property is being used in.
property_name: The name of the property
context: The context the property is being used in.
Returns:
str: The property name converted to the given context.
The property name converted to the given context.
"""
return _css_name(property_name) if context == "css" else _python_name(property_name)
@@ -131,13 +131,13 @@ def property_invalid_value_help_text(
property.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the spacing property is being used in.
property_name: The name of the property.
context: The context the spacing property is being used in.
Keyword Args:
suggested_property_name (str | None): A suggested name for the property (e.g. "width" for "wdth"). Defaults to None.
suggested_property_name: A suggested name for the property (e.g. "width" for "wdth").
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
summary = f"Invalid CSS property {property_name!r}"
@@ -158,12 +158,12 @@ def spacing_wrong_number_of_values_help_text(
for a spacing property (e.g. padding or margin).
Args:
property_name (str): The name of the property
num_values_supplied (int): The number of values the user supplied (a number other than 1, 2 or 4).
context (StylingContext | None): The context the spacing property is being used in.
property_name: The name of the property.
num_values_supplied: The number of values the user supplied (a number other than 1, 2 or 4).
context: The context the spacing property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -188,11 +188,11 @@ def spacing_invalid_value_help_text(
property.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the spacing property is being used in.
property_name: The name of the property.
context: The context the spacing property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -209,12 +209,12 @@ def scalar_help_text(
a scalar property.
Args:
property_name (str): The name of the property
num_values_supplied (int): The number of values the user supplied (a number other than 1, 2 or 4).
context (StylingContext | None): The context the scalar property is being used in.
property_name: The name of the property.
num_values_supplied: The number of values the user supplied (a number other than 1, 2 or 4).
context: The context the scalar property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -258,12 +258,12 @@ def string_enum_help_text(
enum property.
Args:
property_name (str): The name of the property
valid_values (list[str]): A list of the values that are considered valid.
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
valid_values: A list of the values that are considered valid.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -306,12 +306,12 @@ def color_property_help_text(
property. For example, an unparseable color string.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
error (ColorParseError | None): The error that caused this help text to be displayed. Defaults to None.
property_name: The name of the property.
context: The context the property is being used in.
error: The error that caused this help text to be displayed.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
summary = f"Invalid value for the [i]{property_name}[/] property"
@@ -360,14 +360,14 @@ def color_property_help_text(
def border_property_help_text(property_name: str, context: StylingContext) -> HelpText:
"""Help text to show when the user supplies an invalid value for a border
property (such as border, border-right, outline)
property (such as border, border-right, outline).
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -421,11 +421,11 @@ def layout_property_help_text(property_name: str, context: StylingContext) -> He
for a layout property.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -442,11 +442,11 @@ def dock_property_help_text(property_name: str, context: StylingContext) -> Help
"""Help text to show when the user supplies an invalid value for dock.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -477,11 +477,11 @@ def fractional_property_help_text(
"""Help text to show when the user supplies an invalid value for a fractional property.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(
@@ -515,10 +515,10 @@ def offset_property_help_text(context: StylingContext) -> HelpText:
"""Help text to show when the user supplies an invalid value for the offset property.
Args:
context (StylingContext | None): The context the property is being used in.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary="Invalid value for [i]offset[/] property",
@@ -555,10 +555,10 @@ def scrollbar_size_property_help_text(context: StylingContext) -> HelpText:
"""Help text to show when the user supplies an invalid value for the scrollbar-size property.
Args:
context (StylingContext | None): The context the property is being used in.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary="Invalid value for [i]scrollbar-size[/] property",
@@ -594,10 +594,10 @@ def scrollbar_size_single_axis_help_text(property_name: str) -> HelpText:
"""Help text to show when the user supplies an invalid value for a scrollbar-size-* property.
Args:
property_name (str): The name of the property
property_name: The name of the property.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary=f"Invalid value for [i]{property_name}[/]",
@@ -616,10 +616,10 @@ def integer_help_text(property_name: str) -> HelpText:
"""Help text to show when the user supplies an invalid integer value.
Args:
property_name (str): The name of the property
property_name: The name of the property.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary=f"Invalid value for [i]{property_name}[/]",
@@ -638,7 +638,7 @@ def align_help_text() -> HelpText:
"""Help text to show when the user supplies an invalid value for a `align`.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary="Invalid value for [i]align[/] property",
@@ -666,10 +666,10 @@ def align_help_text() -> HelpText:
def text_align_help_text() -> HelpText:
"""Help text to show when the user supplies an invalid value for the text-align property
"""Help text to show when the user supplies an invalid value for the text-align property.
Returns:
HelpText: Renderable for displaying the help text for this property.
Renderable for displaying the help text for this property.
"""
return HelpText(
summary="Invalid value for the [i]text-align[/] property.",
@@ -689,10 +689,10 @@ def offset_single_axis_help_text(property_name: str) -> HelpText:
"""Help text to show when the user supplies an invalid value for an offset-* property.
Args:
property_name (str): The name of the property
property_name: The name of the property.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
return HelpText(
summary=f"Invalid value for [i]{property_name}[/]",
@@ -715,11 +715,11 @@ def style_flags_property_help_text(
"""Help text to show when the user supplies an invalid value for a style flags property.
Args:
property_name (str): The name of the property
context (StylingContext | None): The context the property is being used in.
property_name: The name of the property.
context: The context the property is being used in.
Returns:
HelpText: Renderable for displaying the help text for this property
Renderable for displaying the help text for this property.
"""
property_name = _contextualize_property_name(property_name, context)
return HelpText(

View File

@@ -65,13 +65,13 @@ class GenericProperty(Generic[PropertyGetType, PropertySetType]):
self.layout = layout
def validate_value(self, value: object) -> PropertyGetType:
"""Validate the setter value
"""Validate the setter value.
Args:
value (object): The value being set.
value: The value being set.
Returns:
PropertyType: The value to be set.
The value to be set.
"""
# Raise StyleValueError here
return cast(PropertyGetType, value)
@@ -130,11 +130,11 @@ class ScalarProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> Scalar | None:
"""Get the scalar property
"""Get the scalar property.
Args:
obj (Styles): The ``Styles`` object
objtype (type[Styles]): The ``Styles`` class
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
The Scalar object or ``None`` if it's not set.
@@ -144,11 +144,11 @@ class ScalarProperty:
def __set__(
self, obj: StylesBase, value: float | int | Scalar | str | None
) -> None:
"""Set the scalar property
"""Set the scalar property.
Args:
obj (Styles): The ``Styles`` object.
value (float | int | Scalar | str | None): The value to set the scalar property to.
obj: The ``Styles`` object.
value: The value to set the scalar property to.
You can directly pass a float or int value, which will be interpreted with
a default unit of Cells. You may also provide a string such as ``"50%"``,
as you might do when writing CSS. If a string with no units is supplied,
@@ -254,11 +254,11 @@ class BoxProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> tuple[EdgeType, Color]:
"""Get the box property
"""Get the box property.
Args:
obj (Styles): The ``Styles`` object
objtype (type[Styles]): The ``Styles`` class
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
A ``tuple[EdgeType, Style]`` containing the string type of the box and
@@ -267,11 +267,11 @@ class BoxProperty:
return obj.get_rule(self.name) or ("", self._default_color)
def __set__(self, obj: Styles, border: tuple[EdgeType, str | Color] | None):
"""Set the box property
"""Set the box property.
Args:
obj (Styles): The ``Styles`` object.
value (tuple[EdgeType, str | Color | Style], optional): A 2-tuple containing the type of box to use,
obj: The ``Styles`` object.
value: A 2-tuple containing the type of box to use,
e.g. "dashed", and the ``Style`` to be used. You can supply the ``Style`` directly, or pass a
``str`` (e.g. ``"blue on #f0f0f0"`` ) or ``Color`` instead.
@@ -338,7 +338,7 @@ class Edges(NamedTuple):
"""Get spacing created by borders.
Returns:
tuple[int, int, int, int]: Spacing for top, right, bottom, and left.
Spacing for top, right, bottom, and left.
"""
(top, _), (right, _), (bottom, _), (left, _) = self
return Spacing(
@@ -353,7 +353,7 @@ class BorderProperty:
"""Descriptor for getting and setting full borders and outlines.
Args:
layout (bool): True if the layout should be refreshed after setting, False otherwise.
layout: True if the layout should be refreshed after setting, False otherwise.
"""
@@ -373,11 +373,11 @@ class BorderProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> Edges:
"""Get the border
"""Get the border.
Args:
obj (Styles): The ``Styles`` object
objtype (type[Styles]): The ``Styles`` class
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
An ``Edges`` object describing the type and style of each edge.
@@ -390,11 +390,11 @@ class BorderProperty:
obj: StylesBase,
border: BorderDefinition | None,
) -> None:
"""Set the border
"""Set the border.
Args:
obj (Styles): The ``Styles`` object.
border (Sequence[tuple[EdgeType, str | Color | Style] | None] | tuple[EdgeType, str | Color | Style] | None):
obj: The ``Styles`` object.
border:
A ``tuple[EdgeType, str | Color | Style]`` representing the type of box to use and the ``Style`` to apply
to the box.
Alternatively, you can supply a sequence of these tuples and they will be applied per-edge.
@@ -479,23 +479,23 @@ class SpacingProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> Spacing:
"""Get the Spacing
"""Get the Spacing.
Args:
obj (Styles): The ``Styles`` object
objtype (type[Styles]): The ``Styles`` class
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
Spacing: The Spacing. If unset, returns the null spacing ``(0, 0, 0, 0)``.
The Spacing. If unset, returns the null spacing ``(0, 0, 0, 0)``.
"""
return obj.get_rule(self.name, NULL_SPACING)
def __set__(self, obj: StylesBase, spacing: SpacingDimensions | None):
"""Set the Spacing
"""Set the Spacing.
Args:
obj (Styles): The ``Styles`` object.
style (Style | str, optional): You can supply the ``Style`` directly, or a
obj: The ``Styles`` object.
style: You can supply the ``Style`` directly, or a
string (e.g. ``"blue on #f0f0f0"``).
Raises:
@@ -530,23 +530,23 @@ class DockProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> DockEdge:
"""Get the Dock property
"""Get the Dock property.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
str: The dock name as a string, or "" if the rule is not set.
The dock name as a string, or "" if the rule is not set.
"""
return cast(DockEdge, obj.get_rule("dock", ""))
def __set__(self, obj: Styles, dock_name: str | None):
"""Set the Dock property
"""Set the Dock property.
Args:
obj (Styles): The ``Styles`` object
dock_name (str | None): The name of the dock to attach this widget to
obj: The ``Styles`` object.
dock_name: The name of the dock to attach this widget to.
"""
_rich_traceback_omit = True
if obj.set_rule("dock", dock_name):
@@ -564,8 +564,8 @@ class LayoutProperty:
) -> Layout | None:
"""
Args:
obj (Styles): The Styles object
objtype (type[Styles]): The Styles class
obj: The Styles object.
objtype: The Styles class.
Returns:
The ``Layout`` object.
"""
@@ -574,8 +574,8 @@ class LayoutProperty:
def __set__(self, obj: StylesBase, layout: str | Layout | None):
"""
Args:
obj (Styles): The Styles object.
layout (str | Layout): The layout to use. You can supply the name of the layout
obj: The Styles object.
layout: The layout to use. You can supply the name of the layout
or a ``Layout`` object.
"""
@@ -616,14 +616,14 @@ class OffsetProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> ScalarOffset:
"""Get the offset
"""Get the offset.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
ScalarOffset: The ``ScalarOffset`` indicating the adjustment that
The ``ScalarOffset`` indicating the adjustment that
will be made to widget position prior to it being rendered.
"""
return obj.get_rule(self.name, NULL_SCALAR)
@@ -631,10 +631,10 @@ class OffsetProperty:
def __set__(
self, obj: StylesBase, offset: tuple[int | str, int | str] | ScalarOffset | None
):
"""Set the offset
"""Set the offset.
Args:
obj: The ``Styles`` class
obj: The ``Styles`` class.
offset: A ScalarOffset object, or a 2-tuple of the form ``(x, y)`` indicating
the x and y offsets. When the ``tuple`` form is used, x and y can be specified
as either ``int`` or ``str``. The string format allows you to also specify
@@ -690,14 +690,14 @@ class StringEnumProperty:
self.name = name
def __get__(self, obj: StylesBase, objtype: type[StylesBase] | None = None) -> str:
"""Get the string property, or the default value if it's not set
"""Get the string property, or the default value if it's not set.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
str: The string property value
The string property value.
"""
return obj.get_rule(self.name, self._default)
@@ -705,8 +705,8 @@ class StringEnumProperty:
"""Set the string property and ensure it is in the set of allowed values.
Args:
obj (Styles): The ``Styles`` object
value (str, optional): The string value to set the property to.
obj: The ``Styles`` object.
value: The string value to set the property to.
Raises:
StyleValueError: If the value is not in the set of valid values.
@@ -736,23 +736,23 @@ class NameProperty:
self.name = name
def __get__(self, obj: StylesBase, objtype: type[StylesBase] | None) -> str:
"""Get the name property
"""Get the name property.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
str: The name
The name.
"""
return obj.get_rule(self.name, "")
def __set__(self, obj: StylesBase, name: str | None):
"""Set the name property
"""Set the name property.
Args:
obj: The ``Styles`` object
name: The name to set the property to
obj: The ``Styles`` object.
name: The name to set the property to.
Raises:
StyleTypeError: If the value is not a ``str``.
@@ -807,20 +807,20 @@ class ColorProperty:
"""Get a ``Color``.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
Color: The Color
The Color.
"""
return cast(Color, obj.get_rule(self.name, self._default_color))
def __set__(self, obj: StylesBase, color: Color | str | None):
"""Set the Color
"""Set the Color.
Args:
obj (Styles): The ``Styles`` object
color (Color | str | None): The color to set. Pass a ``Color`` instance directly,
obj: The ``Styles`` object.
color: The color to set. Pass a ``Color`` instance directly,
or pass a ``str`` which will be parsed into a color (e.g. ``"red""``, ``"rgb(20, 50, 80)"``,
``"#f4e32d"``).
@@ -870,27 +870,27 @@ class StyleFlagsProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> Style:
"""Get the ``Style``
"""Get the ``Style``.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
Style: The ``Style`` object
The ``Style`` object.
"""
return obj.get_rule(self.name, Style.null())
def __set__(self, obj: StylesBase, style_flags: Style | str | None):
"""Set the style using a style flag string
"""Set the style using a style flag string.
Args:
obj (Styles): The ``Styles`` object.
style_flags (str, optional): The style flags to set as a string. For example,
obj: The ``Styles`` object.
style_flags: The style flags to set as a string. For example,
``"bold italic"``.
Raises:
StyleValueError: If the value is an invalid style flag
StyleValueError: If the value is an invalid style flag.
"""
_rich_traceback_omit = True
if style_flags is None:
@@ -934,11 +934,11 @@ class TransitionsProperty:
"""Get a mapping of properties to the transitions applied to them.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
dict[str, Transition]: A ``dict`` mapping property names to the ``Transition`` applied to them.
A ``dict`` mapping property names to the ``Transition`` applied to them.
e.g. ``{"offset": Transition(...), ...}``. If no transitions have been set, an empty ``dict``
is returned.
"""
@@ -964,14 +964,14 @@ class FractionalProperty:
self.name = name
def __get__(self, obj: StylesBase, type: type[StylesBase]) -> float:
"""Get the property value as a float between 0 and 1
"""Get the property value as a float between 0 and 1.
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
obj: The ``Styles`` object.
objtype: The ``Styles`` class.
Returns:
float: The value of the property (in the range (0, 1))
The value of the property (in the range (0, 1)).
"""
return cast(float, obj.get_rule(self.name, self.default))
@@ -979,8 +979,8 @@ class FractionalProperty:
"""Set the property value, clamping it between 0 and 1.
Args:
obj (Styles): The Styles object.
value (float|str|None): The value to set as a float between 0 and 1, or
obj: The Styles object.
value: The value to set as a float between 0 and 1, or
as a percentage string such as '10%'.
"""
_rich_traceback_omit = True

View File

@@ -67,11 +67,11 @@ def _join_tokens(tokens: Iterable[Token], joiner: str = "") -> str:
"""Convert tokens into a string by joining their values
Args:
tokens (Iterable[Token]): Tokens to join
joiner (str): String to join on, defaults to ""
tokens: Tokens to join
joiner: String to join on, defaults to ""
Returns:
str: The tokens, joined together to form a string.
The tokens, joined together to form a string.
"""
return joiner.join(token.value for token in tokens)
@@ -135,7 +135,7 @@ class StylesBuilder:
i.e. the ones for which we have a `process_[property name]` method
Returns:
Sequence[str]: All the "Python-ised" CSS property names this class can handle.
All the "Python-ised" CSS property names this class can handle.
Example: ("width", "background", "offset_x", ...)
"""
@@ -173,12 +173,12 @@ class StylesBuilder:
"""Process a declaration that expects an enum.
Args:
name (str): Name of declaration.
tokens (list[Token]): Tokens from parser.
valid_values (list[str]): A set of valid values.
name: Name of declaration.
tokens: Tokens from parser.
valid_values: A set of valid values.
Returns:
bool: True if the value is valid or False if it is invalid (also generates an error)
True if the value is valid or False if it is invalid (also generates an error)
"""
if len(tokens) != 1:
@@ -964,10 +964,10 @@ class StylesBuilder:
Returns a valid CSS property "Python" name, or None if no close matches could be found.
Args:
rule_name (str): An invalid "Python-ised" CSS property (i.e. "offst_x" rather than "offst-x")
rule_name: An invalid "Python-ised" CSS property (i.e. "offst_x" rather than "offst-x")
Returns:
str | None: The closest valid "Python-ised" CSS property.
The closest valid "Python-ised" CSS property.
Returns `None` if no close matches could be found.
Example: returns "background" for rule_name "bkgrund", "offset_x" for "ofset_x"

View File

@@ -27,13 +27,13 @@ class StyleValueError(ValueError):
"""Raised when the value of a style property is not valid
Attributes:
help_text (HelpText | None): Optional HelpText to be rendered when this
help_text: Optional HelpText to be rendered when this
error is raised.
"""
def __init__(self, *args: object, help_text: HelpText | None = None):
super().__init__(*args)
self.help_text = help_text
self.help_text: HelpText | None = help_text
def __rich_console__(
self, console: Console, options: ConsoleOptions

View File

@@ -12,11 +12,11 @@ def match(selector_sets: Iterable[SelectorSet], node: DOMNode) -> bool:
"""Check if a given node matches any of the given selector sets.
Args:
selector_sets (Iterable[SelectorSet]): Iterable of selector sets.
node (DOMNode): DOM node.
selector_sets: Iterable of selector sets.
node: DOM node.
Returns:
bool: True if the node matches the selector, otherwise False.
True if the node matches the selector, otherwise False.
"""
return any(
_check_selectors(selector_set.selectors, node.css_path_nodes)
@@ -28,11 +28,11 @@ def _check_selectors(selectors: list[Selector], css_path_nodes: list[DOMNode]) -
"""Match a list of selectors against DOM nodes.
Args:
selectors (list[Selector]): A list of selectors.
css_path_nodes (list[DOMNode]): The DOM nodes to check the selectors against.
selectors: A list of selectors.
css_path_nodes: The DOM nodes to check the selectors against.
Returns:
bool: True if any node in css_path_nodes matches a selector.
True if any node in css_path_nodes matches a selector.
"""
DESCENDENT = CombinatorType.DESCENDENT

View File

@@ -71,7 +71,7 @@ class Selector:
"""Adds a pseudo class and updates specificity.
Args:
pseudo_class (str): Name of pseudo class.
pseudo_class: Name of pseudo class.
"""
self.pseudo_classes.append(pseudo_class)
specificity1, specificity2, specificity3 = self.specificity
@@ -81,10 +81,10 @@ class Selector:
"""Check if a given node matches the selector.
Args:
node (DOMNode): A DOM node.
node: A DOM node.
Returns:
bool: True if the selector matches, otherwise False.
True if the selector matches, otherwise False.
"""
return self._checks[self.type](node)
@@ -188,7 +188,7 @@ class RuleSet:
"""Generate the CSS this RuleSet
Returns:
str: A string containing CSS code.
A string containing CSS code.
"""
declarations = "\n".join(f" {line}" for line in self.styles.css_lines)
css = f"{self.selectors} {{\n{declarations}\n}}"

View File

@@ -174,11 +174,11 @@ def parse_declarations(css: str, path: str) -> Styles:
"""Parse declarations and return a Styles object.
Args:
css (str): String containing CSS.
path (str): Path to the CSS, or something else to identify the location.
css: String containing CSS.
path: Path to the CSS, or something else to identify the location.
Returns:
Styles: A styles object.
A styles object.
"""
tokens = iter(tokenize_declarations(css, path))
@@ -223,9 +223,9 @@ def _unresolved(variable_name: str, variables: Iterable[str], token: Token) -> N
"""Raise a TokenError regarding an unresolved variable.
Args:
variable_name (str): A variable name.
variables (Iterable[str]): Possible choices used to generate suggestion.
token (Token): The Token.
variable_name: A variable name.
variables: Possible choices used to generate suggestion.
token: The Token.
Raises:
UnresolvedVariableError: Always raises a TokenError.
@@ -252,11 +252,11 @@ def substitute_references(
tokens with the tokens representing their values.
Args:
tokens (Iterable[Token]): Iterator of Tokens which may contain tokens
tokens: Iterator of Tokens which may contain tokens
with the name "variable_ref".
Returns:
Iterable[Token]: Yields Tokens such that any variable references (tokens where
Yields Tokens such that any variable references (tokens where
token.name == "variable_ref") have been replaced with the tokens representing
the value. In other words, an Iterable of Tokens similar to the original input,
but with variables resolved. Substituted tokens will have their referenced_by
@@ -343,10 +343,10 @@ def parse(
and generating rule sets from it.
Args:
css (str): The input CSS
path (str): Path to the CSS
variables (dict[str, str]): Substitution variables to substitute tokens for.
is_default_rules (bool): True if the rules we're extracting are
css: The input CSS
path: Path to the CSS
variables: Substitution variables to substitute tokens for.
is_default_rules: True if the rules we're extracting are
default (i.e. in Widget.DEFAULT_CSS) rules. False if they're from user defined CSS.
"""

View File

@@ -158,10 +158,10 @@ class DOMQuery(Generic[QueryType]):
"""Filter this set by the given CSS selector.
Args:
selector (str): A CSS selector.
selector: A CSS selector.
Returns:
DOMQuery: New DOM Query.
New DOM Query.
"""
return DOMQuery(self.node, filter=selector, parent=self)
@@ -170,10 +170,10 @@ class DOMQuery(Generic[QueryType]):
"""Exclude nodes that match a given selector.
Args:
selector (str): A CSS selector.
selector: A CSS selector.
Returns:
DOMQuery: New DOM query.
New DOM query.
"""
return DOMQuery(self.node, exclude=selector, parent=self)
@@ -193,7 +193,7 @@ class DOMQuery(Generic[QueryType]):
"""Get the *first* matching node.
Args:
expect_type (type[ExpectType] | None, optional): Require matched node is of this type,
expect_type: Require matched node is of this type,
or None for any type. Defaults to None.
Raises:
@@ -201,7 +201,7 @@ class DOMQuery(Generic[QueryType]):
NoMatches: If there are no matching nodes in the query.
Returns:
Widget | ExpectType: The matching Widget.
The matching Widget.
"""
if self.nodes:
first = self.nodes[0]
@@ -228,7 +228,7 @@ class DOMQuery(Generic[QueryType]):
"""Get the *only* matching node.
Args:
expect_type (type[ExpectType] | None, optional): Require matched node is of this type,
expect_type: Require matched node is of this type,
or None for any type. Defaults to None.
Raises:
@@ -237,7 +237,7 @@ class DOMQuery(Generic[QueryType]):
TooManyMatches: If there is more than one matching node in the query.
Returns:
Widget | ExpectType: The matching Widget.
The matching Widget.
"""
# Call on first to get the first item. Here we'll use all of the
# testing and checking it provides.
@@ -272,7 +272,7 @@ class DOMQuery(Generic[QueryType]):
"""Get the *last* matching node.
Args:
expect_type (type[ExpectType] | None, optional): Require matched node is of this type,
expect_type: Require matched node is of this type,
or None for any type. Defaults to None.
Raises:
@@ -280,7 +280,7 @@ class DOMQuery(Generic[QueryType]):
NoMatches: If there are no matching nodes in the query.
Returns:
Widget | ExpectType: The matching Widget.
The matching Widget.
"""
if not self.nodes:
raise NoMatches(f"No nodes match {self!r}")
@@ -305,7 +305,7 @@ class DOMQuery(Generic[QueryType]):
"""Get query results, optionally filtered by a given type.
Args:
filter_type (type[ExpectType] | None): A Widget class to filter results,
filter_type: A Widget class to filter results,
or None for no filter. Defaults to None.
Yields:
@@ -322,10 +322,10 @@ class DOMQuery(Generic[QueryType]):
"""Set the given class name(s) according to a condition.
Args:
add (bool): Add the classes if True, otherwise remove them.
add: Add the classes if True, otherwise remove them.
Returns:
DOMQuery: Self.
Self.
"""
for node in self:
node.set_class(add, *class_names)
@@ -353,7 +353,7 @@ class DOMQuery(Generic[QueryType]):
"""Remove matched nodes from the DOM.
Returns:
AwaitRemove: An awaitable object that waits for the widgets to be removed.
An awaitable object that waits for the widgets to be removed.
"""
app = active_app.get()
await_remove = app._remove_nodes(list(self))
@@ -365,7 +365,7 @@ class DOMQuery(Generic[QueryType]):
"""Set styles on matched nodes.
Args:
css (str, optional): CSS declarations to parser, or None. Defaults to None.
css: CSS declarations to parser, or None. Defaults to None.
"""
_rich_traceback_omit = True
@@ -387,11 +387,11 @@ class DOMQuery(Generic[QueryType]):
"""Refresh matched nodes.
Args:
repaint (bool): Repaint node(s). defaults to True.
layout (bool): Layout node(s). Defaults to False.
repaint: Repaint node(s). defaults to True.
layout: Layout node(s). Defaults to False.
Returns:
DOMQuery: Query for chaining.
Query for chaining.
"""
for node in self:
node.refresh(repaint=repaint, layout=layout)

View File

@@ -60,13 +60,13 @@ def _resolve_cells(
"""Resolves explicit cell size, i.e. width: 10
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return Fraction(value)
@@ -77,13 +77,13 @@ def _resolve_fraction(
"""Resolves a fraction unit i.e. width: 2fr
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return fraction_unit * Fraction(value)
@@ -94,13 +94,13 @@ def _resolve_width(
"""Resolves width unit i.e. width: 50w.
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return Fraction(value) * Fraction(size.width, 100)
@@ -111,13 +111,13 @@ def _resolve_height(
"""Resolves height unit, i.e. height: 12h.
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return Fraction(value) * Fraction(size.height, 100)
@@ -128,13 +128,13 @@ def _resolve_view_width(
"""Resolves view width unit, i.e. width: 25vw.
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return Fraction(value) * Fraction(viewport.width, 100)
@@ -145,13 +145,13 @@ def _resolve_view_height(
"""Resolves view height unit, i.e. height: 25vh.
Args:
value (float): Scalar value.
size (Size): Size of widget.
viewport (Size): Size of viewport.
fraction_unit (Fraction): Size of fraction, i.e. size of 1fr as a Fraction.
value: Scalar value.
size: Size of widget.
viewport: Size of viewport.
fraction_unit: Size of fraction, i.e. size of 1fr as a Fraction.
Returns:
Fraction: Resolved unit.
Resolved unit.
"""
return Fraction(value) * Fraction(viewport.height, 100)
@@ -170,10 +170,10 @@ def get_symbols(units: Iterable[Unit]) -> list[str]:
"""Get symbols for an iterable of units.
Args:
units (Iterable[Unit]): A number of units.
units: A number of units.
Returns:
list[str]: List of symbols.
List of symbols.
"""
return [UNIT_SYMBOL[unit] for unit in units]
@@ -237,10 +237,10 @@ class Scalar(NamedTuple):
"""Create a scalar with cells unit.
Args:
value (float): A number of cells.
value: A number of cells.
Returns:
Scalar: New Scalar.
New Scalar.
"""
return cls(float(value), Unit.CELLS, Unit.WIDTH)
@@ -249,13 +249,13 @@ class Scalar(NamedTuple):
"""Parse a string in to a Scalar
Args:
token (str): A string containing a scalar, e.g. "3.14fr"
token: A string containing a scalar, e.g. "3.14fr"
Raises:
ScalarParseError: If the value is not a valid scalar
Returns:
Scalar: New scalar
New scalar
"""
if token.lower() == "auto":
scalar = cls(1.0, Unit.AUTO, Unit.AUTO)
@@ -274,14 +274,14 @@ class Scalar(NamedTuple):
"""Resolve scalar with units in to a dimensions.
Args:
size (tuple[int, int]): Size of the container.
viewport (tuple[int, int]): Size of the viewport (typically terminal size)
size: Size of the container.
viewport: Size of the viewport (typically terminal size)
Raises:
ScalarResolveError: If the unit is unknown.
Returns:
int: A size (in cells)
A size (in cells)
"""
value, unit, percent_unit = self
@@ -304,9 +304,9 @@ class Scalar(NamedTuple):
"""Get a copy of this Scalar, with values optionally modified
Args:
value (float | None): The new value, or None to keep the same value
unit (Unit | None): The new unit, or None to keep the same unit
percent_unit (Unit | None): The new percent_unit, or None to keep the same percent_unit
value: The new value, or None to keep the same value
unit: The new unit, or None to keep the same unit
percent_unit: The new percent_unit, or None to keep the same percent_unit
"""
return Scalar(
value if value is not None else self.value,
@@ -332,10 +332,10 @@ class ScalarOffset(NamedTuple):
"""Create a Scalar offset from a tuple of integers.
Args:
offset (tuple[int, int]): Offset in cells.
offset: Offset in cells.
Returns:
ScalarOffset: New offset.
New offset.
"""
x, y = offset
return cls(
@@ -355,11 +355,11 @@ class ScalarOffset(NamedTuple):
"""Resolve the offset in to cells.
Args:
size (Size): Size of container.
viewport (Size): Size of viewport.
size: Size of container.
viewport: Size of viewport.
Returns:
Offset: Offset in cells.
Offset in cells.
"""
x, y = self
return Offset(
@@ -375,7 +375,7 @@ def percentage_string_to_float(string: str) -> float:
"""Convert a string percentage e.g. '20%' to a float e.g. 20.0.
Args:
string (str): The percentage string to convert.
string: The percentage string to convert.
"""
string = string.strip()
if string.endswith("%"):

View File

@@ -349,7 +349,7 @@ class StylesBase(ABC):
"""Get space around widget.
Returns:
Spacing: Space around widget content.
Space around widget content.
"""
return self.padding + self.border.spacing
@@ -366,10 +366,10 @@ class StylesBase(ABC):
"""Check if a rule is set on this Styles object.
Args:
rule (str): Rule name.
rule: Rule name.
Returns:
bool: ``True`` if the rules is present, otherwise ``False``.
``True`` if the rules is present, otherwise ``False``.
"""
@abstractmethod
@@ -377,10 +377,10 @@ class StylesBase(ABC):
"""Removes the rule from the Styles object, as if it had never been set.
Args:
rule (str): Rule name.
rule: Rule name.
Returns:
bool: ``True`` if a rule was cleared, or ``False`` if the rule is already not set.
``True`` if a rule was cleared, or ``False`` if the rule is already not set.
"""
@abstractmethod
@@ -388,7 +388,7 @@ class StylesBase(ABC):
"""Get the rules in a mapping.
Returns:
RulesMap: A TypedDict of the rules.
A TypedDict of the rules.
"""
@abstractmethod
@@ -396,11 +396,11 @@ class StylesBase(ABC):
"""Set a rule.
Args:
rule (str): Rule name.
value (object | None): New rule value.
rule: Rule name.
value: New rule value.
Returns:
bool: ``True`` if the rule changed, otherwise ``False``.
``True`` if the rule changed, otherwise ``False``.
"""
@abstractmethod
@@ -408,11 +408,11 @@ class StylesBase(ABC):
"""Get an individual rule.
Args:
rule (str): Name of rule.
default (object, optional): Default if rule does not exists. Defaults to None.
rule: Name of rule.
default: Default if rule does not exists. Defaults to None.
Returns:
object: Rule value or default.
Rule value or default.
"""
@abstractmethod
@@ -420,8 +420,8 @@ class StylesBase(ABC):
"""Mark the styles as requiring a refresh.
Args:
layout (bool, optional): Also require a layout. Defaults to False.
children (bool, optional): Also refresh children. Defaults to False.
layout: Also require a layout. Defaults to False.
children: Also refresh children. Defaults to False.
"""
@abstractmethod
@@ -433,7 +433,7 @@ class StylesBase(ABC):
"""Merge values from another Styles.
Args:
other (Styles): A Styles object.
other: A Styles object.
"""
@abstractmethod
@@ -441,7 +441,7 @@ class StylesBase(ABC):
"""Merge rules in to Styles.
Args:
rules (RulesMap): A mapping of rules.
rules: A mapping of rules.
"""
def get_render_rules(self) -> RulesMap:
@@ -455,10 +455,10 @@ class StylesBase(ABC):
"""Check if a given rule may be animated.
Args:
rule (str): Name of the rule.
rule: Name of the rule.
Returns:
bool: ``True`` if the rule may be animated, otherwise ``False``.
``True`` if the rule may be animated, otherwise ``False``.
"""
return rule in cls.ANIMATABLE
@@ -468,12 +468,12 @@ class StylesBase(ABC):
"""Parse CSS and return a Styles object.
Args:
css (str): Textual CSS.
path (str): Path or string indicating source of CSS.
node (DOMNode, optional): Node to associate with the Styles. Defaults to None.
css: Textual CSS.
path: Path or string indicating source of CSS.
node: Node to associate with the Styles. Defaults to None.
Returns:
Styles: A Styles instance containing result of parsing CSS.
A Styles instance containing result of parsing CSS.
"""
from .parse import parse_declarations
@@ -485,10 +485,10 @@ class StylesBase(ABC):
"""Get a transition.
Args:
key (str): Transition key.
key: Transition key.
Returns:
Transition | None: Transition object or None it no transition exists.
Transition object or None it no transition exists.
"""
if key in self.ANIMATABLE:
return self.transitions.get(key, None)
@@ -499,11 +499,11 @@ class StylesBase(ABC):
"""Align the width dimension.
Args:
width (int): Width of the content.
parent_width (int): Width of the parent container.
width: Width of the content.
parent_width: Width of the parent container.
Returns:
int: An offset to add to the X coordinate.
An offset to add to the X coordinate.
"""
offset_x = 0
align_horizontal = self.align_horizontal
@@ -518,11 +518,11 @@ class StylesBase(ABC):
"""Align the height dimensions
Args:
height (int): Height of the content.
parent_height (int): Height of the parent container.
height: Height of the content.
parent_height: Height of the parent container.
Returns:
int: An offset to add to the Y coordinate.
An offset to add to the Y coordinate.
"""
offset_y = 0
align_vertical = self.align_vertical
@@ -537,11 +537,11 @@ class StylesBase(ABC):
"""Align a size according to alignment rules.
Args:
child (tuple[int, int]): The size of the child (width, height)
parent (tuple[int, int]): The size of the parent (width, height)
child: The size of the child (width, height)
parent: The size of the parent (width, height)
Returns:
Offset: Offset required to align the child.
Offset required to align the child.
"""
width, height = child
parent_width, parent_height = parent
@@ -555,7 +555,7 @@ class StylesBase(ABC):
"""Get the style properties associated with this node only (not including parents in the DOM).
Returns:
Style: Rich Style object.
Rich Style object.
"""
style = Style(
color=(self.color.rich_color if self.has_rule("color") else None),
@@ -588,10 +588,10 @@ class Styles(StylesBase):
"""Removes the rule from the Styles object, as if it had never been set.
Args:
rule (str): Rule name.
rule: Rule name.
Returns:
bool: ``True`` if a rule was cleared, or ``False`` if it was already not set.
``True`` if a rule was cleared, or ``False`` if it was already not set.
"""
changed = self._rules.pop(rule, None) is not None
if changed:
@@ -605,11 +605,11 @@ class Styles(StylesBase):
"""Set a rule.
Args:
rule (str): Rule name.
value (object | None): New rule value.
rule: Rule name.
value: New rule value.
Returns:
bool: ``True`` if the rule changed, otherwise ``False``.
``True`` if the rule changed, otherwise ``False``.
"""
if value is None:
changed = self._rules.pop(rule, None) is not None
@@ -642,7 +642,7 @@ class Styles(StylesBase):
"""Merge values from another Styles.
Args:
other (Styles): A Styles object.
other: A Styles object.
"""
self._updates += 1
self._rules.update(other._rules)
@@ -661,12 +661,12 @@ class Styles(StylesBase):
well as higher specificity of user CSS vs widget CSS.
Args:
specificity (Specificity3): A node specificity.
is_default_rules (bool): True if the rules we're extracting are
specificity: A node specificity.
is_default_rules: True if the rules we're extracting are
default (i.e. in Widget.DEFAULT_CSS) rules. False if they're from user defined CSS.
Returns:
list[tuple[str, Specificity6, Any]]]: A list containing a tuple of <RULE NAME>, <SPECIFICITY> <RULE VALUE>.
A list containing a tuple of <RULE NAME>, <SPECIFICITY> <RULE VALUE>.
"""
is_important = self.important.__contains__
rules = [
@@ -698,11 +698,11 @@ class Styles(StylesBase):
"""Get pairs of strings containing <RULE NAME>, <RULE VALUE> for border css declarations.
Args:
rules (RulesMap): A rules map.
name (str): Name of rules (border or outline)
rules: A rules map.
name: Name of rules (border or outline)
Returns:
Iterable[tuple[str, str]]: An iterable of CSS declarations.
An iterable of CSS declarations.
"""
@@ -965,7 +965,7 @@ class RenderStyles(StylesBase):
"""A key key, that changes when any style is changed.
Returns:
int: An opaque integer.
An opaque integer.
"""
return self._updates + self._base_styles._updates + self._inline_styles._updates
@@ -990,7 +990,7 @@ class RenderStyles(StylesBase):
"""Get space around widget.
Returns:
Spacing: Space around widget content.
Space around widget content.
"""
# This is (surprisingly) a bit of a bottleneck
if self._gutter is not None:
@@ -1016,14 +1016,14 @@ class RenderStyles(StylesBase):
"""Animate an attribute.
Args:
attribute (str): Name of the attribute to animate.
value (float | Animatable): The value to animate to.
final_value (object, optional): The final value of the animation. Defaults to `value` if not set.
duration (float | None, optional): The duration of the animate. Defaults to None.
speed (float | None, optional): The speed of the animation. Defaults to None.
delay (float, optional): A delay (in seconds) before the animation starts. Defaults to 0.0.
easing (EasingFunction | str, optional): An easing method. Defaults to "in_out_cubic".
on_complete (CallbackType | None, optional): A callable to invoke when the animation is finished. Defaults to None.
attribute: Name of the attribute to animate.
value: The value to animate to.
final_value: The final value of the animation. Defaults to `value` if not set.
duration: The duration of the animate. Defaults to None.
speed: The speed of the animation. Defaults to None.
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
easing: An easing method. Defaults to "in_out_cubic".
on_complete: A callable to invoke when the animation is finished. Defaults to None.
"""
if self._animate is None:
@@ -1053,7 +1053,7 @@ class RenderStyles(StylesBase):
"""Merge values from another Styles.
Args:
other (Styles): A Styles object.
other: A Styles object.
"""
self._inline_styles.merge(other)

View File

@@ -109,8 +109,8 @@ class CssSource(NamedTuple):
vs widget-level stylesheets.
Args:
content (str): The CSS as a string.
is_defaults (bool): True if the CSS is default (i.e. that defined at the widget level).
content: The CSS as a string.
is_defaults: True if the CSS is default (i.e. that defined at the widget level).
False if it's user CSS (which will override the defaults).
"""
@@ -143,7 +143,7 @@ class Stylesheet:
"""List of rule sets.
Returns:
list[RuleSet]: List of rules sets for this stylesheet.
List of rules sets for this stylesheet.
"""
if self._require_parse:
self.parse()
@@ -156,7 +156,7 @@ class Stylesheet:
"""Structure that maps a selector on to a list of rules.
Returns:
dict[str, list[RuleSet]]: Mapping of selector to rule sets.
Mapping of selector to rule sets.
"""
if self._rules_map is None:
rules_map: dict[str, list[RuleSet]] = defaultdict(list)
@@ -174,7 +174,7 @@ class Stylesheet:
"""Create a copy of this stylesheet.
Returns:
Stylesheet: New stylesheet.
New stylesheet.
"""
stylesheet = Stylesheet(variables=self._variables.copy())
stylesheet.source = self.source.copy()
@@ -184,7 +184,7 @@ class Stylesheet:
"""Set CSS variables.
Args:
variables (dict[str, str]): A mapping of name to variable.
variables: A mapping of name to variable.
"""
self._variables = variables
self.__variable_tokens = None
@@ -200,16 +200,16 @@ class Stylesheet:
Args:
is_default_rules:
css (str): String containing Textual CSS.
path (str | PurePath): Path to CSS or unique identifier
is_default_rules (bool): True if the rules we're extracting are
css: String containing Textual CSS.
path: Path to CSS or unique identifier
is_default_rules: True if the rules we're extracting are
default (i.e. in Widget.DEFAULT_CSS) rules. False if they're from user defined CSS.
Raises:
StylesheetError: If the CSS is invalid.
Returns:
list[RuleSet]: List of RuleSets.
List of RuleSets.
"""
try:
rules = list(
@@ -232,7 +232,7 @@ class Stylesheet:
"""Read Textual CSS file.
Args:
filename (str | PurePath): filename of CSS.
filename: Filename of CSS.
Raises:
StylesheetError: If the CSS could not be read.
@@ -252,7 +252,7 @@ class Stylesheet:
"""Read multiple CSS files, in order.
Args:
paths (list[PurePath]): The paths of the CSS files to read, in order.
paths: The paths of the CSS files to read, in order.
Raises:
StylesheetError: If the CSS could not be read.
@@ -271,12 +271,12 @@ class Stylesheet:
"""Parse CSS from a string.
Args:
css (str): String with CSS source.
path (str | PurePath, optional): The path of the source if a file, or some other identifier.
css: String with CSS source.
path: The path of the source if a file, or some other identifier.
Defaults to None.
is_default_css (bool): True if the CSS is defined in the Widget, False if the CSS is defined
is_default_css: True if the CSS is defined in the Widget, False if the CSS is defined
in a user stylesheet.
tie_breaker (int): Integer representing the priority of this source.
tie_breaker: Integer representing the priority of this source.
Raises:
StylesheetError: If the CSS could not be read.
@@ -353,12 +353,12 @@ class Stylesheet:
"""Apply the stylesheet to a DOM node.
Args:
node (DOMNode): The ``DOMNode`` to apply the stylesheet to.
node: The ``DOMNode`` to apply the stylesheet to.
Applies the styles defined in this ``Stylesheet`` to the node.
If the same rule is defined multiple times for the node (e.g. multiple
classes modifying the same CSS property), then only the most specific
rule will be applied.
animate (bool, optional): Animate changed rules. Defaults to ``False``.
animate: Animate changed rules. Defaults to ``False``.
"""
# Dictionary of rule attribute names e.g. "text_background" to list of tuples.
# The tuples contain the rule specificity, and the value for that rule.
@@ -420,9 +420,9 @@ class Stylesheet:
"""Replace style rules on a node, animating as required.
Args:
node (DOMNode): A DOM node.
rules (RulesMap): Mapping of rules.
animate (bool, optional): Enable animation. Defaults to False.
node: A DOM node.
rules: Mapping of rules.
animate: Enable animation. Defaults to False.
"""
# Alias styles and base styles
@@ -486,8 +486,8 @@ class Stylesheet:
"""Update styles on node and its children.
Args:
root (DOMNode): Root note to update.
animate (bool, optional): Enable CSS animation. Defaults to False.
root: Root note to update.
animate: Enable CSS animation. Defaults to False.
"""
self.update_nodes(root.walk_children(with_self=True), animate=animate)
@@ -496,8 +496,8 @@ class Stylesheet:
"""Update styles for nodes.
Args:
nodes (DOMNode): Nodes to update.
animate (bool, optional): Enable CSS animation. Defaults to False.
nodes: Nodes to update.
animate: Enable CSS animation. Defaults to False.
"""
rules_map = self.rules_map

View File

@@ -187,11 +187,11 @@ def tokenize_values(values: dict[str, str]) -> dict[str, list[Token]]:
"""Tokens the values in a dict of strings.
Args:
values (dict[str, str]): A mapping of CSS variable name on to a value, to be
values: A mapping of CSS variable name on to a value, to be
added to the CSS context.
Returns:
dict[str, list[Token]]: A mapping of name on to a list of tokens,
A mapping of name on to a list of tokens,
"""
value_tokens = {
name: list(tokenize_value(value, "__name__")) for name, value in values.items()

View File

@@ -28,11 +28,11 @@ class TokenError(Exception):
) -> None:
"""
Args:
path (str): Path to source or "<object>" if source is parsed from a literal.
code (str): The code being parsed.
start (tuple[int, int]): Line number of the error.
message (str): A message associated with the error.
end (tuple[int, int] | None): End location of token, or None if not known. Defaults to None.
path: Path to source or "<object>" if source is parsed from a literal.
code: The code being parsed.
start: Line number of the error.
message: A message associated with the error.
end: End location of token, or None if not known. Defaults to None.
"""
self.path = path
@@ -45,7 +45,7 @@ class TokenError(Exception):
"""Get a short snippet of code around a given line number.
Returns:
Panel: A renderable.
A renderable.
"""
line_no = self.start[0]
# TODO: Highlight column number

View File

@@ -410,8 +410,8 @@ class DemoApp(App):
"""Save an SVG "screenshot". This action will save an SVG file containing the current contents of the screen.
Args:
filename (str | None, optional): Filename of screenshot, or None to auto-generate. Defaults to None.
path (str, optional): Path to directory. Defaults to "./".
filename: Filename of screenshot, or None to auto-generate. Defaults to None.
path: Path to directory. Defaults to "./".
"""
self.bell()
path = self.save_screenshot(filename, path)

View File

@@ -96,13 +96,13 @@ class ColorSystem:
"""Generate a mapping of color name on to a CSS color.
Args:
dark (bool, optional): Enable dark mode. Defaults to False.
luminosity_spread (float, optional): Amount of luminosity to subtract and add to generate
dark: Enable dark mode. Defaults to False.
luminosity_spread: Amount of luminosity to subtract and add to generate
shades. Defaults to 0.2.
text_alpha (float, optional): Alpha value for text. Defaults to 0.9.
text_alpha: Alpha value for text. Defaults to 0.9.
Returns:
dict[str, str]: A mapping of color name on to a CSS-style encoded color
A mapping of color name on to a CSS-style encoded color
"""
@@ -198,11 +198,11 @@ def show_design(light: ColorSystem, dark: ColorSystem) -> Table:
"""Generate a renderable to show color systems.
Args:
light (ColorSystem): Light ColorSystem.
dark (ColorSystem): Dark ColorSystem
light: Light ColorSystem.
dark: Dark ColorSystem
Returns:
Table: Table showing all colors.
Table showing all colors.
"""

View File

@@ -33,10 +33,10 @@ class DevtoolsLog(NamedTuple):
"""A devtools log message.
Attributes:
objects_or_string (tuple[Any, ...]): Corresponds to the data that will
objects_or_string: Corresponds to the data that will
ultimately be passed to Console.print in order to generate the log
Segments.
caller (inspect.FrameInfo): Information about where this log message was
caller: Information about where this log message was
created. In other words, where did the user call `print` or `App.log`
from. Used to display line number and file name in the devtools window.
"""
@@ -54,7 +54,7 @@ class DevtoolsConsole(Console):
"""Return the list of Segments that have be printed using this console
Returns:
list[Segment]: The list of Segments that have been printed using this console
The list of Segments that have been printed using this console
"""
with self._record_buffer_lock:
segments = self._record_buffer[:]
@@ -94,8 +94,8 @@ class DevtoolsClient:
```
Args:
host (str): The host the devtools server is running on, defaults to "127.0.0.1"
port (int): The port the devtools server is accessed via, defaults to 8081
host: The host the devtools server is running on, defaults to "127.0.0.1"
port: The port the devtools server is accessed via, defaults to 8081
"""
def __init__(self, host: str = "127.0.0.1", port: int = DEVTOOLS_PORT) -> None:
@@ -197,7 +197,7 @@ class DevtoolsClient:
"""Checks connection to devtools server.
Returns:
bool: True if this host is connected to the server. False otherwise.
True if this host is connected to the server. False otherwise.
"""
if not self.session or not self.websocket:
return False
@@ -212,7 +212,7 @@ class DevtoolsClient:
"""Queue a log to be sent to the devtools server for display.
Args:
log (DevtoolsLog): The log to write to devtools
log: The log to write to devtools
"""
if isinstance(log.objects_or_string, str):
self.console.print(log.objects_or_string)
@@ -260,10 +260,10 @@ class DevtoolsClient:
"""Pickle a list of Segments
Args:
segments (list[Segment]): A list of Segments to encode
segments: A list of Segments to encode
Returns:
bytes: The Segment list pickled with the latest protocol.
The Segment list pickled with the latest protocol.
"""
pickled = pickle.dumps(segments, protocol=4)
return pickled

View File

@@ -21,8 +21,8 @@ class StdoutRedirector:
def __init__(self, devtools: DevtoolsClient) -> None:
"""
Args:
devtools (DevtoolsClient): The running Textual app instance.
log_file (TextIOWrapper): The log file for the Textual App.
devtools: The running Textual app instance.
log_file: The log file for the Textual App.
"""
self.devtools = devtools
self._buffer: list[DevtoolsLog] = []
@@ -33,7 +33,7 @@ class StdoutRedirector:
buffer will be flushed immediately after.
Args:
string (str): The string to write to the buffer.
string: The string to write to the buffer.
"""
if not self.devtools.is_connected:
@@ -91,7 +91,7 @@ class StdoutRedirector:
logs being displayed.
Args:
log_batch (list[DevtoolsLog]): A batch of logs to send to the
log_batch: A batch of logs to send to the
devtools server as one. Log content will be joined together.
"""

View File

@@ -51,10 +51,10 @@ 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
segments: The segments to display
path: The path of the file on the client that the log call was made from
line_number: The line number of the file on the client the log call was made from
unix_timestamp: Seconds since January 1st 1970
"""
def __init__(
@@ -114,8 +114,8 @@ 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").
message: The message to display
level: The message level ("info", "warning", or "error").
Determines colors used to render the message and the perceived importance.
"""

View File

@@ -17,10 +17,10 @@ async def websocket_handler(request: Request) -> WebSocketResponse:
"""aiohttp websocket handler for sending data between devtools client and server
Args:
request (Request): The request to the websocket endpoint
request: The request to the websocket endpoint
Returns:
WebSocketResponse: The websocket response
The websocket response
"""
service: DevtoolsService = request.app["service"]
return await service.handle(request)

View File

@@ -39,10 +39,10 @@ class DevtoolsService:
) -> None:
"""
Args:
update_frequency (float): The number of seconds to wait between
update_frequency: The number of seconds to wait between
sending updates of the console size to connected clients.
verbose (bool): Enable verbose logging on client.
exclude (list[str]): List of log groups to exclude from output.
verbose: Enable verbose logging on client.
exclude: List of log groups to exclude from output.
"""
self.update_frequency = update_frequency
self.verbose = verbose
@@ -94,7 +94,7 @@ class DevtoolsService:
a connected client.
Args:
client_handler (ClientHandler): The client to send information to
client_handler: The client to send information to
"""
await client_handler.send_message(
{
@@ -138,8 +138,8 @@ class ClientHandler:
def __init__(self, request: Request, service: DevtoolsService) -> None:
"""
Args:
request (Request): The aiohttp.Request associated with this client
service (DevtoolsService): The parent DevtoolsService which is responsible
request: The aiohttp.Request associated with this client
service: The parent DevtoolsService which is responsible
for the handling of this client.
"""
self.request = request
@@ -150,7 +150,7 @@ class ClientHandler:
"""Send a message to a client
Args:
message (dict[str, object]): The dict which will be sent
message: The dict which will be sent
to the client.
"""
await self.outgoing_queue.put(message)
@@ -217,7 +217,7 @@ class ClientHandler:
read messages from the queues.
Returns:
WebSocketResponse: The WebSocketResponse associated with this client.
The WebSocketResponse associated with this client.
"""
await self.websocket.prepare(self.request)

View File

@@ -57,11 +57,11 @@ def check_identifiers(description: str, *names: str) -> None:
"""Validate identifier and raise an error if it fails.
Args:
description (str): Description of where identifier is used for error message.
names (list[str]): Identifiers to check.
description: Description of where identifier is used for error message.
names: Identifiers to check.
Returns:
bool: True if the name is valid.
True if the name is valid.
"""
match = _re_identifier.match
for name in names:
@@ -196,13 +196,13 @@ class DOMNode(MessagePump):
"""Get a "component" styles object (must be defined in COMPONENT_CLASSES classvar).
Args:
name (str): Name of the component.
name: Name of the component.
Raises:
KeyError: If the component class doesn't exist.
Returns:
RenderStyles: A Styles object.
A Styles object.
"""
if name not in self._component_styles:
raise KeyError(f"No {name!r} key in COMPONENT_CLASSES")
@@ -220,10 +220,10 @@ class DOMNode(MessagePump):
"""Get the DOMNode base classes, which inherit CSS.
Args:
base (Type[DOMNode]): A DOMNode class
base: A DOMNode class
Returns:
Iterator[Type[DOMNode]]: An iterable of DOMNode classes.
An iterable of DOMNode classes.
"""
_class = base
while True:
@@ -242,7 +242,7 @@ class DOMNode(MessagePump):
"""Merge bindings from base classes.
Returns:
Bindings: Merged bindings.
Merged bindings.
"""
bindings: list[Bindings] = []
@@ -267,7 +267,7 @@ class DOMNode(MessagePump):
"""Called when the widget is registered
Args:
app (App): Parent application.
app: Parent application.
"""
def __rich_repr__(self) -> rich.repr.Result:
@@ -283,7 +283,7 @@ class DOMNode(MessagePump):
`False` when subclassing.
Returns:
list[tuple[str, str]]: a list of tuples containing (PATH, SOURCE) for this
A list of tuples containing (PATH, SOURCE) for this
and inherited from base classes.
"""
@@ -310,7 +310,7 @@ class DOMNode(MessagePump):
`inherit_component_classes` is set to `False` when subclassing.
Returns:
set[str]: a set with all the component classes available.
A set with all the component classes available.
"""
component_classes: set[str] = set()
@@ -354,7 +354,7 @@ class DOMNode(MessagePump):
"""Sets the ID (may only be done once).
Args:
new_id (str): ID for this node.
new_id: ID for this node.
Raises:
ValueError: If the ID has already been set.
@@ -423,7 +423,7 @@ class DOMNode(MessagePump):
"""Get a set of selectors applicable to this widget.
Returns:
set[str]: Set of selector names.
Set of selector names.
"""
selectors: list[str] = [
"*",
@@ -441,7 +441,7 @@ class DOMNode(MessagePump):
Check if this widget should display or not.
Returns:
bool: ``True`` if this DOMNode is displayed (``display != "none"``) otherwise ``False`` .
``True`` if this DOMNode is displayed (``display != "none"``) otherwise ``False`` .
"""
return self.styles.display != "none" and not (self._closing or self._closed)
@@ -449,7 +449,7 @@ class DOMNode(MessagePump):
def display(self, new_val: bool | str) -> None:
"""
Args:
new_val (bool | str): Shortcut to set the ``display`` CSS property.
new_val: Shortcut to set the ``display`` CSS property.
``False`` will set ``display: none``. ``True`` will set ``display: block``.
A ``False`` value will prevent the DOMNode from consuming space in the layout.
"""
@@ -471,7 +471,7 @@ class DOMNode(MessagePump):
"""Check if the node is visible or None.
Returns:
bool: True if the node is visible.
True if the node is visible.
"""
return self.styles.visibility != "hidden"
@@ -492,7 +492,7 @@ class DOMNode(MessagePump):
"""Get a Rich tree object which will recursively render the structure of the node tree.
Returns:
Tree: A Rich object which may be printed.
A Rich object which may be printed.
"""
from rich.columns import Columns
from rich.console import Group
@@ -547,7 +547,7 @@ class DOMNode(MessagePump):
the child will also be bold.
Returns:
Style: Rich Style object.
Rich Style object.
"""
return Style.combine(
node.styles.text_style for node in reversed(self.ancestors_with_self)
@@ -579,7 +579,7 @@ class DOMNode(MessagePump):
"""Get the background color and the color of the parent's background.
Returns:
tuple[Color, Color]: Tuple of (base background, background)
Tuple of (base background, background)
"""
base_background = background = BLACK
@@ -595,7 +595,7 @@ class DOMNode(MessagePump):
"""Gets the Widgets foreground and background colors, and its parent's (base) colors.
Returns:
tuple[Color, Color, Color, Color]: Tuple of (base background, base color, background, color)
Tuple of (base background, base color, background, color)
"""
base_background = background = WHITE
base_color = color = BLACK
@@ -637,7 +637,7 @@ class DOMNode(MessagePump):
"""The children which don't have display: none set.
Returns:
list[DOMNode]: Children of this widget which will be displayed.
Children of this widget which will be displayed.
"""
return [child for child in self.children if child.display]
@@ -646,7 +646,7 @@ class DOMNode(MessagePump):
"""Get any pseudo classes applicable to this Node, e.g. hover, focus.
Returns:
Iterable[str]: Iterable of strings, such as a generator.
Iterable of strings, such as a generator.
"""
return ()
@@ -664,7 +664,7 @@ class DOMNode(MessagePump):
"""Add a new child node.
Args:
node (DOMNode): A DOM node.
node: A DOM node.
"""
self.children._append(node)
node._attach(self)
@@ -673,7 +673,7 @@ class DOMNode(MessagePump):
"""Add multiple children to this node.
Args:
*nodes (DOMNode): Positional args should be new DOM nodes.
*nodes: Positional args should be new DOM nodes.
"""
_append = self.children._append
for node in nodes:
@@ -714,14 +714,14 @@ class DOMNode(MessagePump):
"""Walk the subtree rooted at this node, and return every descendant encountered in a list.
Args:
filter_type (type[WalkType] | None, optional): Filter only this type, or None for no filter.
filter_type: Filter only this type, or None for no filter.
Defaults to None.
with_self (bool, optional): Also yield self in addition to descendants. Defaults to False.
method (Literal["breadth", "depth"], optional): One of "depth" or "breadth". Defaults to "depth".
reverse (bool, optional): Reverse the order (bottom up). Defaults to False.
with_self: Also yield self in addition to descendants. Defaults to False.
method: One of "depth" or "breadth". Defaults to "depth".
reverse: Reverse the order (bottom up). Defaults to False.
Returns:
list[DOMNode] | list[WalkType]: A list of nodes.
A list of nodes.
"""
check_type = filter_type or DOMNode
@@ -755,10 +755,10 @@ class DOMNode(MessagePump):
"""Get a DOM query matching a selector.
Args:
selector (str | type | None, optional): A CSS selector or `None` for all nodes. Defaults to None.
selector: A CSS selector or `None` for all nodes. Defaults to None.
Returns:
DOMQuery: A query object.
A query object.
"""
from .css.query import DOMQuery
@@ -790,8 +790,8 @@ class DOMNode(MessagePump):
"""Get a single Widget matching the given selector or selector type.
Args:
selector (str | type): A selector.
expect_type (type | None, optional): Require the object be of the supplied type, or None for any type.
selector: A selector.
expect_type: Require the object be of the supplied type, or None for any type.
Defaults to None.
Raises:
@@ -800,7 +800,7 @@ class DOMNode(MessagePump):
TooManyMatches: If there is more than one matching node in the query.
Returns:
Widget | ExpectType: A widget matching the selector.
A widget matching the selector.
"""
from .css.query import DOMQuery
@@ -831,10 +831,10 @@ class DOMNode(MessagePump):
"""Check if the Node has all the given class names.
Args:
*class_names (str): CSS class names to check.
*class_names: CSS class names to check.
Returns:
bool: ``True`` if the node has all the given class names, otherwise ``False``.
``True`` if the node has all the given class names, otherwise ``False``.
"""
return self._classes.issuperset(class_names)
@@ -842,7 +842,7 @@ class DOMNode(MessagePump):
"""Add or remove class(es) based on a condition.
Args:
add (bool): Add the classes if True, otherwise remove them.
add: Add the classes if True, otherwise remove them.
"""
if add:
self.add_class(*class_names)
@@ -853,7 +853,7 @@ class DOMNode(MessagePump):
"""Add class names to this Node.
Args:
*class_names (str): CSS class names to add.
*class_names: CSS class names to add.
"""
check_identifiers("class name", *class_names)
@@ -870,7 +870,7 @@ class DOMNode(MessagePump):
"""Remove class names from this Node.
Args:
*class_names (str): CSS class names to remove.
*class_names: CSS class names to remove.
"""
check_identifiers("class name", *class_names)
@@ -887,7 +887,7 @@ class DOMNode(MessagePump):
"""Toggle class names on this Node.
Args:
*class_names (str): CSS class names to toggle.
*class_names: CSS class names to toggle.
"""
check_identifiers("class name", *class_names)

View File

@@ -124,11 +124,11 @@ def _set_console_mode(file: IO, mode: int) -> bool:
"""Set the console mode for a given file (stdout or stdin).
Args:
file (IO): A file like object.
mode (int): New mode.
file: A file like object.
mode: New mode.
Returns:
bool: True on success, otherwise False.
True on success, otherwise False.
"""
windows_filehandle = msvcrt.get_osfhandle(file.fileno())
success = KERNEL32.SetConsoleMode(windows_filehandle, mode)
@@ -139,10 +139,10 @@ def _get_console_mode(file: IO) -> int:
"""Get the console mode for a given file (stdout or stdin)
Args:
file (IO): A file-like object.
file: A file-like object.
Returns:
int: The current console mode.
The current console mode.
"""
windows_filehandle = msvcrt.get_osfhandle(file.fileno())
mode = wintypes.DWORD()
@@ -154,7 +154,7 @@ def enable_application_mode() -> Callable[[], None]:
"""Enable application mode.
Returns:
Callable[[], None]: A callable that will restore terminal to previous state.
A callable that will restore terminal to previous state.
"""
terminal_in = sys.stdin

View File

@@ -84,10 +84,10 @@ class Action(Event):
class Resize(Event, bubble=False):
"""Sent when the app or widget has been resized.
Args:
sender (MessageTarget): The sender of the event (the Screen).
size (Size): The new size of the Widget.
virtual_size (Size): The virtual size (scrollable size) of the Widget.
container_size (Size | None, optional): The size of the Widget's container widget. Defaults to None.
sender: The sender of the event (the Screen).
size: The new size of the Widget.
virtual_size: The virtual size (scrollable size) of the Widget.
container_size: The size of the Widget's container widget. Defaults to None.
"""
@@ -151,8 +151,8 @@ class MouseCapture(Event, bubble=False):
Args:
sender (MessageTarget): The sender of the event, (in this case the app).
mouse_position (Point): The position of the mouse when captured.
sender: The sender of the event, (in this case the app).
mouse_position: The position of the mouse when captured.
"""
@@ -169,8 +169,8 @@ class MouseRelease(Event, bubble=False):
"""Mouse has been released.
Args:
sender (MessageTarget): The sender of the event, (in this case the app).
mouse_position (Point): The position of the mouse when released.
sender: The sender of the event, (in this case the app).
mouse_position: The position of the mouse when released.
"""
def __init__(self, sender: MessageTarget, mouse_position: Offset) -> None:
@@ -190,12 +190,12 @@ class Key(InputEvent):
"""Sent when the user hits a key on the keyboard.
Args:
sender (MessageTarget): The sender of the event (always the App).
key (str): The key that was pressed.
character (str | None, optional): A printable character or ``None`` if it is not printable.
sender: The sender of the event (always the App).
key: The key that was pressed.
character: A printable character or ``None`` if it is not printable.
Attributes:
aliases (list[str]): The aliases for the key, including the key itself.
aliases: The aliases for the key, including the key itself.
"""
__slots__ = ["key", "character", "aliases"]
@@ -206,7 +206,7 @@ class Key(InputEvent):
self.character = (
(key if len(key) == 1 else None) if character is None else character
)
self.aliases = _get_key_aliases(key)
self.aliases: list[str] = _get_key_aliases(key)
def __rich_repr__(self) -> rich.repr.Result:
yield "key", self.key
@@ -230,7 +230,7 @@ class Key(InputEvent):
"""Check if the key is printable (produces a unicode character).
Returns:
bool: True if the key is printable.
True if the key is printable.
"""
return False if self.character is None else self.character.isprintable()
@@ -247,18 +247,18 @@ class MouseEvent(InputEvent, bubble=True):
"""Sent in response to a mouse event.
Args:
sender (MessageTarget): The sender of the event.
x (int): The relative x coordinate.
y (int): The relative y coordinate.
delta_x (int): Change in x since the last message.
delta_y (int): Change in y since the last message.
button (int): Indexed of the pressed button.
shift (bool): True if the shift key is pressed.
meta (bool): True if the meta key is pressed.
ctrl (bool): True if the ctrl key is pressed.
screen_x (int, optional): The absolute x coordinate.
screen_y (int, optional): The absolute y coordinate.
style (Style, optional): The Rich Style under the mouse cursor.
sender: The sender of the event.
x: The relative x coordinate.
y: The relative y coordinate.
delta_x: Change in x since the last message.
delta_y: Change in y since the last message.
button: Indexed of the pressed button.
shift: True if the shift key is pressed.
meta: True if the meta key is pressed.
ctrl: True if the ctrl key is pressed.
screen_x: The absolute x coordinate.
screen_y: The absolute y coordinate.
style: The Rich Style under the mouse cursor.
"""
@@ -341,7 +341,7 @@ class MouseEvent(InputEvent, bubble=True):
"""The mouse coordinate as an offset.
Returns:
Offset: Mouse coordinate.
Mouse coordinate.
"""
return Offset(self.x, self.y)
@@ -351,7 +351,7 @@ class MouseEvent(InputEvent, bubble=True):
"""Mouse coordinate relative to the screen.
Returns:
Offset: Mouse coordinate.
Mouse coordinate.
"""
return Offset(self.screen_x, self.screen_y)
@@ -360,7 +360,7 @@ class MouseEvent(InputEvent, bubble=True):
"""Mouse coordinate delta (change since last event).
Returns:
Offset: Mouse coordinate.
Mouse coordinate.
"""
return Offset(self.delta_x, self.delta_y)
@@ -378,10 +378,10 @@ class MouseEvent(InputEvent, bubble=True):
"""Get offset within a widget's content area, or None if offset is not in content (i.e. padding or border).
Args:
widget (Widget): Widget receiving the event.
widget: Widget receiving the event.
Returns:
Offset | None: An offset where the origin is at the top left of the content area.
An offset where the origin is at the top left of the content area.
"""
if self.screen_offset not in widget.content_region:
return None
@@ -488,7 +488,7 @@ class Paste(Event, bubble=True):
and disable it when the app shuts down.
Args:
sender (MessageTarget): The sender of the event, (in this case the app).
sender: The sender of the event, (in this case the app).
text: The text that has been pasted.
"""

View File

@@ -12,10 +12,10 @@ def parse_features(features: str) -> frozenset[FeatureFlag]:
"""Parse features env var
Args:
features (str): Comma separated feature flags
features: Comma separated feature flags
Returns:
frozenset[FeatureFlag]: A frozen set of known features.
A frozen set of known features.
"""
features_set = frozenset(

View File

@@ -24,12 +24,12 @@ def clamp(value: T, minimum: T, maximum: T) -> T:
than a maximum value.
Args:
value (T): A value.
minimum (T): Minimum value.
maximum (T): maximum value.
value: A value.
minimum: Minimum value.
maximum: Maximum value.
Returns:
T: New value that is not less than the minimum or greater than the maximum.
New value that is not less than the minimum or greater than the maximum.
"""
if minimum > maximum:
maximum, minimum = minimum, maximum
@@ -59,7 +59,7 @@ class Offset(NamedTuple):
"""Check if the point is at the origin (0, 0).
Returns:
bool: True if the offset is the origin.
True if the offset is the origin.
"""
return self == (0, 0)
@@ -69,7 +69,7 @@ class Offset(NamedTuple):
"""Ensure x and y are above zero.
Returns:
Offset: New offset.
New offset.
"""
x, y = self
return Offset(0 if x < 0 else x, 0 if y < 0 else y)
@@ -105,11 +105,11 @@ class Offset(NamedTuple):
"""Blend (interpolate) to a new point.
Args:
destination (Point): Point where factor would be 1.0.
factor (float): A value between 0 and 1.0.
destination: Point where factor would be 1.0.
factor: A value between 0 and 1.0.
Returns:
Point: A new point on a line between self and destination.
A new point on a line between self and destination.
"""
x1, y1 = self
x2, y2 = destination
@@ -122,10 +122,10 @@ class Offset(NamedTuple):
"""Get the distance to another offset.
Args:
other (Offset): An offset.
other: An offset.
Returns:
float: Distance to other offset.
Distance to other offset.
"""
x1, y1 = self
x2, y2 = other
@@ -151,7 +151,7 @@ class Size(NamedTuple):
"""Get the area of the size.
Returns:
int: Area in cells.
Area in cells.
"""
return self.width * self.height
@@ -160,7 +160,7 @@ class Size(NamedTuple):
"""Get a region of the same size.
Returns:
Region: A region with the same size at (0, 0).
A region with the same size at (0, 0).
"""
width, height = self
@@ -171,7 +171,7 @@ class Size(NamedTuple):
"""Get a range covering lines.
Returns:
range: A builtin range object.
A builtin range object.
"""
return range(self.height)
@@ -193,11 +193,11 @@ class Size(NamedTuple):
"""Check if a point is in area defined by the size.
Args:
x (int): X coordinate.
y (int): Y coordinate.
x: X coordinate.
y: Y coordinate.
Returns:
bool: True if the point is within the region.
True if the point is within the region.
"""
width, height = self
return width > x >= 0 and height > y >= 0
@@ -206,10 +206,10 @@ class Size(NamedTuple):
"""Check if a point is in the area defined by the size.
Args:
point (tuple[int, int]): A tuple of x and y coordinates.
point: A tuple of x and y coordinates.
Returns:
bool: True if the point is within the region.
True if the point is within the region.
"""
x, y = point
width, height = self
@@ -261,10 +261,10 @@ class Region(NamedTuple):
"""Create a Region from the union of other regions.
Args:
regions (Collection[Region]): One or more regions.
regions: One or more regions.
Returns:
Region: A Region that encloses all other regions.
A Region that encloses all other regions.
"""
if not regions:
raise ValueError("At least one region expected")
@@ -279,13 +279,13 @@ class Region(NamedTuple):
"""Construct a Region form the top left and bottom right corners.
Args:
x1 (int): Top left x.
y1 (int): Top left y.
x2 (int): Bottom right x.
y2 (int): Bottom right y.
x1: Top left x.
y1: Top left y.
x2: Bottom right x.
y2: Bottom right y.
Returns:
Region: A new region.
A new region.
"""
return cls(x1, y1, x2 - x1, y2 - y1)
@@ -294,11 +294,11 @@ class Region(NamedTuple):
"""Create a region from offset and size.
Args:
offset (Point): Offset (top left point).
size (tuple[int, int]): Dimensions of region.
offset: Offset (top left point).
size: Dimensions of region.
Returns:
Region: A region instance.
A region instance.
"""
x, y = offset
width, height = size
@@ -314,12 +314,12 @@ class Region(NamedTuple):
This method is used to calculate the required offset to scroll something in to view.
Args:
window_region (Region): The window region.
region (Region): The region to move inside the window.
top (bool, optional): Get offset to top of window. Defaults to False
window_region: The window region.
region: The region to move inside the window.
top: Get offset to top of window. Defaults to False
Returns:
Offset: An offset required to add to region to move it inside window_region.
An offset required to add to region to move it inside window_region.
"""
if region in window_region and not top:
@@ -370,7 +370,7 @@ class Region(NamedTuple):
The end value is exclusive.
Returns:
tuple[int, int]: Pair of x coordinates (column numbers).
Pair of x coordinates (column numbers).
"""
return (self.x, self.x + self.width)
@@ -382,7 +382,7 @@ class Region(NamedTuple):
The end value is exclusive.
Returns:
tuple[int, int]: Pair of y coordinates (line numbers).
Pair of y coordinates (line numbers).
"""
return (self.y, self.y + self.height)
@@ -392,7 +392,7 @@ class Region(NamedTuple):
"""Maximum X value (non inclusive).
Returns:
int: x coordinate.
x coordinate.
"""
return self.x + self.width
@@ -402,7 +402,7 @@ class Region(NamedTuple):
"""Maximum Y value (non inclusive).
Returns:
int: y coordinate.
y coordinate.
"""
return self.y + self.height
@@ -412,7 +412,7 @@ class Region(NamedTuple):
"""Get the area within the region.
Returns:
int: Area covered by this region.
Area covered by this region.
"""
return self.width * self.height
@@ -422,7 +422,7 @@ class Region(NamedTuple):
"""Get the start point of the region.
Returns:
Offset: Top left offset.
Top left offset.
"""
return Offset(*self[:2])
@@ -432,7 +432,7 @@ class Region(NamedTuple):
"""Bottom left offset of the region.
Returns:
Offset: Bottom left offset.
Bottom left offset.
"""
x, y, _width, height = self
@@ -443,7 +443,7 @@ class Region(NamedTuple):
"""Top right offset of the region.
Returns:
Offset: Top right.
Top right.
"""
x, y, width, _height = self
@@ -454,7 +454,7 @@ class Region(NamedTuple):
"""Bottom right of the region.
Returns:
Offset: Bottom right.
Bottom right.
"""
x, y, width, height = self
@@ -465,7 +465,7 @@ class Region(NamedTuple):
"""Get the size of the region.
Returns:
Size: Size of the region.
Size of the region.
"""
return Size(*self[2:])
@@ -475,7 +475,7 @@ class Region(NamedTuple):
"""Get the top left and bottom right coordinates as a tuple of integers.
Returns:
tuple[int, int, int, int]: A tuple of `(<left>, <top>, <right>, <bottom>)`.
A tuple of `(<left>, <top>, <right>, <bottom>)`.
"""
x, y, width, height = self
return x, y, x + width, y + height
@@ -495,7 +495,7 @@ class Region(NamedTuple):
"""An region of the same size at (0, 0).
Returns:
Region: reset region.
Reset region.
"""
_, _, width, height = self
@@ -519,10 +519,10 @@ class Region(NamedTuple):
"""Get a new Region with the same size at a given offset.
Args:
offset (tuple[int, int]): An offset.
offset: An offset.
Returns:
Region: New Region with adjusted offset.
New Region with adjusted offset.
"""
x, y = offset
_x, _y, width, height = self
@@ -532,10 +532,10 @@ class Region(NamedTuple):
"""Get a region with the same offset, with a size no larger than `size`.
Args:
size (tuple[int, int]): Maximum width and height (WIDTH, HEIGHT).
size: Maximum width and height (WIDTH, HEIGHT).
Returns:
Region: New region that could fit within `size`.
New region that could fit within `size`.
"""
x, y, width1, height1 = self
width2, height2 = size
@@ -545,10 +545,10 @@ class Region(NamedTuple):
"""Increase the size of the region by adding a border.
Args:
size (tuple[int, int]): Additional width and height.
size: Additional width and height.
Returns:
Region: A new region.
A new region.
"""
expand_width, expand_height = size
x, y, width, height = self
@@ -563,10 +563,10 @@ class Region(NamedTuple):
"""Clip the size to fit within minimum values.
Args:
size (tuple[int, int]): Maximum width and height.
size: Maximum width and height.
Returns:
Region: No region, not bigger than size.
No region, not bigger than size.
"""
x, y, width, height = self
max_width, max_height = size
@@ -577,10 +577,10 @@ class Region(NamedTuple):
"""Check if another region overlaps this region.
Args:
other (Region): A Region.
other: A Region.
Returns:
bool: True if other region shares any cells with this region.
True if other region shares any cells with this region.
"""
x, y, x2, y2 = self.corners
ox, oy, ox2, oy2 = other.corners
@@ -593,11 +593,11 @@ class Region(NamedTuple):
"""Check if a point is in the region.
Args:
x (int): X coordinate.
y (int): Y coordinate.
x: X coordinate.
y: Y coordinate.
Returns:
bool: True if the point is within the region.
True if the point is within the region.
"""
self_x, self_y, width, height = self
return (self_x + width > x >= self_x) and (self_y + height > y >= self_y)
@@ -606,10 +606,10 @@ class Region(NamedTuple):
"""Check if a point is in the region.
Args:
point (tuple[int, int]): A tuple of x and y coordinates.
point: A tuple of x and y coordinates.
Returns:
bool: True if the point is within the region.
True if the point is within the region.
"""
x1, y1, x2, y2 = self.corners
try:
@@ -623,10 +623,10 @@ class Region(NamedTuple):
"""Check if a region is entirely contained within this region.
Args:
other (Region): A region.
other: A region.
Returns:
bool: True if the other region fits perfectly within this region.
True if the other region fits perfectly within this region.
"""
x1, y1, x2, y2 = self.corners
ox, oy, ox2, oy2 = other.corners
@@ -642,10 +642,10 @@ class Region(NamedTuple):
"""Move the offset of the Region.
Args:
offset (tuple[int, int]): Offset to add to region.
offset: Offset to add to region.
Returns:
Region: A new region shifted by (x, y)
A new region shifted by (x, y)
"""
self_x, self_y, width, height = self
@@ -667,11 +667,11 @@ class Region(NamedTuple):
"""Clip this region to fit within width, height.
Args:
width (int): Width of bounds.
height (int): Height of bounds.
width: Width of bounds.
height: Height of bounds.
Returns:
Region: Clipped region.
Clipped region.
"""
x1, y1, x2, y2 = self.corners
@@ -689,10 +689,10 @@ class Region(NamedTuple):
"""Grow a region by adding spacing.
Args:
margin (tuple[int, int, in, int]): Grow space by `(<top>, <right>, <bottom>, <left>)`.
margin: Grow space by `(<top>, <right>, <bottom>, <left>)`.
Returns:
Region: New region.
New region.
"""
if not any(margin):
return self
@@ -710,10 +710,10 @@ class Region(NamedTuple):
"""Shrink a region by subtracting spacing.
Args:
margin (tuple[int, int, int, int]): Shrink space by `(<top>, <right>, <bottom>, <left>)`.
margin: Shrink space by `(<top>, <right>, <bottom>, <left>)`.
Returns:
Region: The new, smaller region.
The new, smaller region.
"""
if not any(margin):
return self
@@ -731,10 +731,10 @@ class Region(NamedTuple):
"""Get the overlapping portion of the two regions.
Args:
region (Region): A region that overlaps this region.
region: A region that overlaps this region.
Returns:
Region: A new region that covers when the two regions overlap.
A new region that covers when the two regions overlap.
"""
# Unrolled because this method is used a lot
x1, y1, w1, h1 = self
@@ -756,10 +756,10 @@ class Region(NamedTuple):
"""Get the smallest region that contains both regions.
Args:
region (Region): Another region.
region: Another region.
Returns:
Region: An optimally sized region to cover both regions.
An optimally sized region to cover both regions.
"""
x1, y1, x2, y2 = self.corners
ox1, oy1, ox2, oy2 = region.corners
@@ -786,13 +786,13 @@ class Region(NamedTuple):
```
Args:
cut_x (int): Offset from self.x where the cut should be made. If negative, the cut
cut_x: Offset from self.x where the cut should be made. If negative, the cut
is taken from the right edge.
cut_y (int): Offset from self.y where the cut should be made. If negative, the cut
cut_y: Offset from self.y where the cut should be made. If negative, the cut
is taken from the lower edge.
Returns:
tuple[Region, Region, Region, Region]: Four new regions which add up to the original (self).
Four new regions which add up to the original (self).
"""
x, y, width, height = self
@@ -822,11 +822,11 @@ class Region(NamedTuple):
```
Args:
cut (int): An offset from self.x where the cut should be made. If cut is negative,
cut: An offset from self.x where the cut should be made. If cut is negative,
it is taken from the right edge.
Returns:
tuple[Region, Region]: Two regions, which add up to the original (self).
Two regions, which add up to the original (self).
"""
x, y, width, height = self
@@ -853,11 +853,11 @@ class Region(NamedTuple):
```
Args:
cut (int): An offset from self.x where the cut should be made. May be negative,
cut: An offset from self.x where the cut should be made. May be negative,
for the offset to start from the right edge.
Returns:
tuple[Region, Region]: Two regions, which add up to the original (self).
Two regions, which add up to the original (self).
"""
x, y, width, height = self
if cut < 0:
@@ -889,7 +889,7 @@ class Spacing(NamedTuple):
"""Total space in width.
Returns:
int: Width.
Width.
"""
return self.left + self.right
@@ -899,7 +899,7 @@ class Spacing(NamedTuple):
"""Total space in height.
Returns:
int: Height.
Height.
"""
return self.top + self.bottom
@@ -909,7 +909,7 @@ class Spacing(NamedTuple):
"""Top left space.
Returns:
tuple[int, int]: `(<left>, <top>)`
`(<left>, <top>)`
"""
return (self.left, self.top)
@@ -919,7 +919,7 @@ class Spacing(NamedTuple):
"""Bottom right space.
Returns:
tuple[int, int]: `(<right>, <bottom>)`
`(<right>, <bottom>)`
"""
return (self.right, self.bottom)
@@ -929,7 +929,7 @@ class Spacing(NamedTuple):
"""Get total horizontal and vertical space.
Returns:
tuple[int, int]: `(<horizontal>, <vertical>)`
`(<horizontal>, <vertical>)`
"""
@@ -941,7 +941,7 @@ class Spacing(NamedTuple):
"""Gets a string containing the spacing in CSS format.
Returns:
str: Spacing in CSS format.
Spacing in CSS format.
"""
top, right, bottom, left = self
@@ -957,13 +957,13 @@ class Spacing(NamedTuple):
"""Unpack padding specified in CSS style.
Args:
pad (SpacingDimensions): An integer, or tuple of 1, 2, or 4 integers.
pad: An integer, or tuple of 1, 2, or 4 integers.
Raises:
ValueError: If `pad` is an invalid value.
Returns:
Spacing: New Spacing object.
New Spacing object.
"""
if isinstance(pad, int):
return cls(pad, pad, pad, pad)
@@ -987,10 +987,10 @@ class Spacing(NamedTuple):
and no horizontal spacing.
Args:
amount (int): The magnitude of spacing to apply to vertical edges
amount: The magnitude of spacing to apply to vertical edges
Returns:
Spacing: `Spacing(amount, 0, amount, 0)`
`Spacing(amount, 0, amount, 0)`
"""
return Spacing(amount, 0, amount, 0)
@@ -1000,10 +1000,10 @@ class Spacing(NamedTuple):
and no vertical spacing.
Args:
amount (int): The magnitude of spacing to apply to horizontal edges
amount: The magnitude of spacing to apply to horizontal edges
Returns:
Spacing: `Spacing(0, amount, 0, amount)`
`Spacing(0, amount, 0, amount)`
"""
return Spacing(0, amount, 0, amount)
@@ -1012,10 +1012,10 @@ class Spacing(NamedTuple):
"""Construct a Spacing with a given amount of spacing on all edges.
Args:
amount (int): The magnitude of spacing to apply to all edges
amount: The magnitude of spacing to apply to all edges
Returns:
Spacing: `Spacing(amount, amount, amount, amount)`
`Spacing(amount, amount, amount, amount)`
"""
return Spacing(amount, amount, amount, amount)
@@ -1041,10 +1041,10 @@ class Spacing(NamedTuple):
"""Grow spacing with a maximum.
Args:
other (Spacing): Spacing object.
other: Spacing object.
Returns:
Spacing: New spacing were the values are maximum of the two values.
New spacing were the values are maximum of the two values.
"""
top, right, bottom, left = self
other_top, other_right, other_bottom, other_left = other

View File

@@ -20,13 +20,13 @@ def get_layout(name: str) -> Layout:
"""Get a named layout object.
Args:
name (str): Name of the layout.
name: Name of the layout.
Raises:
MissingLayout: If the named layout doesn't exist.
Returns:
Layout: A layout object.
A layout object.
"""
layout_class = LAYOUT_MAP.get(name)

View File

@@ -33,7 +33,7 @@ class GridLayout(Layout):
"""Iterate over table coordinates ad infinitum.
Args:
column_count (int): Number of columns
column_count: Number of columns
"""
row = 0
@@ -48,13 +48,13 @@ class GridLayout(Layout):
"""Get coords occupied by a cell.
Args:
column_start (int): Start column.
row_start (int): Start_row.
columns (int): Number of columns.
rows (int): Number of rows.
column_start: Start column.
row_start: Start_row.
columns: Number of columns.
rows: Number of rows.
Returns:
set[tuple[int, int]]: Set of coords.
Set of coords.
"""
return {
(column, row)
@@ -67,11 +67,11 @@ class GridLayout(Layout):
a list of `count` values.
Args:
scalars (Iterable[T]): Iterable of values.
count (int): Number of values to return.
scalars: Iterable of values.
count: Number of values to return.
Returns:
list[T]: A list of values.
A list of values.
"""
limited_values = list(scalars)[:]
while len(limited_values) < count:

View File

@@ -18,8 +18,11 @@ class Message:
"""Base class for a message.
Args:
sender (MessageTarget): The sender of the message / event.
sender: The sender of the message / event.
Attributes:
sender: The sender of the message.
time: The time when the message was sent.
"""
__slots__ = [
@@ -38,9 +41,9 @@ class Message:
namespace: ClassVar[str] = "" # Namespace to disambiguate messages
def __init__(self, sender: MessageTarget) -> None:
self.sender = sender
self.sender: MessageTarget = sender
self.time = _clock.get_time_no_wait()
self.time: float = _clock.get_time_no_wait()
self._forwarded = False
self._no_default_action = False
self._stop_propagation = False
@@ -87,10 +90,10 @@ class Message:
"""Check if another message may supersede this one.
Args:
message (Message): Another message.
message: Another message.
Returns:
bool: True if this message may replace the given message
True if this message may replace the given message
"""
return False
@@ -99,7 +102,7 @@ class Message:
from being called.
Args:
prevent (bool, optional): True if the default action should be suppressed,
prevent: True if the default action should be suppressed,
or False if the default actions should be performed. Defaults to True.
"""
self._no_default_action = prevent
@@ -109,7 +112,7 @@ class Message:
"""Stop propagation of the message to parent.
Args:
stop (bool, optional): The stop flag. Defaults to True.
stop: The stop flag. Defaults to True.
"""
self._stop_propagation = stop
return self
@@ -118,6 +121,6 @@ class Message:
"""Bubble to a widget (typically the parent).
Args:
widget (Widget): Target of bubble.
widget: Target of bubble.
"""
await widget.post_message(self)

View File

@@ -90,7 +90,7 @@ class MessagePump(metaclass=MessagePumpMeta):
Get the current app.
Returns:
App: The current app.
The current app.
Raises:
NoActiveAppError: if no active app could be found for the current asyncio context
@@ -116,7 +116,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Get a logger for this object.
Returns:
Logger: A logger.
A logger.
"""
return self.app._logger
@@ -124,7 +124,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Set the parent, and therefore attach this node to the tree.
Args:
parent (MessagePump): Parent node.
parent: Parent node.
"""
self._parent = parent
@@ -147,7 +147,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Get the next event on the queue, or None if queue is closed.
Returns:
Optional[Event]: Event object or None.
Event object or None.
"""
if self._closed:
raise MessagePumpClosed("The message pump is closed")
@@ -169,7 +169,7 @@ class MessagePump(metaclass=MessagePumpMeta):
or return None if the queue is empty.
Returns:
Optional[Message]: The message or None.
The message or None.
"""
if self._pending_message is None:
try:
@@ -197,13 +197,13 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Make a function call after a delay.
Args:
delay (float): Time to wait before invoking callback.
callback (TimerCallback | None, optional): Callback to call after time has expired. Defaults to None.
name (str | None, optional): Name of the timer (for debug). Defaults to None.
pause (bool, optional): Start timer paused. Defaults to False.
delay: Time to wait before invoking callback.
callback: Callback to call after time has expired. Defaults to None.
name: Name of the timer (for debug). Defaults to None.
pause: Start timer paused. Defaults to False.
Returns:
Timer: A timer object.
A timer object.
"""
timer = Timer(
self,
@@ -230,14 +230,14 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Call a function at periodic intervals.
Args:
interval (float): Time between calls.
callback (TimerCallback | None, optional): Function to call. Defaults to None.
name (str | None, optional): Name of the timer object. Defaults to None.
repeat (int, optional): Number of times to repeat the call or 0 for continuous. Defaults to 0.
pause (bool, optional): Start the timer paused. Defaults to False.
interval: Time between calls.
callback: Function to call. Defaults to None.
name: Name of the timer object. Defaults to None.
repeat: Number of times to repeat the call or 0 for continuous. Defaults to 0.
pause: Start the timer paused. Defaults to False.
Returns:
Timer: A timer object.
A timer object.
"""
timer = Timer(
self,
@@ -257,7 +257,7 @@ class MessagePump(metaclass=MessagePumpMeta):
has been refreshed. Positional and keyword arguments are passed to the callable.
Args:
callback (Callable): A callable.
callback: A callable.
"""
# We send the InvokeLater message to ourselves first, to ensure we've cleared
# out anything already pending in our own queue.
@@ -269,7 +269,7 @@ class MessagePump(metaclass=MessagePumpMeta):
Positional and keywords arguments are passed to the callable.
Args:
callback (Callable): Callable to call next.
callback: Callable to call next.
"""
message = events.Callback(self, callback=partial(callback, *args, **kwargs))
self.post_message_no_wait(message)
@@ -395,7 +395,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Dispatch a message received from the message queue.
Args:
message (Message): A message object
message: A message object
"""
_rich_traceback_guard = True
if message.no_dispatch:
@@ -413,8 +413,8 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Gets handlers from the MRO
Args:
method_name (str): Handler method name.
message (Message): Message object.
method_name: Handler method name.
message: Message object.
"""
private_method = f"_{method_name}"
@@ -429,7 +429,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Called to process an event.
Args:
event (events.Event): An Event object.
event: An Event object.
"""
await self._on_message(event)
@@ -437,7 +437,7 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Called to process a message.
Args:
message (Message): A Message object.
message: A Message object.
"""
_rich_traceback_guard = True
handler_name = message._handler_name
@@ -473,10 +473,10 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Post a message or an event to this message pump.
Args:
message (Message): A message object.
message: A message object.
Returns:
bool: True if the messages was posted successfully, False if the message was not posted
True if the messages was posted successfully, False if the message was not posted
(because the message pump was in the process of closing).
"""
@@ -496,10 +496,10 @@ class MessagePump(metaclass=MessagePumpMeta):
timer messages to skip the queue, so that they can be more regular.
Args:
message (Message): A message.
message: A message.
Returns:
bool: True if the messages was processed, False if it wasn't.
True if the messages was processed, False if it wasn't.
"""
# TODO: Allow priority messages to jump the queue
if self._closing or self._closed:
@@ -513,10 +513,10 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Posts a message on the queue.
Args:
message (Message): A message (or Event).
message: A message (or Event).
Returns:
bool: True if the messages was processed, False if it wasn't.
True if the messages was processed, False if it wasn't.
"""
if self._closing or self._closed:
return False
@@ -542,10 +542,10 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Send a message to the _parent_, non async version.
Args:
message (Message): A message object.
message: A message object.
Returns:
bool: True if the message was posted successfully.
True if the message was posted successfully.
"""
if self._parent:
return self._parent._post_message_from_child_no_wait(message)
@@ -556,10 +556,10 @@ class MessagePump(metaclass=MessagePumpMeta):
"""Send a message to the _parent_.
Args:
message (Message): A message object.
message: A message object.
Returns:
bool: True if the message was posted successfully.
True if the message was posted successfully.
"""
if self._parent:
return await self._parent._post_message_from_child(message)
@@ -575,10 +575,10 @@ class MessagePump(metaclass=MessagePumpMeta):
If multiple handlers exist that match the key, an exception is raised.
Args:
event (events.Key): A key event.
event: A key event.
Returns:
bool: True if key was handled, otherwise False.
True if key was handled, otherwise False.
Raises:
DuplicateKeyHandlers: When there's more than 1 handler that could handle this key.

View File

@@ -37,7 +37,7 @@ class Pilot(Generic[ReturnType]):
"""Insert a pause.
Args:
delay (float, optional): Seconds to pause. Defaults to 50ms.
delay: Seconds to pause. Defaults to 50ms.
"""
# These sleep zeros, are to force asyncio to give up a time-slice,
await asyncio.sleep(delay)
@@ -50,6 +50,6 @@ class Pilot(Generic[ReturnType]):
"""Exit the app with the given result.
Args:
result (object): The app result returned by `run` or `run_async`.
result: The app result returned by `run` or `run_async`.
"""
self.app.exit(result)

View File

@@ -42,12 +42,12 @@ class Reactive(Generic[ReactiveType]):
"""Reactive descriptor.
Args:
default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
layout (bool, optional): Perform a layout on change. Defaults to False.
repaint (bool, optional): Perform a repaint on change. Defaults to True.
init (bool, optional): Call watchers on initialize (post mount). Defaults to False.
always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
compute (bool, optional): Run compute methods when attribute is changed. Defaults to True.
default: A default value or callable that returns a default.
layout: Perform a layout on change. Defaults to False.
repaint: Perform a repaint on change. Defaults to True.
init: Call watchers on initialize (post mount). Defaults to False.
always_update: Call watchers even when the new value equals the old value. Defaults to False.
compute: Run compute methods when attribute is changed. Defaults to True.
"""
_reactives: TypeVar[dict[str, object]] = {}
@@ -90,14 +90,14 @@ class Reactive(Generic[ReactiveType]):
"""A reactive variable that calls watchers and compute on initialize (post mount).
Args:
default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
layout (bool, optional): Perform a layout on change. Defaults to False.
repaint (bool, optional): Perform a repaint on change. Defaults to True.
always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
compute (bool, optional): Run compute methods when attribute is changed. Defaults to True.
default: A default value or callable that returns a default.
layout: Perform a layout on change. Defaults to False.
repaint: Perform a repaint on change. Defaults to True.
always_update: Call watchers even when the new value equals the old value. Defaults to False.
compute: Run compute methods when attribute is changed. Defaults to True.
Returns:
Reactive: A Reactive instance which calls watchers or initialize.
A Reactive instance which calls watchers or initialize.
"""
return cls(
default,
@@ -116,10 +116,10 @@ class Reactive(Generic[ReactiveType]):
"""A reactive variable that doesn't update or layout.
Args:
default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
default: A default value or callable that returns a default.
Returns:
Reactive: A Reactive descriptor.
A Reactive descriptor.
"""
return cls(default, layout=False, repaint=False, init=False)
@@ -127,8 +127,8 @@ class Reactive(Generic[ReactiveType]):
"""Initialized a reactive attribute on an object.
Args:
obj (Reactable): An object with reactive attributes.
name (str): name of attribute.
obj: An object with reactive attributes.
name: Name of attribute.
"""
internal_name = f"_reactive_{name}"
if hasattr(obj, internal_name):
@@ -153,7 +153,7 @@ class Reactive(Generic[ReactiveType]):
"""Set defaults and call any watchers / computes for the first time.
Args:
obj (Reactable): An object with Reactive descriptors
obj: An object with Reactive descriptors
"""
for name, reactive in obj._reactives.items():
@@ -164,7 +164,7 @@ class Reactive(Generic[ReactiveType]):
"""Reset reactive structures on object (to avoid reference cycles).
Args:
obj (object): A reactive object.
obj: A reactive object.
"""
getattr(obj, "__watchers", {}).clear()
getattr(obj, "__computes", []).clear()
@@ -235,9 +235,9 @@ class Reactive(Generic[ReactiveType]):
"""Check watchers, and call watch methods / computes
Args:
obj (Reactable): The reactable object.
name (str): Attribute name.
old_value (Any): The old (previous) value of the attribute.
obj: The reactable object.
name: Attribute name.
old_value: The old (previous) value of the attribute.
"""
_rich_traceback_omit = True
# Get the current value.
@@ -259,12 +259,12 @@ class Reactive(Generic[ReactiveType]):
"""Invoke a watch function.
Args:
watch_function (Callable): A watch function, which may be sync or async.
old_value (object): The old value of the attribute.
value (object): The new value of the attribute.
watch_function: A watch function, which may be sync or async.
old_value: The old value of the attribute.
value: The new value of the attribute.
Returns:
bool: True if the watcher was run, or False if it was posted.
True if the watcher was run, or False if it was posted.
"""
_rich_traceback_omit = True
param_count = count_parameters(watch_function)
@@ -298,7 +298,7 @@ class Reactive(Generic[ReactiveType]):
"""Invoke all computes.
Args:
obj (Reactable): Reactable object.
obj: Reactable object.
"""
_rich_traceback_guard = True
for compute in obj._reactives.keys():
@@ -317,11 +317,11 @@ class reactive(Reactive[ReactiveType]):
"""Create a reactive attribute.
Args:
default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
layout (bool, optional): Perform a layout on change. Defaults to False.
repaint (bool, optional): Perform a repaint on change. Defaults to True.
init (bool, optional): Call watchers on initialize (post mount). Defaults to True.
always_update (bool, optional): Call watchers even when the new value equals the old value. Defaults to False.
default: A default value or callable that returns a default.
layout: Perform a layout on change. Defaults to False.
repaint: Perform a repaint on change. Defaults to True.
init: Call watchers on initialize (post mount). Defaults to True.
always_update: Call watchers even when the new value equals the old value. Defaults to False.
"""
def __init__(
@@ -346,8 +346,8 @@ class var(Reactive[ReactiveType]):
"""Create a reactive attribute (with no auto-refresh).
Args:
default (ReactiveType | Callable[[], ReactiveType]): A default value or callable that returns a default.
init (bool, optional): Call watchers on initialize (post mount). Defaults to True.
default: A default value or callable that returns a default.
init: Call watchers on initialize (post mount). Defaults to True.
"""
def __init__(
@@ -372,10 +372,10 @@ def watch(
"""Watch a reactive variable on an object.
Args:
obj (Reactable): The parent object.
attribute_name (str): The attribute to watch.
callback (Callable[[Any], object]): A callable to call when the attribute changes.
init (bool, optional): True to call watcher initialization. Defaults to True.
obj: The parent object.
attribute_name: The attribute to watch.
callback: A callable to call when the attribute changes.
init: True to call watcher initialization. Defaults to True.
"""
if not hasattr(obj, "__watchers"):

View File

@@ -6,12 +6,12 @@ def measure(console: Console, renderable: RenderableType, default: int) -> int:
"""Measure a rich renderable.
Args:
console (Console): A console object.
renderable (RenderableType): Rich renderable.
default (int): Default width to use if renderable does not expose dimensions.
console: A console object.
renderable: Rich renderable.
default: Default width to use if renderable does not expose dimensions.
Returns:
int: Width in cells
Width in cells
"""
width = default
renderable = rich_cast(renderable)

View File

@@ -8,12 +8,12 @@ def blend_colors(color1: Color, color2: Color, ratio: float) -> Color:
them in RGB color space.
Args:
color1 (Color): The first color.
color2 (Color): The second color.
ratio (float): The ratio of color1 to color2.
color1: The first color.
color2: The second color.
ratio: The ratio of color1 to color2.
Returns:
Color: A Color representing the blending of the two supplied colors.
A Color representing the blending of the two supplied colors.
"""
r1, g1, b1 = color1.triplet
r2, g2, b2 = color2.triplet
@@ -31,12 +31,12 @@ def blend_colors_rgb(
"""Blend two colors given as a tuple of 3 values for red, green, and blue.
Args:
color1 (tuple[int, int, int]): The first color.
color2 (tuple[int, int, int]): The second color.
ratio (float): The ratio of color1 to color2.
color1: The first color.
color2: The second color.
ratio: The ratio of color1 to color2.
Returns:
Color: A Color representing the blending of the two supplied colors.
A Color representing the blending of the two supplied colors.
"""
r1, g1, b1 = color1
r2, g2, b2 = color2

View File

@@ -22,11 +22,11 @@ class Align:
"""Align a child renderable
Args:
renderable (RenderableType): Renderable to align.
size (Size): Size of container.
style (Style): Style of any padding.
horizontal (AlignHorizontal): Horizontal alignment.
vertical (AlignVertical): Vertical alignment.
renderable: Renderable to align.
size: Size of container.
style: Style of any padding.
horizontal: Horizontal alignment.
vertical: Vertical alignment.
"""
self.renderable = renderable
self.size = size

View File

@@ -19,11 +19,11 @@ class Sparkline(Generic[T]):
"""A sparkline representing a series of data.
Args:
data (Sequence[T]): The sequence of data to render.
width (int, optional): The width of the sparkline/the number of buckets to partition the data into.
min_color (Color, optional): The color of values equal to the min value in data.
max_color (Color, optional): The color of values equal to the max value in data.
summary_function (Callable[list[T]]): Function that will be applied to each bucket.
data: The sequence of data to render.
width: The width of the sparkline/the number of buckets to partition the data into.
min_color: The color of values equal to the min value in data.
max_color: The color of values equal to the max value in data.
summary_function: Function that will be applied to each bucket.
"""
BARS = "▁▂▃▄▅▆▇█"
@@ -49,8 +49,8 @@ class Sparkline(Generic[T]):
[1, 2, 3, 4] partitioned into 2 buckets is [[1, 2], [3, 4]].
Args:
data (Sequence[T]): The data to partition.
num_buckets (int): The number of buckets to partition the data into.
data: The data to partition.
num_buckets: The number of buckets to partition the data into.
"""
num_steps, remainder = divmod(len(data), num_buckets)
for i in range(num_buckets):

View File

@@ -19,12 +19,12 @@ def _get_blended_style_cached(
Cached because when a UI is static the opacity will be constant.
Args:
bg_color (Color): Background color.
fg_color (Color): Foreground color.
opacity (float): Opacity.
bg_color: Background color.
fg_color: Foreground color.
opacity: Opacity.
Returns:
Style: Resulting style.
Resulting style.
"""
return Style.from_color(
color=blend_colors(bg_color, fg_color, ratio=opacity),
@@ -39,8 +39,8 @@ class TextOpacity:
"""Wrap a renderable to blend foreground color into the background color.
Args:
renderable (RenderableType): The RenderableType to manipulate.
opacity (float): The opacity as a float. A value of 1.0 means text is fully visible.
renderable: The RenderableType to manipulate.
opacity: The opacity as a float. A value of 1.0 means text is fully visible.
"""
self.renderable = renderable
self.opacity = opacity
@@ -52,11 +52,11 @@ class TextOpacity:
"""Apply opacity to segments.
Args:
segments (Iterable[Segment]): Incoming segments.
opacity (float): Opacity to apply.
segments: Incoming segments.
opacity: Opacity to apply.
Returns:
Iterable[Segment]: Segments with applied opacity.
Segments with applied opacity.
"""
_Segment = Segment

View File

@@ -16,8 +16,8 @@ class Tint:
"""Wrap a renderable to apply a tint color.
Args:
renderable (RenderableType): A renderable.
color (Color): A color (presumably with alpha).
renderable: A renderable.
color: A color (presumably with alpha).
"""
self.renderable = renderable
self.color = color
@@ -29,11 +29,11 @@ class Tint:
"""Apply tint to segments.
Args:
segments (Iterable[Segment]): Incoming segments.
color (Color): Color of tint.
segments: Incoming segments.
color: Color of tint.
Returns:
Iterable[Segment]: Segments with applied tint.
Segments with applied tint.
"""
from_rich_color = Color.from_rich_color

View File

@@ -9,10 +9,10 @@ class UnderlineBar:
"""Thin horizontal bar with a portion highlighted.
Args:
highlight_range (tuple[float, float]): The range to highlight. Defaults to ``(0, 0)`` (no highlight)
highlight_style (StyleType): The style of the highlighted range of the bar.
background_style (StyleType): The style of the non-highlighted range(s) of the bar.
width (int, optional): The width of the bar, or ``None`` to fill available width.
highlight_range: The range to highlight. Defaults to ``(0, 0)`` (no highlight)
highlight_style: The style of the highlighted range of the bar.
background_style: The style of the non-highlighted range(s) of the bar.
width: The width of the bar, or ``None`` to fill available width.
"""
def __init__(

View File

@@ -99,10 +99,10 @@ class Screen(Widget):
"""Get the absolute offset of a given Widget.
Args:
widget (Widget): A widget
widget: A widget
Returns:
Offset: The widget's offset relative to the top left of the terminal.
The widget's offset relative to the top left of the terminal.
"""
return self._compositor.get_offset(widget)
@@ -110,11 +110,11 @@ class Screen(Widget):
"""Get the widget at a given coordinate.
Args:
x (int): X Coordinate.
y (int): Y Coordinate.
x: X Coordinate.
y: Y Coordinate.
Returns:
tuple[Widget, Region]: Widget and screen region.
Widget and screen region.
"""
return self._compositor.get_widget_at(x, y)
@@ -122,11 +122,11 @@ class Screen(Widget):
"""Get all widgets under a given coordinate.
Args:
x (int): X coordinate.
y (int): Y coordinate.
x: X coordinate.
y: Y coordinate.
Returns:
Iterable[tuple[Widget, Region]]: Sequence of (WIDGET, REGION) tuples.
Sequence of (WIDGET, REGION) tuples.
"""
return self._compositor.get_widgets_at(x, y)
@@ -134,11 +134,11 @@ class Screen(Widget):
"""Get the style under a given coordinate.
Args:
x (int): X Coordinate.
y (int): Y Coordinate.
x: X Coordinate.
y: Y Coordinate.
Returns:
Style: Rich Style object
Rich Style object
"""
return self._compositor.get_style_at(x, y)
@@ -146,10 +146,10 @@ class Screen(Widget):
"""Get the screen region of a Widget.
Args:
widget (Widget): A Widget within the composition.
widget: A Widget within the composition.
Returns:
Region: Region relative to screen.
Region relative to screen.
Raises:
NoWidget: If the widget could not be found in this screen.
@@ -161,7 +161,7 @@ class Screen(Widget):
"""Get widgets that may receive focus, in focus order.
Returns:
list[Widget]: List of Widgets in focus order.
List of Widgets in focus order.
"""
widgets: list[Widget] = []
add_widget = widgets.append
@@ -190,13 +190,13 @@ class Screen(Widget):
If no focusable widget matches the given CSS selector, focus is set to `None`.
Args:
direction (int, optional): 1 to move forward, -1 to move backward, or
direction: 1 to move forward, -1 to move backward, or
0 to keep the current focus.
selector (str | type[DOMNode.ExpectType], optional): CSS selector to filter
selector: CSS selector to filter
what nodes can be focused.
Returns:
Widget | None: Newly focused widget, or None for no focus. If the return
Newly focused widget, or None for no focus. If the return
is not `None`, then it is guaranteed that the widget returned matches
the CSS selectors given in the argument.
"""
@@ -252,11 +252,11 @@ class Screen(Widget):
If no focusable widget matches the given CSS selector, focus is set to `None`.
Args:
selector (str | type[DOMNode.ExpectType], optional): CSS selector to filter
selector: CSS selector to filter
what nodes can be focused.
Returns:
Widget | None: Newly focused widget, or None for no focus. If the return
Newly focused widget, or None for no focus. If the return
is not `None`, then it is guaranteed that the widget returned matches
the CSS selectors given in the argument.
"""
@@ -271,11 +271,11 @@ class Screen(Widget):
If no focusable widget matches the given CSS selector, focus is set to `None`.
Args:
selector (str | type[DOMNode.ExpectType], optional): CSS selector to filter
selector: CSS selector to filter
what nodes can be focused.
Returns:
Widget | None: Newly focused widget, or None for no focus. If the return
Newly focused widget, or None for no focus. If the return
is not `None`, then it is guaranteed that the widget returned matches
the CSS selectors given in the argument.
"""
@@ -287,8 +287,8 @@ class Screen(Widget):
"""Reset the focus when a widget is removed
Args:
widget (Widget): A widget that is removed.
avoiding (list[DOMNode] | None, optional): Optional list of nodes to avoid.
widget: A widget that is removed.
avoiding: Optional list of nodes to avoid.
"""
avoiding = avoiding or []
@@ -337,8 +337,8 @@ class Screen(Widget):
"""Focus (or un-focus) a widget. A focused widget will receive key events first.
Args:
widget (Widget | None): Widget to focus, or None to un-focus.
scroll_visible (bool, optional): Scroll widget in to view.
widget: Widget to focus, or None to un-focus.
scroll_visible: Scroll widget in to view.
"""
if widget is self.focused:
# Widget is already focused
@@ -415,7 +415,7 @@ class Screen(Widget):
"""Enqueue a callback to be invoked after the screen is repainted.
Args:
callback (CallbackType): A callback.
callback: A callback.
"""
self._callbacks.append(callback)

View File

@@ -14,10 +14,10 @@ class ScrollView(Widget):
"""
DEFAULT_CSS = """
ScrollView {
ScrollView {
overflow-y: auto;
overflow-x: auto;
}
overflow-x: auto;
}
"""
@property
@@ -47,11 +47,11 @@ class ScrollView(Widget):
"""Gets the width of the content area.
Args:
container (Size): Size of the container (immediate parent) widget.
viewport (Size): Size of the viewport.
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
Returns:
int: The optimal width of the content.
The optimal width of the content.
"""
return self.virtual_size.width
@@ -59,12 +59,12 @@ class ScrollView(Widget):
"""Gets the height (number of lines) in the content area.
Args:
container (Size): Size of the container (immediate parent) widget.
viewport (Size): Size of the viewport.
width (int): Width of renderable.
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
width: Width of renderable.
Returns:
int: The height of the content.
The height of the content.
"""
return self.virtual_size.height
@@ -74,9 +74,9 @@ class ScrollView(Widget):
"""Called when size is updated.
Args:
size (Size): New size.
virtual_size (Size): New virtual size.
container_size (Size): New container size.
size: New size.
virtual_size: New virtual size.
container_size: New container size.
"""
if self._size != size or container_size != container_size:
self.refresh()
@@ -95,7 +95,7 @@ class ScrollView(Widget):
"""Render the scrollable region (if `render_lines` is not implemented).
Returns:
RenderableType: Renderable object.
Renderable object.
"""
from rich.panel import Panel

View File

@@ -20,8 +20,8 @@ class Strip:
A Strip is like an immutable list of Segments. The immutability allows for effective caching.
Args:
segments (Iterable[Segment]): An iterable of segments.
cell_length (int | None, optional): The cell length if known, or None to calculate on demand. Defaults to None.
segments: An iterable of segments.
cell_length: The cell length if known, or None to calculate on demand. Defaults to None.
"""
__slots__ = [
@@ -48,11 +48,11 @@ class Strip:
"""Create a blank strip.
Args:
cell_length (int): Desired cell length.
style (Style | None): Style of blank.
cell_length: Desired cell length.
style: Style of blank.
Returns:
Strip: New strip.
New strip.
"""
return cls([Segment(" " * cell_length, style)], cell_length)
@@ -63,11 +63,11 @@ class Strip:
"""Convert lines (lists of segments) to a list of Strips.
Args:
lines (list[list[Segment]]): List of lines, where a line is a list of segments.
cell_length (int | None): Cell length of lines (must be same) or None if not known. Defaults to None.
lines: List of lines, where a line is a list of segments.
cell_length: Cell length of lines (must be same) or None if not known. Defaults to None.
Returns:
list[Strip]: List of strips.
List of strips.
"""
return [cls(segments, cell_length) for segments in lines]
@@ -77,10 +77,10 @@ class Strip:
at `index`.
Args:
index (int): The index to convert.
index: The index to convert.
Returns:
int: The cell position of the character at `index`.
The cell position of the character at `index`.
"""
return index_to_cell_position(self._segments, index)
@@ -97,10 +97,10 @@ class Strip:
"""Join a number of strips in to one.
Args:
strips (Iterable[Strip]): An iterable of Strips.
strips: An iterable of Strips.
Returns:
Strip: A new combined strip.
A new combined strip.
"""
segments: list[list[Segment]] = []
@@ -134,11 +134,11 @@ class Strip:
"""Adjust the cell length, possibly truncating or extending.
Args:
cell_length (int): New desired cell length.
style (Style | None): Style when extending, or `None`. Defaults to `None`.
cell_length: New desired cell length.
style: Style when extending, or `None`. Defaults to `None`.
Returns:
Strip: A new strip with the supplied cell length.
A new strip with the supplied cell length.
"""
new_line: list[Segment]
@@ -178,7 +178,7 @@ class Strip:
"""Simplify the segments (join segments with same style)
Returns:
Strip: New strip.
New strip.
"""
line = Strip(
Segment.simplify(self._segments),
@@ -190,10 +190,10 @@ class Strip:
"""Apply a filter to all segments in the strip.
Args:
filter (LineFilter): A line filter object.
filter: A line filter object.
Returns:
Strip: A new Strip.
A new Strip.
"""
return Strip(filter.apply(self._segments), self._cell_length)
@@ -201,11 +201,11 @@ class Strip:
"""Apply a style to Segments with the given link_id.
Args:
link_id (str): A link id.
link_style (Style): Style to apply.
link_id: A link id.
link_style: Style to apply.
Returns:
Strip: New strip (or same Strip if no changes).
New strip (or same Strip if no changes).
"""
_Segment = Segment
if not any(
@@ -230,11 +230,11 @@ class Strip:
"""Crop a strip between two cell positions.
Args:
start (int): The start cell position (inclusive).
end (int): The end cell position (exclusive).
start: The start cell position (inclusive).
end: The end cell position (exclusive).
Returns:
Strip: A new Strip.
A new Strip.
"""
if start == 0 and end == self.cell_length:
return self
@@ -283,10 +283,10 @@ class Strip:
"""Divide the strip in to multiple smaller strips by cutting at given (cell) indices.
Args:
cuts (Iterable[int]): An iterable of cell positions as ints.
cuts: An iterable of cell positions as ints.
Returns:
list[Strip]: A new list of strips.
A new list of strips.
"""
pos = 0

View File

@@ -9,11 +9,11 @@ def get_suggestion(word: str, possible_words: Sequence[str]) -> str | None:
Returns a close match of `word` amongst `possible_words`.
Args:
word (str): The word we want to find a close match for
possible_words (Sequence[str]): The words amongst which we want to find a close match
word: The word we want to find a close match for
possible_words: The words amongst which we want to find a close match
Returns:
str | None: The closest match amongst the `possible_words`. Returns `None` if no close matches could be found.
The closest match amongst the `possible_words`. Returns `None` if no close matches could be found.
Example: returns "red" for word "redu" and possible words ("yellow", "red")
"""
@@ -26,11 +26,11 @@ def get_suggestions(word: str, possible_words: Sequence[str], count: int) -> lis
Returns a list of up to `count` matches of `word` amongst `possible_words`.
Args:
word (str): The word we want to find a close match for
possible_words (Sequence[str]): The words amongst which we want to find close matches
word: The word we want to find a close match for
possible_words: The words amongst which we want to find close matches
Returns:
list[str]: The closest matches amongst the `possible_words`, from the closest to the least close.
The closest matches amongst the `possible_words`, from the closest to the least close.
Returns an empty list if no close matches could be found.
Example: returns ["yellow", "ellow"] for word "yllow" and possible words ("yellow", "red", "ellow")

View File

@@ -32,14 +32,14 @@ class Timer:
"""A class to send timer-based events.
Args:
event_target (MessageTarget): The object which will receive the timer events.
interval (float): The time between timer events.
sender (MessageTarget): The sender of the event.
name (str | None, optional): A name to assign the event (for debugging). Defaults to None.
callback (TimerCallback | None, optional): A optional callback to invoke when the event is handled. Defaults to None.
repeat (int | None, optional): The number of times to repeat the timer, or None to repeat forever. Defaults to None.
skip (bool, optional): Enable skipping of scheduled events that couldn't be sent in time. Defaults to True.
pause (bool, optional): Start the timer paused. Defaults to False.
event_target: The object which will receive the timer events.
interval: The time between timer events.
sender: The sender of the event.
name: A name to assign the event (for debugging). Defaults to None.
callback: A optional callback to invoke when the event is handled. Defaults to None.
repeat: The number of times to repeat the timer, or None to repeat forever. Defaults to None.
skip: Enable skipping of scheduled events that couldn't be sent in time. Defaults to True.
pause: Start the timer paused. Defaults to False.
"""
_timer_count: int = 1
@@ -87,7 +87,7 @@ class Timer:
"""Start the timer return the task.
Returns:
Task: A Task instance for the timer.
A Task instance for the timer.
"""
self._task = asyncio.create_task(self._run_timer())
return self._task

View File

@@ -42,13 +42,13 @@ def walk_depth_first(
Consider [walk_children][textual.dom.DOMNode.walk_children] which doesn't have this limitation.
Args:
root (DOMNode): The root note (starting point).
filter_type (type[WalkType] | None, optional): Optional DOMNode subclass to filter by, or ``None`` for no filter.
root: The root note (starting point).
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
Defaults to None.
with_root (bool, optional): Include the root in the walk. Defaults to True.
with_root: Include the root in the walk. Defaults to True.
Returns:
Iterable[DOMNode] | Iterable[WalkType]: An iterable of DOMNodes, or the type specified in ``filter_type``.
An iterable of DOMNodes, or the type specified in ``filter_type``.
"""
from textual.dom import DOMNode
@@ -104,13 +104,13 @@ def walk_breadth_first(
Consider [walk_children][textual.dom.DOMNode.walk_children] which doesn't have this limitation.
Args:
root (DOMNode): The root note (starting point).
filter_type (type[WalkType] | None, optional): Optional DOMNode subclass to filter by, or ``None`` for no filter.
root: The root note (starting point).
filter_type: Optional DOMNode subclass to filter by, or ``None`` for no filter.
Defaults to None.
with_root (bool, optional): Include the root in the walk. Defaults to True.
with_root: Include the root in the walk. Defaults to True.
Returns:
Iterable[DOMNode] | Iterable[WalkType]: An iterable of DOMNodes, or the type specified in ``filter_type``.
An iterable of DOMNodes, or the type specified in ``filter_type``.
"""
from textual.dom import DOMNode

View File

@@ -108,8 +108,8 @@ class _Styled:
"""Apply a style to a renderable.
Args:
renderable (RenderableType): Any renderable.
style (StyleType): A style to apply across the entire renderable.
renderable: Any renderable.
style: A style to apply across the entire renderable.
"""
def __init__(
@@ -288,7 +288,7 @@ class Widget(DOMNode):
"""Get the widget's siblings (self is removed from the return list).
Returns:
list[Widget]: A list of siblings.
A list of siblings.
"""
parent = self.parent
if parent is not None:
@@ -303,7 +303,7 @@ class Widget(DOMNode):
"""A list of siblings which will be shown.
Returns:
list[Widget]: List of siblings.
List of siblings.
"""
siblings = [
widget for widget in self.siblings if widget.visible and widget.display
@@ -317,7 +317,7 @@ class Widget(DOMNode):
May be overridden if you want different logic regarding allowing scrolling.
Returns:
bool: True if the widget may scroll _vertically_.
True if the widget may scroll _vertically_.
"""
return self.is_scrollable and self.show_vertical_scrollbar
@@ -328,7 +328,7 @@ class Widget(DOMNode):
May be overridden if you want different logic regarding allowing scrolling.
Returns:
bool: True if the widget may scroll _horizontally_.
True if the widget may scroll _horizontally_.
"""
return self.is_scrollable and self.show_horizontal_scrollbar
@@ -337,7 +337,7 @@ class Widget(DOMNode):
"""Check if both axis may be scrolled.
Returns:
bool: True if horizontal and vertical scrolling is enabled.
True if horizontal and vertical scrolling is enabled.
"""
return self.is_scrollable and (
self.allow_horizontal_scroll or self.allow_vertical_scroll
@@ -348,7 +348,7 @@ class Widget(DOMNode):
"""Widget offset from origin.
Returns:
Offset: Relative offset.
Relative offset.
"""
return self.styles.offset.resolve(self.size, self.app.size)
@@ -372,12 +372,12 @@ class Widget(DOMNode):
"""Return the first child (immediate descendent) of this node with the given ID.
Args:
id (str): The ID of the child.
expect_type (type | None, optional): Require the object be of the supplied type, or None for any type.
id: The ID of the child.
expect_type: Require the object be of the supplied type, or None for any type.
Defaults to None.
Returns:
ExpectType | Widget: The first child of this node with the ID.
The first child of this node with the ID.
Raises:
NoMatches: if no children could be found for this ID
@@ -410,12 +410,12 @@ class Widget(DOMNode):
Performs a depth-first search rooted at this widget.
Args:
id (str): The ID to search for in the subtree
expect_type (type | None, optional): Require the object be of the supplied type, or None for any type.
id: The ID to search for in the subtree
expect_type: Require the object be of the supplied type, or None for any type.
Defaults to None.
Returns:
ExpectType | Widget: The first descendant encountered with this ID.
The first descendant encountered with this ID.
Raises:
NoMatches: if no children could be found for this ID
@@ -437,11 +437,11 @@ class Widget(DOMNode):
"""Get a *Rich* style for a component.
Args:
name (str): Name of component.
partial (bool, optional): Return a partial style (not combined with parent).
name: Name of component.
partial: Return a partial style (not combined with parent).
Returns:
Style: A Rich style object.
A Rich style object.
"""
if name not in self._rich_style_cache:
@@ -458,10 +458,10 @@ class Widget(DOMNode):
"""Arrange children.
Args:
size (Size): Size of container.
size: Size of container.
Returns:
ArrangeResult: Widget locations.
Widget locations.
"""
assert self.is_container
@@ -487,7 +487,7 @@ class Widget(DOMNode):
"""Get widgets not part of the DOM.
Returns:
Iterable[Widget]: An iterable of Widgets.
An iterable of Widgets.
"""
if self._horizontal_scrollbar is not None:
@@ -501,10 +501,10 @@ class Widget(DOMNode):
"""Attempt to locate the point where the caller wants to mount something.
Args:
spot (int | str | Widget): The spot to find.
spot: The spot to find.
Returns:
tuple[Widget, int]: The parent and the location in its child list.
The parent and the location in its child list.
Raises:
MountError: If there was an error finding where to mount a widget.
@@ -555,12 +555,12 @@ class Widget(DOMNode):
"""Mount widgets below this widget (making this widget a container).
Args:
*widgets (Widget): The widget(s) to mount.
before (int | str | Widget, optional): Optional location to mount before.
after (int | str | Widget, optional): Optional location to mount after.
*widgets: The widget(s) to mount.
before: Optional location to mount before.
after: Optional location to mount after.
Returns:
AwaitMount: An awaitable object that waits for widgets to be mounted.
An awaitable object that waits for widgets to be mounted.
Raises:
MountError: If there is a problem with the mount request.
@@ -616,7 +616,7 @@ class Widget(DOMNode):
"""Move a child widget within its parent's list of children.
Args:
child (int | Widget): The child widget to move.
child: The child widget to move.
before: (int | Widget, optional): Optional location to move before.
after: (int | Widget, optional): Optional location to move after.
@@ -692,7 +692,7 @@ class Widget(DOMNode):
"""Called when the instance is registered.
Args:
app (App): App instance.
app: App instance.
"""
# Parse the Widget's CSS
for path, css, tie_breaker in self._get_default_css():
@@ -710,13 +710,13 @@ class Widget(DOMNode):
"""Process the box model for this widget.
Args:
container (Size): The size of the container widget (with a layout)
viewport (Size): The viewport size.
width_fraction (Fraction): A fraction used for 1 `fr` unit on the width dimension.
height_fraction (Fraction):A fraction used for 1 `fr` unit on the height dimension.
container: The size of the container widget (with a layout)
viewport: The viewport size.
width_fraction: A fraction used for 1 `fr` unit on the width dimension.
height_fraction: A fraction used for 1 `fr` unit on the height dimension.
Returns:
BoxModel: The size and margin for this widget.
The size and margin for this widget.
"""
box_model = get_box_model(
self.styles,
@@ -733,11 +733,11 @@ class Widget(DOMNode):
"""Called by textual to get the width of the content area. May be overridden in a subclass.
Args:
container (Size): Size of the container (immediate parent) widget.
viewport (Size): Size of the viewport.
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
Returns:
int: The optimal width of the content.
The optimal width of the content.
"""
if self.is_container:
assert self._layout is not None
@@ -763,12 +763,12 @@ class Widget(DOMNode):
"""Called by Textual to get the height of the content area. May be overridden in a subclass.
Args:
container (Size): Size of the container (immediate parent) widget.
viewport (Size): Size of the viewport.
width (int): Width of renderable.
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
width: Width of renderable.
Returns:
int: The height of the content.
The height of the content.
"""
if self.is_container:
assert self._layout is not None
@@ -862,7 +862,7 @@ class Widget(DOMNode):
"""Get a vertical scrollbar (create if necessary).
Returns:
ScrollBar: ScrollBar Widget.
ScrollBar Widget.
"""
from .scrollbar import ScrollBar
@@ -880,7 +880,7 @@ class Widget(DOMNode):
"""Get a vertical scrollbar (create if necessary).
Returns:
ScrollBar: ScrollBar Widget.
ScrollBar Widget.
"""
from .scrollbar import ScrollBar
@@ -944,7 +944,7 @@ class Widget(DOMNode):
"""A tuple of booleans that indicate if scrollbars are enabled.
Returns:
tuple[bool, bool]: A tuple of (<vertical scrollbar enabled>, <horizontal scrollbar enabled>)
A tuple of (<vertical scrollbar enabled>, <horizontal scrollbar enabled>)
"""
if not self.is_scrollable:
@@ -958,7 +958,7 @@ class Widget(DOMNode):
"""Get the width used by the *vertical* scrollbar.
Returns:
int: Number of columns in the vertical scrollbar.
Number of columns in the vertical scrollbar.
"""
styles = self.styles
if styles.scrollbar_gutter == "stable" and styles.overflow_y == "auto":
@@ -970,7 +970,7 @@ class Widget(DOMNode):
"""Get the height used by the *horizontal* scrollbar.
Returns:
int: Number of rows in the horizontal scrollbar.
Number of rows in the horizontal scrollbar.
"""
styles = self.styles
return styles.scrollbar_size_horizontal if self.show_horizontal_scrollbar else 0
@@ -980,7 +980,7 @@ class Widget(DOMNode):
"""Spacing required to fit scrollbar(s).
Returns:
Spacing: Scrollbar gutter spacing.
Scrollbar gutter spacing.
"""
return Spacing(
0, self.scrollbar_size_vertical, self.scrollbar_size_horizontal, 0
@@ -991,7 +991,7 @@ class Widget(DOMNode):
"""Spacing for padding / border / scrollbars.
Returns:
Spacing: Additional spacing around content area.
Additional spacing around content area.
"""
return self.styles.gutter + self.scrollbar_gutter
@@ -1001,7 +1001,7 @@ class Widget(DOMNode):
"""The size of the content area.
Returns:
Size: Content area size.
Content area size.
"""
return self.content_region.size
@@ -1010,7 +1010,7 @@ class Widget(DOMNode):
"""The size of the widget (including padding and border).
Returns:
Size: Outer size.
Outer size.
"""
return self._size
@@ -1019,7 +1019,7 @@ class Widget(DOMNode):
"""The size of the container (parent widget).
Returns:
Size: Container size.
Container size.
"""
return self._container_size
@@ -1028,7 +1028,7 @@ class Widget(DOMNode):
"""Gets an absolute region containing the content (minus padding and border).
Returns:
Region: Screen region that contains a widget's content.
Screen region that contains a widget's content.
"""
content_region = self.region.shrink(self.styles.gutter)
return content_region
@@ -1038,7 +1038,7 @@ class Widget(DOMNode):
"""Gets an absolute region containing the scrollable content (minus padding, border, and scrollbars).
Returns:
Region: Screen region that contains a widget's content.
Screen region that contains a widget's content.
"""
content_region = self.region.shrink(self.styles.gutter).shrink(
self.scrollbar_gutter
@@ -1050,7 +1050,7 @@ class Widget(DOMNode):
"""An offset from the Widget origin where the content begins.
Returns:
Offset: Offset from widget's origin.
Offset from widget's origin.
"""
x, y = self.gutter.top_left
@@ -1070,7 +1070,7 @@ class Widget(DOMNode):
errors.NoWidget: If the widget is not on the screen.
Returns:
Region: Region within screen occupied by widget.
Region within screen occupied by widget.
"""
try:
return self.screen.find_widget(self).region
@@ -1084,7 +1084,7 @@ class Widget(DOMNode):
"""The viewport region (parent window).
Returns:
Region: The region that contains this widget.
The region that contains this widget.
"""
if self.parent is None:
return self.size.region
@@ -1108,7 +1108,7 @@ class Widget(DOMNode):
"""The region within the scrollable area that is currently visible.
Returns:
Region: New region.
New region.
"""
window_region = self.region.at_offset(self.scroll_offset)
return window_region
@@ -1119,7 +1119,7 @@ class Widget(DOMNode):
depending on the scroll offset.
Returns:
Region: The virtual region of the Widget, inclusive of its margin.
The virtual region of the Widget, inclusive of its margin.
"""
return self.virtual_region.grow(self.styles.margin)
@@ -1128,7 +1128,7 @@ class Widget(DOMNode):
"""Get the children which may be focused.
Returns:
list[Widget]: List of widgets that can receive focus.
List of widgets that can receive focus.
"""
focusable = [
@@ -1148,7 +1148,7 @@ class Widget(DOMNode):
"""Get the current scroll offset.
Returns:
Offset: Offset a container has been scrolled by.
Offset a container has been scrolled by.
"""
return Offset(round(self.scroll_x), round(self.scroll_y))
@@ -1157,7 +1157,7 @@ class Widget(DOMNode):
"""Check if the background styles is not set.
Returns:
bool: ``True`` if there is background color, otherwise ``False``.
``True`` if there is background color, otherwise ``False``.
"""
return self.is_scrollable and self.styles.background.is_transparent
@@ -1166,7 +1166,7 @@ class Widget(DOMNode):
"""Get the current console.
Returns:
Console: A Rich console object.
A Rich console object.
"""
return active_app.get().console
@@ -1186,14 +1186,14 @@ class Widget(DOMNode):
"""Animate an attribute.
Args:
attribute (str): Name of the attribute to animate.
value (float | Animatable): The value to animate to.
final_value (object, optional): The final value of the animation. Defaults to `value` if not set.
duration (float | None, optional): The duration of the animate. Defaults to None.
speed (float | None, optional): The speed of the animation. Defaults to None.
delay (float, optional): A delay (in seconds) before the animation starts. Defaults to 0.0.
easing (EasingFunction | str, optional): An easing method. Defaults to "in_out_cubic".
on_complete (CallbackType | None, optional): A callable to invoke when the animation is finished. Defaults to None.
attribute: Name of the attribute to animate.
value: The value to animate to.
final_value: The final value of the animation. Defaults to `value` if not set.
duration: The duration of the animate. Defaults to None.
speed: The speed of the animation. Defaults to None.
delay: A delay (in seconds) before the animation starts. Defaults to 0.0.
easing: An easing method. Defaults to "in_out_cubic".
on_complete: A callable to invoke when the animation is finished. Defaults to None.
"""
if self._animate is None:
@@ -1215,7 +1215,7 @@ class Widget(DOMNode):
"""Get the layout object if set in styles, or a default layout.
Returns:
Layout: A layout object.
A layout object.
"""
return self.styles.layout or self._default_layout
@@ -1225,7 +1225,7 @@ class Widget(DOMNode):
"""Check if this widget is a container (contains other widgets).
Returns:
bool: True if this widget is a container.
True if this widget is a container.
"""
return self.styles.layout is not None or bool(self.children)
@@ -1234,7 +1234,7 @@ class Widget(DOMNode):
"""Check if this Widget may be scrolled.
Returns:
bool: True if this widget may be scrolled.
True if this widget may be scrolled.
"""
return self.styles.layout is not None or bool(self.children)
@@ -1243,7 +1243,7 @@ class Widget(DOMNode):
"""Get the name of this widgets layer.
Returns:
str: Name of layer.
Name of layer.
"""
return self.styles.layer or "default"
@@ -1253,7 +1253,7 @@ class Widget(DOMNode):
"""Layers of from parent.
Returns:
tuple[str, ...]: Tuple of layer names.
Tuple of layer names.
"""
for node in self.ancestors_with_self:
if not isinstance(node, Widget):
@@ -1303,7 +1303,7 @@ class Widget(DOMNode):
the entire widget will be considered dirty.
Args:
*regions (Region): Regions which require a repaint.
*regions: Regions which require a repaint.
"""
if regions:
@@ -1323,7 +1323,7 @@ class Widget(DOMNode):
"""Get a copy of the regions which need a repaint, and clear internal cache.
Returns:
Collection[Region]: Regions to repaint.
Regions to repaint.
"""
regions = self._repaint_regions.copy()
self._repaint_regions.clear()
@@ -1343,17 +1343,17 @@ class Widget(DOMNode):
"""Scroll to a given (absolute) coordinate, optionally animating.
Args:
x (int | None, optional): X coordinate (column) to scroll to, or None for no change. Defaults to None.
y (int | None, optional): Y coordinate (row) to scroll to, or None for no change. Defaults to None.
animate (bool, optional): Animate to new scroll position. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
x: X coordinate (column) to scroll to, or None for no change. Defaults to None.
y: Y coordinate (row) to scroll to, or None for no change. Defaults to None.
animate: Animate to new scroll position. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if the scroll position changed, otherwise False.
True if the scroll position changed, otherwise False.
"""
maybe_scroll_x = x is not None and (self.allow_horizontal_scroll or force)
maybe_scroll_y = y is not None and (self.allow_vertical_scroll or force)
@@ -1415,17 +1415,17 @@ class Widget(DOMNode):
"""Scroll relative to current position.
Args:
x (int | None, optional): X distance (columns) to scroll, or ``None`` for no change. Defaults to None.
y (int | None, optional): Y distance (rows) to scroll, or ``None`` for no change. Defaults to None.
animate (bool, optional): Animate to new scroll position. Defaults to False.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
x: X distance (columns) to scroll, or ``None`` for no change. Defaults to None.
y: Y distance (rows) to scroll, or ``None`` for no change. Defaults to None.
animate: Animate to new scroll position. Defaults to False.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if the scroll position changed, otherwise False.
True if the scroll position changed, otherwise False.
"""
return self.scroll_to(
None if x is None else (self.scroll_x + x),
@@ -1449,15 +1449,15 @@ class Widget(DOMNode):
"""Scroll to home position.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
if speed is None and duration is None:
duration = 1.0
@@ -1483,15 +1483,15 @@ class Widget(DOMNode):
"""Scroll to the end of the container.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
if speed is None and duration is None:
@@ -1518,15 +1518,15 @@ class Widget(DOMNode):
"""Scroll one cell left.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1550,15 +1550,15 @@ class Widget(DOMNode):
"""Scroll on cell right.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1582,15 +1582,15 @@ class Widget(DOMNode):
"""Scroll one line down.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1614,15 +1614,15 @@ class Widget(DOMNode):
"""Scroll one line up.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1646,15 +1646,15 @@ class Widget(DOMNode):
"""Scroll one page up.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1678,15 +1678,15 @@ class Widget(DOMNode):
"""Scroll one page down.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
return self.scroll_to(
@@ -1710,15 +1710,15 @@ class Widget(DOMNode):
"""Scroll one page left.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
if speed is None and duration is None:
@@ -1744,15 +1744,15 @@ class Widget(DOMNode):
"""Scroll one page right.
Args:
animate (bool, optional): Animate scroll. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: Animate scroll. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling was done.
True if any scrolling was done.
"""
if speed is None and duration is None:
@@ -1780,17 +1780,17 @@ class Widget(DOMNode):
"""Scroll scrolling to bring a widget in to view.
Args:
widget (Widget): A descendant widget.
animate (bool, optional): True to animate, or False to jump. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
widget: A descendant widget.
animate: True to animate, or False to jump. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
top (bool, optional): Scroll widget to top of container. Defaults to False.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
top: Scroll widget to top of container. Defaults to False.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
bool: True if any scrolling has occurred in any descendant, otherwise False.
True if any scrolling has occurred in any descendant, otherwise False.
"""
# Grow the region by the margin so to keep the margin in view.
@@ -1844,18 +1844,18 @@ class Widget(DOMNode):
the scrollable area.
Args:
region (Region): A region that should be visible.
spacing (Spacing | None, optional): Optional spacing around the region. Defaults to None.
animate (bool, optional): True to animate, or False to jump. Defaults to True.
speed (float | None, optional): Speed of scroll if animate is True. Or None to use duration.
duration (float | None, optional): Duration of animation, if animate is True and speed is None.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
region: A region that should be visible.
spacing: Optional spacing around the region. Defaults to None.
animate: True to animate, or False to jump. Defaults to True.
speed: Speed of scroll if animate is True. Or None to use duration.
duration: Duration of animation, if animate is True and speed is None.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
top (bool, optional): Scroll region to top of container. Defaults to False.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
top: Scroll region to top of container. Defaults to False.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
Returns:
Offset: The distance that was scrolled.
The distance that was scrolled.
"""
window = self.scrollable_content_region.at_offset(self.scroll_offset)
if spacing is not None:
@@ -1897,13 +1897,13 @@ class Widget(DOMNode):
"""Scroll the container to make this widget visible.
Args:
animate (bool, optional): _description_. Defaults to True.
speed (float | None, optional): _description_. Defaults to None.
duration (float | None, optional): _description_. Defaults to None.
top (bool, optional): Scroll to top of container. Defaults to False.
easing (EasingFunction | str | None, optional): An easing method for the scrolling animation. Defaults to "None",
animate: _description_. Defaults to True.
speed: _description_. Defaults to None.
duration: _description_. Defaults to None.
top: Scroll to top of container. Defaults to False.
easing: An easing method for the scrolling animation. Defaults to "None",
which will result in Textual choosing the configured default scrolling easing function.
force (bool, optional): Force scrolling even when prohibited by overflow styling. Defaults to `False`.
force: Force scrolling even when prohibited by overflow styling. Defaults to `False`.
"""
parent = self.parent
if isinstance(parent, Widget):
@@ -1952,10 +1952,10 @@ class Widget(DOMNode):
"""Adjusts the Widget region to accommodate scrollbars.
Args:
region (Region): A region for the widget.
region: A region for the widget.
Returns:
Region: The widget region minus scrollbars.
The widget region minus scrollbars.
"""
show_vertical_scrollbar, show_horizontal_scrollbar = self.scrollbars_enabled
@@ -1982,10 +1982,10 @@ class Widget(DOMNode):
"""Arrange the 'chrome' widgets (typically scrollbars) for a layout element.
Args:
region (Region): The containing region.
region: The containing region.
Returns:
Iterable[tuple[Widget, Region]]: Tuples of scrollbar Widget and region.
Tuples of scrollbar Widget and region.
"""
@@ -2024,7 +2024,7 @@ class Widget(DOMNode):
"""Pseudo classes for a widget.
Returns:
Iterable[str]: Names of the pseudo classes.
Names of the pseudo classes.
"""
if self.mouse_over:
@@ -2048,7 +2048,7 @@ class Widget(DOMNode):
"""Applies style attributes to the default renderable.
Returns:
RenderableType: A new renderable.
A new renderable.
"""
text_justify: JustifyMethod | None = None
if self.styles.has_rule("text_align"):
@@ -2086,9 +2086,9 @@ class Widget(DOMNode):
"""Called when the widget's size is updated.
Args:
size (Size): Screen size.
virtual_size (Size): Virtual (scrollable) size.
container_size (Size): Container size (size of parent).
size: Screen size.
virtual_size: Virtual (scrollable) size.
container_size: Container size (size of parent).
"""
if (
self._size != size
@@ -2106,7 +2106,7 @@ class Widget(DOMNode):
"""Update scrollbars visibility and dimensions.
Args:
virtual_size (Size): Virtual size.
virtual_size: Virtual size.
"""
self._refresh_scrollbars()
width, height = self.container_size
@@ -2162,10 +2162,10 @@ class Widget(DOMNode):
"""Render a line of content.
Args:
y (int): Y Coordinate of line.
y: Y Coordinate of line.
Returns:
list[Segment]: A rendered line.
A rendered line.
"""
if self._dirty_regions:
self._render_content()
@@ -2179,10 +2179,10 @@ class Widget(DOMNode):
"""Render the widget in to lines.
Args:
crop (Region): Region within visible area to render.
crop: Region within visible area to render.
Returns:
Lines: A list of list of segments.
A list of list of segments.
"""
strips = self._styles_cache.render_widget(self, crop)
return strips
@@ -2191,11 +2191,11 @@ class Widget(DOMNode):
"""Get the Rich style in a widget at a given relative offset.
Args:
x (int): X coordinate relative to the widget.
y (int): Y coordinate relative to the widget.
x: X coordinate relative to the widget.
y: Y coordinate relative to the widget.
Returns:
Style: A rich Style object.
A rich Style object.
"""
offset = Offset(x, y)
screen_offset = offset + self.region.offset
@@ -2234,9 +2234,9 @@ class Widget(DOMNode):
do this automatically.
Args:
*regions (Region, optional): Additional screen regions to mark as dirty.
repaint (bool, optional): Repaint the widget (will call render() again). Defaults to True.
layout (bool, optional): Also layout widgets in the view. Defaults to False.
*regions: Additional screen regions to mark as dirty.
repaint: Repaint the widget (will call render() again). Defaults to True.
layout: Also layout widgets in the view. Defaults to False.
"""
if layout:
@@ -2259,7 +2259,7 @@ class Widget(DOMNode):
"""Remove the Widget from the DOM (effectively deleting it)
Returns:
AwaitRemove: An awaitable object that waits for the widget to be removed.
An awaitable object that waits for the widget to be removed.
"""
await_remove = self.app._remove_nodes([self])
@@ -2269,7 +2269,7 @@ class Widget(DOMNode):
"""Get renderable for widget.
Returns:
RenderableType: Any renderable
Any renderable
"""
render = "" if self.is_container else self.css_identifier_styled
return render
@@ -2278,7 +2278,7 @@ class Widget(DOMNode):
"""Get renderable, promoting str to text as required.
Returns:
ConsoleRenderable | RichCast: A renderable
A renderable
"""
renderable = self.render()
if isinstance(renderable, str):
@@ -2289,7 +2289,7 @@ class Widget(DOMNode):
"""Perform a given action, with this widget as the default namespace.
Args:
action (str): Action encoded as a string.
action: Action encoded as a string.
"""
await self.app.action(action, self)
@@ -2297,10 +2297,10 @@ class Widget(DOMNode):
"""Post a message to this widget.
Args:
message (Message): Message to post.
message: Message to post.
Returns:
bool: True if the message was posted, False if this widget was closed / closing.
True if the message was posted, False if this widget was closed / closing.
"""
if not self.check_message_enabled(message):
return True
@@ -2312,7 +2312,7 @@ class Widget(DOMNode):
"""Called when there are no more events on the queue.
Args:
event (events.Idle): Idle event.
event: Idle event.
"""
if self._parent is not None and not self._closing:
try:
@@ -2331,7 +2331,7 @@ class Widget(DOMNode):
"""Give focus to this widget.
Args:
scroll_visible (bool, optional): Scroll parent to make this widget
scroll_visible: Scroll parent to make this widget
visible. Defaults to True.
"""
@@ -2357,7 +2357,7 @@ class Widget(DOMNode):
When captured, mouse events will go to this widget even when the pointer is not directly over the widget.
Args:
capture (bool, optional): True to capture or False to release. Defaults to True.
capture: True to capture or False to release. Defaults to True.
"""
self.app.capture_mouse(self if capture else None)

View File

@@ -154,7 +154,7 @@ class Button(Static, can_focus=True):
"""Event sent when a `Button` is pressed.
Attributes:
button (Button): The button that was pressed.
button: The button that was pressed.
"""
@property
@@ -174,12 +174,12 @@ class Button(Static, can_focus=True):
"""Create a Button widget.
Args:
label (str, optional): The text that appears within the button.
disabled (bool, optional): Whether the button is disabled or not.
variant (ButtonVariant, optional): The variant of the button.
name (str | None, optional): The name of the button.
id (str | None, optional): The ID of the button in the DOM.
classes (str | None, optional): The CSS classes of the button.
label: The text that appears within the button.
disabled: Whether the button is disabled or not.
variant: The variant of the button.
name: The name of the button.
id: The ID of the button in the DOM.
classes: The CSS classes of the button.
"""
super().__init__(name=name, id=id, classes=classes)
@@ -278,14 +278,14 @@ class Button(Static, can_focus=True):
"""Utility constructor for creating a success Button variant.
Args:
label (str, optional): The text that appears within the button.
disabled (bool, optional): Whether the button is disabled or not.
name (str | None, optional): The name of the button.
id (str | None, optional): The ID of the button in the DOM.
classes(str | None, optional): The CSS classes of the button.
label: The text that appears within the button.
disabled: Whether the button is disabled or not.
name: The name of the button.
id: The ID of the button in the DOM.
classes: The CSS classes of the button.
Returns:
Button: A Button widget of the 'success' variant.
A Button widget of the 'success' variant.
"""
return Button(
label=label,
@@ -309,14 +309,14 @@ class Button(Static, can_focus=True):
"""Utility constructor for creating a warning Button variant.
Args:
label (str, optional): The text that appears within the button.
disabled (bool, optional): Whether the button is disabled or not.
name (str | None, optional): The name of the button.
id (str | None, optional): The ID of the button in the DOM.
classes (str | None, optional): The CSS classes of the button.
label: The text that appears within the button.
disabled: Whether the button is disabled or not.
name: The name of the button.
id: The ID of the button in the DOM.
classes: The CSS classes of the button.
Returns:
Button: A Button widget of the 'warning' variant.
A Button widget of the 'warning' variant.
"""
return Button(
label=label,
@@ -340,14 +340,14 @@ class Button(Static, can_focus=True):
"""Utility constructor for creating an error Button variant.
Args:
label (str, optional): The text that appears within the button.
disabled (bool, optional): Whether the button is disabled or not.
name (str | None, optional): The name of the button.
id (str | None, optional): The ID of the button in the DOM.
classes (str | None, optional): The CSS classes of the button.
label: The text that appears within the button.
disabled: Whether the button is disabled or not.
name: The name of the button.
id: The ID of the button in the DOM.
classes: The CSS classes of the button.
Returns:
Button: A Button widget of the 'error' variant.
A Button widget of the 'error' variant.
"""
return Button(
label=label,

View File

@@ -69,11 +69,11 @@ class Checkbox(Widget, can_focus=True):
"""Initialise the checkbox.
Args:
value (bool, optional): The initial value of the checkbox. Defaults to False.
animate (bool, optional): True if the checkbox should animate when toggled. Defaults to True.
name (str | None, optional): The name of the checkbox.
id (str | None, optional): The ID of the checkbox in the DOM.
classes (str | None, optional): The CSS classes of the checkbox.
value: The initial value of the checkbox. Defaults to False.
animate: True if the checkbox should animate when toggled. Defaults to True.
name: The name of the checkbox.
id: The ID of the checkbox in the DOM.
classes: The CSS classes of the checkbox.
"""
super().__init__(name=name, id=id, classes=classes)
if value:
@@ -129,11 +129,11 @@ class Checkbox(Widget, can_focus=True):
"""Checkbox was toggled.
Attributes:
value (bool): The value that the checkbox was changed to.
input (Checkbox): The `Checkbox` widget that was changed.
value: The value that the checkbox was changed to.
input: The `Checkbox` widget that was changed.
"""
def __init__(self, sender: Checkbox, value: bool) -> None:
super().__init__(sender)
self.value = value
self.input = sender
self.value: bool = value
self.input: Checkbox = sender

View File

@@ -39,10 +39,10 @@ def default_cell_formatter(obj: object) -> RenderableType | None:
"""Format a cell in to a renderable.
Args:
obj (object): Data for a cell.
obj: Data for a cell.
Returns:
RenderableType | None: A renderable or None if the object could not be rendered.
A renderable or None if the object could not be rendered.
"""
if isinstance(obj, str):
return Text.from_markup(obj)
@@ -229,10 +229,10 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Get the value from the cell at the given coordinate.
Args:
coordinate (Coordinate): The coordinate to retrieve the value from.
coordinate: The coordinate to retrieve the value from.
Returns:
CellType: The value of the cell.
The value of the cell.
Raises:
CellDoesntExist: If there is no cell with the given coordinate.
@@ -423,7 +423,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Clear the table.
Args:
columns (bool, optional): Also clear the columns. Defaults to False.
columns: Also clear the columns. Defaults to False.
"""
self.row_count = 0
self._clear_caches()
@@ -451,8 +451,8 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Add a column to the table.
Args:
label (TextType): A str or Text object containing the label (shown top of column).
width (int, optional): Width of the column in cells or None to fit content. Defaults to None.
label: A str or Text object containing the label (shown top of column).
width: Width of the column in cells or None to fit content. Defaults to None.
"""
text_label = Text.from_markup(label) if isinstance(label, str) else label
@@ -479,7 +479,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
Args:
*cells: Positional arguments should contain cell data.
height (int, optional): The height of a row (in lines). Defaults to 1.
height: The height of a row (in lines). Defaults to 1.
"""
row_index = self.row_count
@@ -510,7 +510,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Add a number of rows.
Args:
rows (Iterable[Iterable[CellType]]): Iterable of rows. A row is an iterable of cells.
rows: Iterable of rows. A row is an iterable of cells.
"""
for row in rows:
self.add_row(*row)
@@ -527,8 +527,8 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Refresh a cell.
Args:
row_index (int): Row index.
column_index (int): Column index.
row_index: Row index.
column_index: Column index.
"""
if row_index < 0 or column_index < 0:
return
@@ -539,7 +539,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Refresh the row at the given index.
Args:
row_index (int): The index of the row to refresh.
row_index: The index of the row to refresh.
"""
if row_index < 0 or row_index >= len(self.rows):
return
@@ -551,7 +551,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Refresh the column at the given index.
Args:
column_index (int): The index of the column to refresh.
column_index: The index of the column to refresh.
"""
if column_index < 0 or column_index >= len(self.columns):
return
@@ -572,10 +572,10 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Get renderables for the given row.
Args:
row_index (int): Index of the row.
row_index: Index of the row.
Returns:
list[RenderableType]: List of renderables
List of renderables
"""
if row_index == -1:
@@ -604,15 +604,15 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Render the given cell.
Args:
row_index (int): Index of the row.
column_index (int): Index of the column.
style (Style): Style to apply.
width (int): Width of the cell.
cursor (bool): Is this cell affected by cursor highlighting?
hover (bool): Is this cell affected by hover cursor highlighting?
row_index: Index of the row.
column_index: Index of the column.
style: Style to apply.
width: Width of the cell.
cursor: Is this cell affected by cursor highlighting?
hover: Is this cell affected by hover cursor highlighting?
Returns:
Lines: A list of segments per line.
A list of segments per line.
"""
is_header_row = row_index == -1
@@ -661,14 +661,14 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Render a row in to lines for each cell.
Args:
row_index (int): Index of the row.
line_no (int): Line number (on screen, 0 is top)
base_style (Style): Base style of row.
cursor_location (Coordinate): The location of the cursor in the DataTable.
hover_location (Coordinate): The location of the hover cursor in the DataTable.
row_index: Index of the row.
line_no: Line number (on screen, 0 is top)
base_style: Base style of row.
cursor_location: The location of the cursor in the DataTable.
hover_location: The location of the hover cursor in the DataTable.
Returns:
tuple[Lines, Lines]: Lines for fixed cells, and Lines for scrollable cells.
Lines for fixed cells, and Lines for scrollable cells.
"""
cursor_type = self.cursor_type
show_cursor = self.show_cursor
@@ -761,10 +761,10 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Get row number and line offset for a given line.
Args:
y (int): Y coordinate relative to screen top.
y: Y coordinate relative to screen top.
Returns:
tuple[int, int]: Line number and line offset within cell.
Line number and line offset within cell.
"""
if self.show_header:
if y < self.header_height:
@@ -778,13 +778,13 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
"""Render a line in to a list of segments.
Args:
y (int): Y coordinate of line
x1 (int): X start crop.
x2 (int): X end crop (exclusive).
base_style (Style): Style to apply to line.
y: Y coordinate of line
x1: X start crop.
x2: X end crop (exclusive).
base_style: Style to apply to line.
Returns:
list[Segment]: List of segments for rendering.
List of segments for rendering.
"""
width = self.size.width
@@ -883,7 +883,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
cursor off.
Args:
active (bool): Display the hover cursor.
active: Display the hover cursor.
"""
self._show_hover_cursor = active
cursor_type = self.cursor_type
@@ -976,16 +976,15 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
widget in the DOM.
Attributes:
sender (DataTable): The DataTable the cell was highlighted in.
value (CellType): The value in the highlighted cell.
coordinate (Coordinate): The coordinate of the highlighted cell.
value: The value in the highlighted cell.
coordinate: The coordinate of the highlighted cell.
"""
def __init__(
self, sender: DataTable, value: CellType, coordinate: Coordinate
) -> None:
self.value = value
self.coordinate = coordinate
self.value: CellType = value
self.coordinate: Coordinate = coordinate
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:
@@ -1000,16 +999,15 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
widget in the DOM.
Attributes:
sender (DataTable): The DataTable the cell was selected in.
value (CellType): The value in the cell that was selected.
coordinate (Coordinate): The coordinate of the cell that was selected.
value: The value in the cell that was selected.
coordinate: The coordinate of the cell that was selected.
"""
def __init__(
self, sender: DataTable, value: CellType, coordinate: Coordinate
) -> None:
self.value = value
self.coordinate = coordinate
self.value: CellType = value
self.coordinate: Coordinate = coordinate
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:
@@ -1023,12 +1021,11 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
in a subclass of `DataTable` or in a parent widget in the DOM.
Attributes:
sender (DataTable): The DataTable the row was highlighted in.
cursor_row (int): The y-coordinate of the cursor that highlighted the row.
cursor_row: The y-coordinate of the cursor that highlighted the row.
"""
def __init__(self, sender: DataTable, cursor_row: int) -> None:
self.cursor_row = cursor_row
self.cursor_row: int = cursor_row
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:
@@ -1042,12 +1039,11 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
widget in the DOM.
Attributes:
sender (DataTable): The DataTable the row was selected in.
cursor_row (int): The y-coordinate of the cursor that made the selection.
cursor_row: The y-coordinate of the cursor that made the selection.
"""
def __init__(self, sender: DataTable, cursor_row: int) -> None:
self.cursor_row = cursor_row
self.cursor_row: int = cursor_row
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:
@@ -1061,12 +1057,11 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
widget in the DOM.
Attributes:
sender (DataTable): The DataTable the column was highlighted in.
cursor_column (int): The x-coordinate of the column that was highlighted.
cursor_column: The x-coordinate of the column that was highlighted.
"""
def __init__(self, sender: DataTable, cursor_column: int) -> None:
self.cursor_column = cursor_column
self.cursor_column: int = cursor_column
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:
@@ -1080,12 +1075,11 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
widget in the DOM.
Attributes:
sender (DataTable): The DataTable the column was selected in.
cursor_column (int): The x-coordinate of the column that was selected.
cursor_column: The x-coordinate of the column that was selected.
"""
def __init__(self, sender: DataTable, cursor_column: int) -> None:
self.cursor_column = cursor_column
self.cursor_column: int = cursor_column
super().__init__(sender)
def __rich_repr__(self) -> rich.repr.Result:

View File

@@ -25,10 +25,10 @@ class DirectoryTree(Tree[DirEntry]):
"""A Tree widget that presents files and directories.
Args:
path (str): Path to directory.
name (str | None, optional): The name of the widget, or None for no name. Defaults to None.
id (str | None, optional): The ID of the widget in the DOM, or None for no ID. Defaults to None.
classes (str | None, optional): A space-separated list of classes, or None for no classes. Defaults to None.
path: Path to directory.
name: The name of the widget, or None for no name. Defaults to None.
id: The ID of the widget in the DOM, or None for no ID. Defaults to None.
classes: A space-separated list of classes, or None for no classes. Defaults to None.
"""
COMPONENT_CLASSES: ClassVar[set[str]] = {
@@ -90,10 +90,10 @@ class DirectoryTree(Tree[DirEntry]):
"""Process a str or Text into a label. Maybe overridden in a subclass to modify how labels are rendered.
Args:
label (TextType): Label.
label: Label.
Returns:
Text: A Rich Text object.
A Rich Text object.
"""
if isinstance(label, str):
text_label = Text(label)

View File

@@ -84,7 +84,7 @@ class Header(Widget):
"""A header widget with icon and clock.
Args:
show_clock (bool, optional): True if the clock should be shown on the right of the header.
show_clock: True if the clock should be shown on the right of the header.
"""
DEFAULT_CSS = """

View File

@@ -116,13 +116,13 @@ class Input(Widget, can_focus=True):
"""Initialise the `Input` widget.
Args:
value (str | None, optional): An optional default value for the input.
placeholder (str, optional): Optional placeholder text for the input.
highlighter (Highlighter | None, optional): An optional highlighter for the input.
password (bool, optional): Flag to say if the field should obfuscate its content. Default is `False`.
name (str | None, optional): Optional name for the input widget.
id (str | None): Optional ID for the widget.
classes (str | None): Optional initial classes for the widget.
value: An optional default value for the input.
placeholder: Optional placeholder text for the input.
highlighter: An optional highlighter for the input.
password: Flag to say if the field should obfuscate its content. Default is `False`.
name: Optional name for the input widget.
id: Optional ID for the widget.
classes: Optional initial classes for the widget.
"""
super().__init__(name=name, id=id, classes=classes)
if value is not None:
@@ -277,7 +277,7 @@ class Input(Widget, can_focus=True):
"""Insert new text at the cursor, move the cursor to the end of the new text.
Args:
text (str): new text to insert.
text: New text to insert.
"""
if self.cursor_position > len(self.value):
self.value += text
@@ -333,24 +333,24 @@ class Input(Widget, can_focus=True):
"""Value was changed.
Attributes:
value (str): The value that the input was changed to.
input (Input): The `Input` widget that was changed.
value: The value that the input was changed to.
input: The `Input` widget that was changed.
"""
def __init__(self, sender: Input, value: str) -> None:
super().__init__(sender)
self.value = value
self.input = sender
self.value: str = value
self.input: Input = sender
class Submitted(Message, bubble=True):
"""Sent when the enter key is pressed within an `Input`.
Attributes:
value (str): The value of the `Input` being submitted..
input (Input): The `Input` widget that is being submitted.
value: The value of the `Input` being submitted..
input: The `Input` widget that is being submitted.
"""
def __init__(self, sender: Input, value: str) -> None:
super().__init__(sender)
self.value = value
self.input = sender
self.value: str = value
self.input: Input = sender

View File

@@ -44,7 +44,11 @@ class ListView(Vertical, can_focus=True, can_focus_children=False):
classes: The CSS classes of the widget.
"""
super().__init__(*children, name=name, id=id, classes=classes)
self.index = initial_index
self._index = initial_index
def on_mount(self) -> None:
"""Ensure the ListView is fully-settled after mounting."""
self.index = self._index
@property
def highlighted_child(self) -> ListItem | None:
@@ -91,10 +95,10 @@ class ListView(Vertical, can_focus=True, can_focus_children=False):
"""Append a new ListItem to the end of the ListView.
Args:
item (ListItem): The ListItem to append.
item: The ListItem to append.
Returns:
AwaitMount: An awaitable that yields control to the event loop
An awaitable that yields control to the event loop
until the DOM has been updated with the new child item.
"""
await_mount = self.mount(item)
@@ -106,7 +110,7 @@ class ListView(Vertical, can_focus=True, can_focus_children=False):
"""Clear all items from the ListView.
Returns:
AwaitRemove: An awaitable that yields control to the event loop until
An awaitable that yields control to the event loop until
the DOM has been updated to reflect all children being removed.
"""
await_remove = self.query("ListView > ListItem").remove()
@@ -140,20 +144,20 @@ class ListView(Vertical, can_focus=True, can_focus_children=False):
"""Emitted when the highlighted item changes. Highlighted item is controlled using up/down keys.
Attributes:
item (ListItem | None): The highlighted item, if there is one highlighted.
item: The highlighted item, if there is one highlighted.
"""
def __init__(self, sender: ListView, item: ListItem | None) -> None:
super().__init__(sender)
self.item = item
self.item: ListItem | None = item
class Selected(Message, bubble=True):
"""Emitted when a list item is selected, e.g. when you press the enter key on it
Attributes:
item (ListItem): The selected item.
item: The selected item.
"""
def __init__(self, sender: ListView, item: ListItem) -> None:
super().__init__(sender)
self.item = item
self.item: ListItem = item

View File

@@ -91,14 +91,14 @@ class Placeholder(Widget):
"""Create a Placeholder widget.
Args:
label (str | None, optional): The label to identify the placeholder.
label: The label to identify the placeholder.
If no label is present, uses the placeholder ID instead. Defaults to None.
variant (PlaceholderVariant, optional): The variant of the placeholder.
variant: The variant of the placeholder.
Defaults to "default".
name (str | None, optional): The name of the placeholder. Defaults to None.
id (str | None, optional): The ID of the placeholder in the DOM.
name: The name of the placeholder. Defaults to None.
id: The ID of the placeholder in the DOM.
Defaults to None.
classes (str | None, optional): A space separated string with the CSS classes
classes: A space separated string with the CSS classes
of the placeholder, if any. Defaults to None.
"""
# Create and cache renderables for all the variants.

View File

@@ -13,7 +13,7 @@ def _check_renderable(renderable: object):
(https://rich.readthedocs.io/en/latest/protocol.html)
Args:
renderable (object): A potentially renderable object.
renderable: A potentially renderable object.
Raises:
RenderError: If the object can not be rendered.
@@ -28,14 +28,14 @@ class Static(Widget, inherit_bindings=False):
"""A widget to display simple static content, or use as a base class for more complex widgets.
Args:
renderable (RenderableType, optional): A Rich renderable, or string containing console markup.
renderable: A Rich renderable, or string containing console markup.
Defaults to "".
expand (bool, optional): Expand content if required to fill container. Defaults to False.
shrink (bool, optional): Shrink content if required to fill container. Defaults to False.
markup (bool, optional): True if markup should be parsed and rendered. Defaults to True.
name (str | None, optional): Name of widget. Defaults to None.
id (str | None, optional): ID of Widget. Defaults to None.
classes (str | None, optional): Space separated list of class names. Defaults to None.
expand: Expand content if required to fill container. Defaults to False.
shrink: Shrink content if required to fill container. Defaults to False.
markup: True if markup should be parsed and rendered. Defaults to True.
name: Name of widget. Defaults to None.
id: ID of Widget. Defaults to None.
classes: Space separated list of class names. Defaults to None.
"""
DEFAULT_CSS = """
@@ -83,7 +83,7 @@ class Static(Widget, inherit_bindings=False):
"""Get a rich renderable for the widget's content.
Returns:
RenderableType: A rich renderable.
A rich renderable.
"""
return self._renderable
@@ -91,7 +91,7 @@ class Static(Widget, inherit_bindings=False):
"""Update the widget's content area with new text or Rich renderable.
Args:
renderable (RenderableType, optional): A new rich renderable. Defaults to empty renderable;
renderable: A new rich renderable. Defaults to empty renderable;
"""
_check_renderable(renderable)
self.renderable = renderable

View File

@@ -71,10 +71,10 @@ class TextLog(ScrollView, can_focus=True):
"""Write text or a rich renderable.
Args:
content (RenderableType): Rich renderable (or text).
width (int): Width to render or None to use optimal width. Defaults to `None`.
expand (bool): Enable expand to widget width, or False to use `width`. Defaults to `False`.
shrink (bool): Enable shrinking of content to fit width. Defaults to `True`.
content: Rich renderable (or text).
width: Width to render or None to use optimal width. Defaults to `None`.
expand: Enable expand to widget width, or False to use `width`. Defaults to `False`.
shrink: Enable shrinking of content to fit width. Defaults to `True`.
"""
renderable: RenderableType
@@ -151,10 +151,10 @@ class TextLog(ScrollView, can_focus=True):
"""Render the widget in to lines.
Args:
crop (Region): Region within visible area to.
crop: Region within visible area to.
Returns:
Lines: A list of list of segments
A list of list of segments
"""
lines = self._styles_cache.render_widget(self, crop)
return lines

View File

@@ -44,10 +44,10 @@ class _TreeLine(Generic[TreeDataType]):
"""Get the cell width of the line as rendered.
Args:
guide_depth (int): The guide depth (cells in the indentation).
guide_depth: The guide depth (cells in the indentation).
Returns:
int: Width in cells.
Width in cells.
"""
guides = max(0, len(self.path) - (1 if show_root else 2)) * guide_depth
return guides
@@ -190,7 +190,7 @@ class TreeNode(Generic[TreeDataType]):
"""Set a new label for the node.
Args:
label (TextType): A str or Text object with the new label.
label: A str or Text object with the new label.
"""
self._updates += 1
text_label = self._tree.process_label(label)
@@ -207,13 +207,13 @@ class TreeNode(Generic[TreeDataType]):
"""Add a node to the sub-tree.
Args:
label (TextType): The new node's label.
data (TreeDataType): Data associated with the new node.
expand (bool, optional): Node should be expanded. Defaults to True.
allow_expand (bool, optional): Allow use to expand the node via keyboard or mouse. Defaults to True.
label: The new node's label.
data: Data associated with the new node.
expand: Node should be expanded. Defaults to True.
allow_expand: Allow use to expand the node via keyboard or mouse. Defaults to True.
Returns:
TreeNode[TreeDataType]: A new Tree node
A new Tree node
"""
text_label = self._tree.process_label(label)
node = self._tree._add_node(self, text_label, data)
@@ -230,11 +230,11 @@ class TreeNode(Generic[TreeDataType]):
"""Add a 'leaf' node (a node that can not expand).
Args:
label (TextType): Label for the node.
data (TreeDataType | None, optional): Optional data. Defaults to None.
label: Label for the node.
data: Optional data. Defaults to None.
Returns:
TreeNode[TreeDataType]: New node.
New node.
"""
node = self.add(label, data, expand=False, allow_expand=False)
return node
@@ -330,47 +330,58 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
),
}
class NodeMessage(Generic[EventTreeDataType], Message, bubble=True):
"""Base class for events sent when something happens with a node.
class NodeSelected(Generic[EventTreeDataType], Message, bubble=True):
"""Event sent when a node is selected.
Attributes:
TreeNode[EventTreeDataType]: The node involved in the event.
node: The node that was selected.
"""
def __init__(
self, sender: MessageTarget, node: TreeNode[EventTreeDataType]
) -> None:
self.node = node
self.node: TreeNode[EventTreeDataType] = node
super().__init__(sender)
class NodeSelected(NodeMessage[EventTreeDataType]):
"""Event sent when a node is selected.
Attributes:
TreeNode[EventTreeDataType]: The node that was selected.
"""
class NodeExpanded(NodeMessage[EventTreeDataType]):
class NodeExpanded(Generic[EventTreeDataType], Message, bubble=True):
"""Event sent when a node is expanded.
Attributes:
TreeNode[EventTreeDataType]: The node that was expanded.
node: The node that was expanded.
"""
class NodeCollapsed(NodeMessage[EventTreeDataType]):
def __init__(
self, sender: MessageTarget, node: TreeNode[EventTreeDataType]
) -> None:
self.node: TreeNode[EventTreeDataType] = node
super().__init__(sender)
class NodeCollapsed(Generic[EventTreeDataType], Message, bubble=True):
"""Event sent when a node is collapsed.
Attributes:
TreeNode[EventTreeDataType]: The node that was collapsed.
node: The node that was collapsed.
"""
class NodeHighlighted(NodeMessage[EventTreeDataType]):
def __init__(
self, sender: MessageTarget, node: TreeNode[EventTreeDataType]
) -> None:
self.node: TreeNode[EventTreeDataType] = node
super().__init__(sender)
class NodeHighlighted(Generic[EventTreeDataType], Message, bubble=True):
"""Event sent when a node is highlighted.
Attributes:
TreeNode[EventTreeDataType]: The node that was collapsed.
node: The node that was highlighted.
"""
def __init__(
self, sender: MessageTarget, node: TreeNode[EventTreeDataType]
) -> None:
self.node: TreeNode[EventTreeDataType] = node
super().__init__(sender)
def __init__(
self,
label: TextType,
@@ -407,10 +418,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Process a str or Text in to a label. Maybe overridden in a subclass to change modify how labels are rendered.
Args:
label (TextType): Label.
label: Label.
Returns:
Text: A Rich Text object.
A Rich Text object.
"""
if isinstance(label, str):
text_label = Text.from_markup(label)
@@ -437,12 +448,12 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Render a label for the given node. Override this to modify how labels are rendered.
Args:
node (TreeNode[TreeDataType]): A tree node.
base_style (Style): The base style of the widget.
style (Style): The additional style for the label.
node: A tree node.
base_style: The base style of the widget.
style: The additional style for the label.
Returns:
Text: A Rich Text object containing the label.
A Rich Text object containing the label.
"""
node_label = node._label.copy()
node_label.stylize(style)
@@ -465,10 +476,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
overridden in a sub-class if it can be done more efficiently.
Args:
node (TreeNode[TreeDataType]): A node.
node: A node.
Returns:
int: Width in cells.
Width in cells.
"""
label = self.render_label(node, NULL_STYLE, NULL_STYLE)
return label.cell_len
@@ -495,7 +506,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Move the cursor to the given node, or reset cursor.
Args:
node (TreeNode[TreeDataType] | None): A tree node, or None to reset cursor.
node: A tree node, or None to reset cursor.
"""
self.cursor_line = -1 if node is None else node._line
@@ -503,10 +514,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Get the node for a given line.
Args:
line_no (int): A line number.
line_no: A line number.
Returns:
TreeNode[TreeDataType] | None: A tree node, or ``None`` if there is no node at that line.
A tree node, or ``None`` if there is no node at that line.
"""
try:
line = self._tree_lines[line_no]
@@ -522,10 +533,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Get a tree node by its ID.
Args:
node_id (NodeID): The ID of the node to get.
node_id: The ID of the node to get.
Returns:
TreeNode[TreeDataType]: The node associated with that ID.
The node associated with that ID.
Raises:
Tree.UnknownID: Raised if the `TreeNode` ID is unknown.
@@ -562,7 +573,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Create a new node ID.
Returns:
NodeID: A unique node ID.
A unique node ID.
"""
id = self._current_id
self._current_id += 1
@@ -583,10 +594,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
is visible after the scroll.
Args:
line (int): A line number.
line: A line number.
Returns:
Region | None: the region occupied by the label, or `None` if the
The region occupied by the label, or `None` if the
line is not in the tree.
"""
try:
@@ -634,7 +645,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Scroll to the given line.
Args:
line (int): A line number.
line: A line number.
"""
region = self._get_label_region(line)
if region is not None:
@@ -644,7 +655,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Scroll to the given node.
Args:
node (TreeNode[TreeDataType]): Node to scroll in to view.
node: Node to scroll in to view.
"""
line = node._line
if line != -1:
@@ -654,7 +665,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Refresh (repaint) a given line in the tree.
Args:
line (int): Line number.
line: Line number.
"""
region = Region(0, line - self.scroll_offset.y, self.size.width, 1)
self.refresh(region)
@@ -668,7 +679,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Refresh a node and all its children.
Args:
node (TreeNode[TreeDataType]): A tree node.
node: A tree node.
"""
scroll_y = self.scroll_offset.y
height = self.size.height
@@ -787,10 +798,10 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
"""Get the guide strings for a given style.
Args:
style (Style): A Style object.
style: A Style object.
Returns:
tuple[str, str, str, str]: Strings for space, vertical, terminator and cross.
Strings for space, vertical, terminator and cross.
"""
if self.show_guides:
lines = self.LINES["default"]

View File

@@ -26,8 +26,8 @@ class Tab:
"""Data container representing a single tab.
Attributes:
label (str): The user-facing label that will appear inside the tab.
name (str, optional): A unique string key that will identify the tab. If None, it will default to the label.
label: The user-facing label that will appear inside the tab.
name: A unique string key that will identify the tab. If None, it will default to the label.
If the name is not unique within a single list of tabs, only the final Tab will be displayed.
"""
@@ -175,18 +175,18 @@ class Tabs(Widget):
"""Widget which displays a set of horizontal tabs.
Args:
tabs (list[Tab]): A list of Tab objects defining the tabs which should be rendered.
active_tab (str, optional): The name of the tab that should be active on first render.
active_tab_style (StyleType, optional): Style to apply to the label of the active tab.
active_bar_style (StyleType, optional): Style to apply to the underline of the active tab.
inactive_tab_style (StyleType, optional): Style to apply to the label of inactive tabs.
inactive_bar_style (StyleType, optional): Style to apply to the underline of inactive tabs.
inactive_text_opacity (float, optional): Opacity of the text labels of inactive tabs.
animation_duration (float, optional): The duration of the tab change animation, in seconds.
animation_function (str, optional): The easing function to use for the tab change animation.
tab_padding (int, optional): The padding at the side of each tab. If None, tabs will
tabs: A list of Tab objects defining the tabs which should be rendered.
active_tab: The name of the tab that should be active on first render.
active_tab_style: Style to apply to the label of the active tab.
active_bar_style: Style to apply to the underline of the active tab.
inactive_tab_style: Style to apply to the label of inactive tabs.
inactive_bar_style: Style to apply to the underline of inactive tabs.
inactive_text_opacity: Opacity of the text labels of inactive tabs.
animation_duration: The duration of the tab change animation, in seconds.
animation_function: The easing function to use for the tab change animation.
tab_padding: The padding at the side of each tab. If None, tabs will
automatically be padded such that they fit the available horizontal space.
search_by_first_character (bool, optional): If True, entering a character on your keyboard
search_by_first_character: If True, entering a character on your keyboard
will activate the next tab (in left-to-right order) with a label starting with
that character.
"""
@@ -236,7 +236,7 @@ class Tabs(Widget):
to cycle through tabs with labels beginning with that character.
Args:
event (events.Key): The Key event being handled
event: The Key event being handled
"""
if not self.tabs:
event.prevent_default()
@@ -273,7 +273,7 @@ class Tabs(Widget):
"""Activate the next tab that begins with the character
Args:
char (str): The character to search for
char: The character to search for
"""
def find_next_matching_tab(
@@ -297,7 +297,7 @@ class Tabs(Widget):
"""Activate a tab using the tab number.
Args:
tab_number (int): The number of the tab.
tab_number: The number of the tab.
The leftmost tab is number 1, the next is 2, and so on. 0 represents the 10th tab.
"""
if tab_number > len(self.tabs):
@@ -324,7 +324,7 @@ class Tabs(Widget):
"""Return the index of the first tab with a certain name
Args:
tab_name (str): The name to search for.
tab_name: The name to search for.
"""
return next((i for i, tab in enumerate(self.tabs) if tab.name == tab_name), 0)

View File

@@ -0,0 +1,49 @@
from textual.app import App, ComposeResult
from textual.widgets import ListView, ListItem, Label
class MyListView(ListView):
"""Test child class of a ListView."""
def __init__(self, items: int = 0) -> None:
super().__init__()
self._items = items
def compose(self) -> ComposeResult:
"""Compose the child widgets."""
for n in range(self._items):
yield ListItem(Label(f"This is item {n}"))
class ListViewApp(App[None]):
"""ListView test app."""
def __init__(self, items: int = 0) -> None:
super().__init__()
self._items = items
def compose(self) -> ComposeResult:
"""Compose the child widgets."""
yield MyListView(self._items)
async def test_empty_inherited_list_view() -> None:
"""An empty self-populating inherited ListView should work as expected."""
async with ListViewApp().run_test() as pilot:
await pilot.press("tab")
await pilot.pause(2 / 100)
assert pilot.app.query_one(MyListView).index is None
await pilot.press("down")
await pilot.pause(2 / 100)
assert pilot.app.query_one(MyListView).index is None
async def test_populated_inherited_list_view() -> None:
"""A self-populating inherited ListView should work as normal."""
async with ListViewApp(30).run_test() as pilot:
await pilot.press("tab")
await pilot.pause(2 / 100)
assert pilot.app.query_one(MyListView).index == 0
await pilot.press("down")
await pilot.pause(2 / 100)
assert pilot.app.query_one(MyListView).index == 1

41
tests/test_version.py Normal file
View File

@@ -0,0 +1,41 @@
import re
# https://stackoverflow.com/questions/37972029/regex-to-match-pep440-compliant-version-strings
VERSION_PATTERN = r"""
v?
(?:
(?:(?P<epoch>[0-9]+)!)? # epoch
(?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
(?P<pre> # pre-release
[-_\.]?
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
[-_\.]?
(?P<pre_n>[0-9]+)?
)?
(?P<post> # post release
(?:-(?P<post_n1>[0-9]+))
|
(?:
[-_\.]?
(?P<post_l>post|rev|r)
[-_\.]?
(?P<post_n2>[0-9]+)?
)
)?
(?P<dev> # dev release
[-_\.]?
(?P<dev_l>dev)
[-_\.]?
(?P<dev_n>[0-9]+)?
)?
)
(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
"""
def test_version():
import textual
version = textual.__version__
assert isinstance(version, str)
assert re.match(VERSION_PATTERN, version, re.VERBOSE) is not None