52 self.passive = passive |
52 self.passive = passive |
53 self.process = None |
53 self.process = None |
54 self.__startedVenv = "" |
54 self.__startedVenv = "" |
55 |
55 |
56 self.queue = [] |
56 self.queue = [] |
57 self.__master = None |
57 self.__mainDebugger = None |
58 self.__connections = {} |
58 self.__connections = {} |
59 self.__pendingConnections = [] |
59 self.__pendingConnections = [] |
60 self.__inShutdown = False |
60 self.__inShutdown = False |
61 |
61 |
62 # set default values for capabilities of clients |
62 # set default values for capabilities of clients |
588 """ |
588 """ |
589 if sock in self.__pendingConnections: |
589 if sock in self.__pendingConnections: |
590 self.__connections[debuggerId] = sock |
590 self.__connections[debuggerId] = sock |
591 self.__pendingConnections.remove(sock) |
591 self.__pendingConnections.remove(sock) |
592 |
592 |
593 if self.__master is None: |
593 if self.__mainDebugger is None: |
594 self.__master = debuggerId |
594 self.__mainDebugger = debuggerId |
595 # Get the remote clients capabilities |
595 # Get the remote clients capabilities |
596 self.remoteCapabilities(debuggerId) |
596 self.remoteCapabilities(debuggerId) |
597 |
597 |
598 self.debugServer.signalClientDebuggerId(debuggerId) |
598 self.debugServer.signalClientDebuggerId(debuggerId) |
599 |
599 |
600 if debuggerId == self.__master: |
600 if debuggerId == self.__mainDebugger: |
601 self.__flush() |
601 self.__flush() |
602 self.debugServer.masterClientConnected() |
602 self.debugServer.mainClientConnected() |
603 |
603 |
604 self.debugServer.initializeClient(debuggerId) |
604 self.debugServer.initializeClient(debuggerId) |
605 |
605 |
606 # perform auto-continue except for master |
606 # perform auto-continue except for main |
607 if ( |
607 if ( |
608 debuggerId != self.__master |
608 debuggerId != self.__mainDebugger |
609 and self.__autoContinue |
609 and self.__autoContinue |
610 and not self.__isStepCommand |
610 and not self.__isStepCommand |
611 ): |
611 ): |
612 self.__autoContinued.append(debuggerId) |
612 self.__autoContinued.append(debuggerId) |
613 QTimer.singleShot(0, lambda: self.remoteContinue(debuggerId)) |
613 QTimer.singleShot(0, lambda: self.remoteContinue(debuggerId)) |
620 @type QTcpSocket |
620 @type QTcpSocket |
621 """ |
621 """ |
622 for debuggerId in self.__connections: |
622 for debuggerId in self.__connections: |
623 if self.__connections[debuggerId] is sock: |
623 if self.__connections[debuggerId] is sock: |
624 del self.__connections[debuggerId] |
624 del self.__connections[debuggerId] |
625 if debuggerId == self.__master: |
625 if debuggerId == self.__mainDebugger: |
626 self.__master = None |
626 self.__mainDebugger = None |
627 if debuggerId in self.__autoContinued: |
627 if debuggerId in self.__autoContinued: |
628 self.__autoContinued.remove(debuggerId) |
628 self.__autoContinued.remove(debuggerId) |
629 if not self.__inShutdown: |
629 if not self.__inShutdown: |
630 with contextlib.suppress(RuntimeError): |
630 with contextlib.suppress(RuntimeError): |
631 # can be ignored during a shutdown |
631 # can be ignored during a shutdown |
656 |
656 |
657 def __flush(self): |
657 def __flush(self): |
658 """ |
658 """ |
659 Private slot to flush the queue. |
659 Private slot to flush the queue. |
660 """ |
660 """ |
661 if self.__master: |
661 if self.__mainDebugger: |
662 # Send commands that were waiting for the connection. |
662 # Send commands that were waiting for the connection. |
663 for cmd in self.queue: |
663 for cmd in self.queue: |
664 self.__writeJsonCommandToSocket(cmd, self.__connections[self.__master]) |
664 self.__writeJsonCommandToSocket(cmd, self.__connections[self.__mainDebugger]) |
665 |
665 |
666 self.queue = [] |
666 self.queue = [] |
667 |
667 |
668 def shutdown(self): |
668 def shutdown(self): |
669 """ |
669 """ |
670 Public method to cleanly shut down. |
670 Public method to cleanly shut down. |
671 |
671 |
672 It closes our sockets and shuts down the debug clients. |
672 It closes our sockets and shuts down the debug clients. |
673 (Needed on Win OS) |
673 (Needed on Win OS) |
674 """ |
674 """ |
675 if not self.__master: |
675 if not self.__mainDebugger: |
676 return |
676 return |
677 |
677 |
678 self.__inShutdown = True |
678 self.__inShutdown = True |
679 |
679 |
680 while self.__connections: |
680 while self.__connections: |
771 "filename": fn, |
771 "filename": fn, |
772 "argv": Utilities.parseOptionString(argv), |
772 "argv": Utilities.parseOptionString(argv), |
773 "traceInterpreter": traceInterpreter, |
773 "traceInterpreter": traceInterpreter, |
774 "multiprocess": enableMultiprocess, |
774 "multiprocess": enableMultiprocess, |
775 }, |
775 }, |
776 self.__master, |
776 self.__mainDebugger, |
777 ) |
777 ) |
778 |
778 |
779 def remoteRun(self, fn, argv, wd): |
779 def remoteRun(self, fn, argv, wd): |
780 """ |
780 """ |
781 Public method to load a new program to run. |
781 Public method to load a new program to run. |
796 { |
796 { |
797 "workdir": wd, |
797 "workdir": wd, |
798 "filename": fn, |
798 "filename": fn, |
799 "argv": Utilities.parseOptionString(argv), |
799 "argv": Utilities.parseOptionString(argv), |
800 }, |
800 }, |
801 self.__master, |
801 self.__mainDebugger, |
802 ) |
802 ) |
803 |
803 |
804 def remoteCoverage(self, fn, argv, wd, erase=False): |
804 def remoteCoverage(self, fn, argv, wd, erase=False): |
805 """ |
805 """ |
806 Public method to load a new program to collect coverage data. |
806 Public method to load a new program to collect coverage data. |
825 "workdir": wd, |
825 "workdir": wd, |
826 "filename": fn, |
826 "filename": fn, |
827 "argv": Utilities.parseOptionString(argv), |
827 "argv": Utilities.parseOptionString(argv), |
828 "erase": erase, |
828 "erase": erase, |
829 }, |
829 }, |
830 self.__master, |
830 self.__mainDebugger, |
831 ) |
831 ) |
832 |
832 |
833 def remoteProfile(self, fn, argv, wd, erase=False): |
833 def remoteProfile(self, fn, argv, wd, erase=False): |
834 """ |
834 """ |
835 Public method to load a new program to collect profiling data. |
835 Public method to load a new program to collect profiling data. |
1458 elif method == "ResponseThreadSet": |
1458 elif method == "ResponseThreadSet": |
1459 self.debugServer.signalClientThreadSet(params["debuggerId"]) |
1459 self.debugServer.signalClientThreadSet(params["debuggerId"]) |
1460 |
1460 |
1461 elif method == "ResponseCapabilities": |
1461 elif method == "ResponseCapabilities": |
1462 self.clientCapabilities = params["capabilities"] |
1462 self.clientCapabilities = params["capabilities"] |
1463 if params["debuggerId"] == self.__master: |
1463 if params["debuggerId"] == self.__mainDebugger: |
1464 # signal only for the master connection |
1464 # signal only for the main connection |
1465 self.debugServer.signalClientCapabilities( |
1465 self.debugServer.signalClientCapabilities( |
1466 params["capabilities"], |
1466 params["capabilities"], |
1467 params["clientType"], |
1467 params["clientType"], |
1468 self.__startedVenv, |
1468 self.__startedVenv, |
1469 ) |
1469 ) |
1470 |
1470 |
1471 elif method == "ResponseBanner": |
1471 elif method == "ResponseBanner": |
1472 if params["debuggerId"] == self.__master: |
1472 if params["debuggerId"] == self.__mainDebugger: |
1473 # signal only for the master connection |
1473 # signal only for the main connection |
1474 self.debugServer.signalClientBanner( |
1474 self.debugServer.signalClientBanner( |
1475 params["version"], |
1475 params["version"], |
1476 params["platform"], |
1476 params["platform"], |
1477 self.__startedVenv, |
1477 self.__startedVenv, |
1478 ) |
1478 ) |
1559 params["program"], |
1559 params["program"], |
1560 params["status"], |
1560 params["status"], |
1561 params["message"], |
1561 params["message"], |
1562 params["debuggerId"], |
1562 params["debuggerId"], |
1563 ) |
1563 ) |
1564 if params["debuggerId"] == self.__master: |
1564 if params["debuggerId"] == self.__mainDebugger: |
1565 self.debugServer.signalMainClientExit() |
1565 self.debugServer.signalMainClientExit() |
1566 |
1566 |
1567 elif method == "PassiveStartup": |
1567 elif method == "PassiveStartup": |
1568 self.debugServer.passiveStartUp( |
1568 self.debugServer.passiveStartUp( |
1569 self.translate(params["filename"], True), |
1569 self.translate(params["filename"], True), |
1597 } |
1597 } |
1598 cmd = json.dumps(commandDict) + "\n" |
1598 cmd = json.dumps(commandDict) + "\n" |
1599 |
1599 |
1600 if debuggerId and debuggerId in self.__connections: |
1600 if debuggerId and debuggerId in self.__connections: |
1601 sock = self.__connections[debuggerId] |
1601 sock = self.__connections[debuggerId] |
1602 elif sock is None and self.__master is not None: |
1602 elif sock is None and self.__mainDebugger is not None: |
1603 sock = self.__connections[self.__master] |
1603 sock = self.__connections[self.__mainDebugger] |
1604 if sock is not None: |
1604 if sock is not None: |
1605 self.__writeJsonCommandToSocket(cmd, sock) |
1605 self.__writeJsonCommandToSocket(cmd, sock) |
1606 else: |
1606 else: |
1607 self.queue.append(cmd) |
1607 self.queue.append(cmd) |
1608 |
1608 |