Merge pull request #1752 from Textualize/import-sorting-hook

Adds `isort` pre-commit hook, re-orders all imports in src and test directories
This commit is contained in:
Will McGugan
2023-02-09 15:34:29 +00:00
committed by GitHub
131 changed files with 266 additions and 295 deletions

View File

@@ -1,15 +1,22 @@
# See https://pre-commit.com for more information # See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks # See https://pre-commit.com/hooks.html for more hooks
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v4.3.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
- id: check-yaml - id: check-yaml
args: ['--unsafe'] args: [ '--unsafe' ]
- repo: https://github.com/psf/black - repo: https://github.com/pycqa/isort
rev: 22.10.0 rev: 5.12.0
hooks: hooks:
- id: black - id: isort
name: isort (python)
language_version: '3.11'
args: ["--profile", "black", "--filter-files"]
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
exclude: ^tests/snapshot_tests exclude: ^tests/snapshot_tests

View File

@@ -1,15 +1,14 @@
from __future__ import annotations from __future__ import annotations
import inspect import inspect
from typing import TYPE_CHECKING, Callable
import rich.repr import rich.repr
from rich.console import RenderableType from rich.console import RenderableType
from typing import Callable, TYPE_CHECKING
from ._context import active_app from ._context import active_app
from ._log import LogGroup, LogVerbosity from ._log import LogGroup, LogVerbosity
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import TypeAlias from typing_extensions import TypeAlias

View File

@@ -1,6 +1,5 @@
from .demo import DemoApp from .demo import DemoApp
if __name__ == "__main__": if __name__ == "__main__":
app = DemoApp() app = DemoApp()
app.run() app.run()

View File

@@ -3,11 +3,11 @@ from __future__ import annotations
from collections import defaultdict from collections import defaultdict
from fractions import Fraction from fractions import Fraction
from operator import attrgetter from operator import attrgetter
from typing import Sequence, TYPE_CHECKING from typing import TYPE_CHECKING, Sequence
from .geometry import Region, Size, Spacing
from ._layout import DockArrangeResult, WidgetPlacement from ._layout import DockArrangeResult, WidgetPlacement
from ._partition import partition from ._partition import partition
from .geometry import Region, Size, Spacing
if TYPE_CHECKING: if TYPE_CHECKING:
from .widget import Widget from .widget import Widget

View File

@@ -5,7 +5,6 @@ Compatibility layer for asyncio.
from __future__ import annotations from __future__ import annotations
import sys import sys
__all__ = ["create_task"] __all__ = ["create_task"]

View File

@@ -1,8 +1,7 @@
from __future__ import annotations from __future__ import annotations
from functools import lru_cache from functools import lru_cache
from typing import cast, Tuple, Union from typing import TYPE_CHECKING, Tuple, Union, cast
from typing import TYPE_CHECKING
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -2,8 +2,8 @@ from __future__ import annotations
import asyncio import asyncio
from functools import lru_cache from functools import lru_cache
from inspect import signature, isawaitable from inspect import isawaitable, signature
from typing import Any, Callable, TYPE_CHECKING from typing import TYPE_CHECKING, Any, Callable
from . import active_app from . import active_app

View File

@@ -2,7 +2,6 @@ import asyncio
from ._time import time from ._time import time
""" """
A module that serves as the single source of truth for everything time-related in a Textual app. 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,

View File

@@ -25,14 +25,14 @@ from rich.style import Style
from . import errors from . import errors
from ._cells import cell_len from ._cells import cell_len
from ._loop import loop_last from ._loop import loop_last
from .strip import Strip
from .geometry import NULL_OFFSET, Offset, Region, Size from .geometry import NULL_OFFSET, Offset, Region, Size
from .strip import Strip
if TYPE_CHECKING: if TYPE_CHECKING:
from .widget import Widget
from typing_extensions import TypeAlias from typing_extensions import TypeAlias
from .widget import Widget
class ReflowResult(NamedTuple): class ReflowResult(NamedTuple):
"""The result of a reflow operation. Describes the chances to widgets.""" """The result of a reflow operation. Describes the chances to widgets."""

View File

@@ -1,6 +1,5 @@
from typing import TYPE_CHECKING
from contextvars import ContextVar from contextvars import ContextVar
from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
from .app import App from .app import App

View File

@@ -2,14 +2,13 @@ from __future__ import annotations
import hashlib import hashlib
import os import os
from pathlib import Path
import shlex import shlex
from pathlib import Path
from typing import Iterable from typing import Iterable
from textual._import_app import import_app
from textual.app import App from textual.app import App
from textual.pilot import Pilot from textual.pilot import Pilot
from textual._import_app import import_app
SCREENSHOT_CACHE = ".screenshot_cache" SCREENSHOT_CACHE = ".screenshot_cache"

View File

@@ -3,7 +3,7 @@ Define a series of easing functions for more natural-looking animations.
Taken from https://easings.net/ and translated from JavaScript. Taken from https://easings.net/ and translated from JavaScript.
""" """
from math import pi, cos, sin, sqrt from math import cos, pi, sin, sqrt
def _in_out_expo(x: float) -> float: def _in_out_expo(x: float) -> float:

View File

@@ -1,8 +1,9 @@
"""Provides an immutable sequence view class.""" """Provides an immutable sequence view class."""
from __future__ import annotations from __future__ import annotations
from sys import maxsize from sys import maxsize
from typing import Generic, TypeVar, Iterator, overload, Sequence from typing import Generic, Iterator, Sequence, TypeVar, overload
T = TypeVar("T") T = TypeVar("T")

View File

@@ -1,12 +1,11 @@
from __future__ import annotations from __future__ import annotations
import os import os
import sys
import runpy import runpy
import shlex import shlex
import sys
from pathlib import Path from pathlib import Path
from typing import cast, TYPE_CHECKING from typing import TYPE_CHECKING, cast
if TYPE_CHECKING: if TYPE_CHECKING:
from textual.app import App from textual.app import App
@@ -46,10 +45,10 @@ def import_app(import_name: str) -> App:
A Textual application A Textual application
""" """
import inspect
import importlib import importlib
import inspect
from textual.app import App, WINDOWS from textual.app import WINDOWS, App
import_name, *argv = shlex.split(import_name, posix=not WINDOWS) import_name, *argv = shlex.split(import_name, posix=not WINDOWS)
drive, import_name = os.path.splitdrive(import_name) drive, import_name = os.path.splitdrive(import_name)

View File

@@ -1,12 +1,13 @@
from __future__ import annotations from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import ClassVar, NamedTuple, TYPE_CHECKING from typing import TYPE_CHECKING, ClassVar, NamedTuple
from .geometry import Region, Size, Spacing from .geometry import Region, Size, Spacing
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import TypeAlias from typing_extensions import TypeAlias
from .widget import Widget from .widget import Widget
ArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget]]" ArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget]]"

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
import sys
import sys
from typing import TYPE_CHECKING, Any, Iterator, Sequence, overload from typing import TYPE_CHECKING, Any, Iterator, Sequence, overload
import rich.repr import rich.repr

View File

