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( |
|
665 cmd, self.__connections[self.__mainDebugger] |
|
666 ) |
665 |
667 |
666 self.queue = [] |
668 self.queue = [] |
667 |
669 |
668 def shutdown(self): |
670 def shutdown(self): |
669 """ |
671 """ |
670 Public method to cleanly shut down. |
672 Public method to cleanly shut down. |
671 |
673 |
672 It closes our sockets and shuts down the debug clients. |
674 It closes our sockets and shuts down the debug clients. |
673 (Needed on Win OS) |
675 (Needed on Win OS) |
674 """ |
676 """ |
675 if not self.__master: |
677 if not self.__mainDebugger: |
676 return |
678 return |
677 |
679 |
678 self.__inShutdown = True |
680 self.__inShutdown = True |
679 |
681 |
680 while self.__connections: |
682 while self.__connections: |
771 "filename": fn, |
773 "filename": fn, |
772 "argv": Utilities.parseOptionString(argv), |
774 "argv": Utilities.parseOptionString(argv), |
773 "traceInterpreter": traceInterpreter, |
775 "traceInterpreter": traceInterpreter, |
774 "multiprocess": enableMultiprocess, |
776 "multiprocess": enableMultiprocess, |
775 }, |
777 }, |
776 self.__master, |
778 self.__mainDebugger, |
777 ) |
779 ) |
778 |
780 |
779 def remoteRun(self, fn, argv, wd): |
781 def remoteRun(self, fn, argv, wd): |
780 """ |
782 """ |
781 Public method to load a new program to run. |
783 Public method to load a new program to run. |
796 { |
798 { |
797 "workdir": wd, |
799 "workdir": wd, |
798 "filename": fn, |
800 "filename": fn, |
799 "argv": Utilities.parseOptionString(argv), |
801 "argv": Utilities.parseOptionString(argv), |
800 }, |
802 }, |
801 self.__master, |
803 self.__mainDebugger, |
802 ) |
804 ) |
803 |
805 |
804 def remoteCoverage(self, fn, argv, wd, erase=False): |
806 def remoteCoverage(self, fn, argv, wd, erase=False): |
805 """ |
807 """ |
806 Public method to load a new program to collect coverage data. |
808 Public method to load a new program to collect coverage data. |
825 "workdir": wd, |
827 "workdir": wd, |
826 "filename": fn, |
828 "filename": fn, |
827 "argv": Utilities.parseOptionString(argv), |
829 "argv": Utilities.parseOptionString(argv), |
828 "erase": erase, |
830 "erase": erase, |
829 }, |
831 }, |
830 self.__master, |
832 self.__mainDebugger, |
831 ) |
833 ) |
832 |
834 |
833 def remoteProfile(self, fn, argv, wd, erase=False): |
835 def remoteProfile(self, fn, argv, wd, erase=False): |
834 """ |
836 """ |
835 Public method to load a new program to collect profiling data. |
837 Public method to load a new program to collect profiling data. |
1458 elif method == "ResponseThreadSet": |
1460 elif method == "ResponseThreadSet": |
1459 self.debugServer.signalClientThreadSet(params["debuggerId"]) |
1461 self.debugServer.signalClientThreadSet(params["debuggerId"]) |
1460 |
1462 |
1461 elif method == "ResponseCapabilities": |
1463 elif method == "ResponseCapabilities": |
1462 self.clientCapabilities = params["capabilities"] |
1464 self.clientCapabilities = params["capabilities"] |
1463 if params["debuggerId"] == self.__master: |
1465 if params["debuggerId"] == self.__mainDebugger: |
1464 # signal only for the master connection |
1466 # signal only for the main connection |
1465 self.debugServer.signalClientCapabilities( |
1467 self.debugServer.signalClientCapabilities( |
1466 params["capabilities"], |
1468 params["capabilities"], |
1467 params["clientType"], |
1469 params["clientType"], |
1468 self.__startedVenv, |
1470 self.__startedVenv, |
1469 ) |
1471 ) |
1470 |
1472 |
1471 elif method == "ResponseBanner": |
1473 elif method == "ResponseBanner": |
1472 if params["debuggerId"] == self.__master: |
1474 if params["debuggerId"] == self.__mainDebugger: |
1473 # signal only for the master connection |
1475 # signal only for the main connection |
1474 self.debugServer.signalClientBanner( |
1476 self.debugServer.signalClientBanner( |
1475 params["version"], |
1477 params["version"], |
1476 params["platform"], |
1478 params["platform"], |
1477 self.__startedVenv, |
1479 self.__startedVenv, |
1478 ) |
1480 ) |
1559 params["program"], |
1561 params["program"], |
1560 params["status"], |
1562 params["status"], |
1561 params["message"], |
1563 params["message"], |
1562 params["debuggerId"], |
1564 params["debuggerId"], |
1563 ) |
1565 ) |
1564 if params["debuggerId"] == self.__master: |
1566 if params["debuggerId"] == self.__mainDebugger: |
1565 self.debugServer.signalMainClientExit() |
1567 self.debugServer.signalMainClientExit() |
1566 |
1568 |
1567 elif method == "PassiveStartup": |
1569 elif method == "PassiveStartup": |
1568 self.debugServer.passiveStartUp( |
1570 self.debugServer.passiveStartUp( |
1569 self.translate(params["filename"], True), |
1571 self.translate(params["filename"], True), |
1597 } |
1599 } |
1598 cmd = json.dumps(commandDict) + "\n" |
1600 cmd = json.dumps(commandDict) + "\n" |
1599 |
1601 |
1600 if debuggerId and debuggerId in self.__connections: |
1602 if debuggerId and debuggerId in self.__connections: |
1601 sock = self.__connections[debuggerId] |
1603 sock = self.__connections[debuggerId] |
1602 elif sock is None and self.__master is not None: |
1604 elif sock is None and self.__mainDebugger is not None: |
1603 sock = self.__connections[self.__master] |
1605 sock = self.__connections[self.__mainDebugger] |
1604 if sock is not None: |
1606 if sock is not None: |
1605 self.__writeJsonCommandToSocket(cmd, sock) |
1607 self.__writeJsonCommandToSocket(cmd, sock) |
1606 else: |
1608 else: |
1607 self.queue.append(cmd) |
1609 self.queue.append(cmd) |
1608 |
1610 |