def test_run_code(): # set-up bad_code_syntax = "True = 1" bad_code_exec = "a = b" # Not a syntax error, but a NameError good_code = "c = 1" friendly.set_stream("capture") original_level = friendly.get_level() installed = friendly.is_installed() # ----- end of set-up # When a SyntaxError is raised, run_code returns False assert not friendly.run_code(source=bad_code_syntax) result = friendly.get_output() # content is flushed assert "Python exception" in result assert "SyntaxError" in result assert not friendly.get_output() # confirm that content was flushed assert not friendly.run_code(source=bad_code_exec) result = friendly.get_output() assert "Python exception" in result assert "NameError" in result assert friendly.run_code(source=good_code) assert not friendly.get_output() # no new exceptions recorded try: exec(bad_code_syntax, {}) except Exception: assert not friendly.get_output() # When friendly-traceback is not installed, a call to run_code # will end with level set to 0, which corresponds to normal Python # tracebacks friendly.uninstall() friendly.run_code(source=bad_code_syntax) assert friendly.get_level() == 0 friendly.run_code(source=bad_code_syntax, level=4) assert friendly.get_level() == 0 # When friendly-traceback is "installed", a call to run_code # leaves its level unchanged. friendly.install() friendly.set_level(3) friendly.run_code(source=bad_code_syntax) assert friendly.get_level() == 3 friendly.run_code(source=bad_code_syntax, level=4) assert friendly.get_level() == 3 # Clean up and restore for other tests friendly.get_output() friendly.set_stream(None) if installed: friendly.uninstall() friendly.set_level(original_level)
def test_uncleaned_traceback(): """Assert this test filename appear in tracebacks if we don't exclude it. """ friendly.install(redirect="capture") try: raise ValueError except ValueError: friendly.explain() output = friendly.get_output() assert "test_clean_traceback" in output # cleanup for other tests friendly.uninstall()
def start_console( local_vars=None, use_rich=False, include="friendly_tb", lang="en", banner=None, theme="dark", ): """Starts a console; modified from code.interact""" from . import config if banner is None: banner = BANNER if theme != "light": theme = "dark" if use_rich: config.session.set_formatter("rich", theme=theme) console_defaults = { "explain": explain, "what": what, "where": where, "why": why, "more": more, "get_lang": friendly_traceback.get_lang, "set_lang": friendly_traceback.set_lang, "get_include": friendly_traceback.get_include, "set_include": friendly_traceback.set_include, "hint": hint, "friendly_tb": friendly_tb, "python_tb": python_tb, "debug_tb": debug_tb, "debug": debug, "show_paths": path_utils.show_paths, "_info": _info, } if not friendly_traceback.is_installed(): friendly_traceback.install(include=include, lang=lang) if local_vars is None: local_vars = console_defaults else: local_vars.update(console_defaults) console = FriendlyConsole(locals=local_vars, use_rich=use_rich, theme=theme) console.interact(banner=banner)
def test_cleaned_traceback(): """Assert this test filename does not appear in tracebacks if we exclude it. """ friendly.install(redirect="capture") friendly.exclude_file_from_traceback(__file__) try: raise ValueError except ValueError: friendly.explain() output = friendly.get_output() assert "test_clean_traceback" not in output # cleanup for other tests friendly.include_file_in_traceback(__file__) friendly.uninstall()
def start_console(local_vars=None, use_rich=False, include="friendly_tb", lang="en", banner=None): """Starts a console; modified from code.interact""" # from . import config if banner is None: banner = BANNER if not friendly_traceback.is_installed(): friendly_traceback.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, use_rich=use_rich) console.interact(banner=banner)
def install_in_idle_shell(): """Installs Friendly-traceback 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-traceback is bypassed when code entered in IDLE's repl raises SyntaxErrors. """ import friendly_traceback friendly_traceback.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_traceback.install(include="friendly_tb", redirect=idle_writer) # Current limitation idle_writer(" WARNING\n", "ERROR") # noqa idle_writer( "Friendly-traceback cannot handle SyntaxErrors for code entered in the shell.\n" )
def test_check_syntax(): # set-up bad_code_syntax = "True = 1" bad_code_exec = "a = b" # Not a syntax error, but a NameError good_code = "c = 1" friendly.set_stream("capture") original_verbosity = friendly.get_verbosity() installed = friendly.is_installed() # ----- end of set-up # When a SyntaxError is raised, check_syntax returns False assert not friendly.advanced_check_syntax(source=bad_code_syntax) result = friendly.get_output() # content is flushed assert "Python exception" in result assert "SyntaxError" in result assert not friendly.get_output() # confirm that content was flushed # When no SyntaxError is raised, check_syntax returns a tuple # containing a code object and a file name assert friendly.advanced_check_syntax(source=bad_code_exec) assert friendly.advanced_check_syntax(source=good_code) assert not friendly.get_output() # no new exceptions recorded try: exec(bad_code_syntax, {}) except Exception: assert not friendly.get_output() # When friendly-traceback is not installed, a call to check_syntax # will end with verbosity set to 0, which corresponds to normal Python # tracebacks friendly.uninstall() friendly.advanced_check_syntax(source=bad_code_syntax) assert friendly.get_verbosity() == 0 friendly.advanced_check_syntax(source=bad_code_syntax, verbosity=4) assert friendly.get_verbosity() == 0 # When friendly-traceback is "installed", a call to check_syntax # leaves its verbosity unchanged. friendly.install(redirect="capture") friendly.set_verbosity(3) friendly.advanced_check_syntax(source=bad_code_syntax) assert friendly.get_verbosity() == 3 friendly.advanced_check_syntax(source=bad_code_syntax, verbosity=4) assert friendly.get_verbosity() == 3 # A call to advanced_code_syntax, with a language specified as an argument # should leave the previous language unchanged. friendly.set_lang("en") assert not friendly.advanced_check_syntax(source=bad_code_syntax, lang="fr") result = friendly.get_output() assert "Exception Python" in result # French heading assert friendly.get_lang() == "en" # Clean up and restore for other tests friendly.get_output() friendly.set_stream(None) if installed: friendly.uninstall() friendly.set_verbosity(original_verbosity)
"""Contains a function that should raise NameError""" # flake8: noqa def test(): """Should raise NameError""" a = 1 b = c d = 3 if __name__ == "__main__": import friendly_traceback friendly_traceback.install() test()
try: from IPython.core import interactiveshell as shell from IPython.core import compilerop except ImportError: raise ValueError("IPython cannot be imported.") from friendly_traceback import ( install, exclude_file_from_traceback, explain_traceback, set_formatter, ) from friendly_traceback.console_helpers import * # noqa from friendly_traceback.console_helpers import helpers # noqa __all__ = list(helpers.keys()) __all__.append("set_formatter") 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("repl") print("Friendly-traceback installed.")
"""custom_exception_demo.py This simulates a user program that triggers various exceptions caught by Friendly-traceback; some of the exceptions are custom exceptions and one (NameError) is a standard Python exception """ import friendly_traceback import custom_exception friendly_traceback.install() # sets up excepthook; used in the very last case def next_exception(text): print("\n\n", "=" * 50) input(text) print("-" * 50, "\n") next_exception("Press enter to see the firstexception") try: raise custom_exception.MyException1("A message") # noqa except Exception: friendly_traceback.explain() next_exception("Press enter for second exception") try: raise custom_exception.MyException2("Something went wrong", (1, 2, 3)) # noqa except Exception: friendly_traceback.explain()
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" friendly.set_stream("capture") original_include = friendly.get_include() installed = friendly.is_installed() # ----- end of set-up # When a SyntaxError is raised, exec_code returns False assert not friendly.editors_helper.exec_code(source=bad_code_syntax) result = friendly.get_output() # content is flushed assert "SyntaxError" in result assert not friendly.get_output() # confirm that content was flushed friendly.editors_helper.exec_code(source=bad_code_exec) result = friendly.get_output() assert "NameError" in result assert friendly.editors_helper.exec_code(source=good_code) assert not friendly.get_output() # no new exceptions recorded try: exec(bad_code_syntax, {}) except Exception: assert not friendly.get_output() # Ensure that a call to exec_code only install() temporarily # if it was not installed before. friendly.uninstall() friendly.editors_helper.exec_code(source=bad_code_syntax) assert not friendly.is_installed() friendly.editors_helper.exec_code(source=bad_code_syntax, include="no_tb") assert not friendly.is_installed() # When friendly-traceback is "installed", a call to exec_code # leaves its include unchanged. friendly.install(redirect="capture") friendly.set_include("friendly_tb") friendly.editors_helper.exec_code(source=bad_code_syntax) assert friendly.get_include() == "friendly_tb" friendly.editors_helper.exec_code(source=bad_code_syntax, include="no_tb") assert friendly.get_include() == "friendly_tb" # A call to exec_code, with a language specified as an argument # should leave the previous language unchanged. friendly.set_lang("en") friendly.editors_helper.exec_code(source=bad_code_exec, lang="fr", include="explain") result = friendly.get_output() assert "Une exception `NameError` indique" in result assert friendly.get_lang() == "en" # Clean up and restore for other tests friendly.get_output() friendly.set_stream(None) if installed: friendly.uninstall() friendly.set_include(original_include)