@@ -1,16 +1,8 @@
from __future__ import annotations from __future__ import annotations
from collections import deque
import io import io
from typing import ( from collections import deque
Callable, from typing import Callable, Deque, Generator, Generic, Iterable, TypeVar, Union
Deque,
Generator,
TypeVar,
Generic,
Union,
Iterable,
)
class ParseError(Exception): class ParseError(Exception):

View File

@@ -2,7 +2,6 @@ from __future__ import annotations
from typing import Callable, Iterable, TypeVar from typing import Callable, Iterable, TypeVar
T = TypeVar("T") T = TypeVar("T")

View File

@@ -4,8 +4,8 @@ Timer context manager, only used in debug.
""" """
import contextlib import contextlib
from typing import Generator
from time import perf_counter from time import perf_counter
from typing import Generator
from . import log from . import log

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from fractions import Fraction from fractions import Fraction
from itertools import accumulate from itertools import accumulate
from typing import Sequence, cast, TYPE_CHECKING from typing import TYPE_CHECKING, Sequence, cast
from typing_extensions import Literal from typing_extensions import Literal

View File

@@ -1,9 +1,8 @@
from __future__ import annotations from __future__ import annotations
from asyncio import Future, get_running_loop
from time import sleep, perf_counter from threading import Event, Thread
from asyncio import get_running_loop, Future from time import perf_counter, sleep
from threading import Thread, Event
class Sleeper(Thread): class Sleeper(Thread):

View File

@@ -1,5 +1,5 @@
from asyncio import sleep from asyncio import sleep
from time import process_time, monotonic from time import monotonic, process_time
SLEEP_GRANULARITY: float = 1 / 50 SLEEP_GRANULARITY: float = 1 / 50
SLEEP_IDLE: float = SLEEP_GRANULARITY / 2.0 SLEEP_IDLE: float = SLEEP_GRANULARITY / 2.0

View File

@@ -7,7 +7,6 @@ This should only be imported on Windows.
from time import sleep as time_sleep from time import sleep as time_sleep
__all__ = ["sleep"] __all__ = ["sleep"]

View File

@@ -1,17 +1,15 @@
from __future__ import annotations from __future__ import annotations
import unicodedata
import re import re
import unicodedata
from typing import Any, Callable, Generator, Iterable from typing import Any, Callable, Generator, Iterable
from . import events from . import events, messages
from . import messages
from ._ansi_sequences import ANSI_SEQUENCES_KEYS from ._ansi_sequences import ANSI_SEQUENCES_KEYS
from ._parser import Awaitable, Parser, TokenCallback from ._parser import Awaitable, Parser, TokenCallback
from ._types import MessageTarget from ._types import MessageTarget
from .keys import KEY_NAME_REPLACEMENTS from .keys import KEY_NAME_REPLACEMENTS
# When trying to determine whether the current sequence is a supported/valid # When trying to determine whether the current sequence is a supported/valid
# escape sequence, at which length should we give up and consider our search # escape sequence, at which length should we give up and consider our search
# to be unsuccessful? # to be unsuccessful?

View File

@@ -50,7 +50,6 @@ from ._context import active_app
from ._event_broker import NoHandler, extract_handler_actions from ._event_broker import NoHandler, extract_handler_actions
from ._filter import LineFilter, Monochrome from ._filter import LineFilter, Monochrome
from ._path import _make_path_object_relative from ._path import _make_path_object_relative
from ._wait import wait_for_idle from ._wait import wait_for_idle
from .actions import SkipAction from .actions import SkipAction
from .await_remove import AwaitRemove from .await_remove import AwaitRemove

View File

@@ -1,5 +1,4 @@
import re import re
from typing import Match, Pattern from typing import Match, Pattern

View File

@@ -10,8 +10,8 @@ except ImportError:
from importlib_metadata import version from importlib_metadata import version
from textual._import_app import AppFail, import_app
from textual.pilot import Pilot from textual.pilot import Pilot
from textual._import_app import import_app, AppFail
@click.group() @click.group()
@@ -26,6 +26,7 @@ def run():
def console(verbose: bool, exclude: list[str]) -> None: def console(verbose: bool, exclude: list[str]) -> None:
"""Launch the textual console.""" """Launch the textual console."""
from rich.console import Console from rich.console import Console
from textual.devtools.server import _run_devtools from textual.devtools.server import _run_devtools
console = Console() console = Console()

View File

@@ -1,8 +1,7 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.constants import BORDERS from textual.constants import BORDERS
from textual.widgets import Button, Label
from textual.containers import Vertical from textual.containers import Vertical
from textual.widgets import Button, Label
TEXT = """I must not fear. TEXT = """I must not fear.
Fear is the mind-killer. Fear is the mind-killer.

View File

@@ -2,7 +2,7 @@ from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical from textual.containers import Horizontal, Vertical
from textual.design import ColorSystem from textual.design import ColorSystem
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Footer, Static, Label from textual.widgets import Button, Footer, Label, Static
class ColorButtons(Vertical): class ColorButtons(Vertical):

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from rich.console import RenderableType from rich.console import RenderableType
from textual._easing import EASING from textual._easing import EASING
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.cli.previews.borders import TEXT from textual.cli.previews.borders import TEXT
@@ -8,7 +9,7 @@ from textual.containers import Container, Horizontal, Vertical
from textual.reactive import reactive, var from textual.reactive import reactive, var
from textual.scrollbar import ScrollBarRender from textual.scrollbar import ScrollBarRender
from textual.widget import Widget from textual.widget import Widget
from textual.widgets import Button, Footer, Label, Input from textual.widgets import Button, Footer, Input, Label
VIRTUAL_SIZE = 100 VIRTUAL_SIZE = 100
WINDOW_SIZE = 10 WINDOW_SIZE = 10

View File

@@ -1,16 +1,14 @@
from __future__ import annotations from __future__ import annotations
from rich.panel import Panel from rich.panel import Panel
from rich.text import Text from rich.text import Text
from textual.app import App, ComposeResult
from textual.reactive import var, Reactive
from textual import events from textual import events
from textual.app import App, ComposeResult
from textual.containers import Horizontal from textual.containers import Horizontal
from textual.reactive import Reactive, var
from textual.widgets import Button, Header, TextLog from textual.widgets import Button, Header, TextLog
INSTRUCTIONS = """\ INSTRUCTIONS = """\
[u]Press some keys![/] [u]Press some keys![/]

View File

@@ -1,11 +1,13 @@
"""Textual CLI command code to print diagnostic information.""" """Textual CLI command code to print diagnostic information."""
from __future__ import annotations from __future__ import annotations
import os import os
import sys
import platform import platform
from typing import Any import sys
from functools import singledispatch from functools import singledispatch
from typing import Any
from importlib_metadata import version from importlib_metadata import version
from rich.console import Console, ConsoleDimensions from rich.console import Console, ConsoleDimensions

View File

