diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..d16dd221a --- /dev/null +++ b/.coveragerc @@ -0,0 +1,9 @@ +[run] +omit = + +[report] +exclude_lines = + pragma: no cover + if TYPE_CHECKING: + if __name__ == "__main__": + @overload diff --git a/src/textual/_loop.py b/src/textual/_loop.py index 01c6cafbe..7a057fc21 100644 --- a/src/textual/_loop.py +++ b/src/textual/_loop.py @@ -1,9 +1,11 @@ -from typing import Iterable, Tuple, TypeVar +from __future__ import annotations + +from typing import Iterable, TypeVar T = TypeVar("T") -def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: +def loop_first(values: Iterable[T]) -> Iterable[tuple[bool, T]]: """Iterate and generate a tuple with a flag for first value.""" iter_values = iter(values) try: @@ -15,7 +17,7 @@ def loop_first(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: yield False, value -def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: +def loop_last(values: Iterable[T]) -> Iterable[tuple[bool, T]]: """Iterate and generate a tuple with a flag for last value.""" iter_values = iter(values) try: @@ -28,7 +30,7 @@ def loop_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: yield True, previous_value -def loop_first_last(values: Iterable[T]) -> Iterable[Tuple[bool, bool, T]]: +def loop_first_last(values: Iterable[T]) -> Iterable[tuple[bool, bool, T]]: """Iterate and generate a tuple with a flag for first and last value.""" iter_values = iter(values) try: diff --git a/src/textual/scrollbar.py b/src/textual/scrollbar.py index 0dfba622b..62b5c3726 100644 --- a/src/textual/scrollbar.py +++ b/src/textual/scrollbar.py @@ -14,27 +14,26 @@ from .widget import Reactive, Widget @rich.repr.auto -class ScrollUp(Message, bubble=True): +class ScrollUp(Message): """Message sent when clicking above handle.""" @rich.repr.auto -class ScrollDown(Message, bubble=True): +class ScrollDown(Message): """Message sent when clicking below handle.""" @rich.repr.auto -class ScrollLeft(Message, bubble=True): +class ScrollLeft(Message): """Message sent when clicking above handle.""" @rich.repr.auto -class ScrollRight(Message, bubble=True): +class ScrollRight(Message): """Message sent when clicking below handle.""" -@rich.repr.auto -class ScrollTo(Message, bubble=True): +class ScrollTo(Message): """Message sent when click and dragging handle.""" def __init__( diff --git a/tests/test_case.py b/tests/test_case.py new file mode 100644 index 000000000..dbc7b94b2 --- /dev/null +++ b/tests/test_case.py @@ -0,0 +1,5 @@ +from textual.case import camel_to_snake + + +def test_camel_to_snake(): + assert camel_to_snake("FooBar") == "foo_bar" diff --git a/tests/test_loop.py b/tests/test_loop.py new file mode 100644 index 000000000..c235f23a5 --- /dev/null +++ b/tests/test_loop.py @@ -0,0 +1,28 @@ +from textual._loop import loop_first, loop_last, loop_first_last + + +def test_loop_first(): + assert list(loop_first([])) == [] + iterable = loop_first(["apples", "oranges", "pears", "lemons"]) + assert next(iterable) == (True, "apples") + assert next(iterable) == (False, "oranges") + assert next(iterable) == (False, "pears") + assert next(iterable) == (False, "lemons") + + +def test_loop_last(): + assert list(loop_last([])) == [] + iterable = loop_last(["apples", "oranges", "pears", "lemons"]) + assert next(iterable) == (False, "apples") + assert next(iterable) == (False, "oranges") + assert next(iterable) == (False, "pears") + assert next(iterable) == (True, "lemons") + + +def test_loop_first_last(): + assert list(loop_first_last([])) == [] + iterable = loop_first_last(["apples", "oranges", "pears", "lemons"]) + assert next(iterable) == (True, False, "apples") + assert next(iterable) == (False, False, "oranges") + assert next(iterable) == (False, False, "pears") + assert next(iterable) == (False, True, "lemons")