1import atexit 2import os.path 3import subprocess 4from tkinter import messagebox 5 6from thonny import THONNY_USER_DIR, get_runner, get_workbench, running 7from thonny.languages import tr 8 9_server_started = False 10_server_process = None 11 12 13def _start_debug_enabled(): 14 return ( 15 get_workbench().get_editor_notebook().get_current_editor() is not None 16 and "debug" in get_runner().get_supported_features() 17 ) 18 19 20def start_server(): 21 global _server_process 22 23 out_err_filename = os.path.join(THONNY_USER_DIR, "birdseye.log") 24 output_file = open(out_err_filename, "w") 25 _server_process = subprocess.Popen( 26 [ 27 running.get_interpreter_for_subprocess(), 28 "-m", 29 "birdseye", 30 "-p", 31 str(get_workbench().get_option("run.birdseye_port")), 32 ], 33 stdout=output_file, 34 stderr=output_file, 35 ) 36 atexit.register(close_server) 37 38 39def close_server(): 40 if _server_process is not None: 41 try: 42 _server_process.kill() 43 except Exception: 44 pass 45 46 47def debug_with_birdseye(): 48 global _server_started 49 50 try: 51 import birdseye # @UnusedImport 52 except ImportError: 53 if messagebox.askyesno( 54 tr("About Birdseye"), 55 tr( 56 "Birdseye is a Python debugger which needs to be installed separately.\n\n" 57 + "Do you want to open the help page and learn more?" 58 ), 59 master=get_workbench(), 60 ): 61 get_workbench().open_help_topic("birdseye") 62 63 return 64 65 if not _server_started: 66 start_server() 67 _server_started = True 68 69 os.environ["BIRDSEYE_PORT"] = str(get_workbench().get_option("run.birdseye_port")) 70 get_runner().execute_current("Birdseye") 71 72 73# order_key makes the plugin to be loaded later than other same tier plugins 74# This way it gets positioned after main debug commands in the Run menu 75load_order_key = "zz" 76 77 78def load_plugin(): 79 get_workbench().set_default("run.birdseye_port", 7777) 80 get_workbench().add_command( 81 "birdseye", 82 "run", 83 tr("Debug current script (birdseye)"), 84 debug_with_birdseye, 85 caption="birdseye", 86 tester=_start_debug_enabled, 87 default_sequence="<Control-B>", 88 group=10, 89 image=os.path.join(os.path.dirname(__file__), "..", "res", "birdseye.png"), 90 ) 91