DebugClients/Python/DebugClientBase.py

branch
maintenance
changeset 5680
b93cb6353cc0
parent 5658
e5f6fe5855fd
child 5957
0c10d2701adb
equal deleted inserted replaced
5655:884cd9c9ce05 5680:b93cb6353cc0
177 DebugClient classes. Do not instantiate it directly. 177 DebugClient classes. Do not instantiate it directly.
178 """ 178 """
179 clientCapabilities = DebugClientCapabilities.HasAll 179 clientCapabilities = DebugClientCapabilities.HasAll
180 180
181 # keep these in sync with VariablesViewer.VariableItem.Indicators 181 # keep these in sync with VariablesViewer.VariableItem.Indicators
182 Indicators = ("()", "[]", "{:}", "{}") # __IGNORE_WARNING__ 182 Indicators = ("()", "[]", "{:}", "{}") # __IGNORE_WARNING_M613__
183 183
184 def __init__(self): 184 def __init__(self):
185 """ 185 """
186 Constructor 186 Constructor
187 """ 187 """
220 self.pollingDisabled = False 220 self.pollingDisabled = False
221 221
222 self.callTraceEnabled = None 222 self.callTraceEnabled = None
223 223
224 self.variant = 'You should not see this' 224 self.variant = 'You should not see this'
225
226 # commandline completion stuff
227 self.complete = Completer(self.debugMod.__dict__).complete
228 225
229 self.compile_command = codeop.CommandCompiler() 226 self.compile_command = codeop.CommandCompiler()
230 227
231 self.coding_re = re.compile(r"coding[:=]\s*([-\w_.]+)") 228 self.coding_re = re.compile(r"coding[:=]\s*([-\w_.]+)")
232 self.defaultCoding = 'utf-8' 229 self.defaultCoding = 'utf-8'
290 @param prompt the prompt to be shown (string) 287 @param prompt the prompt to be shown (string)
291 @return the entered string evaluated as a Python expresion 288 @return the entered string evaluated as a Python expresion
292 """ 289 """
293 return eval(self.raw_input(prompt, True)) 290 return eval(self.raw_input(prompt, True))
294 291
295 def sessionClose(self, exit=True): 292 def sessionClose(self, terminate=True):
296 """ 293 """
297 Public method to close the session with the debugger and optionally 294 Public method to close the session with the debugger and optionally
298 terminate. 295 terminate.
299 296
300 @param exit flag indicating to terminate (boolean) 297 @param terminate flag indicating to terminate (boolean)
301 """ 298 """
302 try: 299 try:
303 self.set_quit() 300 self.set_quit()
304 except Exception: 301 except Exception:
305 pass 302 pass
311 # SHOULD be closed on exit, but it does not hurt to do it here 308 # SHOULD be closed on exit, but it does not hurt to do it here
312 self.readstream.close(True) 309 self.readstream.close(True)
313 self.writestream.close(True) 310 self.writestream.close(True)
314 self.errorstream.close(True) 311 self.errorstream.close(True)
315 312
316 if exit: 313 if terminate:
317 # Ok, go away. 314 # Ok, go away.
318 sys.exit() 315 sys.exit()
319 316
320 def __compileFileSource(self, filename, mode='exec'): 317 def __compileFileSource(self, filename, mode='exec'):
321 """ 318 """
724 self.progTerminated(42) 721 self.progTerminated(42)
725 else: 722 else:
726 self.set_quit() 723 self.set_quit()
727 self.eventExit = True 724 self.eventExit = True
728 725
726 elif method == "RequestMoveIP":
727 newLine = params["newLine"]
728 self.currentThreadExec.move_instruction_pointer(newLine)
729
729 elif method == "RequestContinue": 730 elif method == "RequestContinue":
730 self.currentThreadExec.go(params["special"]) 731 self.currentThreadExec.go(params["special"])
731 self.eventExit = True 732 self.eventExit = True
732 733
733 elif method == "RawInput": 734 elif method == "RawInput":
1318 }) 1319 })
1319 1320
1320 # reset coding 1321 # reset coding
1321 self.__coding = self.defaultCoding 1322 self.__coding = self.defaultCoding
1322 1323
1323 def __dumpVariables(self, frmnr, scope, filter): 1324 def __dumpVariables(self, frmnr, scope, filterList):
1324 """ 1325 """
1325 Private method to return the variables of a frame to the debug server. 1326 Private method to return the variables of a frame to the debug server.
1326 1327
1327 @param frmnr distance of frame reported on. 0 is the current frame 1328 @param frmnr distance of frame reported on. 0 is the current frame
1328 (int) 1329 (int)
1329 @param scope 1 to report global variables, 0 for local variables (int) 1330 @param scope 1 to report global variables, 0 for local variables (int)
1330 @param filter the indices of variable types to be filtered 1331 @param filterList the indices of variable types to be filtered
1331 (list of int) 1332 (list of int)
1332 """ 1333 """
1333 if self.currentThread is None: 1334 if self.currentThread is None:
1334 return 1335 return
1335 1336
1343 f = f.f_back 1344 f = f.f_back
1344 frmnr -= 1 1345 frmnr -= 1
1345 1346
1346 if f is None: 1347 if f is None:
1347 if scope: 1348 if scope:
1348 dict = self.debugMod.__dict__ 1349 varDict = self.debugMod.__dict__
1349 else: 1350 else:
1350 scope = -1 1351 scope = -1
1351 elif scope: 1352 elif scope:
1352 dict = f.f_globals 1353 varDict = f.f_globals
1353 elif f.f_globals is f.f_locals: 1354 elif f.f_globals is f.f_locals:
1354 scope = -1 1355 scope = -1
1355 else: 1356 else:
1356 dict = f.f_locals 1357 varDict = f.f_locals
1357 1358
1358 varlist = [] 1359 varlist = []
1359 1360
1360 if scope != -1: 1361 if scope != -1:
1361 keylist = dict.keys() 1362 keylist = varDict.keys()
1362 1363
1363 vlist = self.__formatVariablesList(keylist, dict, scope, filter) 1364 vlist = self.__formatVariablesList(
1365 keylist, varDict, scope, filterList)
1364 varlist.extend(vlist) 1366 varlist.extend(vlist)
1365 1367
1366 self.sendJsonCommand("ResponseVariables", { 1368 self.sendJsonCommand("ResponseVariables", {
1367 "scope": scope, 1369 "scope": scope,
1368 "variables": varlist, 1370 "variables": varlist,
1369 }) 1371 })
1370 1372
1371 def __dumpVariable(self, var, frmnr, scope, filter): 1373 def __dumpVariable(self, var, frmnr, scope, filterList):
1372 """ 1374 """
1373 Private method to return the variables of a frame to the debug server. 1375 Private method to return the variables of a frame to the debug server.
1374 1376
1375 @param var list encoded name of the requested variable 1377 @param var list encoded name of the requested variable
1376 (list of strings) 1378 (list of strings)
1377 @param frmnr distance of frame reported on. 0 is the current frame 1379 @param frmnr distance of frame reported on. 0 is the current frame
1378 (int) 1380 (int)
1379 @param scope 1 to report global variables, 0 for local variables (int) 1381 @param scope 1 to report global variables, 0 for local variables (int)
1380 @param filter the indices of variable types to be filtered 1382 @param filterList the indices of variable types to be filtered
1381 (list of int) 1383 (list of int)
1382 """ 1384 """
1383 if self.currentThread is None: 1385 if self.currentThread is None:
1384 return 1386 return
1385 1387
1390 f = f.f_back 1392 f = f.f_back
1391 frmnr -= 1 1393 frmnr -= 1
1392 1394
1393 if f is None: 1395 if f is None:
1394 if scope: 1396 if scope:
1395 dict = self.debugMod.__dict__ 1397 varDict = self.debugMod.__dict__
1396 else: 1398 else:
1397 scope = -1 1399 scope = -1
1398 elif scope: 1400 elif scope:
1399 dict = f.f_globals 1401 varDict = f.f_globals
1400 elif f.f_globals is f.f_locals: 1402 elif f.f_globals is f.f_locals:
1401 scope = -1 1403 scope = -1
1402 else: 1404 else:
1403 dict = f.f_locals 1405 varDict = f.f_locals
1404 1406
1405 varlist = [] 1407 varlist = []
1406 1408
1407 if scope != -1: 1409 if scope != -1:
1408 variable = dict 1410 variable = varDict
1409 for attribute in var: 1411 for attribute in var:
1410 attribute = self.__extractIndicators(attribute)[0] 1412 attribute = self.__extractIndicators(attribute)[0]
1411 typeObject, typeName, typeStr, resolver = \ 1413 typeObject, typeName, typeStr, resolver = \
1412 DebugVariables.getType(variable) 1414 DebugVariables.getType(variable)
1413 if resolver: 1415 if resolver:
1423 DebugVariables.getType(variable) 1425 DebugVariables.getType(variable)
1424 if typeStr.startswith(("PyQt5.", "PyQt4.")): 1426 if typeStr.startswith(("PyQt5.", "PyQt4.")):
1425 vlist = self.__formatQtVariable(variable, typeName) 1427 vlist = self.__formatQtVariable(variable, typeName)
1426 varlist.extend(vlist) 1428 varlist.extend(vlist)
1427 elif resolver: 1429 elif resolver:
1428 dict = resolver.getDictionary(variable) 1430 varDict = resolver.getDictionary(variable)
1429 vlist = self.__formatVariablesList( 1431 vlist = self.__formatVariablesList(
1430 list(dict.keys()), dict, scope, filter) 1432 list(varDict.keys()), varDict, scope, filterList)
1431 varlist.extend(vlist) 1433 varlist.extend(vlist)
1432 1434
1433 self.sendJsonCommand("ResponseVariable", { 1435 self.sendJsonCommand("ResponseVariable", {
1434 "scope": scope, 1436 "scope": scope,
1435 "variable": var, 1437 "variable": var,
1595 varlist.append( 1597 varlist.append(
1596 ("address", "QHostAddress", "{0}".format(value.toString()))) 1598 ("address", "QHostAddress", "{0}".format(value.toString())))
1597 1599
1598 return varlist 1600 return varlist
1599 1601
1600 def __formatVariablesList(self, keylist, dict_, scope, filter=[], 1602 def __formatVariablesList(self, keylist, dict_, scope, filterList=None,
1601 formatSequences=False): 1603 formatSequences=False):
1602 """ 1604 """
1603 Private method to produce a formated variables list. 1605 Private method to produce a formated variables list.
1604 1606
1605 The dictionary passed in to it is scanned. Variables are 1607 The dictionary passed in to it is scanned. Variables are
1612 @param dict_ the dictionary to be scanned 1614 @param dict_ the dictionary to be scanned
1613 @param scope 1 to filter using the globals filter, 0 using the locals 1615 @param scope 1 to filter using the globals filter, 0 using the locals
1614 filter (int). 1616 filter (int).
1615 Variables are only added to the list, if their name do not match 1617 Variables are only added to the list, if their name do not match
1616 any of the filter expressions. 1618 any of the filter expressions.
1617 @param filter the indices of variable types to be filtered. Variables 1619 @param filterList the indices of variable types to be filtered.
1618 are only added to the list, if their type is not contained in the 1620 Variables are only added to the list, if their type is not
1619 filter list. 1621 contained in the filter list.
1620 @param formatSequences flag indicating, that sequence or dictionary 1622 @param formatSequences flag indicating, that sequence or dictionary
1621 variables should be formatted. If it is 0 (or false), just the 1623 variables should be formatted. If it is 0 (or false), just the
1622 number of items contained in these variables is returned. (boolean) 1624 number of items contained in these variables is returned. (boolean)
1623 @return A tuple consisting of a list of formatted variables. Each 1625 @return A tuple consisting of a list of formatted variables. Each
1624 variable entry is a tuple of three elements, the variable name, 1626 variable entry is a tuple of three elements, the variable name,
1625 its type and value. 1627 its type and value.
1626 """ 1628 """
1629 filterList = [] if filterList is None else filterList[:]
1630
1627 varlist = [] 1631 varlist = []
1628 if scope: 1632 if scope:
1629 patternFilterObjects = self.globalsFilterObjects 1633 patternFilterObjects = self.globalsFilterObjects
1630 else: 1634 else:
1631 patternFilterObjects = self.localsFilterObjects 1635 patternFilterObjects = self.localsFilterObjects
1639 break 1643 break
1640 if matched: 1644 if matched:
1641 continue 1645 continue
1642 1646
1643 # filter hidden attributes (filter #0) 1647 # filter hidden attributes (filter #0)
1644 if 0 in filter and str(key)[:2] == '__' and not ( 1648 if 0 in filterList and str(key)[:2] == '__' and not (
1645 key == "___len___" and 1649 key == "___len___" and
1646 DebugVariables.TooLargeAttribute in keylist): 1650 DebugVariables.TooLargeAttribute in keylist):
1647 continue 1651 continue
1648 1652
1649 # special handling for '__builtins__' (it's way too big) 1653 # special handling for '__builtins__' (it's way too big)
1656 _, valtype = valtypestr.split(' ', 1) 1660 _, valtype = valtypestr.split(' ', 1)
1657 valtype = valtype[1:-1] 1661 valtype = valtype[1:-1]
1658 valtypename = type(value).__name__ 1662 valtypename = type(value).__name__
1659 if valtype not in ConfigVarTypeStrings: 1663 if valtype not in ConfigVarTypeStrings:
1660 if valtype in ["numpy.ndarray", "array.array"]: 1664 if valtype in ["numpy.ndarray", "array.array"]:
1661 if ConfigVarTypeStrings.index('list') in filter: 1665 if ConfigVarTypeStrings.index('list') in filterList:
1662 continue 1666 continue
1663 elif valtypename == "MultiValueDict": 1667 elif valtypename == "MultiValueDict":
1664 if ConfigVarTypeStrings.index('dict') in filter: 1668 if ConfigVarTypeStrings.index('dict') in filterList:
1665 continue 1669 continue
1666 elif valtype == "sip.methoddescriptor": 1670 elif valtype == "sip.methoddescriptor":
1667 if ConfigVarTypeStrings.index( 1671 if ConfigVarTypeStrings.index(
1668 'method') in filter: 1672 'method') in filterList:
1669 continue 1673 continue
1670 elif valtype == "sip.enumtype": 1674 elif valtype == "sip.enumtype":
1671 if ConfigVarTypeStrings.index('class') in filter: 1675 if ConfigVarTypeStrings.index('class') in filterList:
1672 continue 1676 continue
1673 elif ConfigVarTypeStrings.index('instance') in filter: 1677 elif ConfigVarTypeStrings.index('instance') in filterList:
1674 continue 1678 continue
1675 1679
1676 if (not valtypestr.startswith('type ') and 1680 if (not valtypestr.startswith('type ') and
1677 valtypename not in 1681 valtypename not in
1678 ["ndarray", "MultiValueDict", "array"]): 1682 ["ndarray", "MultiValueDict", "array"]):
1681 try: 1685 try:
1682 # Strip 'instance' to be equal with Python 3 1686 # Strip 'instance' to be equal with Python 3
1683 if valtype == "instancemethod": 1687 if valtype == "instancemethod":
1684 valtype = "method" 1688 valtype = "method"
1685 1689
1686 if ConfigVarTypeStrings.index(valtype) in filter: 1690 if ConfigVarTypeStrings.index(valtype) in filterList:
1687 continue 1691 continue
1688 except ValueError: 1692 except ValueError:
1689 if valtype == "classobj": 1693 if valtype == "classobj":
1690 if ConfigVarTypeStrings.index( 1694 if ConfigVarTypeStrings.index(
1691 'instance') in filter: 1695 'instance') in filterList:
1692 continue 1696 continue
1693 elif valtype == "sip.methoddescriptor": 1697 elif valtype == "sip.methoddescriptor":
1694 if ConfigVarTypeStrings.index( 1698 if ConfigVarTypeStrings.index(
1695 'method') in filter: 1699 'method') in filterList:
1696 continue 1700 continue
1697 elif valtype == "sip.enumtype": 1701 elif valtype == "sip.enumtype":
1698 if ConfigVarTypeStrings.index('class') in filter: 1702 if ConfigVarTypeStrings.index('class') in \
1703 filterList:
1699 continue 1704 continue
1700 elif not valtype.startswith("PySide") and \ 1705 elif not valtype.startswith("PySide") and \
1701 ConfigVarTypeStrings.index('other') in filter: 1706 (ConfigVarTypeStrings.index('other') in
1707 filterList):
1702 continue 1708 continue
1703 1709
1704 try: 1710 try:
1705 if valtype in ['list', 'tuple', 'dict', 'set', 1711 if valtype in ['list', 'tuple', 'dict', 'set',
1706 'frozenset', 'array.array']: 1712 'frozenset', 'array.array']:
1771 localdict = self.currentThread.getFrameLocals(self.framenr) 1777 localdict = self.currentThread.getFrameLocals(self.framenr)
1772 localCompleter = Completer(localdict).complete 1778 localCompleter = Completer(localdict).complete
1773 self.__getCompletionList(text, localCompleter, completions) 1779 self.__getCompletionList(text, localCompleter, completions)
1774 except AttributeError: 1780 except AttributeError:
1775 pass 1781 pass
1776 self.__getCompletionList(text, self.complete, completions) 1782
1783 cf = self.currentThread.getCurrentFrame()
1784 frmnr = self.framenr
1785 while cf is not None and frmnr > 0:
1786 cf = cf.f_back
1787 frmnr -= 1
1788
1789 if cf is None:
1790 globaldict = self.debugMod.__dict__
1791 else:
1792 globaldict = cf.f_globals
1793
1794 globalCompleter = Completer(globaldict).complete
1795 self.__getCompletionList(text, globalCompleter, completions)
1777 1796
1778 self.sendJsonCommand("ResponseCompletion", { 1797 self.sendJsonCommand("ResponseCompletion", {
1779 "completions": list(completions), 1798 "completions": list(completions),
1780 "text": text, 1799 "text": text,
1781 }) 1800 })
2000 del args[0] 2019 del args[0]
2001 break 2020 break
2002 else: # unknown option 2021 else: # unknown option
2003 del args[0] 2022 del args[0]
2004 if not args: 2023 if not args:
2005 print("No program given. Aborting!") # __IGNORE_WARNING__ 2024 print("No program given. Aborting!")
2025 # __IGNORE_WARNING_M801__
2006 else: 2026 else:
2007 if not self.noencoding: 2027 if not self.noencoding:
2008 self.__coding = self.defaultCoding 2028 self.__coding = self.defaultCoding
2009 self.startProgInDebugger(args, wd, host, port, 2029 self.startProgInDebugger(args, wd, host, port,
2010 exceptions=exceptions, 2030 exceptions=exceptions,
2041 if not self.noencoding: 2061 if not self.noencoding:
2042 self.__coding = self.defaultCoding 2062 self.__coding = self.defaultCoding
2043 self.connectDebugger(port, remoteAddress, redirect) 2063 self.connectDebugger(port, remoteAddress, redirect)
2044 self.__interact() 2064 self.__interact()
2045 else: 2065 else:
2046 print("No network port given. Aborting...") # __IGNORE_WARNING__ 2066 print("No network port given. Aborting...")
2067 # __IGNORE_WARNING_M801__
2047 2068
2048 def fork(self): 2069 def fork(self):
2049 """ 2070 """
2050 Public method implementing a fork routine deciding which branch 2071 Public method implementing a fork routine deciding which branch
2051 to follow. 2072 to follow.
2059 if pid == 0: 2080 if pid == 0:
2060 # child 2081 # child
2061 if not self.fork_child: 2082 if not self.fork_child:
2062 sys.settrace(None) 2083 sys.settrace(None)
2063 sys.setprofile(None) 2084 sys.setprofile(None)
2064 self.sessionClose(0) 2085 self.sessionClose(False)
2065 else: 2086 else:
2066 # parent 2087 # parent
2067 if self.fork_child: 2088 if self.fork_child:
2068 sys.settrace(None) 2089 sys.settrace(None)
2069 sys.setprofile(None) 2090 sys.setprofile(None)
2070 self.sessionClose(0) 2091 self.sessionClose(False)
2071 return pid 2092 return pid
2072 2093
2073 def close(self, fd): 2094 def close(self, fd):
2074 """ 2095 """
2075 Public method implementing a close method as a replacement for 2096 Public method implementing a close method as a replacement for

eric ide

mercurial