Merge pull request #1759 from Textualize/typing-fix-9-feb-2023

typing fixes
This commit is contained in:
Will McGugan
2023-02-09 17:41:59 +00:00
committed by GitHub
15 changed files with 1333 additions and 1285 deletions

2315
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -69,6 +69,7 @@ syrupy = "^3.0.0"
mkdocs-rss-plugin = "^1.5.0"
httpx = "^0.23.1"
msgpack-types = "^0.2.0"
types-setuptools = "^67.2.0.1"
[tool.black]
includes = "src"

View File

@@ -191,7 +191,7 @@ BORDER_LOCATIONS: dict[
INVISIBLE_EDGE_TYPES = cast("frozenset[EdgeType]", frozenset(("", "none", "hidden")))
BorderValue: TypeAlias = Tuple[EdgeType, Union[str, Color, Style]]
BorderValue: TypeAlias = Tuple[EdgeType, Color]
BoxSegments: TypeAlias = Tuple[
Tuple[Segment, Segment, Segment],

View File

@@ -10,11 +10,12 @@ when setting and getting.
from __future__ import annotations
from operator import attrgetter
from typing import TYPE_CHECKING, Generic, Iterable, NamedTuple, TypeVar, cast
from typing import TYPE_CHECKING, Generic, Iterable, NamedTuple, Sequence, TypeVar, cast
import rich.errors
import rich.repr
from rich.style import Style
from typing_extensions import TypeAlias
from .._border import normalize_border_value
from ..color import Color, ColorParseError
@@ -51,7 +52,7 @@ if TYPE_CHECKING:
from .types import AlignHorizontal, AlignVertical, DockEdge, EdgeType
BorderDefinition = (
BorderDefinition: TypeAlias = (
"Sequence[tuple[EdgeType, str | Color] | None] | tuple[EdgeType, str | Color]"
)
@@ -153,7 +154,7 @@ class ScalarProperty:
Returns:
The Scalar object or ``None`` if it's not set.
"""
return obj.get_rule(self.name)
return cast("Scalar | None", obj.get_rule(self.name))
def __set__(
self, obj: StylesBase, value: float | int | Scalar | str | None
@@ -233,7 +234,7 @@ class ScalarListProperty:
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> tuple[Scalar, ...] | None:
return obj.get_rule(self.name)
return cast("tuple[Scalar, ...]", obj.get_rule(self.name))
def __set__(
self, obj: StylesBase, value: str | Iterable[str | float] | None
@@ -289,7 +290,10 @@ class BoxProperty:
A ``tuple[EdgeType, Style]`` containing the string type of the box and
it's style. Example types are "rounded", "solid", and "dashed".
"""
return obj.get_rule(self.name) or ("", self._default_color)
return cast(
"tuple[EdgeType, Color]",
obj.get_rule(self.name) or ("", self._default_color),
)
def __set__(self, obj: Styles, border: tuple[EdgeType, str | Color] | None):
"""Set the box property.
@@ -452,7 +456,7 @@ class BorderProperty:
check_refresh()
return
if isinstance(border, tuple) and len(border) == 2:
_border = normalize_border_value(border)
_border = normalize_border_value(border) # type: ignore
setattr(obj, top, _border)
setattr(obj, right, _border)
setattr(obj, bottom, _border)
@@ -462,15 +466,15 @@ class BorderProperty:
count = len(border)
if count == 1:
_border = normalize_border_value(border[0])
_border = normalize_border_value(border[0]) # type: ignore
setattr(obj, top, _border)
setattr(obj, right, _border)
setattr(obj, bottom, _border)
setattr(obj, left, _border)
elif count == 2:
_border1, _border2 = (
normalize_border_value(border[0]),
normalize_border_value(border[1]),
normalize_border_value(border[0]), # type: ignore
normalize_border_value(border[1]), # type: ignore
)
setattr(obj, top, _border1)
setattr(obj, bottom, _border1)
@@ -478,10 +482,10 @@ class BorderProperty:
setattr(obj, left, _border2)
elif count == 4:
_border1, _border2, _border3, _border4 = (
normalize_border_value(border[0]),
normalize_border_value(border[1]),
normalize_border_value(border[2]),
normalize_border_value(border[3]),
normalize_border_value(border[0]), # type: ignore
normalize_border_value(border[1]), # type: ignore
normalize_border_value(border[2]), # type: ignore
normalize_border_value(border[3]), # type: ignore
)
setattr(obj, top, _border1)
setattr(obj, right, _border2)
@@ -513,7 +517,7 @@ class SpacingProperty:
Returns:
The Spacing. If unset, returns the null spacing ``(0, 0, 0, 0)``.
"""
return obj.get_rule(self.name, NULL_SPACING)
return cast(Spacing, obj.get_rule(self.name, NULL_SPACING))
def __set__(self, obj: StylesBase, spacing: SpacingDimensions | None):
"""Set the Spacing.
@@ -594,7 +598,7 @@ class LayoutProperty:
Returns:
The ``Layout`` object.
"""
return obj.get_rule(self.name)
return cast("Layout | None", obj.get_rule(self.name))
def __set__(self, obj: StylesBase, layout: str | Layout | None):
"""
@@ -648,7 +652,7 @@ class OffsetProperty:
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)
return cast("ScalarOffset", obj.get_rule(self.name, NULL_SCALAR))
def __set__(
self, obj: StylesBase, offset: tuple[int | str, int | str] | ScalarOffset | None
@@ -734,7 +738,7 @@ class StringEnumProperty:
Returns:
The string property value.
"""
return obj.get_rule(self.name, self._default)
return cast(str, obj.get_rule(self.name, self._default))
def _before_refresh(self, obj: StylesBase, value: str | None) -> None:
"""Do any housekeeping before asking for a layout refresh after a value change."""
@@ -795,7 +799,7 @@ class NameProperty:
Returns:
The name.
"""
return obj.get_rule(self.name, "")
return cast(str, obj.get_rule(self.name, ""))
def __set__(self, obj: StylesBase, name: str | None):
"""Set the name property.
@@ -929,7 +933,7 @@ class StyleFlagsProperty:
Returns:
The ``Style`` object.
"""
return obj.get_rule(self.name, Style.null())
return cast(Style, 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.
@@ -992,7 +996,7 @@ class TransitionsProperty:
e.g. ``{"offset": Transition(...), ...}``. If no transitions have been set, an empty ``dict``
is returned.
"""
return obj.get_rule("transitions", {})
return cast("dict[str, Transition]", obj.get_rule("transitions", {}))
def __set__(self, obj: Styles, transitions: dict[str, Transition] | None) -> None:
_rich_traceback_omit = True

View File

@@ -113,7 +113,6 @@ class StylesBuilder:
suggested_property_name=suggested_property_name,
),
)
return
tokens = declaration.tokens
@@ -182,7 +181,13 @@ class StylesBuilder:
"""
if len(tokens) != 1:
string_enum_help_text(name, valid_values=list(valid_values), context="css"),
self.error(
name,
tokens[0],
string_enum_help_text(
name, valid_values=list(valid_values), context="css"
),
)
token = tokens[0]
token_name, value, _, _, location, _ = token
@@ -239,7 +244,7 @@ class StylesBuilder:
return
if len(tokens) == 1:
try:
self.styles._rules[name.replace("-", "_")] = Scalar.parse(
self.styles._rules[name.replace("-", "_")] = Scalar.parse( # type: ignore
tokens[0].value
)
except ScalarParseError:
@@ -390,7 +395,7 @@ class StylesBuilder:
name, num_values_supplied=len(space), context="css"
),
)
self.styles._rules[name] = Spacing.unpack(cast(SpacingDimensions, tuple(space)))
self.styles._rules[name] = Spacing.unpack(cast(SpacingDimensions, tuple(space))) # type: ignore
def _process_space_partial(self, name: str, tokens: list[Token]) -> None:
"""Process granular margin / padding declarations."""
@@ -418,7 +423,7 @@ class StylesBuilder:
spacing_list = list(current_spacing)
spacing_list[_EDGE_SPACING_MAP[edge]] = space
self.styles._rules[style_name] = Spacing(*spacing_list)
self.styles._rules[style_name] = Spacing(*spacing_list) # type: ignore
process_padding = _process_space
process_margin = _process_space
@@ -444,7 +449,7 @@ class StylesBuilder:
token_name, value, _, _, _, _ = token
if token_name == "token":
if value in VALID_BORDER:
border_type = value
border_type = value # type: ignore
else:
try:
border_color = Color.parse(value)
@@ -464,7 +469,7 @@ class StylesBuilder:
def _process_border_edge(self, edge: str, name: str, tokens: list[Token]) -> None:
border = self._parse_border(name, tokens)
self.styles._rules[f"border_{edge}"] = border
self.styles._rules[f"border_{edge}"] = border # type: ignore
def process_border(self, name: str, tokens: list[Token]) -> None:
border = self._parse_border(name, tokens)
@@ -486,7 +491,7 @@ class StylesBuilder:
def _process_outline(self, edge: str, name: str, tokens: list[Token]) -> None:
border = self._parse_border(name, tokens)
self.styles._rules[f"outline_{edge}"] = border
self.styles._rules[f"outline_{edge}"] = border # type: ignore
def process_outline(self, name: str, tokens: list[Token]) -> None:
border = self._parse_border(name, tokens)
@@ -579,14 +584,14 @@ class StylesBuilder:
color: Color | None = None
alpha: float | None = None
self.styles._rules[f"auto_{name}"] = False
self.styles._rules[f"auto_{name}"] = False # type: ignore
for token in tokens:
if (
"background" not in name
and token.name == "token"
and token.value == "auto"
):
self.styles._rules[f"auto_{name}"] = True
self.styles._rules[f"auto_{name}"] = True # type: ignore
elif token.name == "scalar":
alpha_scalar = Scalar.parse(token.value)
if alpha_scalar.unit != Unit.PERCENT:
@@ -608,7 +613,7 @@ class StylesBuilder:
if color is not None or alpha is not None:
if alpha is not None:
color = (color or Color(255, 255, 255)).with_alpha(alpha)
self.styles._rules[name] = color
self.styles._rules[name] = color # type: ignore
process_tint = process_color
process_background = process_color
@@ -636,7 +641,7 @@ class StylesBuilder:
)
style_definition = " ".join(token.value for token in tokens)
self.styles._rules[name.replace("-", "_")] = style_definition
self.styles._rules[name.replace("-", "_")] = style_definition # type: ignore
process_link_style = process_text_style
process_link_hover_style = process_text_style
@@ -653,7 +658,7 @@ class StylesBuilder:
text_align_help_text(),
)
self.styles._rules["text_align"] = tokens[0].value
self.styles._rules["text_align"] = tokens[0].value # type: ignore
def process_dock(self, name: str, tokens: list[Token]) -> None:
if not tokens:
@@ -766,8 +771,8 @@ class StylesBuilder:
align_error(name, token_horizontal)
name = name.replace("-", "_")
self.styles._rules[f"{name}_horizontal"] = token_horizontal.value
self.styles._rules[f"{name}_vertical"] = token_vertical.value
self.styles._rules[f"{name}_horizontal"] = token_horizontal.value # type: ignore
self.styles._rules[f"{name}_vertical"] = token_vertical.value # type: ignore
def process_align_horizontal(self, name: str, tokens: list[Token]) -> None:
try:
@@ -779,7 +784,7 @@ class StylesBuilder:
string_enum_help_text(name, VALID_ALIGN_HORIZONTAL, context="css"),
)
else:
self.styles._rules[name.replace("-", "_")] = value
self.styles._rules[name.replace("-", "_")] = value # type: ignore
def process_align_vertical(self, name: str, tokens: list[Token]) -> None:
try:
@@ -791,7 +796,7 @@ class StylesBuilder:
string_enum_help_text(name, VALID_ALIGN_VERTICAL, context="css"),
)
else:
self.styles._rules[name.replace("-", "_")] = value
self.styles._rules[name.replace("-", "_")] = value # type: ignore
process_content_align = process_align
process_content_align_horizontal = process_align_horizontal
@@ -807,7 +812,7 @@ class StylesBuilder:
string_enum_help_text(name, VALID_SCROLLBAR_GUTTER, context="css"),
)
else:
self.styles._rules[name.replace("-", "_")] = value
self.styles._rules[name.replace("-", "_")] = value # type: ignore
def process_scrollbar_size(self, name: str, tokens: list[Token]) -> None:
def scrollbar_size_error(name: str, token: Token) -> None:
@@ -876,7 +881,7 @@ class StylesBuilder:
token,
table_rows_or_columns_help_text(name, token.value, context="css"),
)
self.styles._rules[name.replace("-", "_")] = scalars
self.styles._rules[name.replace("-", "_")] = scalars # type: ignore
process_grid_rows = _process_grid_rows_or_columns
process_grid_columns = _process_grid_rows_or_columns
@@ -893,7 +898,7 @@ class StylesBuilder:
value = int(token.value)
if value == 0:
self.error(name, token, integer_help_text(name))
self.styles._rules[name.replace("-", "_")] = value
self.styles._rules[name.replace("-", "_")] = value # type: ignore
process_grid_gutter_horizontal = _process_integer
process_grid_gutter_vertical = _process_integer

View File

@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Iterable
import rich.repr
from ._help_renderables import HelpText
from .styles import Styles
from .tokenize import Token
from .types import Specificity3
@@ -155,7 +156,7 @@ class SelectorSet:
class RuleSet:
selector_set: list[SelectorSet] = field(default_factory=list)
styles: Styles = field(default_factory=Styles)
errors: list[tuple[Token, str]] = field(default_factory=list)
errors: list[tuple[Token, str | HelpText]] = field(default_factory=list)
is_default_rules: bool = False
tie_breaker: int = 0

View File

@@ -5,6 +5,7 @@ from pathlib import PurePath
from typing import Iterable, Iterator, NoReturn
from ..suggestions import get_suggestion
from ._help_renderables import HelpText
from ._styles_builder import DeclarationError, StylesBuilder
from .errors import UnresolvedVariableError
from .model import (
@@ -130,7 +131,7 @@ def parse_rule_set(
declaration = Declaration(token, "")
errors: list[tuple[Token, str]] = []
errors: list[tuple[Token, str | HelpText]] = []
while True:
token = next(tokens)

View File

@@ -367,8 +367,8 @@ class StylesBase(ABC):
def auto_dimensions(self) -> bool:
"""Check if width or height are set to 'auto'."""
has_rule = self.has_rule
return (has_rule("width") and self.width.is_auto) or (
has_rule("height") and self.height.is_auto
return (has_rule("width") and self.width.is_auto) or ( # type: ignore
has_rule("height") and self.height.is_auto # type: ignore
)
@abstractmethod
@@ -603,7 +603,7 @@ class Styles(StylesBase):
Returns:
``True`` if a rule was cleared, or ``False`` if it was already not set.
"""
changed = self._rules.pop(rule, None) is not None
changed = self._rules.pop(rule, None) is not None # type: ignore
if changed:
self._updates += 1
return changed
@@ -622,12 +622,12 @@ class Styles(StylesBase):
``True`` if the rule changed, otherwise ``False``.
"""
if value is None:
changed = self._rules.pop(rule, None) is not None
changed = self._rules.pop(rule, None) is not None # type: ignore
if changed:
self._updates += 1
return changed
current = self._rules.get(rule)
self._rules[rule] = value
self._rules[rule] = value # type: ignore
changed = current != value
if changed:
self._updates += 1
@@ -646,7 +646,7 @@ class Styles(StylesBase):
def reset(self) -> None:
"""Reset the rules to initial state."""
self._updates += 1
self._rules.clear()
self._rules.clear() # type: ignore
def merge(self, other: Styles) -> None:
"""Merge values from another Styles.
@@ -736,25 +736,25 @@ class Styles(StylesBase):
left = get_rule(f"{name}_left")
if top == right and right == bottom and bottom == left:
border_type, border_color = rules[f"{name}_top"]
border_type, border_color = rules[f"{name}_top"] # type: ignore
yield name, f"{border_type} {border_color.hex}"
return
# Check for edges
if has_top:
border_type, border_color = rules[f"{name}_top"]
border_type, border_color = rules[f"{name}_top"] # type: ignore
yield f"{name}-top", f"{border_type} {border_color.hex}"
if has_right:
border_type, border_color = rules[f"{name}_right"]
border_type, border_color = rules[f"{name}_right"] # type: ignore
yield f"{name}-right", f"{border_type} {border_color.hex}"
if has_bottom:
border_type, border_color = rules[f"{name}_bottom"]
border_type, border_color = rules[f"{name}_bottom"] # type: ignore
yield f"{name}-bottom", f"{border_type} {border_color.hex}"
if has_left:
border_type, border_color = rules[f"{name}_left"]
border_type, border_color = rules[f"{name}_left"] # type: ignore
yield f"{name}-left", f"{border_type} {border_color.hex}"
@property
@@ -770,15 +770,14 @@ class Styles(StylesBase):
rules = self.get_rules()
get_rule = rules.get
has_rule = rules.__contains__
if has_rule("display"):
if "display" in rules:
append_declaration("display", rules["display"])
if has_rule("visibility"):
if "visibility" in rules:
append_declaration("visibility", rules["visibility"])
if has_rule("padding"):
if "padding" in rules:
append_declaration("padding", rules["padding"].css)
if has_rule("margin"):
if "margin" in rules:
append_declaration("margin", rules["margin"].css)
for name, rule in self._get_border_css_lines(rules, "border"):
@@ -787,90 +786,90 @@ class Styles(StylesBase):
for name, rule in self._get_border_css_lines(rules, "outline"):
append_declaration(name, rule)
if has_rule("offset"):
if "offset" in rules:
x, y = self.offset
append_declaration("offset", f"{x} {y}")
if has_rule("dock"):
if "dock" in rules:
append_declaration("dock", rules["dock"])
if has_rule("layers"):
if "layers" in rules:
append_declaration("layers", " ".join(self.layers))
if has_rule("layer"):
if "layer" in rules:
append_declaration("layer", self.layer)
if has_rule("layout"):
if "layout" in rules:
assert self.layout is not None
append_declaration("layout", self.layout.name)
if has_rule("color"):
if "color" in rules:
append_declaration("color", self.color.hex)
if has_rule("background"):
if "background" in rules:
append_declaration("background", self.background.hex)
if has_rule("text_style"):
if "text_style" in rules:
append_declaration("text-style", str(get_rule("text_style")))
if has_rule("tint"):
if "tint" in rules:
append_declaration("tint", self.tint.css)
if has_rule("overflow_x"):
if "overflow_x" in rules:
append_declaration("overflow-x", self.overflow_x)
if has_rule("overflow_y"):
if "overflow_y" in rules:
append_declaration("overflow-y", self.overflow_y)
if has_rule("scrollbar_color"):
if "scrollbar_color" in rules:
append_declaration("scrollbar-color", self.scrollbar_color.css)
if has_rule("scrollbar_color_hover"):
if "scrollbar_color_hover" in rules:
append_declaration("scrollbar-color-hover", self.scrollbar_color_hover.css)
if has_rule("scrollbar_color_active"):
if "scrollbar_color_active" in rules:
append_declaration(
"scrollbar-color-active", self.scrollbar_color_active.css
)
if has_rule("scrollbar_corner_color"):
if "scrollbar_corner_color" in rules:
append_declaration(
"scrollbar-corner-color", self.scrollbar_corner_color.css
)
if has_rule("scrollbar_background"):
if "scrollbar_background" in rules:
append_declaration("scrollbar-background", self.scrollbar_background.css)
if has_rule("scrollbar_background_hover"):
if "scrollbar_background_hover" in rules:
append_declaration(
"scrollbar-background-hover", self.scrollbar_background_hover.css
)
if has_rule("scrollbar_background_active"):
if "scrollbar_background_active" in rules:
append_declaration(
"scrollbar-background-active", self.scrollbar_background_active.css
)
if has_rule("scrollbar_gutter"):
if "scrollbar_gutter" in rules:
append_declaration("scrollbar-gutter", self.scrollbar_gutter)
if has_rule("scrollbar_size"):
if "scrollbar_size" in rules:
append_declaration(
"scrollbar-size",
f"{self.scrollbar_size_horizontal} {self.scrollbar_size_vertical}",
)
else:
if has_rule("scrollbar_size_horizontal"):
if "scrollbar_size_horizontal" in rules:
append_declaration(
"scrollbar-size-horizontal", str(self.scrollbar_size_horizontal)
)
if has_rule("scrollbar_size_vertical"):
if "scrollbar_size_vertical" in rules:
append_declaration(
"scrollbar-size-vertical", str(self.scrollbar_size_vertical)
)
if has_rule("box_sizing"):
if "box_sizing" in rules:
append_declaration("box-sizing", self.box_sizing)
if has_rule("width"):
if "width" in rules:
append_declaration("width", str(self.width))
if has_rule("height"):
if "height" in rules:
append_declaration("height", str(self.height))
if has_rule("min_width"):
if "min_width" in rules:
append_declaration("min-width", str(self.min_width))
if has_rule("min_height"):
if "min_height" in rules:
append_declaration("min-height", str(self.min_height))
if has_rule("max_width"):
if "max_width" in rules:
append_declaration("max-width", str(self.min_width))
if has_rule("max_height"):
if "max_height" in rules:
append_declaration("max-height", str(self.min_height))
if has_rule("transitions"):
if "transitions" in rules:
append_declaration(
"transition",
", ".join(
@@ -879,74 +878,74 @@ class Styles(StylesBase):
),
)
if has_rule("align_horizontal") and has_rule("align_vertical"):
if "align_horizontal" in rules and "align_vertical" in rules:
append_declaration(
"align", f"{self.align_horizontal} {self.align_vertical}"
)
elif has_rule("align_horizontal"):
elif "align_horizontal" in rules:
append_declaration("align-horizontal", self.align_horizontal)
elif has_rule("align_vertical"):
elif "align_vertical" in rules:
append_declaration("align-vertical", self.align_vertical)
if has_rule("content_align_horizontal") and has_rule("content_align_vertical"):
if "content_align_horizontal" in rules and "content_align_vertical" in rules:
append_declaration(
"content-align",
f"{self.content_align_horizontal} {self.content_align_vertical}",
)
elif has_rule("content_align_horizontal"):
elif "content_align_horizontal" in rules:
append_declaration(
"content-align-horizontal", self.content_align_horizontal
)
elif has_rule("content_align_vertical"):
elif "content_align_vertical" in rules:
append_declaration("content-align-vertical", self.content_align_vertical)
if has_rule("text_align"):
if "text_align" in rules:
append_declaration("text-align", self.text_align)
if has_rule("opacity"):
if "opacity" in rules:
append_declaration("opacity", str(self.opacity))
if has_rule("text_opacity"):
if "text_opacity" in rules:
append_declaration("text-opacity", str(self.text_opacity))
if has_rule("grid_columns"):
if "grid_columns" in rules:
append_declaration(
"grid-columns",
" ".join(str(scalar) for scalar in self.grid_columns or ()),
)
if has_rule("grid_rows"):
if "grid_rows" in rules:
append_declaration(
"grid-rows",
" ".join(str(scalar) for scalar in self.grid_rows or ()),
)
if has_rule("grid_size_columns"):
if "grid_size_columns" in rules:
append_declaration("grid-size-columns", str(self.grid_size_columns))
if has_rule("grid_size_rows"):
if "grid_size_rows" in rules:
append_declaration("grid-size-rows", str(self.grid_size_rows))
if has_rule("grid_gutter_horizontal"):
if "grid_gutter_horizontal" in rules:
append_declaration(
"grid-gutter-horizontal", str(self.grid_gutter_horizontal)
)
if has_rule("grid_gutter_vertical"):
if "grid_gutter_vertical" in rules:
append_declaration("grid-gutter-vertical", str(self.grid_gutter_vertical))
if has_rule("row_span"):
if "row_span" in rules:
append_declaration("row-span", str(self.row_span))
if has_rule("column_span"):
if "column_span" in rules:
append_declaration("column-span", str(self.column_span))
if has_rule("link_color"):
if "link_color" in rules:
append_declaration("link-color", self.link_color.css)
if has_rule("link_background"):
if "link_background" in rules:
append_declaration("link-background", self.link_background.css)
if has_rule("link_style"):
if "link_style" in rules:
append_declaration("link-style", str(self.link_style))
if has_rule("link_hover_color"):
if "link_hover_color" in rules:
append_declaration("link-hover-color", self.link_hover_color.css)
if has_rule("link_hover_background"):
if "link_hover_background" in rules:
append_declaration("link-hover-background", self.link_hover_background.css)
if has_rule("link_hover_style"):
if "link_hover_style" in rules:
append_declaration("link-hover-style", str(self.link_hover_style))
lines.sort()

View File

@@ -4,7 +4,7 @@ import os
from collections import defaultdict
from operator import itemgetter
from pathlib import Path, PurePath
from typing import Iterable, NamedTuple, cast
from typing import Iterable, NamedTuple, Sequence, cast
import rich.repr
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
@@ -248,7 +248,7 @@ class Stylesheet:
self.source[str(path)] = CssSource(css, False, 0)
self._require_parse = True
def read_all(self, paths: list[PurePath]) -> None:
def read_all(self, paths: Sequence[PurePath]) -> None:
"""Read multiple CSS files, in order.
Args:

View File

@@ -132,10 +132,12 @@ class DOMNode(MessagePump):
check_identifiers("class name", *_classes)
self._classes.update(_classes)
self.children = NodeList()
self.children: NodeList = NodeList()
self._css_styles: Styles = Styles(self)
self._inline_styles: Styles = Styles(self)
self.styles = RenderStyles(self, self._css_styles, self._inline_styles)
self.styles: RenderStyles = RenderStyles(
self, self._css_styles, self._inline_styles
)
# A mapping of class names to Styles set in COMPONENT_CLASSES
self._component_styles: dict[str, RenderStyles] = {}

View File

@@ -7,12 +7,12 @@ from ctypes import Structure, Union, byref, wintypes
from ctypes.wintypes import BOOL, CHAR, DWORD, HANDLE, SHORT, UINT, WCHAR, WORD
from typing import IO, Callable, List, Optional
from .._types import EventTarget
from .._types import MessageTarget
from .._xterm_parser import XTermParser
from ..events import Event, Resize
from ..geometry import Size
KERNEL32 = ctypes.WinDLL("kernel32", use_last_error=True)
KERNEL32 = ctypes.WinDLL("kernel32", use_last_error=True) # type: ignore
# Console input modes
ENABLE_ECHO_INPUT = 0x0004
@@ -130,7 +130,7 @@ def _set_console_mode(file: IO, mode: int) -> bool:
Returns:
True on success, otherwise False.
"""
windows_filehandle = msvcrt.get_osfhandle(file.fileno())
windows_filehandle = msvcrt.get_osfhandle(file.fileno()) # type: ignore
success = KERNEL32.SetConsoleMode(windows_filehandle, mode)
return success
@@ -144,7 +144,7 @@ def _get_console_mode(file: IO) -> int:
Returns:
The current console mode.
"""
windows_filehandle = msvcrt.get_osfhandle(file.fileno())
windows_filehandle = msvcrt.get_osfhandle(file.fileno()) # type: ignore
mode = wintypes.DWORD()
KERNEL32.GetConsoleMode(windows_filehandle, ctypes.byref(mode))
return mode.value
@@ -211,7 +211,7 @@ class EventMonitor(threading.Thread):
self,
loop: AbstractEventLoop,
app,
target: EventTarget,
target: MessageTarget,
exit_event: threading.Event,
process_event: Callable[[Event], None],
) -> None:

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import os
from pathlib import PurePath
from typing import Callable
from typing import Callable, Sequence
import rich.repr
@@ -13,7 +13,7 @@ from ._callback import invoke
class FileMonitor:
"""Monitors files for changes and invokes a callback when it does."""
def __init__(self, paths: list[PurePath], callback: Callable) -> None:
def __init__(self, paths: Sequence[PurePath], callback: Callable) -> None:
self.paths = paths
self.callback = callback
self._modified = self._get_last_modified_time()

View File

@@ -30,14 +30,14 @@ class ScrollView(Widget):
"""Not transparent, i.e. renders something."""
return False
def watch_scroll_x(self, new_value: float) -> None:
if self.show_horizontal_scrollbar:
self.horizontal_scrollbar.position = int(new_value)
def watch_scroll_x(self, old_value: float, new_value: float) -> None:
if self.show_horizontal_scrollbar and round(old_value) != round(new_value):
self.horizontal_scrollbar.position = round(new_value)
self.refresh()
def watch_scroll_y(self, new_value: float) -> None:
if self.show_vertical_scrollbar:
self.vertical_scrollbar.position = int(new_value)
def watch_scroll_y(self, old_value: float, new_value: float) -> None:
if self.show_vertical_scrollbar and round(old_value) != round(new_value):
self.vertical_scrollbar.position = round(new_value)
self.refresh()
def on_mount(self):

View File

@@ -117,7 +117,7 @@ class _Styled:
"""
def __init__(
self, renderable: "RenderableType", style: Style, link_style: Style | None
self, renderable: "ConsoleRenderable", style: Style, link_style: Style | None
) -> None:
self.renderable = renderable
self.style = style
@@ -133,7 +133,7 @@ class _Styled:
if style:
apply = style.__add__
result_segments = (
_Segment(text, apply(_style), control)
_Segment(text, apply(_style), None)
for text, _style, control in result_segments
)
link_style = self.link_style
@@ -141,19 +141,22 @@ class _Styled:
result_segments = (
_Segment(
text,
style
if style._meta is None
else (style + link_style if "@click" in style.meta else style),
(
style
if style._meta is None
else (style + link_style if "@click" in style.meta else style)
),
control,
)
for text, style, control in result_segments
if style is not None
)
return result_segments
def __rich_measure__(
self, console: "Console", options: "ConsoleOptions"
) -> Measurement:
return self.renderable.__rich_measure__(console, options)
return Measurement.get(console, options, self.renderable)
class RenderCache(NamedTuple):
@@ -1414,6 +1417,7 @@ class Widget(DOMNode):
easing = DEFAULT_SCROLL_EASING
if maybe_scroll_x:
assert x is not None
self.scroll_target_x = x
if x != self.scroll_x:
self.animate(
@@ -1425,6 +1429,7 @@ class Widget(DOMNode):
)
scrolled_x = True
if maybe_scroll_y:
assert y is not None
self.scroll_target_y = y
if y != self.scroll_y:
self.animate(
@@ -1438,10 +1443,12 @@ class Widget(DOMNode):
else:
if maybe_scroll_x:
assert x is not None
scroll_x = self.scroll_x
self.scroll_target_x = self.scroll_x = x
scrolled_x = scroll_x != self.scroll_x
if maybe_scroll_y:
assert y is not None
scroll_y = self.scroll_y
self.scroll_target_y = self.scroll_y = y
scrolled_y = scroll_y != self.scroll_y

View File

@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, ClassVar, Generic, NewType, TypeVar
from typing import TYPE_CHECKING, ClassVar, Generic, Iterable, NewType, TypeVar, cast
import rich.repr
from rich.style import NULL_STYLE, Style
@@ -783,7 +783,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
assert self._tree_lines_cached is not None
return self._tree_lines_cached
def _on_idle(self) -> None:
async def _on_idle(self, event: events.Idle) -> None:
"""Check tree needs a rebuild on idle."""
# Property calls build if required
self._tree_lines
@@ -891,6 +891,7 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
Returns:
Strings for space, vertical, terminator and cross.
"""
lines: tuple[Iterable[str], Iterable[str], Iterable[str], Iterable[str]]
if self.show_guides:
lines = self.LINES["default"]
if style.bold:
@@ -901,11 +902,11 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True):
lines = (" ", " ", " ", " ")
guide_depth = max(0, self.guide_depth - 2)
lines = tuple(
f"{vertical}{horizontal * guide_depth} "
for vertical, horizontal in lines
guide_lines = tuple(
f"{characters[0]}{characters[1] * guide_depth} "
for characters in lines
)
return lines
return cast("tuple[str, str, str, str]", guide_lines)
if is_hover:
line_style = self.get_component_rich_style("tree--highlight-line")