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 |