resolved RESOLVED PASS · 8 tool calls · 76 s · Textualize/rich
Fix raw markup printed on prompt errors sometimes ## Type of changes - [x] Bug fix - [ ] New feature - [ ] Documentation / docstrings - [ ] Tests - [ ] Other ## Checklist - [x] I've run the latest [black](https://github.com/psf/black) with default args on new code. - [ ] I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate (see note about typos above). - [x] I've added tests for new code. - [x] I accept that @willmcgugan may be pedantic in the code review. ## Description PromptBase.on_validate_error() should explicitly ask for markup in case the console passed to it has markup disabled globally. Fixes #3881.
| # | Tool | Arguments | Result |
|---|---|---|---|
| 1 | run_command | {
"command": "grep -rn \"PromptBase.on_validate_error\" ."
} | {"status": "error", "error_type": "CommandError", "error_message": "", "details": {"stdout": "", "stderr": "", "exit_code": 1}}full{"status": "error", "error_type": "CommandError", "error_message": "", "details": {"stdout": "", "stderr": "", "exit_code": 1}} |
| 2 | run_command | {
"command": "grep -rn \"on_validate_error\" ."
} | {"status": "ok", "stdout": "./rich/prompt.py:258: def on_validate_error(self, value: str, error: InvalidResponse) -> None:\n./rich/prompt.py:298: self.on_validafull{"status": "ok", "stdout": "./rich/prompt.py:258: def on_validate_error(self, value: str, error: InvalidResponse) -> None:\n./rich/prompt.py:298: self.on_validate_error(value, error)\n", "stderr": "", "exit_code": 0} |
| 3 | run_command | {
"command": "sed -n '250,270p' rich/prompt.py"
} | {"status": "ok", "stdout": " # return the original choice, not the lower case version\n return_value = self.response_type(\n self.choices[\n [choice.lower() forfull{"status": "ok", "stdout": " # return the original choice, not the lower case version\n return_value = self.response_type(\n self.choices[\n [choice.lower() for choice in self.choices].index(value.lower())\n ]\n )\n return return_value\n\n def on_validate_error(self, value: str, error: InvalidResponse) -> None:\n \"\"\"Called to handle validation error.\n\n Args:\n value (str): String entered by user.\n error (InvalidResponse): Exception instance the initiated the error.\n \"\"\"\n self.console.print(error)\n\n def pre_prompt(self) -> None:\n \"\"\"Hook to display something before the prompt.\"\"\"\n\n @overload\n", "stderr": "", "exit_code": 0} |
| 4 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom rich.console import Console\nfrom rich.prompt import Prompt\nfrom rich.errors import InvalidResponse\n\ndef test_prompt_validation_error_markup():\n # Create a console with markup disabled globally\n console = Console(markup=False)\n prompt = Prompt(\"Enter something\", console=console)\n \n # We want to simulate on_validate_error. \n # In Prompt, validation is usually handled by the subclass or if a validator is provided.\n # However, the issue specifically mentions PromptBase.on_validate_error().\n # Let's check if we can trigger it or just test the method directly.\n \n # Mock the error with markup\n error_msg = \"[red]Invalid input![/red]\"\n error = InvalidResponse(error_msg)\n \n # Capture output\n from io import StringIO\n import sys\n \n captured_output = StringIO()\n original_stdout = sys.stdout\n sys.stdout = captured_output\n \n try:\n prompt.on_validate_error(\"wrong value\", error)\n finally:\n sys.stdout = original_stdout\n \n output = captured_output.getvalue()\n print(f\"Output: {repr(output)}\")\n if \"[red]Invalid input![/red]\" in output:\n print(\"FAILED: Markup was printed raw\")\n else:\n print(\"SUCCESS: Markup was processed (or at least not printed raw)\")\n\ntest_prompt_validation_error_markup()\nPY\n"
} | {"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"<stdin>\", line 3, in <module>\nImportError: canfull{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"<stdin>\", line 3, in <module>\nImportError: cannot import name 'InvalidResponse' from 'rich.errors' (/private/workspace/rich/errors.py)\n", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n File \"<stdin>\", line 3, in <module>\nImportError: cannot import name 'InvalidResponse' from 'rich.errors' (/private/workspace/rich/errors.py)\n", "exit_code": 1}} |
| 5 | run_command | {
"command": "grep -rn \"class InvalidResponse\" ."
} | {"status": "ok", "stdout": "./rich/prompt.py:15:class InvalidResponse(PromptError):\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "./rich/prompt.py:15:class InvalidResponse(PromptError):\n", "stderr": "", "exit_code": 0} |
| 6 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom rich.console import Console\nfrom rich.prompt import Prompt, InvalidResponse\nimport sys\nfrom io import StringIO\n\ndef test_prompt_validation_error_markup():\n # Create a console with markup disabled globally\n console = Console(markup=False)\n prompt = Prompt(\"Enter something\", console=console)\n \n # Mock the error with markup\n error_msg = \"[red]Invalid input![/red]\"\n error = InvalidResponse(error_msg)\n \n # Capture output\n captured_output = StringIO()\n original_stdout = sys.stdout\n sys.stdout = captured_output\n \n try:\n prompt.on_validate_error(\"wrong value\", error)\n finally:\n sys.stdout = original_stdout\n \n output = captured_output.getvalue()\n print(f\"Output: {repr(output)}\")\n # If markup=False in Console, console.print(error) normally prints the string as is.\n # If we want it to be processed as markup, we need console.print(error, markup=True)\n if \"[red]Invalid input![/red]\" in output:\n print(\"FAILED: Markup was printed raw\")\n else:\n print(\"SUCCESS: Markup was processed\")\n\ntest_prompt_validation_error_markup()\nPY\n"
} | {"status": "ok", "stdout": "Output: '[red]Invalid input![/red]\\n'\nFAILED: Markup was printed raw\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "Output: '[red]Invalid input![/red]\\n'\nFAILED: Markup was printed raw\n", "stderr": "", "exit_code": 0} |
| 7 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"rich/prompt.py\")\ns = p.read_text()\nold = \"\"\" def on_validate_error(self, value: str, error: InvalidResponse) -> None:\n \\\"\\\"\\\"Called to handle validation error.\n\n Args:\n value (str): String entered by user.\n error (InvalidResponse): Exception instance the initiated the error.\n \\\"\\\"\\\"\n self.console.print(error)\"\"\"\nnew = \"\"\" def on_validate_error(self, value: str, error: InvalidResponse) -> None:\n \\\"\\\"\\\"Called to handle validation error.\n\n Args:\n value (str): String entered by user.\n error (InvalidResponse): Exception instance the initiated the error.\n \\\"\\\"\\\"\n self.console.print(error, markup=True)\"\"\"\nassert s.count(old) == 1, (\"old text found this many times:\", s.count(old))\nt = s.replace(old, new)\np.write_text(t)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 8 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom rich.console import Console\nfrom rich.prompt import Prompt, InvalidResponse\nimport sys\nfrom io import StringIO\n\ndef test_prompt_validation_error_markup():\n # Create a console with markup disabled globally\n console = Console(markup=False)\n prompt = Prompt(\"Enter something\", console=console)\n \n # Mock the error with markup\n error_msg = \"[red]Invalid input![/red]\"\n error = InvalidResponse(error_msg)\n \n # Capture output\n captured_output = StringIO()\n original_stdout = sys.stdout\n sys.stdout = captured_output\n \n try:\n prompt.on_validate_error(\"wrong value\", error)\n finally:\n sys.stdout = original_stdout\n \n output = captured_output.getvalue()\n print(f\"Output: {repr(output)}\")\n # Now that we added markup=True, the [red] tags should be processed\n # and converted to ANSI escape codes, NOT printed as raw text.\n if \"[red]Invalid input![/red]\" in output:\n print(\"FAILED: Markup was printed raw\")\n else:\n print(\"SUCCESS: Markup was processed\")\n\ntest_prompt_validation_error_markup()\nPY\n"
} | {"status": "ok", "stdout": "Output: 'Invalid input!\\n'\nSUCCESS: Markup was processed\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "Output: 'Invalid input!\\n'\nSUCCESS: Markup was processed\n", "stderr": "", "exit_code": 0} |
| 9 | submit_patch | {} | {"status": "ok", "patch_size": 503, "files_changed": 1}full{"status": "ok", "patch_size": 503, "files_changed": 1} |
diff --git a/rich/prompt.py b/rich/prompt.py
index c7cf25ba..ae94d9bb 100644
--- a/rich/prompt.py
+++ b/rich/prompt.py
@@ -262,7 +262,7 @@ class PromptBase(Generic[PromptType]):
value (str): String entered by user.
error (InvalidResponse): Exception instance the initiated the error.
"""
- self.console.print(error)
+ self.console.print(error, markup=True)
def pre_prompt(self) -> None:
"""Hook to display something before the prompt."""
........ [100%] 8 passed in 0.11s