@@ -5,20 +5,20 @@ from typing import Iterable, Sequence
from typing_extensions import Literal from typing_extensions import Literal
from textual.css._error_tools import friendly_list
from textual.css.scalar import SYMBOL_UNIT
from ..color import ColorParseError from ..color import ColorParseError
from ._help_renderables import Example, Bullet, HelpText from ._help_renderables import Bullet, Example, HelpText
from .constants import ( from .constants import (
VALID_BORDER,
VALID_LAYOUT,
VALID_ALIGN_HORIZONTAL, VALID_ALIGN_HORIZONTAL,
VALID_ALIGN_VERTICAL, VALID_ALIGN_VERTICAL,
VALID_BORDER,
VALID_LAYOUT,
VALID_STYLE_FLAGS, VALID_STYLE_FLAGS,
VALID_TEXT_ALIGN, VALID_TEXT_ALIGN,
) )
from textual.css._error_tools import friendly_list
from textual.css.scalar import SYMBOL_UNIT
StylingContext = Literal["inline", "css"] StylingContext = Literal["inline", "css"]
"""The type of styling the user was using when the error was encountered. """The type of styling the user was using when the error was encountered.
Used to give help text specific to the context i.e. we give CSS help if the Used to give help text specific to the context i.e. we give CSS help if the

View File

@@ -10,14 +10,7 @@ when setting and getting.
from __future__ import annotations from __future__ import annotations
from operator import attrgetter from operator import attrgetter
from typing import ( from typing import TYPE_CHECKING, Generic, Iterable, NamedTuple, TypeVar, cast
TYPE_CHECKING,
Generic,
Iterable,
NamedTuple,
TypeVar,
cast,
)
import rich.errors import rich.errors
import rich.repr import rich.repr
@@ -611,11 +604,8 @@ class LayoutProperty:
or a ``Layout`` object. or a ``Layout`` object.
""" """
from ..layouts.factory import ( from ..layouts.factory import Layout # Prevents circular import
Layout, # Prevents circular import from ..layouts.factory import MissingLayout, get_layout
MissingLayout,
get_layout,
)
_rich_traceback_omit = True _rich_traceback_omit = True
if layout is None: if layout is None:

View File

@@ -1,4 +1,5 @@
from __future__ import annotations from __future__ import annotations
import typing import typing
from ..geometry import Spacing from ..geometry import Spacing

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from rich.console import ConsoleOptions, Console, RenderResult from rich.console import Console, ConsoleOptions, RenderResult
from rich.traceback import Traceback from rich.traceback import Traceback
from ._help_renderables import HelpText from ._help_renderables import HelpText

View File

@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from typing import Iterable, TYPE_CHECKING from typing import TYPE_CHECKING, Iterable
from .model import CombinatorType, Selector, SelectorSet
from .model import CombinatorType, Selector, SelectorSet
if TYPE_CHECKING: if TYPE_CHECKING:
from ..dom import DOMNode from ..dom import DOMNode

View File

@@ -1,11 +1,10 @@
from __future__ import annotations from __future__ import annotations
import rich.repr
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Iterable, TYPE_CHECKING from typing import TYPE_CHECKING, Iterable
import rich.repr
from .styles import Styles from .styles import Styles
from .tokenize import Token from .tokenize import Token

View File

