diff --git a/tests/test_async_generator.py b/tests/test_async_generator.py index fd2c109c9..fa17657de 100644 --- a/tests/test_async_generator.py +++ b/tests/test_async_generator.py @@ -1,12 +1,14 @@ +from typing import Iterator + from prompt_toolkit.eventloop import generator_to_async_generator, get_event_loop -def _sync_generator(): +def _sync_generator() -> Iterator[int]: yield 1 yield 10 -def test_generator_to_async_generator(): +def test_generator_to_async_generator() -> None: """ Test conversion of sync to asycn generator. This should run the synchronous parts in a background thread. @@ -15,7 +17,7 @@ def test_generator_to_async_generator(): items = [] - async def consume_async_generator(): + async def consume_async_generator() -> None: async for item in async_gen: items.append(item) diff --git a/tests/test_buffer.py b/tests/test_buffer.py index 413ec9874..23a1c1259 100644 --- a/tests/test_buffer.py +++ b/tests/test_buffer.py @@ -4,23 +4,23 @@ @pytest.fixture -def _buffer(): +def _buffer() -> Buffer: buff = Buffer() return buff -def test_initial(_buffer): +def test_initial(_buffer: Buffer) -> None: assert _buffer.text == "" assert _buffer.cursor_position == 0 -def test_insert_text(_buffer): +def test_insert_text(_buffer: Buffer) -> None: _buffer.insert_text("some_text") assert _buffer.text == "some_text" assert _buffer.cursor_position == len("some_text") -def test_cursor_movement(_buffer): +def test_cursor_movement(_buffer: Buffer) -> None: _buffer.insert_text("some_text") _buffer.cursor_left() _buffer.cursor_left() @@ -32,7 +32,7 @@ def test_cursor_movement(_buffer): assert _buffer.cursor_position == len("some_teA") -def test_backspace(_buffer): +def test_backspace(_buffer: Buffer) -> None: _buffer.insert_text("some_text") _buffer.cursor_left() _buffer.cursor_left() @@ -42,7 +42,7 @@ def test_backspace(_buffer): assert _buffer.cursor_position == len("some_t") -def test_cursor_up(_buffer): +def test_cursor_up(_buffer: Buffer) -> None: # Cursor up to a line thats longer. _buffer.insert_text("long line1\nline2") _buffer.cursor_up() @@ -61,7 +61,7 @@ def test_cursor_up(_buffer): assert _buffer.document.cursor_position == 5 -def test_cursor_down(_buffer): +def test_cursor_down(_buffer: Buffer) -> None: _buffer.insert_text("line1\nline2") _buffer.cursor_position = 3 @@ -78,7 +78,7 @@ def test_cursor_down(_buffer): assert _buffer.document.cursor_position == len("long line1\na") -def test_join_next_line(_buffer): +def test_join_next_line(_buffer: Buffer) -> None: _buffer.insert_text("line1\nline2\nline3") _buffer.cursor_up() _buffer.join_next_line() @@ -94,14 +94,14 @@ def test_join_next_line(_buffer): assert _buffer.text == "line1" -def test_newline(_buffer): +def test_newline(_buffer: Buffer) -> None: _buffer.insert_text("hello world") _buffer.newline() assert _buffer.text == "hello world\n" -def test_swap_characters_before_cursor(_buffer): +def test_swap_characters_before_cursor(_buffer: Buffer) -> None: _buffer.insert_text("hello world") _buffer.cursor_left() _buffer.cursor_left() diff --git a/tests/test_cli.py b/tests/test_cli.py index 53d1e4f28..279fec6da 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2,14 +2,16 @@ These are almost end-to-end tests. They create a Prompt, feed it with some input and check the result. """ -from functools import partial +from typing import Optional, Tuple import pytest -from prompt_toolkit.clipboard import ClipboardData, InMemoryClipboard +from prompt_toolkit.application import Application +from prompt_toolkit.clipboard import Clipboard, ClipboardData, InMemoryClipboard +from prompt_toolkit.document import Document from prompt_toolkit.enums import EditingMode from prompt_toolkit.filters import ViInsertMode -from prompt_toolkit.history import InMemoryHistory +from prompt_toolkit.history import History, InMemoryHistory from prompt_toolkit.input.defaults import create_pipe_input from prompt_toolkit.input.vt100_parser import ANSI_SEQUENCES from prompt_toolkit.key_binding.bindings.named_commands import prefix_meta @@ -18,7 +20,7 @@ from prompt_toolkit.shortcuts import PromptSession -def _history(): +def _history() -> InMemoryHistory: h = InMemoryHistory() h.append_string("line1 first input") h.append_string("line2 second input") @@ -27,14 +29,14 @@ def _history(): def _feed_cli_with_input( - text, - editing_mode=EditingMode.EMACS, - clipboard=None, - history=None, - multiline=False, - check_line_ending=True, - key_bindings=None, -): + text: str, + editing_mode: EditingMode = EditingMode.EMACS, + clipboard: Optional[Clipboard] = None, + history: Optional[History] = None, + multiline: bool = False, + check_line_ending: bool = True, + key_bindings: Optional[KeyBindings] = None, +) -> Tuple[Document, Application]: """ Create a Prompt, feed it with the given user input and return the CLI object. @@ -47,7 +49,7 @@ def _feed_cli_with_input( with create_pipe_input() as inp: inp.send_text(text) - session = PromptSession( + session: PromptSession[str] = PromptSession( input=inp, output=DummyOutput(), editing_mode=editing_mode, @@ -61,14 +63,14 @@ def _feed_cli_with_input( return session.default_buffer.document, session.app -def test_simple_text_input(): +def test_simple_text_input() -> None: # Simple text input, followed by enter. result, cli = _feed_cli_with_input("hello\r") assert result.text == "hello" assert cli.current_buffer.text == "hello" -def test_emacs_cursor_movements(): +def test_emacs_cursor_movements() -> None: """ Test cursor movements with Emacs key bindings. """ @@ -185,7 +187,7 @@ def test_emacs_cursor_movements(): assert result.cursor_position == len("hello") -def test_emacs_kill_multiple_words_and_paste(): +def test_emacs_kill_multiple_words_and_paste() -> None: # Using control-w twice should place both words on the clipboard. result, cli = _feed_cli_with_input( "hello world test" "\x17\x17" "--\x19\x19\r" # Twice c-w. # Twice c-y. @@ -206,7 +208,7 @@ def test_emacs_kill_multiple_words_and_paste(): assert cli.clipboard.get_data().text == "world test" -def test_interrupts(): +def test_interrupts() -> None: # ControlC: raise KeyboardInterrupt. with pytest.raises(KeyboardInterrupt): result, cli = _feed_cli_with_input("hello\x03\r") @@ -219,7 +221,7 @@ def test_interrupts(): result, cli = _feed_cli_with_input("\x04\r") -def test_emacs_yank(): +def test_emacs_yank() -> None: # ControlY (yank) c = InMemoryClipboard(ClipboardData("XYZ")) result, cli = _feed_cli_with_input("hello\x02\x19\r", clipboard=c) @@ -227,13 +229,13 @@ def test_emacs_yank(): assert result.cursor_position == len("hellXYZ") -def test_quoted_insert(): +def test_quoted_insert() -> None: # ControlQ - ControlB (quoted-insert) result, cli = _feed_cli_with_input("hello\x11\x02\r") assert result.text == "hello\x02" -def test_transformations(): +def test_transformations() -> None: # Meta-c (capitalize-word) result, cli = _feed_cli_with_input("hello world\01\x1bc\r") assert result.text == "Hello world" @@ -260,7 +262,7 @@ def test_transformations(): assert result.cursor_position == len("abcd") -def test_emacs_other_bindings(): +def test_emacs_other_bindings() -> None: # Transpose characters. result, cli = _feed_cli_with_input("abcde\x14X\r") # Ctrl-T assert result.text == "abcedX" @@ -300,7 +302,7 @@ def test_emacs_other_bindings(): assert result.text == "hello world /some/very/X" -def test_controlx_controlx(): +def test_controlx_controlx() -> None: # At the end: go to the start of the line. result, cli = _feed_cli_with_input("hello world\x18\x18X\r") assert result.text == "Xhello world" @@ -315,7 +317,7 @@ def test_controlx_controlx(): assert result.text == "hello worldX" -def test_emacs_history_bindings(): +def test_emacs_history_bindings() -> None: # Adding a new item to the history. history = _history() result, cli = _feed_cli_with_input("new input\r", history=history) @@ -345,7 +347,7 @@ def test_emacs_history_bindings(): assert result.text == "line2 second input" -def test_emacs_reverse_search(): +def test_emacs_reverse_search() -> None: history = _history() # ControlR (reverse-search-history) @@ -357,7 +359,7 @@ def test_emacs_reverse_search(): assert result.text == "line2 second input" -def test_emacs_arguments(): +def test_emacs_arguments() -> None: """ Test various combinations of arguments in Emacs mode. """ @@ -386,7 +388,7 @@ def test_emacs_arguments(): assert result.text == "abbbbaaa" -def test_emacs_arguments_for_all_commands(): +def test_emacs_arguments_for_all_commands() -> None: """ Test all Emacs commands with Meta-[0-9] arguments (both positive and negative). No one should crash. @@ -407,7 +409,7 @@ def test_emacs_arguments_for_all_commands(): assert key == "\x03" -def test_emacs_kill_ring(): +def test_emacs_kill_ring() -> None: operations = ( # abc ControlA ControlK "abc\x01\x0b" @@ -432,7 +434,7 @@ def test_emacs_kill_ring(): assert result.text == "ghi" -def test_emacs_selection(): +def test_emacs_selection() -> None: # Copy/paste empty selection should not do anything. operations = ( "hello" @@ -470,7 +472,7 @@ def test_emacs_selection(): assert result.text == "lhelo" -def test_emacs_insert_comment(): +def test_emacs_insert_comment() -> None: # Test insert-comment (M-#) binding. result, cli = _feed_cli_with_input("hello\x1b#", check_line_ending=False) assert result.text == "#hello" @@ -481,7 +483,7 @@ def test_emacs_insert_comment(): assert result.text == "#hello\n#world" -def test_emacs_record_macro(): +def test_emacs_record_macro() -> None: operations = ( " " "\x18(" # Start recording macro. C-X( @@ -497,7 +499,7 @@ def test_emacs_record_macro(): assert result.text == " hello hellohello" -def test_emacs_nested_macro(): +def test_emacs_nested_macro() -> None: "Test calling the macro within a macro." # Calling a macro within a macro should take the previous recording (if one # exists), not the one that is in progress. @@ -530,7 +532,7 @@ def test_emacs_nested_macro(): assert result.text == "helloworld" -def test_prefix_meta(): +def test_prefix_meta() -> None: # Test the prefix-meta command. b = KeyBindings() b.add("j", "j", filter=ViInsertMode())(prefix_meta) @@ -541,7 +543,7 @@ def test_prefix_meta(): assert result.text == "Xhello" -def test_bracketed_paste(): +def test_bracketed_paste() -> None: result, cli = _feed_cli_with_input("\x1b[200~hello world\x1b[201~\r") assert result.text == "hello world" @@ -557,11 +559,13 @@ def test_bracketed_paste(): assert result.text == "hello\nworld" -def test_vi_cursor_movements(): +def test_vi_cursor_movements() -> None: """ Test cursor movements with Vi key bindings. """ - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI) result, cli = feed("\x1b\r") assert result.text == "" @@ -604,8 +608,9 @@ def test_vi_cursor_movements(): assert result.text == "heXlo" -def test_vi_operators(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) +def test_vi_operators() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI) # Esc g~0 result, cli = feed("hello\x1bg~0\r") @@ -620,8 +625,9 @@ def test_vi_operators(): assert result.text == "o" -def test_vi_text_objects(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) +def test_vi_text_objects() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI) # Esc gUgg result, cli = feed("hello\x1bgUgg\r") @@ -644,8 +650,9 @@ def test_vi_text_objects(): assert result.text == "beforeafter" -def test_vi_digraphs(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) +def test_vi_digraphs() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI) # C-K o/ result, cli = feed("hello\x0bo/\r") @@ -664,9 +671,11 @@ def test_vi_digraphs(): assert result.text == "helloy" -def test_vi_block_editing(): +def test_vi_block_editing() -> None: "Test Vi Control-V style block insertion." - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) operations = ( # Six lines of text. @@ -698,9 +707,11 @@ def test_vi_block_editing(): assert result.text == "-line1\n-line***2\n-line***3\n-line***4\n-line5\n-line6" -def test_vi_block_editing_empty_lines(): +def test_vi_block_editing_empty_lines() -> None: "Test block editing on empty lines." - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) operations = ( # Six empty lines. @@ -732,8 +743,9 @@ def test_vi_block_editing_empty_lines(): assert result.text == "***\n***\n***\n\n\n" -def test_vi_visual_line_copy(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) +def test_vi_visual_line_copy() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) operations = ( # Three lines of text. @@ -764,11 +776,13 @@ def test_vi_visual_line_copy(): ) -def test_vi_visual_empty_line(): +def test_vi_visual_empty_line() -> None: """ Test edge case with an empty line in Visual-line mode. """ - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) # 1. Delete first two lines. operations = ( @@ -798,9 +812,11 @@ def test_vi_visual_empty_line(): assert result.text == "hello\nworld" -def test_vi_character_delete_after_cursor(): +def test_vi_character_delete_after_cursor() -> None: "Test 'x' keypress." - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) # Delete one character. result, cli = feed("abcd\x1bHx\r") @@ -823,9 +839,11 @@ def test_vi_character_delete_after_cursor(): assert result.text == "lo\n\n" -def test_vi_character_delete_before_cursor(): +def test_vi_character_delete_before_cursor() -> None: "Test 'X' keypress." - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI, multiline=True) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) # Delete one character. result, cli = feed("abcd\x1bX\r") @@ -847,8 +865,9 @@ def test_vi_character_delete_before_cursor(): assert result.text == "\n\n" -def test_vi_character_paste(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) +def test_vi_character_paste() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) # Test 'p' character paste. result, cli = feed("abcde\x1bhhxp\r") @@ -861,11 +880,13 @@ def test_vi_character_paste(): assert result.cursor_position == 2 -def test_vi_temp_navigation_mode(): +def test_vi_temp_navigation_mode() -> None: """ Test c-o binding: go for one action into navigation mode. """ - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) + + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) result, cli = feed("abcde" "\x0f" "3h" "x\r") # c-o # 3 times to the left. assert result.text == "axbcde" @@ -890,8 +911,9 @@ def test_vi_temp_navigation_mode(): assert result.cursor_position == 5 -def test_vi_macros(): - feed = partial(_feed_cli_with_input, editing_mode=EditingMode.VI) +def test_vi_macros() -> None: + def feed(text: str) -> Tuple[Document, Application]: + return _feed_cli_with_input(text, editing_mode=EditingMode.VI, multiline=True) # Record and execute macro. result, cli = feed("\x1bqcahello\x1bq@c\r") @@ -924,12 +946,12 @@ def test_vi_macros(): assert result.text == "helloworld" -def test_accept_default(): +def test_accept_default() -> None: """ Test `prompt(accept_default=True)`. """ with create_pipe_input() as inp: - session = PromptSession(input=inp, output=DummyOutput()) + session: PromptSession[str] = PromptSession(input=inp, output=DummyOutput()) result = session.prompt(default="hello", accept_default=True) assert result == "hello" diff --git a/tests/test_document.py b/tests/test_document.py index ba65ffc83..26d216518 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -4,46 +4,46 @@ @pytest.fixture -def document(): +def document() -> Document: return Document( "line 1\n" + "line 2\n" + "line 3\n" + "line 4\n", len("line 1\n" + "lin") ) -def test_current_char(document): +def test_current_char(document: Document) -> None: assert document.current_char == "e" assert document.char_before_cursor == "n" -def test_text_before_cursor(document): +def test_text_before_cursor(document: Document) -> None: assert document.text_before_cursor == "line 1\nlin" -def test_text_after_cursor(document): +def test_text_after_cursor(document: Document) -> None: assert document.text_after_cursor == "e 2\n" + "line 3\n" + "line 4\n" -def test_lines(document): +def test_lines(document: Document) -> None: assert document.lines == ["line 1", "line 2", "line 3", "line 4", ""] -def test_line_count(document): +def test_line_count(document: Document) -> None: assert document.line_count == 5 -def test_current_line_before_cursor(document): +def test_current_line_before_cursor(document: Document) -> None: assert document.current_line_before_cursor == "lin" -def test_current_line_after_cursor(document): +def test_current_line_after_cursor(document: Document) -> None: assert document.current_line_after_cursor == "e 2" -def test_current_line(document): +def test_current_line(document: Document) -> None: assert document.current_line == "line 2" -def test_cursor_position(document): +def test_cursor_position(document: Document) -> None: assert document.cursor_position_row == 1 assert document.cursor_position_col == 3 @@ -52,7 +52,7 @@ def test_cursor_position(document): assert d.cursor_position_col == 0 -def test_translate_index_to_position(document): +def test_translate_index_to_position(document: Document) -> None: pos = document.translate_index_to_position(len("line 1\nline 2\nlin")) assert pos[0] == 2 @@ -62,6 +62,6 @@ def test_translate_index_to_position(document): assert pos == (0, 0) -def test_is_cursor_at_the_end(document): +def test_is_cursor_at_the_end(document: Document) -> None: assert Document("hello", 5).is_cursor_at_the_end assert not Document("hello", 4).is_cursor_at_the_end diff --git a/tests/test_filter.py b/tests/test_filter.py index e47b3b5cf..4bcffa7c6 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -3,15 +3,15 @@ from prompt_toolkit.filters import Always, Condition, Filter, Never, to_filter -def test_never(): +def test_never() -> None: assert not Never()() -def test_always(): +def test_always() -> None: assert Always()() -def test_invert(): +def test_invert() -> None: assert not (~Always())() assert ~Never()() @@ -19,7 +19,7 @@ def test_invert(): assert c() -def test_or(): +def test_or() -> None: for a in (True, False): for b in (True, False): c1 = Condition(lambda: a) @@ -30,7 +30,7 @@ def test_or(): assert c3() == a or b -def test_and(): +def test_and() -> None: for a in (True, False): for b in (True, False): c1 = Condition(lambda: a) @@ -41,7 +41,7 @@ def test_and(): assert c3() == (a and b) -def test_to_filter(): +def test_to_filter() -> None: f1 = to_filter(True) f2 = to_filter(False) f3 = to_filter(Condition(lambda: True)) @@ -57,4 +57,4 @@ def test_to_filter(): assert not f4() with pytest.raises(TypeError): - to_filter(4) + to_filter(4) # type: ignore diff --git a/tests/test_formatted_text.py b/tests/test_formatted_text.py index 8b4924f96..c568c8274 100644 --- a/tests/test_formatted_text.py +++ b/tests/test_formatted_text.py @@ -10,7 +10,7 @@ from prompt_toolkit.formatted_text.utils import split_lines -def test_basic_html(): +def test_basic_html() -> None: html = HTML("hello") assert to_formatted_text(html) == [("class:i", "hello")] @@ -31,7 +31,7 @@ def test_basic_html(): assert isinstance(to_formatted_text(html), FormattedText) -def test_html_with_fg_bg(): +def test_html_with_fg_bg() -> None: html = HTML('') assert to_formatted_text(html) == [ ("bg:ansired", "hello"), @@ -51,7 +51,7 @@ def test_html_with_fg_bg(): ] -def test_ansi_formatting(): +def test_ansi_formatting() -> None: value = ANSI("\x1b[32mHe\x1b[45mllo") assert to_formatted_text(value) == [ @@ -87,7 +87,7 @@ def test_ansi_formatting(): assert isinstance(to_formatted_text(value), FormattedText) -def test_ansi_256_color(): +def test_ansi_256_color() -> None: assert to_formatted_text(ANSI("\x1b[38;5;124mtest")) == [ ("#af0000", "t"), ("#af0000", "e"), @@ -96,7 +96,7 @@ def test_ansi_256_color(): ] -def test_ansi_true_color(): +def test_ansi_true_color() -> None: assert to_formatted_text(ANSI("\033[38;2;144;238;144m$\033[0;39;49m ")) == [ ("#90ee90", "$"), ("ansidefault bg:ansidefault", " "), diff --git a/tests/test_history.py b/tests/test_history.py index 07db8117e..35cf81500 100644 --- a/tests/test_history.py +++ b/tests/test_history.py @@ -1,14 +1,23 @@ +from typing import List + +import py + from prompt_toolkit.eventloop import get_event_loop -from prompt_toolkit.history import FileHistory, InMemoryHistory, ThreadedHistory +from prompt_toolkit.history import ( + FileHistory, + History, + InMemoryHistory, + ThreadedHistory, +) -def _call_history_load(history): +def _call_history_load(history: History) -> List[str]: """ Helper: Call the history "load" method and return the result as a list of strings. """ - result = [] + result: List[str] = [] - async def call_load(): + async def call_load() -> None: async for item in history.load(): result.append(item) @@ -16,7 +25,7 @@ async def call_load(): return result -def test_in_memory_history(): +def test_in_memory_history() -> None: history = InMemoryHistory() history.append_string("hello") history.append_string("world") @@ -35,10 +44,10 @@ def test_in_memory_history(): assert _call_history_load(history2) == ["def", "abc"] -def test_file_history(tmpdir): +def test_file_history(tmpdir: py.path.local) -> None: histfile = tmpdir.join("history") - history = FileHistory(histfile) + history = FileHistory(str(histfile)) history.append_string("hello") history.append_string("world") @@ -53,14 +62,14 @@ def test_file_history(tmpdir): assert _call_history_load(history) == ["test3", "world", "hello"] # Create another history instance pointing to the same file. - history2 = FileHistory(histfile) + history2 = FileHistory(str(histfile)) assert _call_history_load(history2) == ["test3", "world", "hello"] -def test_threaded_file_history(tmpdir): +def test_threaded_file_history(tmpdir: py.path.local) -> None: histfile = tmpdir.join("history") - history = ThreadedHistory(FileHistory(histfile)) + history = ThreadedHistory(FileHistory(str(histfile))) history.append_string("hello") history.append_string("world") @@ -75,11 +84,11 @@ def test_threaded_file_history(tmpdir): assert _call_history_load(history) == ["test3", "world", "hello"] # Create another history instance pointing to the same file. - history2 = ThreadedHistory(FileHistory(histfile)) + history2 = ThreadedHistory(FileHistory(str(histfile))) assert _call_history_load(history2) == ["test3", "world", "hello"] -def test_threaded_in_memory_history(): +def test_threaded_in_memory_history() -> None: # Threaded in memory history is not useful. But testing it anyway, just to # see whether everything plays nicely together. history = ThreadedHistory(InMemoryHistory()) diff --git a/tests/test_inputstream.py b/tests/test_inputstream.py index 8c3d8fd7c..de9e40257 100644 --- a/tests/test_inputstream.py +++ b/tests/test_inputstream.py @@ -1,28 +1,31 @@ +from typing import List + import pytest from prompt_toolkit.input.vt100_parser import Vt100Parser +from prompt_toolkit.key_binding.key_processor import KeyPress from prompt_toolkit.keys import Keys class _ProcessorMock: - def __init__(self): - self.keys = [] + def __init__(self) -> None: + self.keys: List[KeyPress] = [] - def feed_key(self, key_press): + def feed_key(self, key_press: KeyPress) -> None: self.keys.append(key_press) @pytest.fixture -def processor(): +def processor() -> _ProcessorMock: return _ProcessorMock() @pytest.fixture -def stream(processor): +def stream(processor: _ProcessorMock) -> Vt100Parser: return Vt100Parser(processor.feed_key) -def test_control_keys(processor, stream): +def test_control_keys(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x01\x02\x10") assert len(processor.keys) == 3 @@ -34,7 +37,7 @@ def test_control_keys(processor, stream): assert processor.keys[2].data == "\x10" -def test_arrows(processor, stream): +def test_arrows(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x1b[A\x1b[B\x1b[C\x1b[D") assert len(processor.keys) == 4 @@ -48,7 +51,7 @@ def test_arrows(processor, stream): assert processor.keys[3].data == "\x1b[D" -def test_escape(processor, stream): +def test_escape(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x1bhello") assert len(processor.keys) == 1 + len("hello") @@ -58,7 +61,7 @@ def test_escape(processor, stream): assert processor.keys[1].data == "h" -def test_special_double_keys(processor, stream): +def test_special_double_keys(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x1b[1;3D") # Should both send escape and left. assert len(processor.keys) == 2 @@ -68,7 +71,7 @@ def test_special_double_keys(processor, stream): assert processor.keys[1].data == "" -def test_flush_1(processor, stream): +def test_flush_1(processor: _ProcessorMock, stream: Vt100Parser) -> None: # Send left key in two parts without flush. stream.feed("\x1b") stream.feed("[D") @@ -78,7 +81,7 @@ def test_flush_1(processor, stream): assert processor.keys[0].data == "\x1b[D" -def test_flush_2(processor, stream): +def test_flush_2(processor: _ProcessorMock, stream: Vt100Parser) -> None: # Send left key with a 'Flush' in between. # The flush should make sure that we process everything before as-is, # with makes the first part just an escape character instead. @@ -96,7 +99,7 @@ def test_flush_2(processor, stream): assert processor.keys[2].data == "D" -def test_meta_arrows(processor, stream): +def test_meta_arrows(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x1b\x1b[D") assert len(processor.keys) == 2 @@ -104,7 +107,7 @@ def test_meta_arrows(processor, stream): assert processor.keys[1].key == Keys.Left -def test_control_square_close(processor, stream): +def test_control_square_close(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("\x1dC") assert len(processor.keys) == 2 @@ -112,7 +115,7 @@ def test_control_square_close(processor, stream): assert processor.keys[1].key == "C" -def test_invalid(processor, stream): +def test_invalid(processor: _ProcessorMock, stream: Vt100Parser) -> None: # Invalid sequence that has at two characters in common with other # sequences. stream.feed("\x1b[*") @@ -123,7 +126,7 @@ def test_invalid(processor, stream): assert processor.keys[2].key == "*" -def test_cpr_response(processor, stream): +def test_cpr_response(processor: _ProcessorMock, stream: Vt100Parser) -> None: stream.feed("a\x1b[40;10Rb") assert len(processor.keys) == 3 assert processor.keys[0].key == "a" @@ -131,7 +134,7 @@ def test_cpr_response(processor, stream): assert processor.keys[2].key == "b" -def test_cpr_response_2(processor, stream): +def test_cpr_response_2(processor: _ProcessorMock, stream: Vt100Parser) -> None: # Make sure that the newline is not included in the CPR response. stream.feed("\x1b[40;1R\n") assert len(processor.keys) == 2 diff --git a/tests/test_layout.py b/tests/test_layout.py index 8a0826d33..9afb7e800 100644 --- a/tests/test_layout.py +++ b/tests/test_layout.py @@ -5,7 +5,7 @@ from prompt_toolkit.layout.controls import BufferControl -def test_layout_class(): +def test_layout_class() -> None: c1 = BufferControl() c2 = BufferControl() c3 = BufferControl() @@ -46,6 +46,6 @@ def test_layout_class(): assert layout.previous_control == c1 -def test_create_invalid_layout(): +def test_create_invalid_layout() -> None: with pytest.raises(InvalidLayoutError): Layout(HSplit([])) diff --git a/tests/test_regular_languages.py b/tests/test_regular_languages.py index 7404b231a..2cfe37dfd 100644 --- a/tests/test_regular_languages.py +++ b/tests/test_regular_languages.py @@ -1,3 +1,5 @@ +from typing import Iterator + from prompt_toolkit.completion import CompleteEvent, Completer, Completion from prompt_toolkit.contrib.regular_languages import compile from prompt_toolkit.contrib.regular_languages.compiler import Match, Variables @@ -5,7 +7,7 @@ from prompt_toolkit.document import Document -def test_simple_match(): +def test_simple_match() -> None: g = compile("hello|world") m = g.match("hello") @@ -18,32 +20,35 @@ def test_simple_match(): assert m is None -def test_variable_varname(): +def test_variable_varname() -> None: """ Test `Variable` with varname. """ g = compile("((?Phello|world)|test)") m = g.match("hello") + assert m is not None variables = m.variables() assert isinstance(variables, Variables) assert variables.get("varname") == "hello" assert variables["varname"] == "hello" m = g.match("world") + assert m is not None variables = m.variables() assert isinstance(variables, Variables) assert variables.get("varname") == "world" assert variables["varname"] == "world" m = g.match("test") + assert m is not None variables = m.variables() assert isinstance(variables, Variables) assert variables.get("varname") is None assert variables["varname"] is None -def test_prefix(): +def test_prefix() -> None: """ Test `match_prefix`. """ @@ -65,22 +70,32 @@ def test_prefix(): assert isinstance(m, Match) m = g.match_prefix("no-match") - assert m.trailing_input().start == 0 - assert m.trailing_input().stop == len("no-match") + assert m is not None + match_variable = m.trailing_input() + assert match_variable is not None + assert match_variable.start == 0 + assert match_variable.stop == len("no-match") m = g.match_prefix("hellotest") - assert m.trailing_input().start == len("hello") - assert m.trailing_input().stop == len("hellotest") + assert m is not None + match_variable = m.trailing_input() + assert match_variable is not None + assert match_variable.start == len("hello") + assert match_variable.stop == len("hellotest") -def test_completer(): +def test_completer() -> None: class completer1(Completer): - def get_completions(self, document, complete_event): + def get_completions( + self, document: Document, complete_event: CompleteEvent + ) -> Iterator[Completion]: yield Completion("before-%s-after" % document.text, -len(document.text)) yield Completion("before-%s-after-B" % document.text, -len(document.text)) class completer2(Completer): - def get_completions(self, document, complete_event): + def get_completions( + self, document: Document, complete_event: CompleteEvent + ) -> Iterator[Completion]: yield Completion("before2-%s-after2" % document.text, -len(document.text)) yield Completion("before2-%s-after2-B" % document.text, -len(document.text)) diff --git a/tests/test_shortcuts.py b/tests/test_shortcuts.py index 10ee73a20..4b58a28d8 100644 --- a/tests/test_shortcuts.py +++ b/tests/test_shortcuts.py @@ -1,12 +1,13 @@ +from prompt_toolkit.formatted_text import StyleAndTextTuples from prompt_toolkit.shortcuts import print_container from prompt_toolkit.shortcuts.prompt import _split_multiline_prompt from prompt_toolkit.shortcuts.utils import print_container from prompt_toolkit.widgets import Frame, TextArea -def test_split_multiline_prompt(): +def test_split_multiline_prompt() -> None: # Test 1: no newlines: - tokens = [("class:testclass", "ab")] + tokens: StyleAndTextTuples = [("class:testclass", "ab")] has_before_tokens, before, first_input_line = _split_multiline_prompt( lambda: tokens ) diff --git a/tests/test_style.py b/tests/test_style.py index e78373419..d7c4c97bf 100644 --- a/tests/test_style.py +++ b/tests/test_style.py @@ -1,7 +1,7 @@ from prompt_toolkit.styles import Attrs, Style, SwapLightAndDarkStyleTransformation -def test_style_from_dict(): +def test_style_from_dict() -> None: style = Style.from_dict( { "a": "#ff0000 bold underline strike italic", @@ -79,7 +79,7 @@ def test_style_from_dict(): assert style.get_attrs_for_style_str("#00ff00 class:a") == expected -def test_class_combinations_1(): +def test_class_combinations_1() -> None: # In this case, our style has both class 'a' and 'b'. # Given that the style for 'a b' is defined at the end, that one is used. style = Style( @@ -109,7 +109,7 @@ def test_class_combinations_1(): assert style.get_attrs_for_style_str("class:b,a") == expected -def test_class_combinations_2(): +def test_class_combinations_2() -> None: # In this case, our style has both class 'a' and 'b'. # The style that is defined the latest get priority. style = Style( @@ -150,7 +150,7 @@ def test_class_combinations_2(): assert style.get_attrs_for_style_str("class:b,a") == expected -def test_substyles(): +def test_substyles() -> None: style = Style( [ ("a.b", "#ff0000 bold"), @@ -218,7 +218,7 @@ def test_substyles(): assert style.get_attrs_for_style_str("class:b.c.d") == expected -def test_swap_light_and_dark_style_transformation(): +def test_swap_light_and_dark_style_transformation() -> None: transformation = SwapLightAndDarkStyleTransformation() # Test with 6 digit hex colors. diff --git a/tests/test_style_transformation.py b/tests/test_style_transformation.py index 1193649e3..566a068fc 100644 --- a/tests/test_style_transformation.py +++ b/tests/test_style_transformation.py @@ -4,7 +4,7 @@ @pytest.fixture -def default_attrs(): +def default_attrs() -> Attrs: return Attrs( color="", bgcolor="", @@ -18,7 +18,7 @@ def default_attrs(): ) -def test_adjust_brightness_style_transformation(default_attrs): +def test_adjust_brightness_style_transformation(default_attrs: Attrs) -> None: tr = AdjustBrightnessStyleTransformation(0.5, 1.0) attrs = tr.transform_attrs(default_attrs._replace(color="ff0000")) diff --git a/tests/test_utils.py b/tests/test_utils.py index 6a1c17955..12b730843 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,12 +1,13 @@ import itertools +from typing import Iterator, List import pytest from prompt_toolkit.utils import take_using_weights -def test_using_weights(): - def take(generator, count): +def test_using_weights() -> None: + def take(generator: Iterator[str], count: int) -> List[str]: return list(itertools.islice(generator, 0, count)) # Check distribution. diff --git a/tests/test_vt100_output.py b/tests/test_vt100_output.py index f7163da83..ba3825af0 100644 --- a/tests/test_vt100_output.py +++ b/tests/test_vt100_output.py @@ -1,7 +1,7 @@ from prompt_toolkit.output.vt100 import _get_closest_ansi_color -def test_get_closest_ansi_color(): +def test_get_closest_ansi_color() -> None: # White assert _get_closest_ansi_color(255, 255, 255) == "ansiwhite" assert _get_closest_ansi_color(250, 250, 250) == "ansiwhite" diff --git a/tests/test_widgets.py b/tests/test_widgets.py index bf89a2581..07068c06d 100644 --- a/tests/test_widgets.py +++ b/tests/test_widgets.py @@ -1,18 +1,19 @@ from prompt_toolkit.formatted_text import fragment_list_to_text -from prompt_toolkit.layout import to_window +from prompt_toolkit.layout import FormattedTextControl, to_window from prompt_toolkit.widgets import Button def _to_text(button: Button) -> str: - control = to_window(button).content - return fragment_list_to_text(control.text()) + control = to_window(button) + assert isinstance(control, FormattedTextControl) + return fragment_list_to_text(control.content.text()) -def test_defaulf_button(): +def test_defaulf_button() -> None: button = Button("Exit") assert _to_text(button) == "< Exit >" -def test_custom_button(): +def test_custom_button() -> None: button = Button("Exit", left_symbol="[", right_symbol="]") assert _to_text(button) == "[ Exit ]" diff --git a/tests/test_yank_nth_arg.py b/tests/test_yank_nth_arg.py index edd3f2f59..c65a70e95 100644 --- a/tests/test_yank_nth_arg.py +++ b/tests/test_yank_nth_arg.py @@ -1,11 +1,11 @@ import pytest from prompt_toolkit.buffer import Buffer -from prompt_toolkit.history import InMemoryHistory +from prompt_toolkit.history import History, InMemoryHistory @pytest.fixture -def _history(): +def _history() -> InMemoryHistory: "Prefilled history." history = InMemoryHistory() history.append_string("alpha beta gamma delta") @@ -16,45 +16,45 @@ def _history(): # Test yank_last_arg. -def test_empty_history(): +def test_empty_history() -> None: buf = Buffer() buf.yank_last_arg() assert buf.document.current_line == "" -def test_simple_search(_history): +def test_simple_search(_history: History) -> None: buff = Buffer(history=_history) buff.yank_last_arg() assert buff.document.current_line == "four" -def test_simple_search_with_quotes(_history): +def test_simple_search_with_quotes(_history: History) -> None: _history.append_string("""one two "three 'x' four"\n""") buff = Buffer(history=_history) buff.yank_last_arg() assert buff.document.current_line == '''"three 'x' four"''' -def test_simple_search_with_arg(_history): +def test_simple_search_with_arg(_history: History) -> None: buff = Buffer(history=_history) buff.yank_last_arg(n=2) assert buff.document.current_line == "three" -def test_simple_search_with_arg_out_of_bounds(_history): +def test_simple_search_with_arg_out_of_bounds(_history: History) -> None: buff = Buffer(history=_history) buff.yank_last_arg(n=8) assert buff.document.current_line == "" -def test_repeated_search(_history): +def test_repeated_search(_history: History) -> None: buff = Buffer(history=_history) buff.yank_last_arg() buff.yank_last_arg() assert buff.document.current_line == "delta" -def test_repeated_search_with_wraparound(_history): +def test_repeated_search_with_wraparound(_history: History) -> None: buff = Buffer(history=_history) buff.yank_last_arg() buff.yank_last_arg() @@ -65,20 +65,20 @@ def test_repeated_search_with_wraparound(_history): # Test yank_last_arg. -def test_yank_nth_arg(_history): +def test_yank_nth_arg(_history: History) -> None: buff = Buffer(history=_history) buff.yank_nth_arg() assert buff.document.current_line == "two" -def test_repeated_yank_nth_arg(_history): +def test_repeated_yank_nth_arg(_history: History) -> None: buff = Buffer(history=_history) buff.yank_nth_arg() buff.yank_nth_arg() assert buff.document.current_line == "beta" -def test_yank_nth_arg_with_arg(_history): +def test_yank_nth_arg_with_arg(_history: History) -> None: buff = Buffer(history=_history) buff.yank_nth_arg(n=2) assert buff.document.current_line == "three"