406 # Remove any newline. |
398 # Remove any newline. |
407 if line[-1] == '\n': |
399 if line[-1] == '\n': |
408 line = line[:-1] |
400 line = line[:-1] |
409 |
401 |
410 ## printerr(line) ##debug |
402 ## printerr(line) ##debug |
411 |
403 |
412 eoc = line.find('<') |
404 self.handleJsonCommand(line) |
413 |
405 |
414 if eoc >= 0 and line[0] == '>': |
406 def handleJsonCommand(self, jsonStr): |
415 # Get the command part and any argument. |
407 """ |
416 cmd = line[:eoc + 1] |
408 Public method to handle a command serialized as a JSON string. |
417 arg = line[eoc + 1:] |
409 |
418 |
410 @param jsonStr string containing the command received from the IDE |
419 if cmd == DebugProtocol.RequestVariables: |
411 @type str |
420 frmnr, scope, filter = eval(arg) |
412 """ |
421 self.__dumpVariables(int(frmnr), int(scope), filter) |
413 import json |
422 return |
414 |
423 |
415 try: |
424 if cmd == DebugProtocol.RequestVariable: |
416 commandDict = json.loads(jsonStr.strip()) |
425 var, frmnr, scope, filter = eval(arg) |
417 except json.JSONDecodeError as err: |
426 self.__dumpVariable(var, int(frmnr), int(scope), filter) |
418 printerr(str(err)) |
427 return |
419 return |
428 |
420 |
429 if cmd == DebugProtocol.RequestThreadList: |
421 method = commandDict["method"] |
430 self.__dumpThreadList() |
422 params = commandDict["params"] |
431 return |
423 |
432 |
424 if method == "RequestVariables": |
433 if cmd == DebugProtocol.RequestThreadSet: |
425 self.__dumpVariables( |
434 tid = eval(arg) |
426 params["frameNumber"], params["scope"], params["filters"]) |
435 if tid in self.threads: |
427 |
436 self.setCurrentThread(tid) |
428 elif method == "RequestVariable": |
437 self.write(DebugProtocol.ResponseThreadSet + '\n') |
429 self.__dumpVariable( |
438 stack = self.currentThread.getStack() |
430 params["variable"], params["frameNumber"], |
439 self.write('%s%s\n' % (DebugProtocol.ResponseStack, |
431 params["scope"], params["filters"]) |
440 unicode(stack))) |
432 |
441 return |
433 elif method == "RequestThreadList": |
442 |
434 self.__dumpThreadList() |
443 if cmd == DebugProtocol.RequestStep: |
435 |
444 self.currentThread.step(1) |
436 elif method == "RequestThreadSet": |
445 self.eventExit = 1 |
437 if params["threadID"] in self.threads: |
446 return |
438 self.setCurrentThread(params["threadID"]) |
447 |
439 self.sendJsonCommand("ResponseThreadSet", {}) |
448 if cmd == DebugProtocol.RequestStepOver: |
440 stack = self.currentThread.getStack() |
449 self.currentThread.step(0) |
441 self.sendJsonCommand("ResponseStack", { |
450 self.eventExit = 1 |
442 "stack": stack, |
451 return |
443 }) |
452 |
444 |
453 if cmd == DebugProtocol.RequestStepOut: |
445 elif method == "RequestCapabilities": |
454 self.currentThread.stepOut() |
446 self.sendJsonCommand("ResponseCapabilities", { |
455 self.eventExit = 1 |
447 "capabilities": self.__clientCapabilities(), |
456 return |
448 "clientType": "Python3" |
457 |
449 }) |
458 if cmd == DebugProtocol.RequestStepQuit: |
450 |
459 if self.passive: |
451 elif method == "RequestBanner": |
460 self.progTerminated(42) |
452 self.sendJsonCommand("ResponseBanner", { |
|
453 "version": "Python {0}".format(sys.version), |
|
454 "platform": socket.gethostname(), |
|
455 "dbgclient": self.variant, |
|
456 }) |
|
457 |
|
458 elif method == "RequestSetFilter": |
|
459 self.__generateFilterObjects(params["scope"], params["filter"]) |
|
460 |
|
461 elif method == "RequestCallTrace": |
|
462 if self.debugging: |
|
463 self.callTraceEnabled = params["enable"] |
|
464 else: |
|
465 self.__newCallTraceEnabled = params["enable"] |
|
466 # remember for later |
|
467 |
|
468 elif method == "RequestEnvironment": |
|
469 for key, value in params["environment"].items(): |
|
470 if key.endswith("+"): |
|
471 if key[:-1] in os.environ: |
|
472 os.environ[key[:-1]] += value |
|
473 else: |
|
474 os.environ[key[:-1]] = value |
461 else: |
475 else: |
462 self.set_quit() |
476 os.environ[key] = value |
463 self.eventExit = 1 |
477 |
464 return |
478 elif method == "RequestLoad": |
465 |
479 self._fncache = {} |
466 if cmd == DebugProtocol.RequestContinue: |
480 self.dircache = [] |
467 special = int(arg) |
481 sys.argv = [] |
468 self.currentThread.go(special) |
482 params["filename"] = params["filename"].encode( |
469 self.eventExit = 1 |
483 sys.getfilesystemencoding()) |
470 return |
484 self.__setCoding(params["filename"]) |
471 |
485 sys.argv.append(params["filename"]) |
472 if cmd == DebugProtocol.RequestOK: |
486 sys.argv.extend(params["argv"]) |
473 self.write(self.pendingResponse + '\n') |
487 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
474 self.pendingResponse = DebugProtocol.ResponseOK |
488 if params["workdir"] == '': |
475 return |
489 os.chdir(sys.path[1]) |
476 |
490 else: |
477 if cmd == DebugProtocol.RequestCallTrace: |
491 os.chdir(params["workdir"]) |
478 if arg.strip().lower() == "on": |
492 |
479 callTraceEnabled = True |
493 self.running = sys.argv[0] |
|
494 self.mainFrame = None |
|
495 self.debugging = True |
|
496 |
|
497 self.fork_auto = params["autofork"] |
|
498 self.fork_child = params["forkChild"] |
|
499 |
|
500 self.threads.clear() |
|
501 self.attachThread(mainThread=True) |
|
502 |
|
503 # set the system exception handling function to ensure, that |
|
504 # we report on all unhandled exceptions |
|
505 sys.excepthook = self.__unhandled_exception |
|
506 self.__interceptSignals() |
|
507 |
|
508 # clear all old breakpoints, they'll get set after we have |
|
509 # started |
|
510 self.mainThread.clear_all_breaks() |
|
511 |
|
512 self.mainThread.tracePython = params["traceInterpreter"] |
|
513 |
|
514 # This will eventually enter a local event loop. |
|
515 self.debugMod.__dict__['__file__'] = self.running |
|
516 sys.modules['__main__'] = self.debugMod |
|
517 self.callTraceEnabled = self.__newCallTraceEnabled |
|
518 res = self.mainThread.run( |
|
519 'execfile(' + repr(self.running) + ')', |
|
520 self.debugMod.__dict__) |
|
521 self.progTerminated(res) |
|
522 |
|
523 elif method == "RequestRun": |
|
524 sys.argv = [] |
|
525 params["filename"] = params["filename"].encode( |
|
526 sys.getfilesystemencoding()) |
|
527 self.__setCoding(params["filename"]) |
|
528 sys.argv.append(params["filename"]) |
|
529 sys.argv.extend(params["argv"]) |
|
530 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
531 if params["workdir"] == '': |
|
532 os.chdir(sys.path[1]) |
|
533 else: |
|
534 os.chdir(params["workdir"]) |
|
535 |
|
536 self.running = sys.argv[0] |
|
537 self.mainFrame = None |
|
538 self.botframe = None |
|
539 |
|
540 self.fork_auto = params["autofork"] |
|
541 self.fork_child = params["forkChild"] |
|
542 |
|
543 self.threads.clear() |
|
544 self.attachThread(mainThread=True) |
|
545 |
|
546 # set the system exception handling function to ensure, that |
|
547 # we report on all unhandled exceptions |
|
548 sys.excepthook = self.__unhandled_exception |
|
549 self.__interceptSignals() |
|
550 |
|
551 self.mainThread.tracePython = False |
|
552 |
|
553 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
554 sys.modules['__main__'] = self.debugMod |
|
555 res = 0 |
|
556 try: |
|
557 execfile(sys.argv[0], self.debugMod.__dict__) |
|
558 except SystemExit as exc: |
|
559 res = exc.code |
|
560 atexit._run_exitfuncs() |
|
561 self.writestream.flush() |
|
562 self.progTerminated(res) |
|
563 |
|
564 elif method == "RequestCoverage": |
|
565 from coverage import coverage |
|
566 sys.argv = [] |
|
567 params["filename"] = params["filename"].encode( |
|
568 sys.getfilesystemencoding()) |
|
569 self.__setCoding(params["filename"]) |
|
570 sys.argv.append(params["filename"]) |
|
571 sys.argv.extend(params["argv"]) |
|
572 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
573 if params["workdir"] == '': |
|
574 os.chdir(sys.path[1]) |
|
575 else: |
|
576 os.chdir(params["workdir"]) |
|
577 |
|
578 # set the system exception handling function to ensure, that |
|
579 # we report on all unhandled exceptions |
|
580 sys.excepthook = self.__unhandled_exception |
|
581 self.__interceptSignals() |
|
582 |
|
583 # generate a coverage object |
|
584 self.cover = coverage( |
|
585 auto_data=True, |
|
586 data_file="%s.coverage" % os.path.splitext(sys.argv[0])[0]) |
|
587 |
|
588 if params["erase"]: |
|
589 self.cover.erase() |
|
590 sys.modules['__main__'] = self.debugMod |
|
591 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
592 self.running = sys.argv[0] |
|
593 res = 0 |
|
594 self.cover.start() |
|
595 try: |
|
596 execfile(sys.argv[0], self.debugMod.__dict__) |
|
597 except SystemExit as exc: |
|
598 res = exc.code |
|
599 atexit._run_exitfuncs() |
|
600 self.cover.stop() |
|
601 self.cover.save() |
|
602 self.writestream.flush() |
|
603 self.progTerminated(res) |
|
604 |
|
605 elif method == "RequestProfile": |
|
606 sys.setprofile(None) |
|
607 import PyProfile |
|
608 sys.argv = [] |
|
609 params["filename"] = params["filename"].encode( |
|
610 sys.getfilesystemencoding()) |
|
611 self.__setCoding(params["filename"]) |
|
612 sys.argv.append(params["filename"]) |
|
613 sys.argv.extend(params["argv"]) |
|
614 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
615 if params["workdir"] == '': |
|
616 os.chdir(sys.path[1]) |
|
617 else: |
|
618 os.chdir(params["workdir"]) |
|
619 |
|
620 # set the system exception handling function to ensure, that |
|
621 # we report on all unhandled exceptions |
|
622 sys.excepthook = self.__unhandled_exception |
|
623 self.__interceptSignals() |
|
624 |
|
625 # generate a profile object |
|
626 self.prof = PyProfile.PyProfile(sys.argv[0]) |
|
627 |
|
628 if params["erase"]: |
|
629 self.prof.erase() |
|
630 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
631 sys.modules['__main__'] = self.debugMod |
|
632 self.running = sys.argv[0] |
|
633 res = 0 |
|
634 try: |
|
635 self.prof.run('execfile(%r)' % sys.argv[0]) |
|
636 except SystemExit as exc: |
|
637 res = exc.code |
|
638 atexit._run_exitfuncs() |
|
639 self.prof.save() |
|
640 self.writestream.flush() |
|
641 self.progTerminated(res) |
|
642 |
|
643 elif method == "ExecuteStatement": |
|
644 if self.buffer: |
|
645 self.buffer = self.buffer + '\n' + params["statement"] |
|
646 else: |
|
647 self.buffer = params["statement"] |
|
648 |
|
649 try: |
|
650 code = self.compile_command(self.buffer, self.readstream.name) |
|
651 except (OverflowError, SyntaxError, ValueError): |
|
652 # Report the exception |
|
653 sys.last_type, sys.last_value, sys.last_traceback = \ |
|
654 sys.exc_info() |
|
655 self.sendJsonCommand("ClientOutput", { |
|
656 "text": "".join(traceback.format_exception_only( |
|
657 sys.last_type, sys.last_value)) |
|
658 }) |
|
659 self.buffer = '' |
|
660 else: |
|
661 if code is None: |
|
662 self.sendJsonCommand("ResponseContinue", {}) |
|
663 return |
480 else: |
664 else: |
481 callTraceEnabled = False |
665 self.buffer = '' |
482 if self.debugging: |
666 |
483 self.callTraceEnabled = callTraceEnabled |
667 try: |
484 else: |
668 if self.running is None: |
485 self.__newCallTraceEnabled = callTraceEnabled |
669 exec code in self.debugMod.__dict__ |
486 # remember for later |
|
487 return |
|
488 |
|
489 if cmd == DebugProtocol.RequestEnv: |
|
490 env = eval(arg) |
|
491 for key, value in env.items(): |
|
492 if key.endswith("+"): |
|
493 if key[:-1] in os.environ: |
|
494 os.environ[key[:-1]] += value |
|
495 else: |
670 else: |
496 os.environ[key[:-1]] = value |
671 if self.currentThread is None: |
497 else: |
672 # program has terminated |
498 os.environ[key] = value |
|
499 return |
|
500 |
|
501 if cmd == DebugProtocol.RequestLoad: |
|
502 self._fncache = {} |
|
503 self.dircache = [] |
|
504 sys.argv = [] |
|
505 wd, fn, args, tracePython = arg.split('|') |
|
506 fn = fn.encode(sys.getfilesystemencoding()) |
|
507 self.__setCoding(fn) |
|
508 sys.argv.append(fn) |
|
509 sys.argv.extend(eval(args)) |
|
510 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
511 if wd == '': |
|
512 os.chdir(sys.path[1]) |
|
513 else: |
|
514 os.chdir(wd) |
|
515 tracePython = int(tracePython) |
|
516 self.running = sys.argv[0] |
|
517 self.mainFrame = None |
|
518 self.inRawMode = 0 |
|
519 self.debugging = 1 |
|
520 |
|
521 self.threads.clear() |
|
522 self.attachThread(mainThread=1) |
|
523 |
|
524 # set the system exception handling function to ensure, that |
|
525 # we report on all unhandled exceptions |
|
526 sys.excepthook = self.__unhandled_exception |
|
527 self.__interceptSignals() |
|
528 |
|
529 # clear all old breakpoints, they'll get set after we |
|
530 # have started |
|
531 self.mainThread.clear_all_breaks() |
|
532 |
|
533 self.mainThread.tracePython = tracePython |
|
534 |
|
535 # This will eventually enter a local event loop. |
|
536 # Note the use of backquotes to cause a repr of self.running. |
|
537 # The need for this is on Windows os where backslash is the |
|
538 # path separator. They will get inadvertantly stripped away |
|
539 # during the eval causing IOErrors, if self.running is passed |
|
540 # as a normal str. |
|
541 self.debugMod.__dict__['__file__'] = self.running |
|
542 sys.modules['__main__'] = self.debugMod |
|
543 self.callTraceEnabled = self.__newCallTraceEnabled |
|
544 res = self.mainThread.run( |
|
545 'execfile(' + repr(self.running) + ')', |
|
546 self.debugMod.__dict__) |
|
547 self.progTerminated(res) |
|
548 return |
|
549 |
|
550 if cmd == DebugProtocol.RequestRun: |
|
551 sys.argv = [] |
|
552 wd, fn, args = arg.split('|') |
|
553 fn = fn.encode(sys.getfilesystemencoding()) |
|
554 self.__setCoding(fn) |
|
555 sys.argv.append(fn) |
|
556 sys.argv.extend(eval(args)) |
|
557 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
558 if wd == '': |
|
559 os.chdir(sys.path[1]) |
|
560 else: |
|
561 os.chdir(wd) |
|
562 |
|
563 self.running = sys.argv[0] |
|
564 self.mainFrame = None |
|
565 self.botframe = None |
|
566 self.inRawMode = 0 |
|
567 |
|
568 self.threads.clear() |
|
569 self.attachThread(mainThread=1) |
|
570 |
|
571 # set the system exception handling function to ensure, that |
|
572 # we report on all unhandled exceptions |
|
573 sys.excepthook = self.__unhandled_exception |
|
574 self.__interceptSignals() |
|
575 |
|
576 self.mainThread.tracePython = 0 |
|
577 |
|
578 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
579 sys.modules['__main__'] = self.debugMod |
|
580 res = 0 |
|
581 try: |
|
582 execfile(sys.argv[0], self.debugMod.__dict__) |
|
583 except SystemExit as exc: |
|
584 res = exc.code |
|
585 atexit._run_exitfuncs() |
|
586 self.writestream.flush() |
|
587 self.progTerminated(res) |
|
588 return |
|
589 |
|
590 if cmd == DebugProtocol.RequestCoverage: |
|
591 from coverage import coverage |
|
592 sys.argv = [] |
|
593 wd, fn, args, erase = arg.split('@@') |
|
594 fn = fn.encode(sys.getfilesystemencoding()) |
|
595 self.__setCoding(fn) |
|
596 sys.argv.append(fn) |
|
597 sys.argv.extend(eval(args)) |
|
598 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
599 if wd == '': |
|
600 os.chdir(sys.path[1]) |
|
601 else: |
|
602 os.chdir(wd) |
|
603 |
|
604 # set the system exception handling function to ensure, that |
|
605 # we report on all unhandled exceptions |
|
606 sys.excepthook = self.__unhandled_exception |
|
607 self.__interceptSignals() |
|
608 |
|
609 # generate a coverage object |
|
610 self.cover = coverage( |
|
611 auto_data=True, |
|
612 data_file="%s.coverage" % os.path.splitext(sys.argv[0])[0]) |
|
613 |
|
614 if int(erase): |
|
615 self.cover.erase() |
|
616 sys.modules['__main__'] = self.debugMod |
|
617 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
618 self.running = sys.argv[0] |
|
619 res = 0 |
|
620 self.cover.start() |
|
621 try: |
|
622 execfile(sys.argv[0], self.debugMod.__dict__) |
|
623 except SystemExit as exc: |
|
624 res = exc.code |
|
625 atexit._run_exitfuncs() |
|
626 self.cover.stop() |
|
627 self.cover.save() |
|
628 self.writestream.flush() |
|
629 self.progTerminated(res) |
|
630 return |
|
631 |
|
632 if cmd == DebugProtocol.RequestProfile: |
|
633 sys.setprofile(None) |
|
634 import PyProfile |
|
635 sys.argv = [] |
|
636 wd, fn, args, erase = arg.split('|') |
|
637 fn = fn.encode(sys.getfilesystemencoding()) |
|
638 self.__setCoding(fn) |
|
639 sys.argv.append(fn) |
|
640 sys.argv.extend(eval(args)) |
|
641 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
642 if wd == '': |
|
643 os.chdir(sys.path[1]) |
|
644 else: |
|
645 os.chdir(wd) |
|
646 |
|
647 # set the system exception handling function to ensure, that |
|
648 # we report on all unhandled exceptions |
|
649 sys.excepthook = self.__unhandled_exception |
|
650 self.__interceptSignals() |
|
651 |
|
652 # generate a profile object |
|
653 self.prof = PyProfile.PyProfile(sys.argv[0]) |
|
654 |
|
655 if int(erase): |
|
656 self.prof.erase() |
|
657 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
658 sys.modules['__main__'] = self.debugMod |
|
659 self.running = sys.argv[0] |
|
660 res = 0 |
|
661 try: |
|
662 self.prof.run('execfile(%r)' % sys.argv[0]) |
|
663 except SystemExit as exc: |
|
664 res = exc.code |
|
665 atexit._run_exitfuncs() |
|
666 self.prof.save() |
|
667 self.writestream.flush() |
|
668 self.progTerminated(res) |
|
669 return |
|
670 |
|
671 if cmd == DebugProtocol.RequestShutdown: |
|
672 self.sessionClose() |
|
673 return |
|
674 |
|
675 if cmd == DebugProtocol.RequestBreak: |
|
676 fn, line, temporary, set, cond = arg.split('@@') |
|
677 fn = fn.encode(sys.getfilesystemencoding()) |
|
678 line = int(line) |
|
679 set = int(set) |
|
680 temporary = int(temporary) |
|
681 |
|
682 if set: |
|
683 if cond == 'None' or cond == '': |
|
684 cond = None |
|
685 else: |
|
686 try: |
|
687 compile(cond, '<string>', 'eval') |
|
688 except SyntaxError: |
|
689 self.write( |
|
690 '%s%s,%d\n' % |
|
691 (DebugProtocol.ResponseBPConditionError, |
|
692 fn, line)) |
|
693 return |
|
694 self.mainThread.set_break(fn, line, temporary, cond) |
|
695 else: |
|
696 self.mainThread.clear_break(fn, line) |
|
697 |
|
698 return |
|
699 |
|
700 if cmd == DebugProtocol.RequestBreakEnable: |
|
701 fn, line, enable = arg.split(',') |
|
702 fn = fn.encode(sys.getfilesystemencoding()) |
|
703 line = int(line) |
|
704 enable = int(enable) |
|
705 |
|
706 bp = self.mainThread.get_break(fn, line) |
|
707 if bp is not None: |
|
708 if enable: |
|
709 bp.enable() |
|
710 else: |
|
711 bp.disable() |
|
712 |
|
713 return |
|
714 |
|
715 if cmd == DebugProtocol.RequestBreakIgnore: |
|
716 fn, line, count = arg.split(',') |
|
717 fn = fn.encode(sys.getfilesystemencoding()) |
|
718 line = int(line) |
|
719 count = int(count) |
|
720 |
|
721 bp = self.mainThread.get_break(fn, line) |
|
722 if bp is not None: |
|
723 bp.ignore = count |
|
724 |
|
725 return |
|
726 |
|
727 if cmd == DebugProtocol.RequestWatch: |
|
728 cond, temporary, set = arg.split('@@') |
|
729 set = int(set) |
|
730 temporary = int(temporary) |
|
731 |
|
732 if set: |
|
733 if not cond.endswith('??created??') and \ |
|
734 not cond.endswith('??changed??'): |
|
735 try: |
|
736 compile(cond, '<string>', 'eval') |
|
737 except SyntaxError: |
|
738 self.write('%s%s\n' % ( |
|
739 DebugProtocol.ResponseWPConditionError, cond)) |
|
740 return |
|
741 self.mainThread.set_watch(cond, temporary) |
|
742 else: |
|
743 self.mainThread.clear_watch(cond) |
|
744 |
|
745 return |
|
746 |
|
747 if cmd == DebugProtocol.RequestWatchEnable: |
|
748 cond, enable = arg.split(',') |
|
749 enable = int(enable) |
|
750 |
|
751 bp = self.mainThread.get_watch(cond) |
|
752 if bp is not None: |
|
753 if enable: |
|
754 bp.enable() |
|
755 else: |
|
756 bp.disable() |
|
757 |
|
758 return |
|
759 |
|
760 if cmd == DebugProtocol.RequestWatchIgnore: |
|
761 cond, count = arg.split(',') |
|
762 count = int(count) |
|
763 |
|
764 bp = self.mainThread.get_watch(cond) |
|
765 if bp is not None: |
|
766 bp.ignore = count |
|
767 |
|
768 return |
|
769 |
|
770 if cmd == DebugProtocol.RequestEval: |
|
771 try: |
|
772 value = eval( |
|
773 arg, self.currentThread.getCurrentFrame().f_globals, |
|
774 self.currentThread.getFrameLocals(self.framenr)) |
|
775 self.currentThread.storeFrameLocals(self.framenr) |
|
776 except Exception: |
|
777 # Report the exception and the traceback |
|
778 try: |
|
779 type, value, tb = sys.exc_info() |
|
780 sys.last_type = type |
|
781 sys.last_value = value |
|
782 sys.last_traceback = tb |
|
783 tblist = traceback.extract_tb(tb) |
|
784 del tblist[:1] |
|
785 list = traceback.format_list(tblist) |
|
786 if list: |
|
787 list.insert(0, "Traceback (innermost last):\n") |
|
788 list[len(list):] = \ |
|
789 traceback.format_exception_only(type, value) |
|
790 finally: |
|
791 tblist = tb = None |
|
792 |
|
793 map(self.write, list) |
|
794 |
|
795 self.write(DebugProtocol.ResponseException + '\n') |
|
796 |
|
797 else: |
|
798 self.write(unicode(value) + '\n') |
|
799 self.write(DebugProtocol.ResponseOK + '\n') |
|
800 |
|
801 return |
|
802 |
|
803 if cmd == DebugProtocol.RequestExec: |
|
804 _globals = self.currentThread.getCurrentFrame().f_globals |
|
805 _locals = self.currentThread.getFrameLocals(self.framenr) |
|
806 try: |
|
807 code = compile(arg + '\n', '<stdin>', 'single') |
|
808 exec code in _globals, _locals |
|
809 self.currentThread.storeFrameLocals(self.framenr) |
|
810 except Exception: |
|
811 # Report the exception and the traceback |
|
812 try: |
|
813 type, value, tb = sys.exc_info() |
|
814 sys.last_type = type |
|
815 sys.last_value = value |
|
816 sys.last_traceback = tb |
|
817 tblist = traceback.extract_tb(tb) |
|
818 del tblist[:1] |
|
819 list = traceback.format_list(tblist) |
|
820 if list: |
|
821 list.insert(0, "Traceback (innermost last):\n") |
|
822 list[len(list):] = \ |
|
823 traceback.format_exception_only(type, value) |
|
824 finally: |
|
825 tblist = tb = None |
|
826 |
|
827 map(self.write, list) |
|
828 |
|
829 self.write(DebugProtocol.ResponseException + '\n') |
|
830 |
|
831 return |
|
832 |
|
833 if cmd == DebugProtocol.RequestBanner: |
|
834 self.write( |
|
835 '%s%s\n' % ( |
|
836 DebugProtocol.ResponseBanner, |
|
837 unicode(("Python %s" % sys.version, |
|
838 socket.gethostname(), |
|
839 self.variant)))) |
|
840 return |
|
841 |
|
842 if cmd == DebugProtocol.RequestCapabilities: |
|
843 self.write('%s%d, "Python2"\n' % ( |
|
844 DebugProtocol.ResponseCapabilities, |
|
845 self.__clientCapabilities())) |
|
846 return |
|
847 |
|
848 if cmd == DebugProtocol.RequestCompletion: |
|
849 self.__completionList(arg) |
|
850 return |
|
851 |
|
852 if cmd == DebugProtocol.RequestSetFilter: |
|
853 scope, filterString = eval(arg) |
|
854 self.__generateFilterObjects(int(scope), filterString) |
|
855 return |
|
856 |
|
857 if cmd == DebugProtocol.RequestUTPrepare: |
|
858 fn, tn, tfn, failed, cov, covname, erase = arg.split('|') |
|
859 fn = fn.encode(sys.getfilesystemencoding()) |
|
860 sys.path.insert(0, os.path.dirname(os.path.abspath(fn))) |
|
861 os.chdir(sys.path[0]) |
|
862 failed = eval(failed) |
|
863 |
|
864 # set the system exception handling function to ensure, that |
|
865 # we report on all unhandled exceptions |
|
866 sys.excepthook = self.__unhandled_exception |
|
867 self.__interceptSignals() |
|
868 |
|
869 try: |
|
870 import unittest |
|
871 utModule = __import__(tn) |
|
872 try: |
|
873 if failed: |
|
874 self.test = unittest.defaultTestLoader\ |
|
875 .loadTestsFromNames(failed, utModule) |
|
876 else: |
|
877 self.test = unittest.defaultTestLoader\ |
|
878 .loadTestsFromName(tfn, utModule) |
|
879 except AttributeError: |
|
880 self.test = unittest.defaultTestLoader\ |
|
881 .loadTestsFromModule(utModule) |
|
882 except Exception: |
|
883 exc_type, exc_value, exc_tb = sys.exc_info() |
|
884 self.write( |
|
885 '%s%s\n' % ( |
|
886 DebugProtocol.ResponseUTPrepared, |
|
887 unicode((0, str(exc_type), str(exc_value))))) |
|
888 self.__exceptionRaised() |
|
889 return |
|
890 |
|
891 # generate a coverage object |
|
892 if int(cov): |
|
893 from coverage import coverage |
|
894 self.cover = coverage( |
|
895 auto_data=True, |
|
896 data_file="%s.coverage" % os.path.splitext(covname)[0]) |
|
897 if int(erase): |
|
898 self.cover.erase() |
|
899 else: |
|
900 self.cover = None |
|
901 |
|
902 self.write( |
|
903 '%s%s\n' % ( |
|
904 DebugProtocol.ResponseUTPrepared, |
|
905 unicode((self.test.countTestCases(), "", "")))) |
|
906 return |
|
907 |
|
908 if cmd == DebugProtocol.RequestUTRun: |
|
909 from DCTestResult import DCTestResult |
|
910 self.testResult = DCTestResult(self) |
|
911 if self.cover: |
|
912 self.cover.start() |
|
913 self.test.run(self.testResult) |
|
914 if self.cover: |
|
915 self.cover.stop() |
|
916 self.cover.save() |
|
917 self.write('%s\n' % DebugProtocol.ResponseUTFinished) |
|
918 return |
|
919 |
|
920 if cmd == DebugProtocol.RequestUTStop: |
|
921 self.testResult.stop() |
|
922 return |
|
923 |
|
924 if cmd == DebugProtocol.ResponseForkTo: |
|
925 # this results from a separate event loop |
|
926 self.fork_child = (arg == 'child') |
|
927 self.eventExit = 1 |
|
928 return |
|
929 |
|
930 if cmd == DebugProtocol.RequestForkMode: |
|
931 self.fork_auto, self.fork_child = eval(arg) |
|
932 return |
|
933 |
|
934 # If we are handling raw mode input then reset the mode and break out |
|
935 # of the current event loop. |
|
936 if self.inRawMode: |
|
937 self.inRawMode = 0 |
|
938 self.rawLine = line |
|
939 self.eventExit = 1 |
|
940 return |
|
941 |
|
942 if self.buffer: |
|
943 self.buffer = self.buffer + '\n' + line |
|
944 else: |
|
945 self.buffer = line |
|
946 |
|
947 try: |
|
948 code = self.compile_command(self.buffer, self.readstream.name) |
|
949 except (OverflowError, SyntaxError, ValueError): |
|
950 # Report the exception |
|
951 sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() |
|
952 map(self.write, traceback.format_exception_only( |
|
953 sys.last_type, sys.last_value)) |
|
954 self.buffer = '' |
|
955 else: |
|
956 if code is None: |
|
957 self.pendingResponse = DebugProtocol.ResponseContinue |
|
958 else: |
|
959 self.buffer = '' |
|
960 |
|
961 try: |
|
962 if self.running is None: |
|
963 exec code in self.debugMod.__dict__ |
|
964 else: |
|
965 if self.currentThread is None: |
|
966 # program has terminated |
|
967 self.running = None |
|
968 _globals = self.debugMod.__dict__ |
|
969 _locals = _globals |
|
970 else: |
|
971 cf = self.currentThread.getCurrentFrame() |
|
972 # program has terminated |
|
973 if cf is None: |
|
974 self.running = None |
673 self.running = None |
975 _globals = self.debugMod.__dict__ |
674 _globals = self.debugMod.__dict__ |
976 _locals = _globals |
675 _locals = _globals |
977 else: |
676 else: |
978 frmnr = self.framenr |
677 cf = self.currentThread.getCurrentFrame() |
979 while cf is not None and frmnr > 0: |
678 # program has terminated |
980 cf = cf.f_back |
679 if cf is None: |
981 frmnr -= 1 |
680 self.running = None |
982 _globals = cf.f_globals |
681 _globals = self.debugMod.__dict__ |
983 _locals = \ |
682 _locals = _globals |
984 self.currentThread.getFrameLocals( |
683 else: |
985 self.framenr) |
684 frmnr = self.framenr |
986 # reset sys.stdout to our redirector (unconditionally) |
685 while cf is not None and frmnr > 0: |
987 if "sys" in _globals: |
686 cf = cf.f_back |
988 __stdout = _globals["sys"].stdout |
687 frmnr -= 1 |
989 _globals["sys"].stdout = self.writestream |
688 _globals = cf.f_globals |
990 exec code in _globals, _locals |
689 _locals = \ |
991 _globals["sys"].stdout = __stdout |
690 self.currentThread.getFrameLocals( |
992 elif "sys" in _locals: |
691 self.framenr) |
993 __stdout = _locals["sys"].stdout |
692 # reset sys.stdout to our redirector |
994 _locals["sys"].stdout = self.writestream |
693 # (unconditionally) |
995 exec code in _globals, _locals |
694 if "sys" in _globals: |
996 _locals["sys"].stdout = __stdout |
695 __stdout = _globals["sys"].stdout |
997 else: |
696 _globals["sys"].stdout = self.writestream |
998 exec code in _globals, _locals |
697 exec code in _globals, _locals |
999 |
698 _globals["sys"].stdout = __stdout |
1000 self.currentThread.storeFrameLocals(self.framenr) |
699 elif "sys" in _locals: |
1001 except SystemExit, exc: |
700 __stdout = _locals["sys"].stdout |
1002 self.progTerminated(exc.code) |
701 _locals["sys"].stdout = self.writestream |
1003 except Exception: |
702 exec code in _globals, _locals |
1004 # Report the exception and the traceback |
703 _locals["sys"].stdout = __stdout |
|
704 else: |
|
705 exec code in _globals, _locals |
|
706 |
|
707 self.currentThread.storeFrameLocals(self.framenr) |
|
708 except SystemExit, exc: |
|
709 self.progTerminated(exc.code) |
|
710 except Exception: |
|
711 # Report the exception and the traceback |
|
712 tlist = [] |
|
713 try: |
|
714 exc_type, exc_value, exc_tb = sys.exc_info() |
|
715 sys.last_type = exc_type |
|
716 sys.last_value = exc_value |
|
717 sys.last_traceback = exc_tb |
|
718 tblist = traceback.extract_tb(exc_tb) |
|
719 del tblist[:1] |
|
720 tlist = traceback.format_list(tblist) |
|
721 if tlist: |
|
722 tlist.insert( |
|
723 0, "Traceback (innermost last):\n") |
|
724 tlist.extend(traceback.format_exception_only( |
|
725 exc_type, exc_value)) |
|
726 finally: |
|
727 tblist = exc_tb = None |
|
728 |
|
729 self.sendJsonCommand("ClientOutput", { |
|
730 "text": "".join(tlist) |
|
731 }) |
|
732 |
|
733 self.sendJsonCommand("ResponseOK", {}) |
|
734 |
|
735 elif method == "RequestStep": |
|
736 self.currentThread.step(True) |
|
737 self.eventExit = True |
|
738 |
|
739 elif method == "RequestStepOver": |
|
740 self.currentThread.step(False) |
|
741 self.eventExit = True |
|
742 |
|
743 elif method == "RequestStepOut": |
|
744 self.currentThread.stepOut() |
|
745 self.eventExit = True |
|
746 |
|
747 elif method == "RequestStepQuit": |
|
748 if self.passive: |
|
749 self.progTerminated(42) |
|
750 else: |
|
751 self.set_quit() |
|
752 self.eventExit = True |
|
753 |
|
754 elif method == "RequestContinue": |
|
755 self.currentThread.go(params["special"]) |
|
756 self.eventExit = True |
|
757 |
|
758 elif method == "RawInput": |
|
759 # If we are handling raw mode input then break out of the current |
|
760 # event loop. |
|
761 self.rawLine = params["input"] |
|
762 self.eventExit = True |
|
763 |
|
764 elif method == "RequestBreakpoint": |
|
765 params["filename"] = params["filename"].encode( |
|
766 sys.getfilesystemencoding()) |
|
767 if params["setBreakpoint"]: |
|
768 if params["condition"] in ['None', '']: |
|
769 params["condition"] = None |
|
770 elif params["condition"] is not None: |
1005 try: |
771 try: |
1006 type, value, tb = sys.exc_info() |
772 compile(params["condition"], '<string>', 'eval') |
1007 sys.last_type = type |
773 except SyntaxError: |
1008 sys.last_value = value |
774 self.sendJsonCommand("ResponseBPConditionError", { |
1009 sys.last_traceback = tb |
775 "filename": params["filename"], |
1010 tblist = traceback.extract_tb(tb) |
776 "line": params["line"], |
1011 del tblist[:1] |
777 }) |
1012 list = traceback.format_list(tblist) |
778 return |
1013 if list: |
779 self.mainThread.set_break( |
1014 list.insert(0, "Traceback (innermost last):\n") |
780 params["filename"], params["line"], params["temporary"], |
1015 list[len(list):] = \ |
781 params["condition"]) |
1016 traceback.format_exception_only(type, value) |
782 else: |
1017 finally: |
783 self.mainThread.clear_break(params["filename"], params["line"]) |
1018 tblist = tb = None |
784 |
1019 |
785 elif method == "RequestBreakpointEnable": |
1020 map(self.write, list) |
786 params["filename"] = params["filename"].encode( |
|
787 sys.getfilesystemencoding()) |
|
788 bp = self.mainThread.get_break(params["filename"], params["line"]) |
|
789 if bp is not None: |
|
790 if params["enable"]: |
|
791 bp.enable() |
|
792 else: |
|
793 bp.disable() |
|
794 |
|
795 |
|
796 elif method == "RequestBreakpointIgnore": |
|
797 params["filename"] = params["filename"].encode( |
|
798 sys.getfilesystemencoding()) |
|
799 bp = self.mainThread.get_break(params["filename"], params["line"]) |
|
800 if bp is not None: |
|
801 bp.ignore = params["count"] |
|
802 |
|
803 elif method == "RequestWatch": |
|
804 if params["setWatch"]: |
|
805 if not params["condition"].endswith( |
|
806 ('??created??', '??changed??')): |
|
807 try: |
|
808 compile(params["condition"], '<string>', 'eval') |
|
809 except SyntaxError: |
|
810 self.sendJsonCommand("ResponseWatchConditionError", { |
|
811 "condition": params["condition"], |
|
812 }) |
|
813 return |
|
814 self.mainThread.set_watch( |
|
815 params["condition"], params["temporary"]) |
|
816 else: |
|
817 self.mainThread.clear_watch(params["condition"]) |
|
818 |
|
819 elif method == "RequestWatchEnable": |
|
820 wp = self.mainThread.get_watch(params["condition"]) |
|
821 if wp is not None: |
|
822 if params["enable"]: |
|
823 wp.enable() |
|
824 else: |
|
825 wp.disable() |
|
826 |
|
827 elif method == "RequestWatchIgnore": |
|
828 wp = self.mainThread.get_watch(params["condition"]) |
|
829 if wp is not None: |
|
830 wp.ignore = params["count"] |
|
831 |
|
832 elif method == "RequestShutdown": |
|
833 self.sessionClose() |
|
834 |
|
835 elif method == "RequestCompletion": |
|
836 self.__completionList(params["text"]) |
|
837 |
|
838 elif method == "RequestUTPrepare": |
|
839 params["filename"] = params["filename"].encode( |
|
840 sys.getfilesystemencoding()) |
|
841 sys.path.insert( |
|
842 0, os.path.dirname(os.path.abspath(params["filename"]))) |
|
843 os.chdir(sys.path[0]) |
|
844 |
|
845 # set the system exception handling function to ensure, that |
|
846 # we report on all unhandled exceptions |
|
847 sys.excepthook = self.__unhandled_exception |
|
848 self.__interceptSignals() |
|
849 |
|
850 try: |
|
851 import unittest |
|
852 utModule = __import__(params["testname"]) |
|
853 try: |
|
854 if params["failed"]: |
|
855 self.test = unittest.defaultTestLoader\ |
|
856 .loadTestsFromNames(params["failed"], utModule) |
|
857 else: |
|
858 self.test = unittest.defaultTestLoader\ |
|
859 .loadTestsFromName(params["testfunctionname"], |
|
860 utModule) |
|
861 except AttributeError: |
|
862 self.test = unittest.defaultTestLoader\ |
|
863 .loadTestsFromModule(utModule) |
|
864 except Exception: |
|
865 exc_type, exc_value, exc_tb = sys.exc_info() |
|
866 self.sendJsonCommand("ResponseUTPrepared", { |
|
867 "count": 0, |
|
868 "exception": exc_type.__name__, |
|
869 "message": str(exc_value), |
|
870 }) |
|
871 return |
|
872 |
|
873 # generate a coverage object |
|
874 if params["coverage"]: |
|
875 from coverage import coverage |
|
876 self.cover = coverage( |
|
877 auto_data=True, |
|
878 data_file="%s.coverage" % \ |
|
879 os.path.splitext(params["coveragefile"])[0]) |
|
880 if params["coverageerase"]: |
|
881 self.cover.erase() |
|
882 else: |
|
883 self.cover = None |
|
884 |
|
885 self.sendJsonCommand("ResponseUTPrepared", { |
|
886 "count": self.test.countTestCases(), |
|
887 "exception": "", |
|
888 "message": "", |
|
889 }) |
|
890 |
|
891 elif method == "RequestUTRun": |
|
892 from DCTestResult import DCTestResult |
|
893 self.testResult = DCTestResult(self) |
|
894 if self.cover: |
|
895 self.cover.start() |
|
896 self.test.run(self.testResult) |
|
897 if self.cover: |
|
898 self.cover.stop() |
|
899 self.cover.save() |
|
900 self.sendJsonCommand("ResponseUTFinished", {}) |
|
901 |
|
902 elif method == "RequestUTStop": |
|
903 self.testResult.stop() |
|
904 |
|
905 elif method == "ResponseForkTo": |
|
906 # this results from a separate event loop |
|
907 self.fork_child = (params["target"] == 'child') |
|
908 self.eventExit = True |
|
909 |
|
910 def sendJsonCommand(self, method, params): |
|
911 """ |
|
912 Public method to send a single command or response to the IDE. |
|
913 |
|
914 @param method command or response command name to be sent |
|
915 @type str |
|
916 @param params dictionary of named parameters for the command or |
|
917 response |
|
918 @type dict |
|
919 """ |
|
920 cmd = prepareJsonCommand(method, params) |
|
921 |
|
922 self.writestream.write_p(cmd) |
|
923 self.writestream.flush() |
|
924 |
|
925 def sendClearTemporaryBreakpoint(self, filename, lineno): |
|
926 """ |
|
927 Public method to signal the deletion of a temporary breakpoint. |
|
928 |
|
929 @param filename name of the file the bp belongs to |
|
930 @type str |
|
931 @param lineno linenumber of the bp |
|
932 @type int |
|
933 """ |
|
934 self.sendJsonCommand("ResponseClearBreakpoint", { |
|
935 "filename": filename, |
|
936 "line": lineno |
|
937 }) |
|
938 |
|
939 def sendClearTemporaryWatch(self, condition): |
|
940 """ |
|
941 Public method to signal the deletion of a temporary watch expression. |
|
942 |
|
943 @param condition condition of the watch expression to be cleared |
|
944 @type str |
|
945 """ |
|
946 self.sendJsonCommand("ResponseClearWatch", { |
|
947 "condition": condition, |
|
948 }) |
|
949 |
|
950 def sendResponseLine(self, stack): |
|
951 """ |
|
952 Public method to send the current call stack. |
|
953 |
|
954 @param stack call stack |
|
955 @type list |
|
956 """ |
|
957 self.sendJsonCommand("ResponseLine", { |
|
958 "stack": stack, |
|
959 }) |
|
960 |
|
961 def sendCallTrace(self, event, fromStr, toStr): |
|
962 """ |
|
963 Public method to send a call trace entry. |
|
964 |
|
965 @param event trace event (call or return) |
|
966 @type str |
|
967 @param fromStr pre-formatted origin info |
|
968 @type str |
|
969 @param toStr pre-formatted target info |
|
970 @type str |
|
971 """ |
|
972 self.sendJsonCommand("CallTrace", { |
|
973 "event": event[0], |
|
974 "from": fromStr, |
|
975 "to": toStr, |
|
976 }) |
|
977 |
|
978 def sendException(self, exceptionType, exceptionMessage, stack): |
|
979 """ |
|
980 Public method to send information for an exception. |
|
981 |
|
982 @param exceptionType type of exception raised |
|
983 @type str |
|
984 @param exceptionMessage message of the exception |
|
985 @type str |
|
986 @param stack stack trace information |
|
987 @type list |
|
988 """ |
|
989 self.sendJsonCommand("ResponseException", { |
|
990 "type": exceptionType, |
|
991 "message": exceptionMessage, |
|
992 "stack": stack, |
|
993 }) |
|
994 |
|
995 def sendSyntaxError(self, message, filename, lineno, charno): |
|
996 """ |
|
997 Public method to send information for a syntax error. |
|
998 |
|
999 @param message syntax error message |
|
1000 @type str |
|
1001 @param filename name of the faulty file |
|
1002 @type str |
|
1003 @param lineno line number info |
|
1004 @type int |
|
1005 @param charno character number info |
|
1006 @tyoe int |
|
1007 """ |
|
1008 self.sendJsonCommand("ResponseSyntax", { |
|
1009 "message": message, |
|
1010 "filename": filename, |
|
1011 "linenumber": lineno, |
|
1012 "characternumber": charno, |
|
1013 }) |
|
1014 |
|
1015 def sendPassiveStartup(self, filename, exceptions): |
|
1016 """ |
|
1017 Public method to send the passive start information. |
|
1018 |
|
1019 @param filename name of the script |
|
1020 @type str |
|
1021 @param exceptions flag to enable exception reporting of the IDE |
|
1022 @type bool |
|
1023 """ |
|
1024 self.sendJsonCommand("PassiveStartup", { |
|
1025 "filename": filename, |
|
1026 "exceptions": exceptions, |
|
1027 }) |
1021 |
1028 |
1022 def __clientCapabilities(self): |
1029 def __clientCapabilities(self): |
1023 """ |
1030 """ |
1024 Private method to determine the clients capabilities. |
1031 Private method to determine the clients capabilities. |
1025 |
1032 |