@@ -2,23 +2,23 @@ from __future__ import annotations
from functools import lru_cache from functools import lru_cache
from pathlib import PurePath from pathlib import PurePath
from typing import Iterator, Iterable, NoReturn from typing import Iterable, Iterator, NoReturn
from ..suggestions import get_suggestion
from ._styles_builder import DeclarationError, StylesBuilder
from .errors import UnresolvedVariableError from .errors import UnresolvedVariableError
from .types import Specificity3
from ._styles_builder import StylesBuilder, DeclarationError
from .model import ( from .model import (
CombinatorType,
Declaration, Declaration,
RuleSet, RuleSet,
Selector, Selector,
CombinatorType,
SelectorSet, SelectorSet,
SelectorType, SelectorType,
) )
from .styles import Styles from .styles import Styles
from ..suggestions import get_suggestion from .tokenize import Token, tokenize, tokenize_declarations, tokenize_values
from .tokenize import tokenize, tokenize_declarations, Token, tokenize_values
from .tokenizer import EOFError, ReferencedBy from .tokenizer import EOFError, ReferencedBy
from .types import Specificity3
SELECTOR_MAP: dict[str, tuple[SelectorType, Specificity3]] = { SELECTOR_MAP: dict[str, tuple[SelectorType, Specificity3]] = {
"selector": (SelectorType.TYPE, (0, 0, 1)), "selector": (SelectorType.TYPE, (0, 0, 1)),

View File

@@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
import re
from enum import Enum, unique from enum import Enum, unique
from fractions import Fraction from fractions import Fraction
from functools import lru_cache from functools import lru_cache
import re
from typing import Iterable, NamedTuple from typing import Iterable, NamedTuple
import rich.repr import rich.repr

View File

@@ -2,15 +2,12 @@ from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from .scalar import ScalarOffset, Scalar from .._animator import Animation, EasingFunction
from .._animator import Animation
from .._animator import EasingFunction
from .._types import CallbackType from .._types import CallbackType
from .scalar import Scalar, ScalarOffset
if TYPE_CHECKING: if TYPE_CHECKING:
from ..dom import DOMNode from ..dom import DOMNode
from .styles import StylesBase from .styles import StylesBase

View File

@@ -4,8 +4,7 @@ from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from functools import lru_cache from functools import lru_cache
from operator import attrgetter from operator import attrgetter
from typing import Iterable, cast from typing import TYPE_CHECKING, Any, Iterable, NamedTuple, cast
from typing import TYPE_CHECKING, Any, NamedTuple
import rich.repr import rich.repr
from rich.style import Style from rich.style import Style

View File

@@ -4,7 +4,7 @@ import re
from pathlib import PurePath from pathlib import PurePath
from typing import Iterable from typing import Iterable
from textual.css.tokenizer import Expect, Tokenizer, Token from textual.css.tokenizer import Expect, Token, Tokenizer
PERCENT = r"-?\d+\.?\d*%" PERCENT = r"-?\d+\.?\d*%"
DECIMAL = r"-?\d+\.?\d*" DECIMAL = r"-?\d+\.?\d*"

View File

@@ -4,11 +4,11 @@ import re
from pathlib import PurePath from pathlib import PurePath
from typing import NamedTuple from typing import NamedTuple
import rich.repr
from rich.console import Group, RenderableType from rich.console import Group, RenderableType
from rich.highlighter import ReprHighlighter from rich.highlighter import ReprHighlighter
from rich.padding import Padding from rich.padding import Padding
from rich.panel import Panel from rich.panel import Panel
import rich.repr
from rich.syntax import Syntax from rich.syntax import Syntax
from rich.text import Text from rich.text import Text

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Tuple from typing import Tuple
from typing_extensions import Literal from typing_extensions import Literal
from ..color import Color from ..color import Color

View File

@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from importlib_metadata import version
from pathlib import Path from pathlib import Path
from importlib_metadata import version
from rich import box from rich import box
from rich.console import RenderableType from rich.console import RenderableType
from rich.json import JSON from rich.json import JSON

View File

@@ -7,8 +7,7 @@ from rich.padding import Padding
from rich.table import Table from rich.table import Table
from rich.text import Text from rich.text import Text
from .color import Color, WHITE from .color import WHITE, Color
NUMBER_OF_SHADES = 3 NUMBER_OF_SHADES = 3

View File

@@ -9,21 +9,14 @@ from io import StringIO
from time import time from time import time
from typing import Any, NamedTuple, Type from typing import Any, NamedTuple, Type
import aiohttp
import msgpack
from aiohttp import ClientConnectorError, ClientResponseError, ClientWebSocketResponse
from rich.console import Console from rich.console import Console
from rich.segment import Segment from rich.segment import Segment
from .._log import LogGroup, LogVerbosity from .._log import LogGroup, LogVerbosity
import aiohttp
import msgpack
from aiohttp import (
ClientConnectorError,
ClientResponseError,
ClientWebSocketResponse,
)
DEVTOOLS_PORT = 8081 DEVTOOLS_PORT = 8081
WEBSOCKET_CONNECT_TIMEOUT = 3 WEBSOCKET_CONNECT_TIMEOUT = 3
LOG_QUEUE_MAXSIZE = 512 LOG_QUEUE_MAXSIZE = 512

View File

@@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
import inspect import inspect
from typing import TYPE_CHECKING, cast from typing import TYPE_CHECKING, cast
from .client import DevtoolsLog
from .._log import LogGroup, LogVerbosity from .._log import LogGroup, LogVerbosity
from .client import DevtoolsLog
if TYPE_CHECKING: if TYPE_CHECKING:
from .client import DevtoolsClient from .client import DevtoolsClient

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from aiohttp.web import run_app from aiohttp.web import run_app
from aiohttp.web_app import Application from aiohttp.web_app import Application
from aiohttp.web_request import Request from aiohttp.web_request import Request

View File

@@ -7,19 +7,19 @@ import pickle
from json import JSONDecodeError from json import JSONDecodeError
from typing import Any, cast from typing import Any, cast
import msgpack
from aiohttp import WSMessage, WSMsgType from aiohttp import WSMessage, WSMsgType
from aiohttp.abc import Request from aiohttp.abc import Request
from aiohttp.web_ws import WebSocketResponse from aiohttp.web_ws import WebSocketResponse
from rich.console import Console from rich.console import Console
from rich.markup import escape from rich.markup import escape
import msgpack
from textual._log import LogGroup from textual._log import LogGroup
from textual._time import time from textual._time import time
from textual.devtools.renderables import ( from textual.devtools.renderables import (
DevConsoleHeader,
DevConsoleLog, DevConsoleLog,
DevConsoleNotice, DevConsoleNotice,
DevConsoleHeader,
) )
QUEUEABLE_TYPES = {"client_log", "client_spillover"} QUEUEABLE_TYPES = {"client_log", "client_spillover"}

View File

@@ -1,9 +1,10 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
from .. import events
from ..driver import Driver from ..driver import Driver
from ..geometry import Size from ..geometry import Size
from .. import events
class HeadlessDriver(Driver): class HeadlessDriver(Driver):

View File

@@ -2,27 +2,26 @@ from __future__ import annotations
import asyncio import asyncio
import os import os
from codecs import getincrementaldecoder
import selectors import selectors
import signal import signal
import sys import sys
import termios import termios
import tty import tty
from typing import Any, TYPE_CHECKING from codecs import getincrementaldecoder
from threading import Event, Thread from threading import Event, Thread
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING: if TYPE_CHECKING:
from rich.console import Console from rich.console import Console
import rich.repr import rich.repr
from .. import log from .. import events, log
from ..driver import Driver from .._profile import timer
from ..geometry import Size
from .._types import MessageTarget from .._types import MessageTarget
from .._xterm_parser import XTermParser from .._xterm_parser import XTermParser
from .._profile import timer from ..driver import Driver
from .. import events from ..geometry import Size
@rich.repr.auto @rich.repr.auto

View File

@@ -9,6 +9,7 @@ from __future__ import annotations
from functools import lru_cache from functools import lru_cache
from operator import attrgetter, itemgetter from operator import attrgetter, itemgetter
from typing import ( from typing import (
TYPE_CHECKING,
Any, Any,
Collection, Collection,
NamedTuple, NamedTuple,
@@ -16,7 +17,6 @@ from typing import (
TypeVar, TypeVar,
Union, Union,
cast, cast,
TYPE_CHECKING,
) )
if TYPE_CHECKING: if TYPE_CHECKING:

View File

@@ -1,8 +1,8 @@
from __future__ import annotations from __future__ import annotations
from .._layout import Layout from .._layout import Layout
from .horizontal import HorizontalLayout
from .grid import GridLayout from .grid import GridLayout
from .horizontal import HorizontalLayout
from .vertical import VerticalLayout from .vertical import VerticalLayout
LAYOUT_MAP: dict[str, type[Layout]] = { LAYOUT_MAP: dict[str, type[Layout]] = {

View File

@@ -2,9 +2,9 @@ from __future__ import annotations
from fractions import Fraction from fractions import Fraction
from .._resolve import resolve_box_models
from ..geometry import Size, Region
from .._layout import ArrangeResult, Layout, WidgetPlacement from .._layout import ArrangeResult, Layout, WidgetPlacement
from .._resolve import resolve_box_models
from ..geometry import Region, Size
from ..widget import Widget from ..widget import Widget

View File

@@ -3,9 +3,9 @@ from __future__ import annotations
from fractions import Fraction from fractions import Fraction
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from .._layout import ArrangeResult, Layout, WidgetPlacement
from .._resolve import resolve_box_models from .._resolve import resolve_box_models
from ..geometry import Region, Size from ..geometry import Region, Size
from .._layout import ArrangeResult, Layout, WidgetPlacement
if TYPE_CHECKING: if TYPE_CHECKING:
from ..widget import Widget from ..widget import Widget

View File

@@ -1,16 +1,16 @@
from __future__ import annotations from __future__ import annotations
from typing import ClassVar, TYPE_CHECKING from typing import TYPE_CHECKING, ClassVar
import rich.repr import rich.repr
from . import _clock from . import _clock
from .case import camel_to_snake
from ._types import MessageTarget as MessageTarget from ._types import MessageTarget as MessageTarget
from .case import camel_to_snake
if TYPE_CHECKING: if TYPE_CHECKING:
from .widget import Widget
from .message_pump import MessagePump from .message_pump import MessagePump
from .widget import Widget
@rich.repr.auto @rich.repr.auto

View File

@@ -1,13 +1,13 @@
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import rich.repr import rich.repr
from .geometry import Region
from ._types import CallbackType from ._types import CallbackType
from .geometry import Region
from .message import Message from .message import Message
if TYPE_CHECKING: if TYPE_CHECKING:
from .message_pump import MessagePump from .message_pump import MessagePump
from .widget import Widget from .widget import Widget

View File

@@ -1,12 +1,12 @@
from __future__ import annotations from __future__ import annotations
import rich.repr
import asyncio import asyncio
from typing import Generic from typing import Generic
from .app import App, ReturnType import rich.repr
from ._wait import wait_for_idle from ._wait import wait_for_idle
from .app import App, ReturnType
@rich.repr.auto(angular=True) @rich.repr.auto(angular=True)

View File

@@ -17,7 +17,7 @@ import rich.repr
from . import events from . import events
from ._callback import count_parameters from ._callback import count_parameters
from ._types import MessageTarget, CallbackType from ._types import CallbackType, MessageTarget
if TYPE_CHECKING: if TYPE_CHECKING:
from .dom import DOMNode from .dom import DOMNode

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from rich.console import ConsoleOptions, Console, RenderResult from rich.console import Console, ConsoleOptions, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -1,7 +1,6 @@
from __future__ import annotations from __future__ import annotations
from rich.console import ConsoleOptions, Console, RenderResult from rich.console import Console, ConsoleOptions, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
import statistics import statistics
from typing import Generic, Sequence, Iterable, Callable, TypeVar from typing import Callable, Generic, Iterable, Sequence, TypeVar
from rich.color import Color from rich.color import Color
from rich.console import ConsoleOptions, Console, RenderResult from rich.console import Console, ConsoleOptions, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -3,7 +3,7 @@ from typing import Iterable, Tuple, cast
from rich.cells import cell_len from rich.cells import cell_len
from rich.color import Color from rich.color import Color
from rich.console import ConsoleOptions, Console, RenderResult, RenderableType from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from typing import Iterable from typing import Iterable
from rich.console import ConsoleOptions, Console, RenderResult, RenderableType from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from rich.console import ConsoleOptions, Console, RenderResult from rich.console import Console, ConsoleOptions, RenderResult
from rich.style import StyleType from rich.style import StyleType
from rich.text import Text from rich.text import Text
@@ -99,6 +99,7 @@ class UnderlineBar:
if __name__ == "__main__": if __name__ == "__main__":
import random import random
from time import sleep from time import sleep
from rich.color import ANSI_COLOR_NAMES from rich.color import ANSI_COLOR_NAMES
console = Console() console = Console()

View File

@@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from typing import Iterable, Iterator, TYPE_CHECKING from typing import TYPE_CHECKING, Iterable, Iterator
import rich.repr import rich.repr
from rich.console import RenderableType from rich.console import RenderableType
@@ -9,14 +9,14 @@ from rich.style import Style
from . import errors, events, messages from . import errors, events, messages
from ._callback import invoke from ._callback import invoke
from ._compositor import Compositor, MapGeometry from ._compositor import Compositor, MapGeometry
from ._types import CallbackType
from .css.match import match from .css.match import match
from .css.parse import parse_selectors from .css.parse import parse_selectors
from .dom import DOMNode from .dom import DOMNode
from .timer import Timer
from ._types import CallbackType
from .geometry import Offset, Region, Size from .geometry import Offset, Region, Size
from .reactive import Reactive from .reactive import Reactive
from .renderables.blank import Blank from .renderables.blank import Blank
from .timer import Timer
from .widget import Widget from .widget import Widget
if TYPE_CHECKING: if TYPE_CHECKING:

View File

@@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from collections import deque from collections import deque
from typing import Iterable, Iterator, TypeVar, overload, TYPE_CHECKING from typing import TYPE_CHECKING, Iterable, Iterator, TypeVar, overload
if TYPE_CHECKING: if TYPE_CHECKING:
from textual.dom import DOMNode from textual.dom import DOMNode

View File

@@ -35,9 +35,9 @@ from rich.text import Text
from rich.traceback import Traceback from rich.traceback import Traceback
from . import errors, events, messages from . import errors, events, messages
from ._asyncio import create_task
from ._animator import DEFAULT_EASING, Animatable, BoundAnimator, EasingFunction from ._animator import DEFAULT_EASING, Animatable, BoundAnimator, EasingFunction
from ._arrange import DockArrangeResult, arrange from ._arrange import DockArrangeResult, arrange
from ._asyncio import create_task
from ._context import active_app from ._context import active_app
from ._easing import DEFAULT_SCROLL_EASING from ._easing import DEFAULT_SCROLL_EASING
from ._layout import Layout from ._layout import Layout

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from importlib import import_module
import typing import typing
from importlib import import_module
from ..case import camel_to_snake from ..case import camel_to_snake
@@ -8,6 +9,7 @@ from ..case import camel_to_snake
# but also to the `__init__.pyi` file in this same folder - otherwise text editors and type checkers won't # but also to the `__init__.pyi` file in this same folder - otherwise text editors and type checkers won't
# be able to "see" them. # be able to "see" them.
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from ..widget import Widget
from ._button import Button from ._button import Button
from ._data_table import DataTable from ._data_table import DataTable
from ._directory_tree import DirectoryTree from ._directory_tree import DirectoryTree
@@ -24,7 +26,6 @@ if typing.TYPE_CHECKING:
from ._text_log import TextLog from ._text_log import TextLog
from ._tree import Tree from ._tree import Tree
from ._welcome import Welcome from ._welcome import Welcome
from ..widget import Widget
__all__ = [ __all__ = [

View File

@@ -6,8 +6,8 @@ from ._footer import Footer as Footer
from ._header import Header as Header from ._header import Header as Header
from ._input import Input as Input from ._input import Input as Input
from ._label import Label as Label from ._label import Label as Label
from ._list_view import ListView as ListView
from ._list_item import ListItem as ListItem from ._list_item import ListItem as ListItem
from ._list_view import ListView as ListView
from ._placeholder import Placeholder as Placeholder from ._placeholder import Placeholder as Placeholder
from ._pretty import Pretty as Pretty from ._pretty import Pretty as Pretty
from ._static import Static as Static from ._static import Static as Static

View File

@@ -2,11 +2,11 @@ from __future__ import annotations
from functools import partial from functools import partial
from typing import cast from typing import cast
from typing_extensions import Literal
import rich.repr import rich.repr
from rich.console import RenderableType from rich.console import RenderableType
from rich.text import Text, TextType from rich.text import Text, TextType
from typing_extensions import Literal
from .. import events from .. import events
from ..css._error_tools import friendly_list from ..css._error_tools import friendly_list
@@ -14,7 +14,6 @@ from ..message import Message
from ..reactive import reactive from ..reactive import reactive
from ..widgets import Static from ..widgets import Static
ButtonVariant = Literal["default", "primary", "success", "warning", "error"] ButtonVariant = Literal["default", "primary", "success", "warning", "error"]
_VALID_BUTTON_VARIANTS = {"default", "primary", "success", "warning", "error"} _VALID_BUTTON_VARIANTS = {"default", "primary", "success", "warning", "error"}

View File

@@ -3,7 +3,6 @@ from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field
from itertools import chain, zip_longest from itertools import chain, zip_longest
from typing import Generic, Iterable, cast from typing import Generic, Iterable, cast
from typing_extensions import ClassVar, TypeVar, Literal
import rich.repr import rich.repr
from rich.console import RenderableType from rich.console import RenderableType
@@ -12,6 +11,7 @@ from rich.protocol import is_renderable
from rich.segment import Segment from rich.segment import Segment
from rich.style import Style from rich.style import Style
from rich.text import Text, TextType from rich.text import Text, TextType
from typing_extensions import ClassVar, Literal, TypeVar
from .. import events, messages from .. import events, messages
from .._cache import LRUCache from .._cache import LRUCache

View File

@@ -7,9 +7,9 @@ from typing import ClassVar
from rich.style import Style from rich.style import Style
from rich.text import Text, TextType from rich.text import Text, TextType
from ..message import Message
from ._tree import Tree, TreeNode, TOGGLE_STYLE
from .._types import MessageTarget from .._types import MessageTarget
from ..message import Message
from ._tree import TOGGLE_STYLE, Tree, TreeNode
@dataclass @dataclass

View File

@@ -4,8 +4,8 @@ from datetime import datetime
from rich.text import Text from rich.text import Text
from ..widget import Widget
from ..reactive import Reactive from ..reactive import Reactive
from ..widget import Widget
class HeaderIcon(Widget): class HeaderIcon(Widget):

View File

@@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
from typing import ClassVar
import re import re
from typing import ClassVar
from rich.cells import cell_len, get_character_cell_size from rich.cells import cell_len, get_character_cell_size
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult from rich.console import Console, ConsoleOptions, RenderableType, RenderResult

View File

@@ -1,4 +1,5 @@
from __future__ import annotations from __future__ import annotations
from typing import ClassVar from typing import ClassVar
from textual.await_remove import AwaitRemove from textual.await_remove import AwaitRemove

View File

@@ -7,8 +7,7 @@ from typing_extensions import Literal
from .. import events from .. import events
from ..css._error_tools import friendly_list from ..css._error_tools import friendly_list
from ..reactive import Reactive, reactive from ..reactive import Reactive, reactive
from ..widget import Widget, RenderResult from ..widget import RenderResult, Widget
PlaceholderVariant = Literal["default", "size", "text"] PlaceholderVariant = Literal["default", "size", "text"]
_VALID_PLACEHOLDER_VARIANTS_ORDERED: list[PlaceholderVariant] = [ _VALID_PLACEHOLDER_VARIANTS_ORDERED: list[PlaceholderVariant] = [

View File

@@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Any from typing import Any
from rich.pretty import Pretty as PrettyRenderable from rich.pretty import Pretty as PrettyRenderable
from ..widget import Widget from ..widget import Widget

View File

@@ -8,8 +8,8 @@ from ..binding import Binding, BindingType
from ..geometry import Size from ..geometry import Size
from ..message import Message from ..message import Message
from ..reactive import reactive from ..reactive import reactive
from ..widget import Widget
from ..scrollbar import ScrollBarRender from ..scrollbar import ScrollBarRender
from ..widget import Widget
class Switch(Widget, can_focus=True): class Switch(Widget, can_focus=True):

View File

@@ -1,10 +1,10 @@
from ..app import ComposeResult
from ._static import Static
from ._button import Button
from ..containers import Container
from rich.markdown import Markdown from rich.markdown import Markdown
from ..app import ComposeResult
from ..containers import Container
from ._button import Button
from ._static import Static
WELCOME_MD = """\ WELCOME_MD = """\
# Welcome! # Welcome!

View File

@@ -7,11 +7,11 @@ from typing import Iterable
from rich.cells import cell_len from rich.cells import cell_len
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
from rich.segment import Segment from rich.segment import Segment
from rich.style import StyleType, Style from rich.style import Style, StyleType
from rich.text import Text from rich.text import Text
from textual import events from textual import events
from textual._layout_resolve import layout_resolve, Edge from textual._layout_resolve import Edge, layout_resolve
from textual.keys import Keys from textual.keys import Keys
from textual.reactive import Reactive from textual.reactive import Reactive
from textual.renderables.text_opacity import TextOpacity from textual.renderables.text_opacity import TextOpacity

View File

@@ -2,17 +2,17 @@ import pytest
from tests.utilities.render import render from tests.utilities.render import render
from textual.css._help_text import ( from textual.css._help_text import (
spacing_wrong_number_of_values_help_text,
spacing_invalid_value_help_text,
scalar_help_text,
string_enum_help_text,
color_property_help_text,
border_property_help_text,
layout_property_help_text,
fractional_property_help_text,
offset_property_help_text,
align_help_text, align_help_text,
border_property_help_text,
color_property_help_text,
fractional_property_help_text,
layout_property_help_text,
offset_property_help_text,
offset_single_axis_help_text, offset_single_axis_help_text,
scalar_help_text,
spacing_invalid_value_help_text,
spacing_wrong_number_of_values_help_text,
string_enum_help_text,
style_flags_property_help_text, style_flags_property_help_text,
) )

View File

@@ -8,7 +8,7 @@ from textual.css.parse import substitute_references
from textual.css.scalar import Scalar, Unit from textual.css.scalar import Scalar, Unit
from textual.css.stylesheet import Stylesheet, StylesheetParseError from textual.css.stylesheet import Stylesheet, StylesheetParseError
from textual.css.tokenize import tokenize from textual.css.tokenize import tokenize
from textual.css.tokenizer import Token, ReferencedBy from textual.css.tokenizer import ReferencedBy, Token
from textual.css.transition import Transition from textual.css.transition import Transition
from textual.geometry import Spacing from textual.geometry import Spacing
from textual.layouts.vertical import VerticalLayout from textual.layouts.vertical import VerticalLayout

View File

@@ -1,13 +1,12 @@
from decimal import Decimal from decimal import Decimal
import pytest import pytest
from rich.style import Style from rich.style import Style
from textual.color import Color from textual.color import Color
from textual.css.errors import StyleValueError from textual.css.errors import StyleValueError
from textual.css.scalar import Scalar, Unit from textual.css.scalar import Scalar, Unit
from textual.css.styles import Styles, RenderStyles from textual.css.styles import RenderStyles, Styles
from textual.dom import DOMNode from textual.dom import DOMNode
from textual.widget import Widget from textual.widget import Widget

View File

@@ -11,6 +11,4 @@ _WINDOWS = sys.platform == "win32"
# and the error messages suggest the event loop is being shutdown before async fixture # and the error messages suggest the event loop is being shutdown before async fixture
# teardown code has finished running. These are very rare, but are much more of an issue on # teardown code has finished running. These are very rare, but are much more of an issue on
# CI since they can delay builds that have passed locally. # CI since they can delay builds that have passed locally.
pytestmark = pytest.mark.skipif( pytestmark = pytest.mark.skipif(_MACOS_CI or _WINDOWS, reason="Issue #411")
_MACOS_CI or _WINDOWS, reason="Issue #411"
)

View File

@@ -30,7 +30,6 @@ async def test_devtools_client_is_connected(devtools):
@time_machine.travel(datetime.utcfromtimestamp(TIMESTAMP)) @time_machine.travel(datetime.utcfromtimestamp(TIMESTAMP))
async def test_devtools_log_places_encodes_and_queues_message(devtools): async def test_devtools_log_places_encodes_and_queues_message(devtools):
await devtools._stop_log_queue_processing() await devtools._stop_log_queue_processing()
devtools.log(DevtoolsLog("Hello, world!", CALLER)) devtools.log(DevtoolsLog("Hello, world!", CALLER))
queued_log = await devtools.log_queue.get() queued_log = await devtools.log_queue.get()

View File

@@ -5,7 +5,6 @@ from __future__ import annotations
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import Input from textual.widgets import Input
TEST_INPUTS: dict[str | None, str] = { TEST_INPUTS: dict[str | None, str] = {
"empty": "", "empty": "",
"multi-no-punctuation": "Curse your sudden but inevitable betrayal", "multi-no-punctuation": "Curse your sudden but inevitable betrayal",

View File

@@ -1,4 +1,5 @@
from rich.console import Console from rich.console import Console
from textual.app import App from textual.app import App
from textual.widgets import Input from textual.widgets import Input

View File

@@ -1,12 +1,11 @@
import pytest import pytest
from textual.geometry import Size
from textual.layouts.grid import GridLayout from textual.layouts.grid import GridLayout
from textual.layouts.horizontal import HorizontalLayout from textual.layouts.horizontal import HorizontalLayout
from textual.layouts.vertical import VerticalLayout from textual.layouts.vertical import VerticalLayout
from textual.geometry import Size
from textual.widget import Widget from textual.widget import Widget
LAYOUTS = [GridLayout, HorizontalLayout, VerticalLayout] LAYOUTS = [GridLayout, HorizontalLayout, VerticalLayout]

View File

@@ -1,6 +1,6 @@
import pytest import pytest
from textual.layouts.factory import get_layout, MissingLayout from textual.layouts.factory import MissingLayout, get_layout
from textual.layouts.vertical import VerticalLayout from textual.layouts.vertical import VerticalLayout

View File

@@ -1,5 +1,5 @@
from textual.app import App, ComposeResult from textual.app import App, ComposeResult
from textual.widgets import ListView, ListItem, Label from textual.widgets import Label, ListItem, ListView
class MyListView(ListView): class MyListView(ListView):

View File

@@ -20,22 +20,35 @@ def test_sparkline_two_values_min_max():
def test_sparkline_expand_data_to_width(): def test_sparkline_expand_data_to_width():
assert render(Sparkline([2, 4], assert (
width=4)) == f"{GREEN}{STOP}{GREEN}{STOP}{RED}{STOP}{RED}{STOP}" render(Sparkline([2, 4], width=4))
== f"{GREEN}{STOP}{GREEN}{STOP}{RED}{STOP}{RED}{STOP}"
)
def test_sparkline_expand_data_to_width_non_divisible(): def test_sparkline_expand_data_to_width_non_divisible():
assert render(Sparkline([2, 4], width=3)) == f"{GREEN}{STOP}{GREEN}{STOP}{RED}{STOP}" assert (
render(Sparkline([2, 4], width=3))
== f"{GREEN}{STOP}{GREEN}{STOP}{RED}{STOP}"
)
def test_sparkline_shrink_data_to_width(): def test_sparkline_shrink_data_to_width():
assert render(Sparkline([2, 2, 4, 4, 6, 6], width=3)) == f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}" assert (
render(Sparkline([2, 2, 4, 4, 6, 6], width=3))
== f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}"
)
def test_sparkline_shrink_data_to_width_non_divisible(): def test_sparkline_shrink_data_to_width_non_divisible():
assert render( assert (
Sparkline([1, 2, 3, 4, 5], width=3, summary_function=min)) == f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}" render(Sparkline([1, 2, 3, 4, 5], width=3, summary_function=min))
== f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}"
)
def test_sparkline_color_blend(): def test_sparkline_color_blend():
assert render(Sparkline([1, 2, 3], width=3)) == f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}" assert (
render(Sparkline([1, 2, 3], width=3))
== f"{GREEN}{STOP}{BLENDED}{STOP}{RED}{STOP}"
)

View File

@@ -14,7 +14,7 @@ def text():
def test_simple_text_opacity(text): def test_simple_text_opacity(text):
blended_red_on_green = "\x1b[38;2;127;127;0;48;2;0;255;0m" blended_red_on_green = "\x1b[38;2;127;127;0;48;2;0;255;0m"
assert render(TextOpacity(text, opacity=.5)) == ( assert render(TextOpacity(text, opacity=0.5)) == (
f"{blended_red_on_green}Hello, world!{STOP}" f"{blended_red_on_green}Hello, world!{STOP}"
) )
@@ -31,19 +31,21 @@ def test_text_opacity_value_of_one_noop(text):
def test_ansi_colors_noop(): def test_ansi_colors_noop():
ansi_colored_text = Text("Hello, world!", style="red on green", end="") ansi_colored_text = Text("Hello, world!", style="red on green", end="")
assert render(TextOpacity(ansi_colored_text, opacity=.5)) == render(ansi_colored_text) assert render(TextOpacity(ansi_colored_text, opacity=0.5)) == render(
ansi_colored_text
)
def test_text_opacity_no_style_noop(): def test_text_opacity_no_style_noop():
text_no_style = Text("Hello, world!", end="") text_no_style = Text("Hello, world!", end="")
assert render(TextOpacity(text_no_style, opacity=.2)) == render(text_no_style) assert render(TextOpacity(text_no_style, opacity=0.2)) == render(text_no_style)
def test_text_opacity_only_fg_noop(): def test_text_opacity_only_fg_noop():
text_only_fg = Text("Hello, world!", style="#ff0000", end="") text_only_fg = Text("Hello, world!", style="#ff0000", end="")
assert render(TextOpacity(text_only_fg, opacity=.5)) == render(text_only_fg) assert render(TextOpacity(text_only_fg, opacity=0.5)) == render(text_only_fg)
def test_text_opacity_only_bg_noop(): def test_text_opacity_only_bg_noop():
text_only_bg = Text("Hello, world!", style="on #ff0000", end="") text_only_bg = Text("Hello, world!", style="on #ff0000", end="")
assert render(TextOpacity(text_only_bg, opacity=.5)) == render(text_only_bg) assert render(TextOpacity(text_only_bg, opacity=0.5)) == render(text_only_bg)

View File

@@ -1,7 +1,6 @@
from unittest.mock import create_autospec from unittest.mock import create_autospec
from rich.console import Console from rich.console import Console, ConsoleOptions
from rich.console import ConsoleOptions
from rich.text import Text from rich.text import Text
from tests.utilities.render import render from tests.utilities.render import render
@@ -21,16 +20,12 @@ def test_no_highlight():
def test_highlight_from_zero(): def test_highlight_from_zero():
bar = UnderlineBar(highlight_range=(0, 2.5), width=6) bar = UnderlineBar(highlight_range=(0, 2.5), width=6)
assert render(bar) == ( assert render(bar) == (f"{MAGENTA}━━{STOP}{MAGENTA}{STOP}{GREY}━━━{STOP}")
f"{MAGENTA}━━{STOP}{MAGENTA}{STOP}{GREY}━━━{STOP}"
)
def test_highlight_from_zero_point_five(): def test_highlight_from_zero_point_five():
bar = UnderlineBar(highlight_range=(0.5, 2), width=6) bar = UnderlineBar(highlight_range=(0.5, 2), width=6)
assert render(bar) == ( assert render(bar) == (f"{MAGENTA}╺━{STOP}{GREY}{STOP}{GREY}━━━{STOP}")
f"{MAGENTA}╺━{STOP}{GREY}{STOP}{GREY}━━━{STOP}"
)
def test_highlight_middle(): def test_highlight_middle():
@@ -47,10 +42,7 @@ def test_highlight_middle():
def test_highlight_half_start(): def test_highlight_half_start():
bar = UnderlineBar(highlight_range=(2.5, 4), width=6) bar = UnderlineBar(highlight_range=(2.5, 4), width=6)
assert render(bar) == ( assert render(bar) == (
f"{GREY}━━{STOP}" f"{GREY}━━{STOP}" f"{MAGENTA}╺━{STOP}" f"{GREY}{STOP}" f"{GREY}{STOP}"
f"{MAGENTA}╺━{STOP}"
f"{GREY}{STOP}"
f"{GREY}{STOP}"
) )
@@ -68,42 +60,30 @@ def test_highlight_half_end():
def test_highlight_half_start_and_half_end(): def test_highlight_half_start_and_half_end():
bar = UnderlineBar(highlight_range=(2.5, 4.5), width=6) bar = UnderlineBar(highlight_range=(2.5, 4.5), width=6)
assert render(bar) == ( assert render(bar) == (
f"{GREY}━━{STOP}" f"{GREY}━━{STOP}" f"{MAGENTA}╺━{STOP}" f"{MAGENTA}{STOP}" f"{GREY}{STOP}"
f"{MAGENTA}╺━{STOP}"
f"{MAGENTA}{STOP}"
f"{GREY}{STOP}"
) )
def test_highlight_to_near_end(): def test_highlight_to_near_end():
bar = UnderlineBar(highlight_range=(3, 5.5), width=6) bar = UnderlineBar(highlight_range=(3, 5.5), width=6)
assert render(bar) == ( assert render(bar) == (
f"{GREY}━━{STOP}" f"{GREY}━━{STOP}" f"{GREY}{STOP}" f"{MAGENTA}━━{STOP}" f"{MAGENTA}{STOP}"
f"{GREY}{STOP}"
f"{MAGENTA}━━{STOP}"
f"{MAGENTA}{STOP}"
) )
def test_highlight_to_end(): def test_highlight_to_end():
bar = UnderlineBar(highlight_range=(3, 6), width=6) bar = UnderlineBar(highlight_range=(3, 6), width=6)
assert render(bar) == ( assert render(bar) == (f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}")
f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}"
)
def test_highlight_out_of_bounds_start(): def test_highlight_out_of_bounds_start():
bar = UnderlineBar(highlight_range=(-2, 3), width=6) bar = UnderlineBar(highlight_range=(-2, 3), width=6)
assert render(bar) == ( assert render(bar) == (f"{MAGENTA}━━━{STOP}{GREY}{STOP}{GREY}━━{STOP}")
f"{MAGENTA}━━━{STOP}{GREY}{STOP}{GREY}━━{STOP}"
)
def test_highlight_out_of_bounds_end(): def test_highlight_out_of_bounds_end():
bar = UnderlineBar(highlight_range=(3, 9), width=6) bar = UnderlineBar(highlight_range=(3, 9), width=6)
assert render(bar) == ( assert render(bar) == (f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}")
f"{GREY}━━{STOP}{GREY}{STOP}{MAGENTA}━━━{STOP}"
)
def test_highlight_full_range_out_of_bounds_end(): def test_highlight_full_range_out_of_bounds_end():
@@ -117,7 +97,9 @@ def test_highlight_full_range_out_of_bounds_start():
def test_custom_styles(): def test_custom_styles():
bar = UnderlineBar(highlight_range=(2, 4), highlight_style="red", background_style="green", width=6) bar = UnderlineBar(
highlight_range=(2, 4), highlight_style="red", background_style="green", width=6
)
assert render(bar) == ( assert render(bar) == (
f"{GREEN}{STOP}" f"{GREEN}{STOP}"
f"{GREEN}{STOP}" f"{GREEN}{STOP}"
@@ -128,7 +110,9 @@ def test_custom_styles():
def test_clickable_ranges(): def test_clickable_ranges():
bar = UnderlineBar(highlight_range=(0, 1), width=6, clickable_ranges={"foo": (0, 2), "bar": (4, 5)}) bar = UnderlineBar(
highlight_range=(0, 1), width=6, clickable_ranges={"foo": (0, 2), "bar": (4, 5)}
)
console = create_autospec(Console) console = create_autospec(Console)
options = create_autospec(ConsoleOptions) options = create_autospec(ConsoleOptions)
@@ -136,8 +120,8 @@ def test_clickable_ranges():
start, end, style = text.spans[-2] start, end, style = text.spans[-2]
assert (start, end) == (0, 2) assert (start, end) == (0, 2)
assert style.meta == {'@click': "range_clicked('foo')"} assert style.meta == {"@click": "range_clicked('foo')"}
start, end, style = text.spans[-1] start, end, style = text.spans[-1]
assert (start, end) == (4, 5) assert (start, end) == (4, 5)
assert style.meta == {'@click': "range_clicked('bar')"} assert style.meta == {"@click": "range_clicked('bar')"}

View File

@@ -6,7 +6,7 @@ from unittest.mock import Mock
import pytest import pytest
from textual._animator import Animator, SimpleAnimation from textual._animator import Animator, SimpleAnimation
from textual._easing import EASING, DEFAULT_EASING from textual._easing import DEFAULT_EASING, EASING
class Animatable: class Animatable:

View File

@@ -1,6 +1,6 @@
import pytest import pytest
from textual._arrange import arrange, TOP_Z from textual._arrange import TOP_Z, arrange
from textual._layout import WidgetPlacement from textual._layout import WidgetPlacement
from textual.geometry import Region, Size, Spacing from textual.geometry import Region, Size, Spacing
from textual.widget import Widget from textual.widget import Widget

View File

@@ -1,10 +1,9 @@
from textual import events
from textual.app import App from textual.app import App
from textual.pilot import Pilot from textual.pilot import Pilot
from textual import events
def test_auto_pilot() -> None: def test_auto_pilot() -> None:
keys_pressed: list[str] = [] keys_pressed: list[str] = []
class TestApp(App): class TestApp(App):
@@ -12,7 +11,6 @@ def test_auto_pilot() -> None:
keys_pressed.append(event.key) keys_pressed.append(event.key)
async def auto_pilot(pilot: Pilot) -> None: async def auto_pilot(pilot: Pilot) -> None:
await pilot.press("tab", *"foo") await pilot.press("tab", *"foo")
await pilot.exit("bar") await pilot.exit("bar")

View File

@@ -3,7 +3,7 @@ from string import ascii_lowercase
import pytest import pytest
from textual.app import App from textual.app import App
from textual.binding import Bindings, Binding, BindingError, NoBinding, InvalidBinding from textual.binding import Binding, BindingError, Bindings, InvalidBinding, NoBinding
BINDING1 = Binding("a,b", action="action1", description="description1") BINDING1 = Binding("a,b", action="action1", description="description1")
BINDING2 = Binding("c", action="action2", description="description2") BINDING2 = Binding("c", action="action2", description="description2")

Some files were not shown because too many files have changed in this diff Show More