File indexing completed on 2025-03-09 04:10:20

0001 """
0002 SPDX-FileCopyrightText: 2017 Eliakin Costa <eliakim170@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-2.0-or-later
0005 """
0006 import bdb
0007 import multiprocessing
0008 import sys
0009 import asyncio
0010 from . import debuggerformatter
0011 
0012 
0013 class Debugger(bdb.Bdb):
0014 
0015     def __init__(self, scripter, cmd):
0016         bdb.Bdb.__init__(self)
0017 
0018         self.quit = False
0019         self.debugq = multiprocessing.Queue()
0020         self.scripter = scripter
0021         self.applicationq = multiprocessing.Queue()
0022         self.filePath = self.scripter.documentcontroller.activeDocument.filePath
0023         self.application_data = {}
0024         self.exception_data = {}
0025         self.debugprocess = multiprocessing.Process(target=self._run, args=(self.filePath,))
0026         self.currentLine = 0
0027 
0028         bdb.Bdb.reset(self)
0029 
0030     def _run(self, filename):
0031         try:
0032             self.mainpyfile = self.canonic(filename)
0033             with open(filename, "rb") as fp:
0034                 statement = "exec(compile(%r, %r, 'exec'))" % \
0035                             (fp.read(), self.mainpyfile)
0036             self.run(statement)
0037         except Exception as e:
0038             raise e
0039 
0040     def user_call(self, frame, args):
0041         name = frame.f_code.co_name or "<unknown>"
0042 
0043     def user_line(self, frame):
0044         """Handler that executes with every line of code"""
0045         co = frame.f_code
0046 
0047         if self.filePath != co.co_filename:
0048             return
0049 
0050         self.currentLine = frame.f_lineno
0051         self.applicationq.put({"code": {"file": co.co_filename,
0052                                         "name": co.co_name,
0053                                         "lineNumber": str(frame.f_lineno)
0054                                         },
0055                                "frame": {"firstLineNumber": co.co_firstlineno,
0056                                          "locals": debuggerformatter.format_data(frame.f_locals),
0057                                          "globals": debuggerformatter.format_data(frame.f_globals)
0058                                          },
0059                                "trace": "line"
0060                                })
0061 
0062         if self.quit:
0063             return self.set_quit()
0064         if self.currentLine == 0:
0065             return
0066         else:
0067             cmd = self.debugq.get()
0068 
0069             if cmd == "step":
0070                 return
0071             if cmd == "stop":
0072                 return self.set_quit()
0073 
0074     def user_return(self, frame, value):
0075         name = frame.f_code.co_name or "<unknown>"
0076 
0077         if name == '<module>':
0078             self.applicationq.put({"quit": True})
0079 
0080     def user_exception(self, frame, exception):
0081         self.applicationq.put({"exception": str(exception[1])})
0082 
0083     async def display(self):
0084         """Coroutine for updating the UI"""
0085 
0086         while True:
0087             if self.applicationq.empty():
0088                 await asyncio.sleep(0.3)
0089             else:
0090                 while not self.applicationq.empty():
0091                     self.application_data.update(self.applicationq.get())
0092                     self.scripter.uicontroller.repaintDebugArea()
0093                     return
0094 
0095     async def start(self):
0096         await self.display()
0097 
0098     async def step(self):
0099         self.debugq.put("step")
0100         await self.display()
0101 
0102     async def stop(self):
0103         self.debugq.put("stop")
0104         self.applicationq.put({"quit": True})
0105         await self.display()