diff options
Diffstat (limited to 'pw_console/py')
-rw-r--r-- | pw_console/py/BUILD.bazel | 1 | ||||
-rw-r--r-- | pw_console/py/BUILD.gn | 1 | ||||
-rw-r--r-- | pw_console/py/pw_console/console_prefs.py | 2 | ||||
-rw-r--r-- | pw_console/py/pw_console/html/main.js | 2 | ||||
-rw-r--r-- | pw_console/py/pw_console/pw_ptpython_repl.py | 79 | ||||
-rw-r--r-- | pw_console/py/setup.cfg | 4 |
6 files changed, 73 insertions, 16 deletions
diff --git a/pw_console/py/BUILD.bazel b/pw_console/py/BUILD.bazel index 9fdeebd91..b5a7b87ab 100644 --- a/pw_console/py/BUILD.bazel +++ b/pw_console/py/BUILD.bazel @@ -100,6 +100,7 @@ py_library( ":event_count_history", ":pyserial_wrapper", "//pw_cli/py:pw_cli", + "//pw_config_loader/py:pw_config_loader", "//pw_log_tokenized/py:pw_log_tokenized", "@python_packages_jinja2//:pkg", "@python_packages_prompt_toolkit//:pkg", diff --git a/pw_console/py/BUILD.gn b/pw_console/py/BUILD.gn index 3683004d5..7f5758011 100644 --- a/pw_console/py/BUILD.gn +++ b/pw_console/py/BUILD.gn @@ -94,6 +94,7 @@ pw_python_package("py") { ] python_deps = [ "$dir_pw_cli/py", + "$dir_pw_config_loader/py", "$dir_pw_log_tokenized/py", ] inputs = [ diff --git a/pw_console/py/pw_console/console_prefs.py b/pw_console/py/pw_console/console_prefs.py index 966d6ba21..05f821874 100644 --- a/pw_console/py/pw_console/console_prefs.py +++ b/pw_console/py/pw_console/console_prefs.py @@ -21,7 +21,7 @@ from typing import Dict, Callable, List, Optional, Union from prompt_toolkit.key_binding import KeyBindings import yaml -from pw_cli.yaml_config_loader_mixin import YamlConfigLoaderMixin +from pw_config_loader.yaml_config_loader_mixin import YamlConfigLoaderMixin from pw_console.style import get_theme_colors, generate_styles from pw_console.key_bindings import DEFAULT_KEY_BINDINGS diff --git a/pw_console/py/pw_console/html/main.js b/pw_console/py/pw_console/html/main.js index 79e239eca..4083af24a 100644 --- a/pw_console/py/pw_console/html/main.js +++ b/pw_console/py/pw_console/html/main.js @@ -73,7 +73,7 @@ class PwConsoleLogSource extends LogSource { fields.push({ key: 'message', value: data.message }); fields.push({ key: 'py_file', value: data.py_file }); fields.push({ key: 'py_logger', value: data.py_logger }); - this.emitEvent('logEntry', { + this.publishLogEntry({ severity: logLevelToSeverity[data.levelno], timestamp: new Date(), fields: fields, diff --git a/pw_console/py/pw_console/pw_ptpython_repl.py b/pw_console/py/pw_console/pw_ptpython_repl.py index 03f405424..301979364 100644 --- a/pw_console/py/pw_console/pw_ptpython_repl.py +++ b/pw_console/py/pw_console/pw_ptpython_repl.py @@ -21,9 +21,15 @@ import os import sys import shlex import subprocess -from typing import Iterable, Optional, TYPE_CHECKING +from typing import Any, Iterable, Optional, TYPE_CHECKING from unittest.mock import patch +# inclusive-language: disable +from prompt_toolkit.input import DummyInput as IgnoredInput + +# inclusive-language: enable + +from prompt_toolkit.output.plain_text import PlainTextOutput from prompt_toolkit.buffer import Buffer from prompt_toolkit.layout.controls import BufferControl from prompt_toolkit.completion import merge_completers @@ -32,10 +38,13 @@ from prompt_toolkit.filters import ( has_focus, to_filter, ) +from prompt_toolkit.formatted_text import StyleAndTextTuples + from ptpython.completer import ( # type: ignore CompletePrivateAttributes, PythonCompleter, ) +from ptpython.printer import OutputPrinter import ptpython.repl # type: ignore from ptpython.layout import ( # type: ignore CompletionVisualisation, @@ -129,9 +138,7 @@ class PwPtPythonRepl( # Change some ptpython.repl defaults. self.show_status_bar = False self.show_exit_confirmation = False - self.complete_private_attributes = ( - CompletePrivateAttributes.IF_NO_PUBLIC - ) + self.complete_private_attributes = CompletePrivateAttributes.NEVER # Function signature that shows args, kwargs, and types under the cursor # of the input window. @@ -203,7 +210,7 @@ class PwPtPythonRepl( def _save_result(self, formatted_text): """Save the last repl execution result.""" - unformatted_result = remove_formatting(formatted_text) + unformatted_result = formatted_text self._last_result = unformatted_result def _save_exception(self, formatted_text): @@ -216,15 +223,39 @@ class PwPtPythonRepl( self._last_result = None self._last_exception = None - def show_result(self, result): + def _format_result_output(self, result: Any) -> Optional[str]: + """Return a plaintext repr of any object.""" + try: + formatted_result = repr(result) + except BaseException as e: # pylint: disable=broad-exception-caught + self._handle_exception(e) + formatted_result = None + return formatted_result + + def _show_result(self, result: Any): """Format and save output results. This function is called from the _run_user_code() function which is always run from the user code thread, within .run_and_show_expression_async(). """ - formatted_result = self._format_result_output(result) - self._save_result(formatted_result) + self._save_result(self._format_result_output(result)) + + def _get_output_printer(self) -> OutputPrinter: + return OutputPrinter( + output=PlainTextOutput(io.StringIO()), + input=IgnoredInput(), + style=self._current_style, + style_transformation=self.style_transformation, + title=self.title, + ) + + def _format_exception_output(self, e: BaseException) -> StyleAndTextTuples: + output_printer = self._get_output_printer() + formatted_result = output_printer._format_exception_output( # pylint: disable=protected-access + e, highlight=False + ) + return list(formatted_result) def _handle_exception(self, e: BaseException) -> None: """Format and save output results. @@ -233,8 +264,33 @@ class PwPtPythonRepl( always run from the user code thread, within .run_and_show_expression_async(). """ - formatted_result = self._format_exception_output(e) - self._save_exception(formatted_result.__pt_formatted_text__()) + self._save_exception(self._format_exception_output(e)) + + async def run_and_show_expression_async(self, text: str) -> Any: + """Run user code and handle the result. + + This function is similar to ptpython version v3.0.23. + """ + loop = asyncio.get_event_loop() + + try: + result = await self.eval_async(text) + except KeyboardInterrupt: + raise + except SystemExit: + return + except BaseException as e: # pylint: disable=broad-exception-caught + self._handle_exception(e) + else: + # Print. + if result is not None: + await loop.run_in_executor( + None, lambda: self._show_result(result) + ) + + self.current_statement_index += 1 + self.signatures = [] + return result def user_code_complete_callback(self, input_text, future): """Callback to run after user repl code is finished.""" @@ -256,8 +312,7 @@ class PwPtPythonRepl( if result_object is not None: # Use ptpython formatted results: - formatted_result = self._format_result_output(result_object) - result_text = remove_formatting(formatted_result) + result_text = self._format_result_output(result_object) # Job is finished, append the last result. self.repl_pane.append_result_to_executed_code( diff --git a/pw_console/py/setup.cfg b/pw_console/py/setup.cfg index 60021a431..70748c0e3 100644 --- a/pw_console/py/setup.cfg +++ b/pw_console/py/setup.cfg @@ -24,8 +24,8 @@ zip_safe = False install_requires = ipython jinja2 - prompt-toolkit>=3.0.26 - ptpython>=3.0.20 + prompt-toolkit>=3.0.34 + ptpython>=3.0.25 pygments pyperclip pyserial>=3.5,<4.0 |