eric6/Debugger/DebuggerInterfacePython.py

branch
multi_processing
changeset 7379
72a72fd56494
parent 7377
cc920e534ac0
child 7389
770ffcb88be5
equal deleted inserted replaced
7377:cc920e534ac0 7379:72a72fd56494
56 self.passive = passive 56 self.passive = passive
57 self.process = None 57 self.process = None
58 self.__variant = pythonVariant 58 self.__variant = pythonVariant
59 self.__startedVenv = "" 59 self.__startedVenv = ""
60 60
61 self.qsock = None
62 self.queue = [] 61 self.queue = []
62 self.__master = None
63 self.__connections = {} 63 self.__connections = {}
64 self.__pendingConnections = [] 64 self.__pendingConnections = []
65 65
66 # set default values for capabilities of clients 66 # set default values for capabilities of clients
67 self.clientCapabilities = ClientDefaultCapabilities 67 self.clientCapabilities = ClientDefaultCapabilities
485 """<p>The debugger backend could not be started.</p>""")) 485 """<p>The debugger backend could not be started.</p>"""))
486 else: 486 else:
487 self.__startedVenv = venvName 487 self.__startedVenv = venvName
488 488
489 return process, self.__isNetworked, interpreter 489 return process, self.__isNetworked, interpreter
490 490
491 def getClientCapabilities(self): 491 def getClientCapabilities(self):
492 """ 492 """
493 Public method to retrieve the debug clients capabilities. 493 Public method to retrieve the debug clients capabilities.
494 494
495 @return debug client capabilities (integer) 495 @return debug client capabilities (integer)
498 498
499 def newConnection(self, sock): 499 def newConnection(self, sock):
500 """ 500 """
501 Public slot to handle a new connection. 501 Public slot to handle a new connection.
502 502
503 @param sock reference to the socket object (QTcpSocket) 503 @param sock reference to the socket object
504 @return flag indicating success (boolean) 504 @type QTcpSocket
505 """ 505 @return flag indicating success
506 sock.disconnected.connect(self.debugServer.startClient) 506 @rtype bool
507 """
508 self.__pendingConnections.append(sock)
509
507 sock.readyRead.connect(lambda: self.__parseClientLine(sock)) 510 sock.readyRead.connect(lambda: self.__parseClientLine(sock))
508 511 sock.disconnected.connect(lambda: self.__socketDisconnected(sock))
509 if self.qsock is None: 512
510 # first connection is the main one
511 self.qsock = sock
512 self.__pendingConnections.append(sock)
513
514 # Get the remote clients capabilities
515 self.remoteCapabilities()
516 return True 513 return True
517 514
518 def __assignDebuggerId(self, sock, debuggerId): 515 def __assignDebuggerId(self, sock, debuggerId):
519 """ 516 """
520 Private method to set the debugger id for a recent debugger connection 517 Private method to set the debugger id for a recent debugger connection
527 """ 524 """
528 if sock in self.__pendingConnections: 525 if sock in self.__pendingConnections:
529 self.__connections[debuggerId] = sock 526 self.__connections[debuggerId] = sock
530 self.__pendingConnections.remove(sock) 527 self.__pendingConnections.remove(sock)
531 528
529 if self.__master is None:
530 self.__master = debuggerId
531 # Get the remote clients capabilities
532 self.remoteCapabilities()
533
532 self.debugServer.signalClientDebuggerIds( 534 self.debugServer.signalClientDebuggerIds(
533 sorted(self.__connections.keys())) 535 sorted(self.__connections.keys()))
536
537 if debuggerId == self.__master:
538 self.__flush()
539 self.debugServer.masterClientConnected()
540
541 self.debugServer.initializeClient(debuggerId)
542
543 def __socketDisconnected(self, sock):
544 """
545 Private slot handling a socket disconnecting.
546
547 @param sock reference to the disconnected socket
548 @type QTcpSocket
549 """
550 for debuggerId in self.__connections:
551 if self.__connections[debuggerId] is sock:
552 del self.__connections[debuggerId]
553 break
554 else:
555 if sock in self.__pendingConnections:
556 self.__pendingConnections.remove(sock)
557
558 if not self.__connections:
559 # no active connections anymore => restart the backend
560 self.debugServer.startClient()
534 561
535 def getDebuggerIds(self): 562 def getDebuggerIds(self):
536 """ 563 """
537 Public method to return the IDs of the connected debugger backends. 564 Public method to return the IDs of the connected debugger backends.
538 565
539 @return list of connected debugger backend IDs 566 @return list of connected debugger backend IDs
540 @rtype list of str 567 @rtype list of str
541 """ 568 """
542 return sorted(self.__connections.keys()) 569 return sorted(self.__connections.keys())
543 570
544 def flush(self): 571 def __flush(self):
545 """ 572 """
546 Public slot to flush the queue. 573 Private slot to flush the queue.
547 """ 574 """
548 if self.qsock: 575 if self.__master:
549 # Send commands that were waiting for the connection. 576 # Send commands that were waiting for the connection.
550 for cmd in self.queue: 577 for cmd in self.queue:
551 self.__writeJsonCommandToSocket(cmd, self.qsock) 578 self.__writeJsonCommandToSocket(
579 cmd, self.__connections[self.__master])
552 580
553 self.queue = [] 581 self.queue = []
554 582
555 def shutdown(self): 583 def shutdown(self):
556 """ 584 """
557 Public method to cleanly shut down. 585 Public method to cleanly shut down.
558 586
559 It closes our socket and shuts down 587 It closes our sockets and shuts down the debug clients.
560 the debug client. (Needed on Win OS) 588 (Needed on Win OS)
561 """ 589 """
562 if self.qsock is None: 590 if not self.__master:
563 return 591 return
564 592
565 for sock in ( 593 while self.__connections:
566 list(self.__connections.values()) + self.__pendingConnections 594 debuggerId, sock = self.__connections.popitem()
567 ): 595 self.__shutdownSocket(sock)
568 # do not want any slots called during shutdown 596
569 sock.disconnected.disconnect() 597 while self.__pendingConnections:
570 sock.readyRead.disconnect() 598 sock = self.__pendingConnections.pop()
571 599 self.__shutdownSocket(sock)
572 # close down socket, and shut down client as well.
573 self.__sendJsonCommand("RequestShutdown", {}, sock=sock)
574 sock.flush()
575 sock.close()
576 600
577 # reinitialize 601 # reinitialize
578 self.qsock = None
579 self.queue = [] 602 self.queue = []
580 603
581 self.__pendingConnections = [] 604 self.__master = None
582 self.__connections = {} 605
606 def __shutdownSocket(self, sock):
607 """
608 Private slot to shut down a socket.
609
610 @param sock reference to the socket
611 @type QTcpSocket
612 """
613 # do not want any slots called during shutdown
614 sock.readyRead.disconnect()
615 sock.disconnected.disconnect()
616
617 # close down socket, and shut down client as well.
618 self.__sendJsonCommand("RequestShutdown", {}, sock=sock)
619 sock.flush()
620 sock.close()
621
622 sock.setParent(None)
623 sock.deleteLater()
624 del sock
583 625
584 def isConnected(self): 626 def isConnected(self):
585 """ 627 """
586 Public method to test, if a debug client has connected. 628 Public method to test, if a debug client has connected.
587 629
588 @return flag indicating the connection status (boolean) 630 @return flag indicating the connection status
589 """ 631 @rtype bool
590 return self.qsock is not None 632 """
633 return bool(self.__connections)
591 634
592 def remoteEnvironment(self, env): 635 def remoteEnvironment(self, env):
593 """ 636 """
594 Public method to set the environment for a program to debug, run, ... 637 Public method to set the environment for a program to debug, run, ...
595 638
596 @param env environment settings (dictionary) 639 @param env environment settings (dictionary)
597 """ 640 """
598 self.__sendJsonCommand("RequestEnvironment", {"environment": env}) 641 if self.__master:
642 self.__sendJsonCommand("RequestEnvironment", {"environment": env},
643 self.__master)
599 644
600 def remoteLoad(self, fn, argv, wd, traceInterpreter=False, 645 def remoteLoad(self, fn, argv, wd, traceInterpreter=False,
601 autoContinue=True, autoFork=False, forkChild=False): 646 autoContinue=True, autoFork=False, forkChild=False):
602 """ 647 """
603 Public method to load a new program to debug. 648 Public method to load a new program to debug.
623 "filename": fn, 668 "filename": fn,
624 "argv": Utilities.parseOptionString(argv), 669 "argv": Utilities.parseOptionString(argv),
625 "traceInterpreter": traceInterpreter, 670 "traceInterpreter": traceInterpreter,
626 "autofork": autoFork, 671 "autofork": autoFork,
627 "forkChild": forkChild, 672 "forkChild": forkChild,
628 }) 673 }, self.__master)
629 674
630 def remoteRun(self, fn, argv, wd, autoFork=False, forkChild=False): 675 def remoteRun(self, fn, argv, wd, autoFork=False, forkChild=False):
631 """ 676 """
632 Public method to load a new program to run. 677 Public method to load a new program to run.
633 678
646 "workdir": wd, 691 "workdir": wd,
647 "filename": fn, 692 "filename": fn,
648 "argv": Utilities.parseOptionString(argv), 693 "argv": Utilities.parseOptionString(argv),
649 "autofork": autoFork, 694 "autofork": autoFork,
650 "forkChild": forkChild, 695 "forkChild": forkChild,
651 }) 696 }, self.__master)
652 697
653 def remoteCoverage(self, fn, argv, wd, erase=False): 698 def remoteCoverage(self, fn, argv, wd, erase=False):
654 """ 699 """
655 Public method to load a new program to collect coverage data. 700 Public method to load a new program to collect coverage data.
656 701
667 self.__sendJsonCommand("RequestCoverage", { 712 self.__sendJsonCommand("RequestCoverage", {
668 "workdir": wd, 713 "workdir": wd,
669 "filename": fn, 714 "filename": fn,
670 "argv": Utilities.parseOptionString(argv), 715 "argv": Utilities.parseOptionString(argv),
671 "erase": erase, 716 "erase": erase,
672 }) 717 }, self.__master)
673 718
674 def remoteProfile(self, fn, argv, wd, erase=False): 719 def remoteProfile(self, fn, argv, wd, erase=False):
675 """ 720 """
676 Public method to load a new program to collect profiling data. 721 Public method to load a new program to collect profiling data.
677 722
688 self.__sendJsonCommand("RequestProfile", { 733 self.__sendJsonCommand("RequestProfile", {
689 "workdir": wd, 734 "workdir": wd,
690 "filename": fn, 735 "filename": fn,
691 "argv": Utilities.parseOptionString(argv), 736 "argv": Utilities.parseOptionString(argv),
692 "erase": erase, 737 "erase": erase,
693 }) 738 }, self.__master)
694 739
695 def remoteStatement(self, stmt): 740 def remoteStatement(self, debuggerId, stmt):
696 """ 741 """
697 Public method to execute a Python statement. 742 Public method to execute a Python statement.
698 743
699 @param stmt the Python statement to execute (string). It 744 @param debuggerId ID of the debugger backend
700 should not have a trailing newline. 745 @type str
746 @param stmt the Python statement to execute.
747 @type str
701 """ 748 """
702 self.__sendJsonCommand("ExecuteStatement", { 749 self.__sendJsonCommand("ExecuteStatement", {
703 "statement": stmt, 750 "statement": stmt,
704 }) 751 }, debuggerId)
705 752
706 def remoteStep(self): 753 def remoteStep(self, debuggerId):
707 """ 754 """
708 Public method to single step the debugged program. 755 Public method to single step the debugged program.
709 """ 756
710 self.__sendJsonCommand("RequestStep", {}) 757 @param debuggerId ID of the debugger backend
711 758 @type str
712 def remoteStepOver(self): 759 """
760 self.__sendJsonCommand("RequestStep", {}, debuggerId)
761
762 def remoteStepOver(self, debuggerId):
713 """ 763 """
714 Public method to step over the debugged program. 764 Public method to step over the debugged program.
715 """ 765
716 self.__sendJsonCommand("RequestStepOver", {}) 766 @param debuggerId ID of the debugger backend
717 767 @type str
718 def remoteStepOut(self): 768 """
769 self.__sendJsonCommand("RequestStepOver", {}, debuggerId)
770
771 def remoteStepOut(self, debuggerId):
719 """ 772 """
720 Public method to step out the debugged program. 773 Public method to step out the debugged program.
721 """ 774
722 self.__sendJsonCommand("RequestStepOut", {}) 775 @param debuggerId ID of the debugger backend
723 776 @type str
724 def remoteStepQuit(self): 777 """
778 self.__sendJsonCommand("RequestStepOut", {}, debuggerId)
779
780 def remoteStepQuit(self, debuggerId):
725 """ 781 """
726 Public method to stop the debugged program. 782 Public method to stop the debugged program.
727 """ 783
728 self.__sendJsonCommand("RequestStepQuit", {}) 784 @param debuggerId ID of the debugger backend
729 785 @type str
730 def remoteContinue(self, special=False): 786 """
787 self.__sendJsonCommand("RequestStepQuit", {}, debuggerId)
788
789 def remoteContinue(self, debuggerId, special=False):
731 """ 790 """
732 Public method to continue the debugged program. 791 Public method to continue the debugged program.
733 792
793 @param debuggerId ID of the debugger backend
794 @type str
734 @param special flag indicating a special continue operation 795 @param special flag indicating a special continue operation
796 @type bool
735 """ 797 """
736 self.__sendJsonCommand("RequestContinue", { 798 self.__sendJsonCommand("RequestContinue", {
737 "special": special, 799 "special": special,
738 }) 800 }, debuggerId)
739 801
740 def remoteMoveIP(self, line): 802 def remoteMoveIP(self, debuggerId, line):
741 """ 803 """
742 Public method to move the instruction pointer to a different line. 804 Public method to move the instruction pointer to a different line.
743 805
806 @param debuggerId ID of the debugger backend
807 @type str
744 @param line the new line, where execution should be continued 808 @param line the new line, where execution should be continued
809 @type int
745 """ 810 """
746 self.__sendJsonCommand("RequestMoveIP", { 811 self.__sendJsonCommand("RequestMoveIP", {
747 "newLine": line, 812 "newLine": line,
748 }) 813 }, debuggerId)
749 814
750 def remoteBreakpoint(self, fn, line, setBreakpoint, cond=None, temp=False): 815 def remoteBreakpoint(self, debuggerId, fn, line, setBreakpoint, cond=None,
816 temp=False):
751 """ 817 """
752 Public method to set or clear a breakpoint. 818 Public method to set or clear a breakpoint.
753 819
754 @param fn filename the breakpoint belongs to (string) 820 @param debuggerId ID of the debugger backend
755 @param line linenumber of the breakpoint (int) 821 @type str
756 @param setBreakpoint flag indicating setting or resetting a 822 @param fn filename the breakpoint belongs to
757 breakpoint (boolean) 823 @type str
758 @param cond condition of the breakpoint (string) 824 @param line linenumber of the breakpoint
759 @param temp flag indicating a temporary breakpoint (boolean) 825 @type int
760 """ 826 @param setBreakpoint flag indicating setting or resetting a breakpoint
761 self.__sendJsonCommand("RequestBreakpoint", { 827 @type bool
762 "filename": self.translate(fn, False), 828 @param cond condition of the breakpoint
763 "line": line, 829 @type str
764 "temporary": temp, 830 @param temp flag indicating a temporary breakpoint
765 "setBreakpoint": setBreakpoint, 831 @type bool
766 "condition": cond, 832 """
767 }) 833 if debuggerId:
768 834 debuggerList = [debuggerId]
769 def remoteBreakpointEnable(self, fn, line, enable): 835 else:
836 debuggerList = list(self.__connections.keys())
837 for debuggerId in debuggerList:
838 self.__sendJsonCommand("RequestBreakpoint", {
839 "filename": self.translate(fn, False),
840 "line": line,
841 "temporary": temp,
842 "setBreakpoint": setBreakpoint,
843 "condition": cond,
844 }, debuggerId)
845
846 def remoteBreakpointEnable(self, debuggerId, fn, line, enable):
770 """ 847 """
771 Public method to enable or disable a breakpoint. 848 Public method to enable or disable a breakpoint.
772 849
773 @param fn filename the breakpoint belongs to (string) 850 @param debuggerId ID of the debugger backend
774 @param line linenumber of the breakpoint (int) 851 @type str
852 @param fn filename the breakpoint belongs to
853 @type str
854 @param line linenumber of the breakpoint
855 @type int
775 @param enable flag indicating enabling or disabling a breakpoint 856 @param enable flag indicating enabling or disabling a breakpoint
776 (boolean) 857 @type bool
777 """ 858 """
778 self.__sendJsonCommand("RequestBreakpointEnable", { 859 if debuggerId:
779 "filename": self.translate(fn, False), 860 debuggerList = [debuggerId]
780 "line": line, 861 else:
781 "enable": enable, 862 debuggerList = list(self.__connections.keys())
782 }) 863 for debuggerId in debuggerList:
783 864 self.__sendJsonCommand("RequestBreakpointEnable", {
784 def remoteBreakpointIgnore(self, fn, line, count): 865 "filename": self.translate(fn, False),
866 "line": line,
867 "enable": enable,
868 }, debuggerId)
869
870 def remoteBreakpointIgnore(self, debuggerId, fn, line, count):
785 """ 871 """
786 Public method to ignore a breakpoint the next couple of occurrences. 872 Public method to ignore a breakpoint the next couple of occurrences.
787 873
788 @param fn filename the breakpoint belongs to (string) 874 @param debuggerId ID of the debugger backend
789 @param line linenumber of the breakpoint (int) 875 @type str
790 @param count number of occurrences to ignore (int) 876 @param fn filename the breakpoint belongs to
791 """ 877 @type str
792 self.__sendJsonCommand("RequestBreakpointIgnore", { 878 @param line linenumber of the breakpoint
793 "filename": self.translate(fn, False), 879 @type int
794 "line": line, 880 @param count number of occurrences to ignore
795 "count": count, 881 @type int
796 }) 882 """
797 883 if debuggerId:
798 def remoteWatchpoint(self, cond, setWatch, temp=False): 884 debuggerList = [debuggerId]
885 else:
886 debuggerList = list(self.__connections.keys())
887 for debuggerId in debuggerList:
888 self.__sendJsonCommand("RequestBreakpointIgnore", {
889 "filename": self.translate(fn, False),
890 "line": line,
891 "count": count,
892 }, debuggerId)
893
894 def remoteWatchpoint(self, debuggerId, cond, setWatch, temp=False):
799 """ 895 """
800 Public method to set or clear a watch expression. 896 Public method to set or clear a watch expression.
801 897
802 @param cond expression of the watch expression (string) 898 @param debuggerId ID of the debugger backend
899 @type str
900 @param cond expression of the watch expression
901 @type str
803 @param setWatch flag indicating setting or resetting a watch expression 902 @param setWatch flag indicating setting or resetting a watch expression
804 (boolean) 903 @type bool
805 @param temp flag indicating a temporary watch expression (boolean) 904 @param temp flag indicating a temporary watch expression
806 """ 905 @type bool
807 # cond is combination of cond and special (s. watch expression viewer) 906 """
808 self.__sendJsonCommand("RequestWatch", { 907 if debuggerId:
809 "temporary": temp, 908 debuggerList = [debuggerId]
810 "setWatch": setWatch, 909 else:
811 "condition": cond, 910 debuggerList = list(self.__connections.keys())
812 }) 911 for debuggerId in debuggerList:
813 912 # cond is combination of cond and special (s. watch expression
814 def remoteWatchpointEnable(self, cond, enable): 913 # viewer)
914 self.__sendJsonCommand("RequestWatch", {
915 "temporary": temp,
916 "setWatch": setWatch,
917 "condition": cond,
918 }, debuggerId)
919
920 def remoteWatchpointEnable(self, debuggerId, cond, enable):
815 """ 921 """
816 Public method to enable or disable a watch expression. 922 Public method to enable or disable a watch expression.
817 923
818 @param cond expression of the watch expression (string) 924 @param debuggerId ID of the debugger backend
925 @type str
926 @param cond expression of the watch expression
927 @type str
819 @param enable flag indicating enabling or disabling a watch expression 928 @param enable flag indicating enabling or disabling a watch expression
820 (boolean) 929 @type bool
821 """ 930 """
822 # cond is combination of cond and special (s. watch expression viewer) 931 if debuggerId:
823 self.__sendJsonCommand("RequestWatchEnable", { 932 debuggerList = [debuggerId]
824 "condition": cond, 933 else:
825 "enable": enable, 934 debuggerList = list(self.__connections.keys())
826 }) 935 for debuggerId in debuggerList:
827 936 # cond is combination of cond and special (s. watch expression
828 def remoteWatchpointIgnore(self, cond, count): 937 # viewer)
938 self.__sendJsonCommand("RequestWatchEnable", {
939 "condition": cond,
940 "enable": enable,
941 }, debuggerId)
942
943 def remoteWatchpointIgnore(self, debuggerId, cond, count):
829 """ 944 """
830 Public method to ignore a watch expression the next couple of 945 Public method to ignore a watch expression the next couple of
831 occurrences. 946 occurrences.
832 947
833 @param cond expression of the watch expression (string) 948 @param debuggerId ID of the debugger backend
834 @param count number of occurrences to ignore (int) 949 @type str
835 """ 950 @param cond expression of the watch expression
836 # cond is combination of cond and special (s. watch expression viewer) 951 @type str
837 self.__sendJsonCommand("RequestWatchIgnore", { 952 @param count number of occurrences to ignore
838 "condition": cond, 953 @type int
839 "count": count, 954 """
840 }) 955 if debuggerId:
841 956 debuggerList = [debuggerId]
957 else:
958 debuggerList = list(self.__connections.keys())
959 for debuggerId in debuggerList:
960 # cond is combination of cond and special (s. watch expression
961 # viewer)
962 self.__sendJsonCommand("RequestWatchIgnore", {
963 "condition": cond,
964 "count": count,
965 }, debuggerId)
966
967 # TODO: add debuggerId
842 def remoteRawInput(self, s): 968 def remoteRawInput(self, s):
843 """ 969 """
844 Public method to send the raw input to the debugged program. 970 Public method to send the raw input to the debugged program.
845 971
846 @param s the raw input (string) 972 @param s the raw input (string)
847 """ 973 """
848 self.__sendJsonCommand("RawInput", { 974 self.__sendJsonCommand("RawInput", {
849 "input": s, 975 "input": s,
850 }) 976 })
851 977
852 def remoteThreadList(self, debuggerId=""): 978 def remoteThreadList(self, debuggerId):
853 """ 979 """
854 Public method to request the list of threads from the client. 980 Public method to request the list of threads from the client.
855 981
856 @param debuggerId ID of the debugger backend 982 @param debuggerId ID of the debugger backend
857 @type str 983 @type str
858 """ 984 """
859 self.__sendJsonCommand("RequestThreadList", {}, debuggerId=debuggerId) 985 self.__sendJsonCommand("RequestThreadList", {}, debuggerId)
860 986
861 def remoteSetThread(self, tid, debuggerId=""): 987 def remoteSetThread(self, debuggerId, tid):
862 """ 988 """
863 Public method to request to set the given thread as current thread. 989 Public method to request to set the given thread as current thread.
864 990
991 @param debuggerId ID of the debugger backend
992 @type str
865 @param tid id of the thread 993 @param tid id of the thread
866 @type int 994 @type int
867 @param debuggerId ID of the debugger backend
868 @type str
869 """ 995 """
870 self.__sendJsonCommand("RequestThreadSet", { 996 self.__sendJsonCommand("RequestThreadSet", {
871 "threadID": tid, 997 "threadID": tid,
872 }, debuggerId=debuggerId) 998 }, debuggerId)
873 999
874 def remoteClientStack(self, debuggerId=""): 1000 def remoteClientStack(self, debuggerId):
875 """ 1001 """
876 Public method to request the stack of the main thread. 1002 Public method to request the stack of the main thread.
877 1003
878 @param debuggerId ID of the debugger backend 1004 @param debuggerId ID of the debugger backend
879 @type str 1005 @type str
880 """ 1006 """
881 self.__sendJsonCommand("RequestStack", {}, debuggerId=debuggerId) 1007 self.__sendJsonCommand("RequestStack", {}, debuggerId)
882 1008
883 def remoteClientVariables(self, scope, filterList, framenr=0, maxSize=0, 1009 def remoteClientVariables(self, debuggerId, scope, filterList, framenr=0,
884 debuggerId=""): 1010 maxSize=0):
885 """ 1011 """
886 Public method to request the variables of the debugged program. 1012 Public method to request the variables of the debugged program.
887 1013
1014 @param debuggerId ID of the debugger backend
1015 @type str
888 @param scope the scope of the variables (0 = local, 1 = global) 1016 @param scope the scope of the variables (0 = local, 1 = global)
889 @type int 1017 @type int
890 @param filterList list of variable types to filter out 1018 @param filterList list of variable types to filter out
891 @type list of int 1019 @type list of int
892 @param framenr framenumber of the variables to retrieve 1020 @param framenr framenumber of the variables to retrieve
893 @type int 1021 @type int
894 @param maxSize maximum size the formatted value of a variable will 1022 @param maxSize maximum size the formatted value of a variable will
895 be shown. If it is bigger than that, a 'too big' indication will 1023 be shown. If it is bigger than that, a 'too big' indication will
896 be given (@@TOO_BIG_TO_SHOW@@). 1024 be given (@@TOO_BIG_TO_SHOW@@).
897 @type int 1025 @type int
898 @param debuggerId ID of the debugger backend
899 @type str
900 """ 1026 """
901 self.__sendJsonCommand("RequestVariables", { 1027 self.__sendJsonCommand("RequestVariables", {
902 "frameNumber": framenr, 1028 "frameNumber": framenr,
903 "scope": scope, 1029 "scope": scope,
904 "filters": filterList, 1030 "filters": filterList,
905 "maxSize": maxSize, 1031 "maxSize": maxSize,
906 }, debuggerId=debuggerId) 1032 }, debuggerId)
907 1033
908 def remoteClientVariable(self, scope, filterList, var, framenr=0, 1034 def remoteClientVariable(self, debuggerId, scope, filterList, var,
909 maxSize=0): 1035 framenr=0, maxSize=0):
910 """ 1036 """
911 Public method to request the variables of the debugged program. 1037 Public method to request the variables of the debugged program.
912 1038
1039 @param debuggerId ID of the debugger backend
1040 @type str
913 @param scope the scope of the variables (0 = local, 1 = global) 1041 @param scope the scope of the variables (0 = local, 1 = global)
914 @type int 1042 @type int
915 @param filterList list of variable types to filter out 1043 @param filterList list of variable types to filter out
916 @type list of int 1044 @type list of int
917 @param var list encoded name of variable to retrieve 1045 @param var list encoded name of variable to retrieve
927 "variable": var, 1055 "variable": var,
928 "frameNumber": framenr, 1056 "frameNumber": framenr,
929 "scope": scope, 1057 "scope": scope,
930 "filters": filterList, 1058 "filters": filterList,
931 "maxSize": maxSize, 1059 "maxSize": maxSize,
932 }) 1060 }, debuggerId)
933 1061
1062 # TODO: add debuggerId
934 def remoteClientSetFilter(self, scope, filterStr): 1063 def remoteClientSetFilter(self, scope, filterStr):
935 """ 1064 """
936 Public method to set a variables filter list. 1065 Public method to set a variables filter list.
937 1066
938 @param scope the scope of the variables (0 = local, 1 = global) 1067 @param scope the scope of the variables (0 = local, 1 = global)
942 self.__sendJsonCommand("RequestSetFilter", { 1071 self.__sendJsonCommand("RequestSetFilter", {
943 "scope": scope, 1072 "scope": scope,
944 "filter": filterStr, 1073 "filter": filterStr,
945 }) 1074 })
946 1075
947 def setCallTraceEnabled(self, on): 1076 def setCallTraceEnabled(self, debuggerId, on):
948 """ 1077 """
949 Public method to set the call trace state. 1078 Public method to set the call trace state.
950 1079
951 @param on flag indicating to enable the call trace function (boolean) 1080 @param debuggerId ID of the debugger backend
1081 @type str
1082 @param on flag indicating to enable the call trace function
1083 @type bool
952 """ 1084 """
953 self.__sendJsonCommand("RequestCallTrace", { 1085 self.__sendJsonCommand("RequestCallTrace", {
954 "enable": on, 1086 "enable": on,
955 }) 1087 }, debuggerId)
956 1088
957 def remoteBanner(self): 1089 def remoteBanner(self):
958 """ 1090 """
959 Public slot to get the banner info of the remote client. 1091 Public slot to get the banner info of the remote client.
960 """ 1092 """
961 self.__sendJsonCommand("RequestBanner", {}) 1093 self.__sendJsonCommand("RequestBanner", {})
962 1094
963 def remoteCapabilities(self): 1095 def remoteCapabilities(self, debuggerId):
964 """ 1096 """
965 Public slot to get the debug clients capabilities. 1097 Public slot to get the debug clients capabilities.
966 """ 1098
967 self.__sendJsonCommand("RequestCapabilities", {}) 1099 @param debuggerId ID of the debugger backend
1100 @type str
1101 """
1102 self.__sendJsonCommand("RequestCapabilities", {}, debuggerId)
968 1103
969 def remoteCompletion(self, text): 1104 def remoteCompletion(self, text):
970 """ 1105 """
971 Public slot to get the a list of possible commandline completions 1106 Public slot to get the a list of possible commandline completions
972 from the remote client. 1107 from the remote client.
1157 1292
1158 elif method in ["ResponseLine", "ResponseStack"]: 1293 elif method in ["ResponseLine", "ResponseStack"]:
1159 # Check if obsolet thread was clicked 1294 # Check if obsolet thread was clicked
1160 if params["stack"] == []: 1295 if params["stack"] == []:
1161 # Request updated list 1296 # Request updated list
1162 self.remoteThreadList() 1297 self.remoteThreadList(params["debuggerId"])
1163 return 1298 return
1164 for s in params["stack"]: 1299 for s in params["stack"]:
1165 s[0] = self.translate(s[0], True) 1300 s[0] = self.translate(s[0], True)
1166 cf = params["stack"][0] 1301 cf = params["stack"][0]
1167 if self.__autoContinue: 1302 if self.__autoContinue:
1168 self.__autoContinue = False 1303 self.__autoContinue = False
1169 QTimer.singleShot(0, self.remoteContinue) 1304 QTimer.singleShot(
1305 0, lambda: self.remoteContinue(params["debuggerId"]))
1170 else: 1306 else:
1171 self.debugServer.signalClientLine( 1307 self.debugServer.signalClientLine(
1172 cf[0], int(cf[1]), params["debuggerId"], 1308 cf[0], int(cf[1]), params["debuggerId"],
1173 method == "ResponseStack") 1309 method == "ResponseStack")
1174 self.debugServer.signalClientStack( 1310 self.debugServer.signalClientStack(
1181 self.debugServer.signalClientCallTrace( 1317 self.debugServer.signalClientCallTrace(
1182 isCall, 1318 isCall,
1183 fromInfo["filename"], str(fromInfo["linenumber"]), 1319 fromInfo["filename"], str(fromInfo["linenumber"]),
1184 fromInfo["codename"], 1320 fromInfo["codename"],
1185 toInfo["filename"], str(toInfo["linenumber"]), 1321 toInfo["filename"], str(toInfo["linenumber"]),
1186 toInfo["codename"]) 1322 toInfo["codename"],
1323 params["debuggerId"])
1187 1324
1188 elif method == "ResponseVariables": 1325 elif method == "ResponseVariables":
1189 self.debugServer.signalClientVariables( 1326 self.debugServer.signalClientVariables(
1190 params["scope"], params["variables"]) 1327 params["scope"], params["variables"], params["debuggerId"])
1191 1328
1192 elif method == "ResponseVariable": 1329 elif method == "ResponseVariable":
1193 self.debugServer.signalClientVariable( 1330 self.debugServer.signalClientVariable(
1194 params["scope"], [params["variable"]] + params["variables"]) 1331 params["scope"], [params["variable"]] + params["variables"],
1332 params["debuggerId"])
1195 1333
1196 elif method == "ResponseThreadList": 1334 elif method == "ResponseThreadList":
1197 self.debugServer.signalClientThreadList( 1335 self.debugServer.signalClientThreadList(
1198 params["currentID"], params["threadList"], 1336 params["currentID"], params["threadList"],
1199 params["debuggerId"]) 1337 params["debuggerId"])
1200 1338
1201 elif method == "ResponseThreadSet": 1339 elif method == "ResponseThreadSet":
1202 self.debugServer.signalClientThreadSet() 1340 self.debugServer.signalClientThreadSet(params["debuggerId"])
1203 1341
1204 elif method == "ResponseCapabilities": 1342 elif method == "ResponseCapabilities":
1205 self.clientCapabilities = params["capabilities"] 1343 self.clientCapabilities = params["capabilities"]
1206 self.debugServer.signalClientCapabilities( 1344 if params["debuggerId"] == self.__master:
1207 params["capabilities"], 1345 # signal only for the master connection
1208 params["clientType"], 1346 self.debugServer.signalClientCapabilities(
1209 self.__startedVenv, 1347 params["capabilities"],
1210 ) 1348 params["clientType"],
1349 self.__startedVenv,
1350 )
1211 1351
1212 elif method == "ResponseBanner": 1352 elif method == "ResponseBanner":
1213 self.debugServer.signalClientBanner( 1353 if params["debuggerId"] == self.__master:
1214 params["version"], 1354 # signal only for the master connection
1215 params["platform"], 1355 self.debugServer.signalClientBanner(
1216 params["dbgclient"], 1356 params["version"],
1217 self.__startedVenv, 1357 params["platform"],
1218 ) 1358 params["dbgclient"],
1359 self.__startedVenv,
1360 )
1219 1361
1220 elif method == "ResponseOK": 1362 elif method == "ResponseOK":
1221 self.debugServer.signalClientStatement(False) 1363 self.debugServer.signalClientStatement(False, params["debuggerId"])
1222 1364
1223 elif method == "ResponseContinue": 1365 elif method == "ResponseContinue":
1224 self.debugServer.signalClientStatement(True) 1366 self.debugServer.signalClientStatement(True, params["debuggerId"])
1225 1367
1368 # TODO: add debuggerId
1226 elif method == "RequestRaw": 1369 elif method == "RequestRaw":
1227 self.debugServer.signalClientRawInput( 1370 self.debugServer.signalClientRawInput(
1228 params["prompt"], params["echo"]) 1371 params["prompt"], params["echo"])
1229 1372
1373 # TODO: add debuggerId
1230 elif method == "ResponseBPConditionError": 1374 elif method == "ResponseBPConditionError":
1231 fn = self.translate(params["filename"], True) 1375 fn = self.translate(params["filename"], True)
1232 self.debugServer.signalClientBreakConditionError( 1376 self.debugServer.signalClientBreakConditionError(
1233 fn, params["line"]) 1377 fn, params["line"])
1234 1378
1379 # TODO: add debuggerId
1235 elif method == "ResponseClearBreakpoint": 1380 elif method == "ResponseClearBreakpoint":
1236 fn = self.translate(params["filename"], True) 1381 fn = self.translate(params["filename"], True)
1237 self.debugServer.signalClientClearBreak(fn, params["line"]) 1382 self.debugServer.signalClientClearBreak(fn, params["line"])
1238 1383
1384 # TODO: add debuggerId
1239 elif method == "ResponseWatchConditionError": 1385 elif method == "ResponseWatchConditionError":
1240 self.debugServer.signalClientWatchConditionError( 1386 self.debugServer.signalClientWatchConditionError(
1241 params["condition"]) 1387 params["condition"])
1242 1388
1389 # TODO: add debuggerId
1243 elif method == "ResponseClearWatch": 1390 elif method == "ResponseClearWatch":
1244 self.debugServer.signalClientClearWatch(params["condition"]) 1391 self.debugServer.signalClientClearWatch(params["condition"])
1245 1392
1246 elif method == "ResponseException": 1393 elif method == "ResponseException":
1247 if params: 1394 exctype = params["type"]
1248 exctype = params["type"] 1395 excmessage = params["message"]
1249 excmessage = params["message"] 1396 stack = params["stack"]
1250 stack = params["stack"] 1397 if stack:
1251 if stack: 1398 for stackEntry in stack:
1399 stackEntry[0] = self.translate(stackEntry[0], True)
1400 if stack[0] and stack[0][0] == "<string>":
1252 for stackEntry in stack: 1401 for stackEntry in stack:
1253 stackEntry[0] = self.translate(stackEntry[0], True) 1402 if stackEntry[0] == "<string>":
1254 if stack[0] and stack[0][0] == "<string>": 1403 stackEntry[0] = self.__scriptName
1255 for stackEntry in stack: 1404 else:
1256 if stackEntry[0] == "<string>": 1405 break
1257 stackEntry[0] = self.__scriptName
1258 else:
1259 break
1260 else:
1261 exctype = ''
1262 excmessage = ''
1263 stack = []
1264 1406
1265 self.debugServer.signalClientException( 1407 self.debugServer.signalClientException(
1266 exctype, excmessage, stack) 1408 exctype, excmessage, stack, params["debuggerId"])
1267 1409
1268 elif method == "ResponseSyntax": 1410 elif method == "ResponseSyntax":
1269 self.debugServer.signalClientSyntaxError( 1411 self.debugServer.signalClientSyntaxError(
1270 params["message"], self.translate(params["filename"], True), 1412 params["message"], self.translate(params["filename"], True),
1271 params["linenumber"], params["characternumber"]) 1413 params["linenumber"], params["characternumber"],
1414 params["debuggerId"])
1272 1415
1273 elif method == "ResponseSignal": 1416 elif method == "ResponseSignal":
1274 self.debugServer.signalClientSignal( 1417 self.debugServer.signalClientSignal(
1275 params["message"], self.translate(params["filename"], True), 1418 params["message"], self.translate(params["filename"], True),
1276 params["linenumber"], params["function"], params["arguments"]) 1419 params["linenumber"], params["function"], params["arguments"],
1420 params["debuggerId"])
1277 1421
1278 elif method == "ResponseExit": 1422 elif method == "ResponseExit":
1279 self.__scriptName = "" 1423 self.__scriptName = ""
1280 self.debugServer.signalClientExit( 1424 self.debugServer.signalClientExit(
1281 params["status"], params["message"]) 1425 params["status"], params["message"], params["debuggerId"])
1282 1426
1283 elif method == "PassiveStartup": 1427 elif method == "PassiveStartup":
1284 self.debugServer.passiveStartUp( 1428 self.debugServer.passiveStartUp(
1285 self.translate(params["filename"], True), params["exceptions"]) 1429 self.translate(params["filename"], True), params["exceptions"])
1286 1430
1287 elif method == "ResponseCompletion": 1431 elif method == "ResponseCompletion":
1288 self.debugServer.signalClientCompletionList( 1432 if params["debuggerId"] == self.__master:
1289 params["completions"], params["text"]) 1433 # signal only for the master connection
1434 self.debugServer.signalClientCompletionList(
1435 params["completions"], params["text"])
1436
1437 ###################################################################
1438 ## Unit test related stuff is not done with multi processing
1439 ###################################################################
1290 1440
1291 elif method == "ResponseUTDiscover": 1441 elif method == "ResponseUTDiscover":
1292 self.debugServer.clientUtDiscovered( 1442 self.debugServer.clientUtDiscovered(
1293 params["testCasesList"], params["exception"], 1443 params["testCasesList"], params["exception"],
1294 params["message"]) 1444 params["message"])
1325 1475
1326 elif method == "ResponseUTTestSucceededUnexpected": 1476 elif method == "ResponseUTTestSucceededUnexpected":
1327 self.debugServer.clientUtTestSucceededUnexpected( 1477 self.debugServer.clientUtTestSucceededUnexpected(
1328 params["testname"], params["id"]) 1478 params["testname"], params["id"])
1329 1479
1480 # TODO: add debuggerId
1330 elif method == "RequestForkTo": 1481 elif method == "RequestForkTo":
1331 self.__askForkTo() 1482 self.__askForkTo()
1332 1483
1333 def __sendJsonCommand(self, command, params, debuggerId="", sock=None): 1484 def __sendJsonCommand(self, command, params, debuggerId="", sock=None):
1334 """ 1485 """
1353 } 1504 }
1354 cmd = json.dumps(commandDict) + '\n' 1505 cmd = json.dumps(commandDict) + '\n'
1355 1506
1356 if debuggerId and debuggerId in self.__connections: 1507 if debuggerId and debuggerId in self.__connections:
1357 sock = self.__connections[debuggerId] 1508 sock = self.__connections[debuggerId]
1358 elif sock is None and self.qsock is not None: 1509 elif sock is None and self.__master is not None:
1359 sock = self.qsock 1510 sock = self.__connections[self.__master]
1360 if sock is not None: 1511 if sock is not None:
1361 self.__writeJsonCommandToSocket(cmd, sock) 1512 self.__writeJsonCommandToSocket(cmd, sock)
1362 else: 1513 else:
1363 self.queue.append(cmd) 1514 self.queue.append(cmd)
1364 1515

eric ide

mercurial