def install_in_idle_shell(lang="en"): """Installs Friendly in IDLE's shell so that it can retrieve code entered in IDLE's repl. Note that this requires Python version 3.10+ since IDLE did not support custom excepthook in previous versions of Python. Furthermore, Friendly is bypassed when code entered in IDLE's repl raises SyntaxErrors. """ friendly.exclude_file_from_traceback(idlelib_run.__file__) rpchandler = rpc.objecttable["exec"].rpchandler # noqa def get_lines(filename, linenumber): lines = rpchandler.remotecall("linecache", "getlines", (filename, None), {}) new_lines = [] for line in lines: if not line.endswith("\n"): line += "\n" if filename.startswith("<pyshell#") and line.startswith("\t"): # Remove extra indentation added in the shell (\t == 8 spaces) line = " " + line[1:] new_lines.append(line) if linenumber is None: return new_lines return new_lines[linenumber - 1 : linenumber] source_cache.idle_get_lines = get_lines friendly.install(include="friendly_tb", redirect=idle_writer, lang=lang) # Current limitation idle_writer(" WARNING\n", "ERROR") # noqa idle_writer("Friendly cannot handle SyntaxErrors for code entered in the shell.\n")
def start_console( local_vars=None, formatter="dark", include="friendly_tb", lang="en", banner=None, background=None, ): """Starts a console; modified from code.interact""" # from . import config if banner is None: banner = BANNER if not friendly.is_installed(): friendly.install(include=include, lang=lang) source_cache.idle_get_lines = None if local_vars is not None: # Make sure we don't overwrite with our own functions helpers.update(local_vars) console = FriendlyConsole(locals=helpers, formatter=formatter, background=background) console.interact(banner=banner)
def test_uncleaned_traceback(): """Assert this test filename appear in tracebacks if we don't exclude it. """ ft.install(redirect="capture") try: from . import raise_exception except ValueError: ft.explain_traceback() output = ft.get_output() assert "test_clean_traceback" in output assert "André" in output # cleanup for other tests ft.uninstall()
def test_cleaned_traceback(): """Assert this test filename does not appear in tracebacks if we exclude it. """ ft.install(redirect="capture") ft.exclude_file_from_traceback(__file__) try: from . import raise_exception except ValueError: ft.explain_traceback() output = ft.get_output() assert "test_clean_traceback" not in output assert "André" in output # cleanup for other tests ft.path_info.include_file_in_traceback(__file__) ft.uninstall()
def test_uncleaned_traceback(): """Assert this test filename appear in tracebacks if we don't exclude it. """ friendly.install(redirect="capture") old_debug = friendly.debug_helper.DEBUG friendly.debug_helper.DEBUG = False try: from . import raise_exception except ValueError: friendly.explain_traceback() output = friendly.get_output() assert "test_clean_traceback" in output assert "André" in output # cleanup for other tests friendly.uninstall() friendly.debug_helper.DEBUG = old_debug
def start_console( local_vars=None, formatter="dark", include="friendly_tb", lang="en", banner=None, color_schemes=None, background=None, displayhook=None, ): """Starts a console; modified from code.interact""" # from . import config if banner is None: banner = BANNER + type_friendly() + "\n" if displayhook is None: displayhook = _displayhook if not friendly.is_installed(): friendly.install(include=include, lang=lang) source_cache.idle_get_lines = None if local_vars is not None: # Make sure we don't overwrite with our own functions helpers.update(local_vars) if color_schemes is None: color_schemes = default_color_schemes helpers.update(color_schemes) console = FriendlyConsole( locals=helpers, formatter=formatter, background=background, displayhook=displayhook, ) console.interact(banner=banner)
# is correct! import os import sys import platform this_dir = os.path.dirname(__file__) sys.path.append(os.path.join(this_dir, "..")) import friendly # Make it possible to find docs and tests source docs_root_dir = os.path.abspath( os.path.join(this_dir, "..", "..", "friendly-traceback-docs")) assert os.path.isdir(docs_root_dir), "Separate docs repo need to exist" LANG = "en" friendly.install() friendly.set_lang(LANG) friendly.set_formatter("docs") sys.path.insert(0, this_dir) py_version = f"{sys.version_info.major}.{sys.version_info.minor}" import trb_syntax_common target = os.path.normpath( os.path.join(docs_root_dir, f"docs/source/syntax_tracebacks_{LANG}_{py_version}.rst")) intro_text = """ Friendly SyntaxError tracebacks - in English =============================================
def test_exec_code(): # set-up bad_code_syntax = "True = 1" bad_code_exec = "a = b" # Not a syntax error, but a NameError good_code = "c = 1" ft.set_stream("capture") original_include = ft.get_include() installed = ft.is_installed() # ----- end of set-up # When a SyntaxError is raised, exec_code returns False assert not ft.editors_helpers.exec_code(source=bad_code_syntax) result = ft.get_output() # content is flushed assert "SyntaxError" in result assert not ft.get_output() # confirm that content was flushed ft.editors_helpers.exec_code(source=bad_code_exec) result = ft.get_output() assert "NameError" in result assert ft.editors_helpers.exec_code(source=good_code) assert not ft.get_output() # no new exceptions recorded try: exec(bad_code_syntax, {}) except Exception: assert not ft.get_output() # Ensure that a call to exec_code only install() temporarily # if it was not installed before. ft.uninstall() ft.editors_helpers.exec_code(source=bad_code_syntax) assert not ft.is_installed() ft.editors_helpers.exec_code(source=bad_code_syntax, include="no_tb") assert not ft.is_installed() # When friendly is "installed", a call to exec_code # leaves its include unchanged. ft.install(redirect="capture") ft.set_include("friendly_tb") ft.editors_helpers.exec_code(source=bad_code_syntax) assert ft.get_include() == "friendly_tb" ft.editors_helpers.exec_code(source=bad_code_syntax, include="no_tb") assert ft.get_include() == "friendly_tb" # A call to exec_code, with a language specified as an argument # should leave the previous language unchanged. ft.set_lang("en") ft.editors_helpers.exec_code(source=bad_code_exec, lang="fr", include="explain") result = ft.get_output() assert "Une exception `NameError` indique" in result assert ft.get_lang() == "en" # Clean up and restore for other tests ft.get_output() ft.set_stream(None) if installed: ft.uninstall() ft.set_include(original_include)
except Exception: # noqa pass colorama.deinit() colorama.init(convert=False, strip=False) def set_width(width=80): """Sets the width in a iPython/Jupyter session using Rich.""" if session.use_rich: session.console._width = width else: print("set_width() is only available using 'light' or 'dark' mode.") __all__.append("set_width") Friendly.set_width = set_width # noqa shell.InteractiveShell.showtraceback = lambda self, *args, **kwargs: explain_traceback() shell.InteractiveShell.showsyntaxerror = ( lambda self, *args, **kwargs: explain_traceback() ) exclude_file_from_traceback(shell.__file__) exclude_file_from_traceback(compilerop.__file__) install(include="friendly_tb") set_formatter("dark") # noqa