src/eric7/DebugClients/Python/DebugClientBase.py

branch
eric7-maintenance
changeset 10460
3b34efa2857c
parent 10439
21c28b0f9e41
child 10496
f9925e08dbce
equal deleted inserted replaced
10366:411df92e881f 10460:3b34efa2857c
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (c) 2002 - 2023 Detlev Offenbach <detlev@die-offenbachs.de> 3 # Copyright (c) 2002 - 2024 Detlev Offenbach <detlev@die-offenbachs.de>
4 # 4 #
5 5
6 """ 6 """
7 Module implementing a debug client base class. 7 Module implementing a debug client base class.
8 """ 8 """
79 79
80 def DebugClientClose(fd): 80 def DebugClientClose(fd):
81 """ 81 """
82 Replacement for the standard os.close(fd). 82 Replacement for the standard os.close(fd).
83 83
84 @param fd open file descriptor to be closed (integer) 84 @param fd open file descriptor to be closed
85 @type int
85 """ 86 """
86 if DebugClientInstance is None: 87 if DebugClientInstance is None:
87 DebugClientOrigClose(fd) 88 DebugClientOrigClose(fd)
88 else: 89 else:
89 DebugClientInstance.close(fd) 90 DebugClientInstance.close(fd)
99 100
100 def DebugClientSetRecursionLimit(limit): 101 def DebugClientSetRecursionLimit(limit):
101 """ 102 """
102 Replacement for the standard sys.setrecursionlimit(limit). 103 Replacement for the standard sys.setrecursionlimit(limit).
103 104
104 @param limit recursion limit (integer) 105 @param limit recursion limit
106 @type int
105 """ 107 """
106 rl = max(limit, 64) 108 rl = max(limit, 64)
107 setRecursionLimit(rl) 109 setRecursionLimit(rl)
108 DebugClientOrigSetRecursionLimit(rl + 64) 110 DebugClientOrigSetRecursionLimit(rl + 64)
109 111
205 207
206 def getCoding(self): 208 def getCoding(self):
207 """ 209 """
208 Public method to return the current coding. 210 Public method to return the current coding.
209 211
210 @return codec name (string) 212 @return codec name
213 @rtype str
211 """ 214 """
212 return self.__coding 215 return self.__coding
213 216
214 def __setCoding(self, filename): 217 def __setCoding(self, filename):
215 """ 218 """
216 Private method to set the coding used by a python file. 219 Private method to set the coding used by a python file.
217 220
218 @param filename name of the file to inspect (string) 221 @param filename name of the file to inspect
222 @type str
219 """ 223 """
220 if self.noencoding: 224 if self.noencoding:
221 self.__coding = sys.getdefaultencoding() 225 self.__coding = sys.getdefaultencoding()
222 else: 226 else:
223 default = "utf-8" 227 default = "utf-8"
261 def sessionClose(self, terminate=True): 265 def sessionClose(self, terminate=True):
262 """ 266 """
263 Public method to close the session with the debugger and optionally 267 Public method to close the session with the debugger and optionally
264 terminate. 268 terminate.
265 269
266 @param terminate flag indicating to terminate (boolean) 270 @param terminate flag indicating to terminate
271 @type bool
267 """ 272 """
268 with contextlib.suppress(Exception): # secok 273 with contextlib.suppress(Exception): # secok
269 self.set_quit() 274 self.set_quit()
270 275
271 self.debugging = False 276 self.debugging = False
291 @param filename name of the source file 296 @param filename name of the source file
292 @type str 297 @type str
293 @param mode kind of code to be generated (exec or eval) 298 @param mode kind of code to be generated (exec or eval)
294 @type str 299 @type str
295 @return compiled code object (None in case of errors) 300 @return compiled code object (None in case of errors)
301 @rtype Code
296 """ 302 """
297 with codecs.open(filename, encoding=self.__coding) as fp: 303 with codecs.open(filename, encoding=self.__coding) as fp:
298 statement = fp.read() 304 statement = fp.read()
299 305
300 return self.__compileCommand(statement, filename=filename, mode=mode) 306 return self.__compileCommand(statement, filename=filename, mode=mode)
308 @param filename name of the source file 314 @param filename name of the source file
309 @type str 315 @type str
310 @param mode kind of code to be generated (exec or eval) 316 @param mode kind of code to be generated (exec or eval)
311 @type str 317 @type str
312 @return compiled code object (None in case of errors) 318 @return compiled code object (None in case of errors)
319 @rtype Code
313 """ 320 """
314 try: 321 try:
315 code = compile(statement + "\n", filename, mode) 322 code = compile(statement + "\n", filename, mode)
316 except SyntaxError: 323 except SyntaxError:
317 exctype, excval, exctb = sys.exc_info() 324 exctype, excval, exctb = sys.exc_info()
339 Public method to handle a command serialized as a JSON string. 346 Public method to handle a command serialized as a JSON string.
340 347
341 @param jsonStr string containing the command received from the IDE 348 @param jsonStr string containing the command received from the IDE
342 @type str 349 @type str
343 """ 350 """
344 ## printerr(jsonStr) ## debug # __IGNORE_WARNING_M891__ 351 ## printerr(jsonStr) ## debug # noqa: M891
345 352
346 try: 353 try:
347 commandDict = json.loads(jsonStr.strip()) 354 commandDict = json.loads(jsonStr.strip())
348 except (TypeError, ValueError) as err: 355 except (TypeError, ValueError) as err:
349 printerr("Error handling command: " + jsonStr) 356 printerr("Error handling command: " + jsonStr)
890 """ 897 """
891 Public method to signal the deletion of a temporary breakpoint. 898 Public method to signal the deletion of a temporary breakpoint.
892 899
893 @param filename name of the file the bp belongs to 900 @param filename name of the file the bp belongs to
894 @type str 901 @type str
895 @param lineno linenumber of the bp 902 @param lineno line number of the bp
896 @type int 903 @type int
897 """ 904 """
898 self.sendJsonCommand( 905 self.sendJsonCommand(
899 "ResponseClearBreakpoint", {"filename": filename, "line": lineno} 906 "ResponseClearBreakpoint", {"filename": filename, "line": lineno}
900 ) 907 )
1027 1034
1028 def __clientCapabilities(self): 1035 def __clientCapabilities(self):
1029 """ 1036 """
1030 Private method to determine the clients capabilities. 1037 Private method to determine the clients capabilities.
1031 1038
1032 @return client capabilities (integer) 1039 @return client capabilities
1040 @rtype int
1033 """ 1041 """
1034 if importlib.util.find_spec("PyProfile") is None: 1042 if importlib.util.find_spec("PyProfile") is None:
1035 return self.clientCapabilities & ~DebugClientCapabilities.HasProfiler 1043 return self.clientCapabilities & ~DebugClientCapabilities.HasProfiler
1036 else: 1044 else:
1037 return self.clientCapabilities 1045 return self.clientCapabilities
1039 def readReady(self, stream): 1047 def readReady(self, stream):
1040 """ 1048 """
1041 Public method called when there is data ready to be read. 1049 Public method called when there is data ready to be read.
1042 1050
1043 @param stream file like object that has data to be read 1051 @param stream file like object that has data to be read
1052 @type file like
1044 @return flag indicating an error condition 1053 @return flag indicating an error condition
1045 @rtype bool 1054 @rtype bool
1046 """ 1055 """
1047 error = False 1056 error = False
1048 1057
1064 def writeReady(self, stream): 1073 def writeReady(self, stream):
1065 """ 1074 """
1066 Public method called when we are ready to write data. 1075 Public method called when we are ready to write data.
1067 1076
1068 @param stream file like object that has data to be written 1077 @param stream file like object that has data to be written
1078 @type file like
1069 """ 1079 """
1070 stream.write_p("") 1080 stream.write_p("")
1071 stream.flush() 1081 stream.flush()
1072 1082
1073 def __interact(self): 1083 def __interact(self):
1086 def eventLoop(self, disablePolling=False): 1096 def eventLoop(self, disablePolling=False):
1087 """ 1097 """
1088 Public method implementing our event loop. 1098 Public method implementing our event loop.
1089 1099
1090 @param disablePolling flag indicating to enter an event loop with 1100 @param disablePolling flag indicating to enter an event loop with
1091 polling disabled (boolean) 1101 polling disabled
1102 @type bool
1092 """ 1103 """
1093 self.eventExit = False 1104 self.eventExit = False
1094 self.pollingDisabled = disablePolling 1105 self.pollingDisabled = disablePolling
1095 selectErrors = 0 1106 selectErrors = 0
1096 1107
1218 1229
1219 def __unhandled_exception(self, exctype, excval, exctb): 1230 def __unhandled_exception(self, exctype, excval, exctb):
1220 """ 1231 """
1221 Private method called to report an uncaught exception. 1232 Private method called to report an uncaught exception.
1222 1233
1223 @param exctype the type of the exception 1234 @param exctype class of the exception
1224 @param excval data about the exception 1235 @type type
1236 @param excval exception instance
1237 @type Exception
1225 @param exctb traceback for the exception 1238 @param exctb traceback for the exception
1239 @type traceback
1226 """ 1240 """
1227 self.mainThread.user_exception((exctype, excval, exctb), True) 1241 self.mainThread.user_exception((exctype, excval, exctb), True)
1228 1242
1229 def __interceptSignals(self): 1243 def __interceptSignals(self):
1230 """ 1244 """
1293 Public method to convert a filename to an absolute name. 1307 Public method to convert a filename to an absolute name.
1294 1308
1295 sys.path is used as a set of possible prefixes. The name stays 1309 sys.path is used as a set of possible prefixes. The name stays
1296 relative if a file could not be found. 1310 relative if a file could not be found.
1297 1311
1298 @param fn filename (string) 1312 @param fn filename
1299 @return the converted filename (string) 1313 @type str
1314 @return the converted filename
1315 @rtype str
1300 """ 1316 """
1301 if os.path.isabs(fn): 1317 if os.path.isabs(fn):
1302 return fn 1318 return fn
1303 1319
1304 # Check the cache. 1320 # Check the cache.
1331 1347
1332 def getRunning(self): 1348 def getRunning(self):
1333 """ 1349 """
1334 Public method to return the main script we are currently running. 1350 Public method to return the main script we are currently running.
1335 1351
1336 @return flag indicating a running debug session (boolean) 1352 @return flag indicating a running debug session
1353 @rtype bool
1337 """ 1354 """
1338 return self.running 1355 return self.running
1339 1356
1340 def progTerminated(self, status, message="", closeSession=True): 1357 def progTerminated(self, status, message="", closeSession=True):
1341 """ 1358 """
1673 def __generateFilterObjects(self, scope, filterString): 1690 def __generateFilterObjects(self, scope, filterString):
1674 """ 1691 """
1675 Private slot to convert a filter string to a list of filter objects. 1692 Private slot to convert a filter string to a list of filter objects.
1676 1693
1677 @param scope 1 to generate filter for global variables, 0 for local 1694 @param scope 1 to generate filter for global variables, 0 for local
1678 variables (int) 1695 variables
1696 @type int
1679 @param filterString string of filter patterns separated by ';' 1697 @param filterString string of filter patterns separated by ';'
1698 @type str
1680 """ 1699 """
1681 patternFilterObjects = None 1700 patternFilterObjects = None
1682 filterString = filterString.strip() 1701 filterString = filterString.strip()
1683 if filterString: 1702 if filterString:
1684 if filterString[0] == "~": 1703 if filterString[0] == "~":
1701 1720
1702 def __completionList(self, text): 1721 def __completionList(self, text):
1703 """ 1722 """
1704 Private slot to handle the request for a commandline completion list. 1723 Private slot to handle the request for a commandline completion list.
1705 1724
1706 @param text the text to be completed (string) 1725 @param text the text to be completed
1726 @type str
1707 """ 1727 """
1708 completerDelims = " \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?" 1728 completerDelims = " \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?"
1709 1729
1710 completions = set() 1730 completions = set()
1711 # find position of last delim character 1731 # find position of last delim character
1740 1760
1741 def __getCompletionList(self, text, completer, completions): 1761 def __getCompletionList(self, text, completer, completions):
1742 """ 1762 """
1743 Private method to create a completions list. 1763 Private method to create a completions list.
1744 1764
1745 @param text text to complete (string) 1765 @param text text to complete
1766 @type str
1746 @param completer completer method 1767 @param completer completer method
1747 @param completions set where to add new completions strings (set) 1768 @type function
1769 @param completions set where to add new completions strings
1770 @type set
1748 """ 1771 """
1749 state = 0 1772 state = 0
1750 try: 1773 try:
1751 comp = completer(text, state) 1774 comp = completer(text, state)
1752 except Exception: 1775 except Exception:
1964 1987
1965 def run_call(self, scriptname, func, *args): 1988 def run_call(self, scriptname, func, *args):
1966 """ 1989 """
1967 Public method used to start the remote debugger and call a function. 1990 Public method used to start the remote debugger and call a function.
1968 1991
1969 @param scriptname name of the script to be debugged (string) 1992 @param scriptname name of the script to be debugged
1993 @type str
1970 @param func function to be called 1994 @param func function to be called
1995 @type function
1971 @param *args arguments being passed to func 1996 @param *args arguments being passed to func
1997 @type list
1972 @return result of the function call 1998 @return result of the function call
1999 @rtype Any
1973 """ 2000 """
1974 self.startDebugger(scriptname, enableTrace=False) 2001 self.startDebugger(scriptname, enableTrace=False)
1975 res = self.mainThread.runcall(func, *args) 2002 res = self.mainThread.runcall(func, *args)
1976 self.progTerminated(res, closeSession=False) 2003 self.progTerminated(res, closeSession=False)
1977 return res 2004 return res
1978 2005
1979 def __resolveHost(self, host): 2006 def __resolveHost(self, host):
1980 """ 2007 """
1981 Private method to resolve a hostname to an IP address. 2008 Private method to resolve a hostname to an IP address.
1982 2009
1983 @param host hostname of the debug server (string) 2010 @param host hostname of the debug server
1984 @return IP address (string) 2011 @type str
2012 @return IP address
2013 @rtype str
1985 """ 2014 """
1986 try: 2015 try:
1987 host, version = host.split("@@") 2016 host, version = host.split("@@")
1988 except ValueError: 2017 except ValueError:
1989 version = "v4" 2018 version = "v4"
2166 Public method implementing a close method as a replacement for 2195 Public method implementing a close method as a replacement for
2167 os.close(). 2196 os.close().
2168 2197
2169 It prevents the debugger connections from being closed. 2198 It prevents the debugger connections from being closed.
2170 2199
2171 @param fd file descriptor to be closed (integer) 2200 @param fd file descriptor to be closed
2201 @type int
2172 """ 2202 """
2173 if fd in [ 2203 if fd in [
2174 self.readstream.fileno(), 2204 self.readstream.fileno(),
2175 self.writestream.fileno(), 2205 self.writestream.fileno(),
2176 self.errorstream.fileno(), 2206 self.errorstream.fileno(),
2182 def __getSysPath(self, firstEntry): 2212 def __getSysPath(self, firstEntry):
2183 """ 2213 """
2184 Private slot to calculate a path list including the PYTHONPATH 2214 Private slot to calculate a path list including the PYTHONPATH
2185 environment variable. 2215 environment variable.
2186 2216
2187 @param firstEntry entry to be put first in sys.path (string) 2217 @param firstEntry entry to be put first in sys.path
2188 @return path list for use as sys.path (list of strings) 2218 @type str
2219 @return path list for use as sys.path
2220 @rtype list of str
2189 """ 2221 """
2190 sysPath = [ 2222 sysPath = [
2191 path 2223 path
2192 for path in os.environ.get("PYTHONPATH", "").split(os.pathsep) 2224 for path in os.environ.get("PYTHONPATH", "").split(os.pathsep)
2193 if path not in sys.path 2225 if path not in sys.path

eric ide

mercurial