Beim Versuch, eine Urwid-basierte Frage mit Eingabevalidierung und automatischen Vorschlägen zu testen, habe ich einige Schwierigkeiten. Der Code, den ich mit PyTest testen möchte
from typing import List
import urwid
from typeguard import typechecked
from tui_labeller.file_read_write_helper import write_to_file
@typechecked
def get_filtered_suggestions(
*, input_text: str, available_suggestions: List[str]
) -> List[str]:
"""
Filter suggestions based on input text, matching from start with wildcard support.
Special case: '*' alone shows all available suggestions.
Args:
input_text (str): The text entered by user, can include '*' as wildcard
available_suggestions (list): List of possible suggestion strings
Returns:
list: Filtered suggestions based on input criteria
"""
input_text = input_text.strip()
# Special case: if input is '*', return all suggestions
if input_text == "*":
return available_suggestions
# If no input, return all suggestions
if not input_text:
return available_suggestions
# Handle wildcard case
if "*" in input_text:
# Split input by wildcard
parts = input_text.lower().split("*")
prefix = parts[0] # What comes before the wildcard
# Filter suggestions
filtered = [
suggestion
for suggestion in available_suggestions
if suggestion.lower().startswith(prefix)
and all(part in suggestion.lower() for part in parts[1:] if part)
]
else:
# Original filtering for non-wildcard case
filtered = [
suggestion
for suggestion in available_suggestions
if suggestion.lower().startswith(input_text.lower())
]
# If no matches found, return ['-']
return filtered if filtered else ["-"]
class InputValidationQuestion(urwid.Edit):
def __init__(
self, caption, suggestions=None, autocomplete_box=None, pile=None
):
super().__init__(caption=caption)
self.suggestions = suggestions or []
self.autocomplete_box = autocomplete_box
self.pile = pile
self._in_autocomplete: bool = False
def handle_autocomplete(self, key, size):
"""Handle autocomplete logic based on input key and suggestions.
Args:
key: The pressed key
size: The size parameter for keypress
Returns:
The result of keypress or None if handled
Raises:
ValueError: When autocomplete conditions aren't met
"""
if not self.suggestions:
write_to_file(
filename="eg.txt",
content=f"self.suggestions={self.suggestions}",
append=True,
)
return super().keypress(size, key)
# Handle automatic substitution when '*' yields single match
if "*" in self.edit_text:
matches = [s for s in self.suggestions if self._match_pattern(s)]
if len(matches) == 1:
self.set_edit_text(matches[0])
self.owner.set_attr_map({None: "normal"})
write_to_file(
filename="eg.txt",
content=f"self.edit_text={self.edit_text}",
append=True,
)
return None
elif len(matches) == 0:
raise ValueError("No matches found for pattern")
# TODO: do stuff here.
# If multiple matches, continue to tab handling
# Handle tab key press
if key == "tab":
matches = [s for s in self.suggestions if self._match_pattern(s)]
if len(matches) == 1:
self.set_edit_text(matches[0])
self.owner.set_attr_map({None: "normal"})
return None
elif len(matches) == 0:
raise ValueError("No matching suggestion found")
else:
raise ValueError("Multiple ambiguous suggestions available")
return super().keypress(size, key)
def valid_char(self, ch):
return len(ch) == 1 and (ch.isalpha() or ch in [":", "*"])
def keypress(self, size, key):
write_to_file(
filename="eg.txt",
content=f"key={key}, self.edit_text={self.edit_text}",
append=True,
)
if key in ["tab", "*"]:
return self.handle_autocomplete(key, size)
elif key == "enter":
return "enter"
elif key in ("up", "down"):
if self.pile:
current_pos = self.pile.focus_position
new_pos = current_pos - 1 if key == "up" else current_pos + 1
if 0
InputValidationquestions.py:
import urwid
from tui_labeller.file_read_write_helper import write_to_file
from tui_labeller.tuis.urwid.InputValidationQuestion import (
InputValidationQuestion,
)
class InputValidationQuestions:
def __init__(self):
self.questions = [
("Question 1: ", ["apple", "apricot", "avocado"]),
("Question 2: ", ["banana", "blueberry", "blackberry"]),
("Question 3: ", ["cat", "caterpillar", "cactus"]),
]
self.palette = [
("normal", "white", "black"),
("highlight", "white", "dark red"),
("autocomplete", "yellow", "dark blue"),
]
self.autocomplete_box = urwid.AttrMap(
urwid.Text("", align="left"), "autocomplete"
)
self.pile = urwid.Pile([])
self.inputs = []
for question, suggestions in self.questions:
edit = InputValidationQuestion(
question, suggestions, self.autocomplete_box, self.pile
)
attr_edit = urwid.AttrMap(edit, "normal")
edit.owner = attr_edit
self.inputs.append(attr_edit)
self.pile.contents = [
(self.inputs[0], ("pack", None)),
(self.inputs[1], ("pack", None)),
(self.inputs[2], ("pack", None)),
(urwid.Divider(), ("pack", None)),
(
urwid.Columns(
[(30, urwid.Text("Autocomplete: ")), self.autocomplete_box]
),
("pack", None),
),
]
self.fill = urwid.Filler(self.pile, valign="top")
self.loop = urwid.MainLoop(
self.fill, self.palette, unhandled_input=self.handle_input
)
def handle_input(self, key):
print(f"Unhandled input: {key}")
write_to_file(
filename="eg.txt", content=f"Unhandled input: {key}", append=False
)
# TODO: if cursor is at the first question and up is pressed, go to last question.
# TODO: if cursor is at the last question and down is pressed, go to first question.
raise ValueError(f"STOPPED at:{key}")
def run(self):
def update_autocomplete(widget, new_text):
widget.update_autocomplete()
for input_widget in self.inputs:
urwid.connect_signal(
input_widget.base_widget, "change", update_autocomplete
)
if self.inputs:
self.pile.focus_position = 0
self.inputs[0].base_widget.update_autocomplete()
self.loop.run()
< /code>
Diese werden mit: < /p>
ausgeführt.from typeguard import typechecked
from src.tui_labeller.tuis.urwid.InputValidationQuestions import (
InputValidationQuestions,
)
app = InputValidationQuestions()
app.run()
Erwartete Verhalten
Die Klasse verhandelt inkrementelle Eingaben (z. B. tippt "a, v, " Select "Avocado") in einem Tui -App mit Python -m Src.tui_labeller -i -o -tur -Tuwid . Im realen Lauf wirkt "A, V, " und drücken Sie die Eingabetaste ein ValueError: Stopp bei: Enter , was erwartet wird/fein. Verarbeitung.
import urwid
import pytest
from tui_labeller.tuis.urwid.SUBSTITUECLASSHERE import SUBSTITUECLASSHERE
@pytest.fixture
def app():
app = SUBSTITUECLASSHERE()
app.loop.screen = urwid.raw_display.Screen()
return app
def test_avocado_selection(app):
input_sequence = ["a", "v", "*"]
for key in input_sequence:
app.loop.process_input([key])
if hasattr(app.loop, "unhandled_input") and app.loop.unhandled_input:
app.loop.unhandled_input(key)
# How to check "avocado" is selected? Edit widget, ListBox, or custom attribute?
def test_enter_error_handling(app):
input_sequence = ["a", "v", "*", "enter"]
with pytest.raises(ValueError, match="STOPPED at:enter"):
for key in input_sequence:
app.loop.process_input([key])
if hasattr(app.loop, "unhandled_input") and app.loop.unhandled_input:
app.loop.unhandled_input(key)
< /code>
Der Test schlägt fehl mit: < /p>
ValueError: STOPPED at:a
AssertionError: Regex pattern 'STOPPED at:enter' did not match 'STOPPED at:a'
Frage
Wie modifiziere ich den Test an:
[*] Prozess "a, v,*", um "Avocado" ohne frühes Erhäuerungsfehler auszuwählen,
Verifizieren Sie die Selektion (was Widget/Attribut hält es.>
Beim Versuch, eine Urwid-basierte Frage mit Eingabevalidierung und automatischen Vorschlägen zu testen, habe ich einige Schwierigkeiten. Der Code, den ich mit PyTest testen möchte[code]from typing import List
import urwid from typeguard import typechecked
from tui_labeller.file_read_write_helper import write_to_file
@typechecked def get_filtered_suggestions( *, input_text: str, available_suggestions: List[str] ) -> List[str]: """ Filter suggestions based on input text, matching from start with wildcard support. Special case: '*' alone shows all available suggestions.
Args: input_text (str): The text entered by user, can include '*' as wildcard available_suggestions (list): List of possible suggestion strings
Returns: list: Filtered suggestions based on input criteria """ input_text = input_text.strip()
# Special case: if input is '*', return all suggestions if input_text == "*": return available_suggestions
# If no input, return all suggestions if not input_text: return available_suggestions
# Handle wildcard case if "*" in input_text: # Split input by wildcard parts = input_text.lower().split("*") prefix = parts[0] # What comes before the wildcard
# Filter suggestions filtered = [ suggestion for suggestion in available_suggestions if suggestion.lower().startswith(prefix) and all(part in suggestion.lower() for part in parts[1:] if part) ] else: # Original filtering for non-wildcard case filtered = [ suggestion for suggestion in available_suggestions if suggestion.lower().startswith(input_text.lower()) ]
# If no matches found, return ['-'] return filtered if filtered else ["-"]
def handle_autocomplete(self, key, size): """Handle autocomplete logic based on input key and suggestions.
Args: key: The pressed key size: The size parameter for keypress Returns: The result of keypress or None if handled Raises: ValueError: When autocomplete conditions aren't met """ if not self.suggestions: write_to_file( filename="eg.txt", content=f"self.suggestions={self.suggestions}", append=True, ) return super().keypress(size, key)
# Handle automatic substitution when '*' yields single match if "*" in self.edit_text: matches = [s for s in self.suggestions if self._match_pattern(s)] if len(matches) == 1: self.set_edit_text(matches[0]) self.owner.set_attr_map({None: "normal"}) write_to_file( filename="eg.txt", content=f"self.edit_text={self.edit_text}", append=True, ) return None elif len(matches) == 0: raise ValueError("No matches found for pattern") # TODO: do stuff here. # If multiple matches, continue to tab handling
# Handle tab key press if key == "tab": matches = [s for s in self.suggestions if self._match_pattern(s)]
def handle_input(self, key): print(f"Unhandled input: {key}") write_to_file( filename="eg.txt", content=f"Unhandled input: {key}", append=False ) # TODO: if cursor is at the first question and up is pressed, go to last question.
# TODO: if cursor is at the last question and down is pressed, go to first question. raise ValueError(f"STOPPED at:{key}")
for input_widget in self.inputs: urwid.connect_signal( input_widget.base_widget, "change", update_autocomplete )
if self.inputs: self.pile.focus_position = 0 self.inputs[0].base_widget.update_autocomplete()
self.loop.run()
< /code> Diese werden mit: < /p> ausgeführt.from typeguard import typechecked
from src.tui_labeller.tuis.urwid.InputValidationQuestions import ( InputValidationQuestions, )
app = InputValidationQuestions() app.run() [/code] Erwartete Verhalten Die Klasse verhandelt inkrementelle Eingaben (z. B. tippt "a, v, " Select "Avocado") in einem Tui -App mit Python -m Src.tui_labeller -i -o -tur -Tuwid . Im realen Lauf wirkt "A, V, " und drücken Sie die Eingabetaste ein ValueError: Stopp bei: Enter , was erwartet wird/fein. Verarbeitung.[code]import urwid import pytest from tui_labeller.tuis.urwid.SUBSTITUECLASSHERE import SUBSTITUECLASSHERE @pytest.fixture def app(): app = SUBSTITUECLASSHERE() app.loop.screen = urwid.raw_display.Screen() return app def test_avocado_selection(app): input_sequence = ["a", "v", "*"] for key in input_sequence: app.loop.process_input([key]) if hasattr(app.loop, "unhandled_input") and app.loop.unhandled_input: app.loop.unhandled_input(key) # How to check "avocado" is selected? Edit widget, ListBox, or custom attribute? def test_enter_error_handling(app): input_sequence = ["a", "v", "*", "enter"] with pytest.raises(ValueError, match="STOPPED at:enter"): for key in input_sequence: app.loop.process_input([key]) if hasattr(app.loop, "unhandled_input") and app.loop.unhandled_input: app.loop.unhandled_input(key) < /code> Der Test schlägt fehl mit: < /p> ValueError: STOPPED at:a AssertionError: Regex pattern 'STOPPED at:enter' did not match 'STOPPED at:a' [/code] Frage Wie modifiziere ich den Test an:
[*] Prozess "a, v,*", um "Avocado" ohne frühes Erhäuerungsfehler auszuwählen, Verifizieren Sie die Selektion (was Widget/Attribut hält es.>
Ich habe dieses kleine Chase -Spiel mit dem gesegneten Modul geschrieben. Während des Schreibens habe ich es mit urxvt getestet. Es funktioniert genau, wie ich in diesem Terminalemulator möchte. Wenn...
Ich versuche, einen Spring -Boot -Controller zu testen, der Controller hat eine UserService Abhängigkeit und der UserService hat eine UserMapper Abhängigkeit, der Code kompilt und läuft makellose,...
Ich habe ein Problem mit meinem Spring Boot-Integrationstest mit @MockMvc. Wenn ich den Test ausführe, schlagen die jsonPath-Behauptungen fehl, weil der Antworttext ($) nichts enthält.
package...
Ich habe ein Problem mit meinem Spring Boot-Integrationstest mit @MockMvc. Wenn ich den Test ausführe, schlagen die jsonPath-Behauptungen fehl, weil der Antworttext ($) nichts enthält.
package...
In Java habe ich einen Web -Schaber geschrieben. Die Zielwebsite ist sehr dynamisch, was es sehr schwierig macht, einen Test für meinen Web -Schaber zu schreiben. Die Website ist ein https ( Ich habe...