394 # Remove any newline. |
372 # Remove any newline. |
395 if line[-1] == '\n': |
373 if line[-1] == '\n': |
396 line = line[:-1] |
374 line = line[:-1] |
397 |
375 |
398 ## printerr(line) ##debug |
376 ## printerr(line) ##debug |
399 |
377 |
400 eoc = line.find('<') |
378 self.handleJsonCommand(line) |
401 |
379 |
402 if eoc >= 0 and line[0] == '>': |
380 def handleJsonCommand(self, jsonStr): |
403 # Get the command part and any argument. |
381 """ |
404 cmd = line[:eoc + 1] |
382 Public method to handle a command serialized as a JSON string. |
405 arg = line[eoc + 1:] |
383 |
406 |
384 @param jsonStr string containing the command received from the IDE |
407 if cmd == DebugProtocol.RequestVariables: |
385 @type str |
408 frmnr, scope, filter = eval(arg.replace("u'", "'")) |
386 """ |
409 self.__dumpVariables(int(frmnr), int(scope), filter) |
387 try: |
410 return |
388 commandDict = json.loads(jsonStr.strip()) |
411 |
389 except (TypeError, ValueError) as err: |
412 if cmd == DebugProtocol.RequestVariable: |
390 printerr(str(err)) |
413 var, frmnr, scope, filter = eval(arg.replace("u'", "'")) |
391 return |
414 self.__dumpVariable(var, int(frmnr), int(scope), filter) |
392 |
415 return |
393 method = commandDict["method"] |
416 |
394 params = commandDict["params"] |
417 if cmd == DebugProtocol.RequestThreadList: |
395 |
418 self.__dumpThreadList() |
396 if method == "RequestVariables": |
419 return |
397 self.__dumpVariables( |
420 |
398 params["frameNumber"], params["scope"], params["filters"]) |
421 if cmd == DebugProtocol.RequestThreadSet: |
399 |
422 tid = eval(arg) |
400 elif method == "RequestVariable": |
423 if tid in self.threads: |
401 self.__dumpVariable( |
424 self.setCurrentThread(tid) |
402 params["variable"], params["frameNumber"], |
425 self.write(DebugProtocol.ResponseThreadSet + '\n') |
403 params["scope"], params["filters"]) |
426 stack = self.currentThread.getStack() |
404 |
427 self.write('{0}{1!r}\n'.format( |
405 elif method == "RequestThreadList": |
428 DebugProtocol.ResponseStack, stack)) |
406 self.__dumpThreadList() |
429 return |
407 |
430 |
408 elif method == "RequestThreadSet": |
431 if cmd == DebugProtocol.RequestStep: |
409 if params["threadID"] in self.threads: |
432 self.currentThread.step(True) |
410 self.setCurrentThread(params["threadID"]) |
433 self.eventExit = True |
411 self.sendJsonCommand("ResponseThreadSet", {}) |
434 return |
412 stack = self.currentThread.getStack() |
435 |
413 self.sendJsonCommand("ResponseStack", { |
436 if cmd == DebugProtocol.RequestStepOver: |
414 "stack": stack, |
437 self.currentThread.step(False) |
415 }) |
438 self.eventExit = True |
416 |
439 return |
417 elif method == "RequestCapabilities": |
440 |
418 self.sendJsonCommand("ResponseCapabilities", { |
441 if cmd == DebugProtocol.RequestStepOut: |
419 "capabilities": self.__clientCapabilities(), |
442 self.currentThread.stepOut() |
420 "clientType": "Python3" |
443 self.eventExit = True |
421 }) |
444 return |
422 |
445 |
423 elif method == "RequestBanner": |
446 if cmd == DebugProtocol.RequestStepQuit: |
424 self.sendJsonCommand("ResponseBanner", { |
447 if self.passive: |
425 "version": "Python {0}".format(sys.version), |
448 self.progTerminated(42) |
426 "platform": socket.gethostname(), |
|
427 "dbgclient": self.variant, |
|
428 }) |
|
429 |
|
430 elif method == "RequestSetFilter": |
|
431 self.__generateFilterObjects(params["scope"], params["filter"]) |
|
432 |
|
433 elif method == "RequestCallTrace": |
|
434 if params["enable"]: |
|
435 callTraceEnabled = self.profile |
|
436 else: |
|
437 callTraceEnabled = None |
|
438 |
|
439 if self.debugging: |
|
440 sys.setprofile(callTraceEnabled) |
|
441 else: |
|
442 # remember for later |
|
443 self.callTraceEnabled = callTraceEnabled |
|
444 |
|
445 elif method == "RequestEnvironment": |
|
446 for key, value in params["environment"].items(): |
|
447 if key.endswith("+"): |
|
448 if key[:-1] in os.environ: |
|
449 os.environ[key[:-1]] += value |
|
450 else: |
|
451 os.environ[key[:-1]] = value |
449 else: |
452 else: |
450 self.set_quit() |
453 os.environ[key] = value |
451 self.eventExit = True |
454 |
452 return |
455 elif method == "RequestLoad": |
453 |
456 self._fncache = {} |
454 if cmd == DebugProtocol.RequestContinue: |
457 self.dircache = [] |
455 special = int(arg) |
458 sys.argv = [] |
456 self.currentThread.go(special) |
459 self.__setCoding(params["filename"]) |
457 self.eventExit = True |
460 sys.argv.append(params["filename"]) |
458 return |
461 sys.argv.extend(params["argv"]) |
459 |
462 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
460 if cmd == DebugProtocol.RequestOK: |
463 if params["workdir"] == '': |
461 self.write(self.pendingResponse + '\n') |
464 os.chdir(sys.path[1]) |
462 self.pendingResponse = DebugProtocol.ResponseOK |
465 else: |
463 return |
466 os.chdir(params["workdir"]) |
464 |
467 |
465 if cmd == DebugProtocol.RequestCallTrace: |
468 self.running = sys.argv[0] |
466 if arg.strip().lower() == "on": |
469 self.mainFrame = None |
467 callTraceEnabled = self.profile |
470 self.debugging = True |
|
471 |
|
472 self.fork_auto = params["autofork"] |
|
473 self.fork_child = params["forkChild"] |
|
474 |
|
475 self.threads.clear() |
|
476 self.attachThread(mainThread=True) |
|
477 |
|
478 # set the system exception handling function to ensure, that |
|
479 # we report on all unhandled exceptions |
|
480 sys.excepthook = self.__unhandled_exception |
|
481 self.__interceptSignals() |
|
482 |
|
483 # clear all old breakpoints, they'll get set after we have |
|
484 # started |
|
485 Breakpoint.clear_all_breaks() |
|
486 Watch.clear_all_watches() |
|
487 |
|
488 self.mainThread.tracePythonLibs(params["traceInterpreter"]) |
|
489 |
|
490 # This will eventually enter a local event loop. |
|
491 self.debugMod.__dict__['__file__'] = self.running |
|
492 sys.modules['__main__'] = self.debugMod |
|
493 code = self.__compileFileSource(self.running) |
|
494 if code: |
|
495 sys.setprofile(self.callTraceEnabled) |
|
496 res = self.mainThread.run(code, self.debugMod.__dict__) |
|
497 self.progTerminated(res) |
|
498 |
|
499 elif method == "RequestRun": |
|
500 sys.argv = [] |
|
501 self.__setCoding(params["filename"]) |
|
502 sys.argv.append(params["filename"]) |
|
503 sys.argv.extend(params["argv"]) |
|
504 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
505 if params["workdir"] == '': |
|
506 os.chdir(sys.path[1]) |
|
507 else: |
|
508 os.chdir(params["workdir"]) |
|
509 |
|
510 self.running = sys.argv[0] |
|
511 self.mainFrame = None |
|
512 self.botframe = None |
|
513 |
|
514 self.fork_auto = params["autofork"] |
|
515 self.fork_child = params["forkChild"] |
|
516 |
|
517 self.threads.clear() |
|
518 self.attachThread(mainThread=True) |
|
519 |
|
520 # set the system exception handling function to ensure, that |
|
521 # we report on all unhandled exceptions |
|
522 sys.excepthook = self.__unhandled_exception |
|
523 self.__interceptSignals() |
|
524 |
|
525 self.mainThread.tracePythonLibs(False) |
|
526 |
|
527 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
528 sys.modules['__main__'] = self.debugMod |
|
529 res = 0 |
|
530 code = self.__compileFileSource(self.running) |
|
531 if code: |
|
532 try: |
|
533 exec(code, self.debugMod.__dict__) |
|
534 except SystemExit as exc: |
|
535 res = exc.code |
|
536 atexit._run_exitfuncs() |
|
537 self.writestream.flush() |
|
538 self.progTerminated(res) |
|
539 |
|
540 elif method == "RequestCoverage": |
|
541 from coverage import coverage |
|
542 sys.argv = [] |
|
543 self.__setCoding(params["filename"]) |
|
544 sys.argv.append(params["filename"]) |
|
545 sys.argv.extend(params["argv"]) |
|
546 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
547 if params["workdir"] == '': |
|
548 os.chdir(sys.path[1]) |
|
549 else: |
|
550 os.chdir(params["workdir"]) |
|
551 |
|
552 # set the system exception handling function to ensure, that |
|
553 # we report on all unhandled exceptions |
|
554 sys.excepthook = self.__unhandled_exception |
|
555 self.__interceptSignals() |
|
556 |
|
557 # generate a coverage object |
|
558 self.cover = coverage( |
|
559 auto_data=True, |
|
560 data_file="{0}.coverage".format( |
|
561 os.path.splitext(sys.argv[0])[0])) |
|
562 |
|
563 if params["erase"]: |
|
564 self.cover.erase() |
|
565 sys.modules['__main__'] = self.debugMod |
|
566 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
567 fp = open(sys.argv[0], encoding=self.__coding) |
|
568 try: |
|
569 script = fp.read() |
|
570 finally: |
|
571 fp.close() |
|
572 if script: |
|
573 if not script.endswith('\n'): |
|
574 script += '\n' |
|
575 code = compile(script, sys.argv[0], 'exec') |
|
576 self.running = sys.argv[0] |
|
577 res = 0 |
|
578 self.cover.start() |
|
579 try: |
|
580 exec(code, self.debugMod.__dict__) |
|
581 except SystemExit as exc: |
|
582 res = exc.code |
|
583 atexit._run_exitfuncs() |
|
584 self.cover.stop() |
|
585 self.cover.save() |
|
586 self.writestream.flush() |
|
587 self.progTerminated(res) |
|
588 |
|
589 elif method == "RequestProfile": |
|
590 sys.setprofile(None) |
|
591 import PyProfile |
|
592 sys.argv = [] |
|
593 self.__setCoding(params["filename"]) |
|
594 sys.argv.append(params["filename"]) |
|
595 sys.argv.extend(params["argv"]) |
|
596 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
597 if params["workdir"] == '': |
|
598 os.chdir(sys.path[1]) |
|
599 else: |
|
600 os.chdir(params["workdir"]) |
|
601 |
|
602 # set the system exception handling function to ensure, that |
|
603 # we report on all unhandled exceptions |
|
604 sys.excepthook = self.__unhandled_exception |
|
605 self.__interceptSignals() |
|
606 |
|
607 # generate a profile object |
|
608 self.prof = PyProfile.PyProfile(sys.argv[0]) |
|
609 |
|
610 if params["erase"]: |
|
611 self.prof.erase() |
|
612 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
613 sys.modules['__main__'] = self.debugMod |
|
614 fp = open(sys.argv[0], encoding=self.__coding) |
|
615 try: |
|
616 script = fp.read() |
|
617 finally: |
|
618 fp.close() |
|
619 if script: |
|
620 if not script.endswith('\n'): |
|
621 script += '\n' |
|
622 self.running = sys.argv[0] |
|
623 res = 0 |
|
624 try: |
|
625 self.prof.run(script) |
|
626 except SystemExit as exc: |
|
627 res = exc.code |
|
628 atexit._run_exitfuncs() |
|
629 self.prof.save() |
|
630 self.writestream.flush() |
|
631 self.progTerminated(res) |
|
632 |
|
633 elif method == "ExecuteStatement": |
|
634 if self.buffer: |
|
635 self.buffer = self.buffer + '\n' + params["statement"] |
|
636 else: |
|
637 self.buffer = params["statement"] |
|
638 |
|
639 try: |
|
640 code = self.compile_command(self.buffer, self.readstream.name) |
|
641 except (OverflowError, SyntaxError, ValueError): |
|
642 # Report the exception |
|
643 sys.last_type, sys.last_value, sys.last_traceback = \ |
|
644 sys.exc_info() |
|
645 self.sendJsonCommand("ClientOutput", { |
|
646 "text": "".join(traceback.format_exception_only( |
|
647 sys.last_type, sys.last_value)) |
|
648 }) |
|
649 self.buffer = '' |
|
650 else: |
|
651 if code is None: |
|
652 self.sendJsonCommand("ResponseContinue", {}) |
|
653 return |
468 else: |
654 else: |
469 callTraceEnabled = None |
655 self.buffer = '' |
470 if self.debugging: |
656 |
471 sys.setprofile(callTraceEnabled) |
657 try: |
472 else: |
658 if self.running is None: |
473 # remember for later |
659 exec(code, self.debugMod.__dict__) |
474 self.callTraceEnabled = callTraceEnabled |
|
475 |
|
476 return |
|
477 |
|
478 if cmd == DebugProtocol.RequestEnv: |
|
479 env = eval(arg.replace("u'", "'")) |
|
480 for key, value in env.items(): |
|
481 if key.endswith("+"): |
|
482 if key[:-1] in os.environ: |
|
483 os.environ[key[:-1]] += value |
|
484 else: |
660 else: |
485 os.environ[key[:-1]] = value |
661 if self.currentThread is None: |
486 else: |
662 # program has terminated |
487 os.environ[key] = value |
|
488 return |
|
489 |
|
490 if cmd == DebugProtocol.RequestLoad: |
|
491 self._fncache = {} |
|
492 self.dircache = [] |
|
493 sys.argv = [] |
|
494 wd, fn, args, tracePython = arg.split('|') |
|
495 self.__setCoding(fn) |
|
496 sys.argv.append(fn) |
|
497 sys.argv.extend(eval(args.replace("u'", "'"))) |
|
498 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
499 if wd == '': |
|
500 os.chdir(sys.path[1]) |
|
501 else: |
|
502 os.chdir(wd) |
|
503 self.running = sys.argv[0] |
|
504 self.mainFrame = None |
|
505 self.inRawMode = False |
|
506 self.debugging = True |
|
507 |
|
508 self.threads.clear() |
|
509 self.attachThread(mainThread=True) |
|
510 |
|
511 # set the system exception handling function to ensure, that |
|
512 # we report on all unhandled exceptions |
|
513 sys.excepthook = self.__unhandled_exception |
|
514 self.__interceptSignals() |
|
515 |
|
516 # clear all old breakpoints, they'll get set after we have |
|
517 # started |
|
518 Breakpoint.clear_all_breaks() |
|
519 Watch.clear_all_watches() |
|
520 |
|
521 self.mainThread.tracePythonLibs(int(tracePython)) |
|
522 |
|
523 # This will eventually enter a local event loop. |
|
524 # Note the use of backquotes to cause a repr of self.running. |
|
525 # The need for this is on Windows os where backslash is the |
|
526 # path separator. They will get inadvertantly stripped away |
|
527 # during the eval causing IOErrors, if self.running is passed |
|
528 # as a normal str. |
|
529 self.debugMod.__dict__['__file__'] = self.running |
|
530 sys.modules['__main__'] = self.debugMod |
|
531 code = self.__compileFileSource(self.running) |
|
532 if code: |
|
533 sys.setprofile(self.callTraceEnabled) |
|
534 res = self.mainThread.run(code, self.debugMod.__dict__) |
|
535 self.progTerminated(res) |
|
536 return |
|
537 |
|
538 if cmd == DebugProtocol.RequestRun: |
|
539 sys.argv = [] |
|
540 wd, fn, args = arg.split('|') |
|
541 self.__setCoding(fn) |
|
542 sys.argv.append(fn) |
|
543 sys.argv.extend(eval(args.replace("u'", "'"))) |
|
544 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
545 if wd == '': |
|
546 os.chdir(sys.path[1]) |
|
547 else: |
|
548 os.chdir(wd) |
|
549 |
|
550 self.running = sys.argv[0] |
|
551 self.mainFrame = None |
|
552 self.botframe = None |
|
553 self.inRawMode = False |
|
554 |
|
555 self.threads.clear() |
|
556 self.attachThread(mainThread=True) |
|
557 |
|
558 # set the system exception handling function to ensure, that |
|
559 # we report on all unhandled exceptions |
|
560 sys.excepthook = self.__unhandled_exception |
|
561 self.__interceptSignals() |
|
562 |
|
563 self.mainThread.tracePythonLibs(0) |
|
564 |
|
565 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
566 sys.modules['__main__'] = self.debugMod |
|
567 res = 0 |
|
568 code = self.__compileFileSource(self.running) |
|
569 if code: |
|
570 try: |
|
571 exec(code, self.debugMod.__dict__) |
|
572 except SystemExit as exc: |
|
573 res = exc.code |
|
574 atexit._run_exitfuncs() |
|
575 self.writestream.flush() |
|
576 self.progTerminated(res) |
|
577 return |
|
578 |
|
579 if cmd == DebugProtocol.RequestProfile: |
|
580 sys.setprofile(None) |
|
581 import PyProfile |
|
582 sys.argv = [] |
|
583 wd, fn, args, erase = arg.split('|') |
|
584 self.__setCoding(fn) |
|
585 sys.argv.append(fn) |
|
586 sys.argv.extend(eval(args.replace("u'", "'"))) |
|
587 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
588 if wd == '': |
|
589 os.chdir(sys.path[1]) |
|
590 else: |
|
591 os.chdir(wd) |
|
592 |
|
593 # set the system exception handling function to ensure, that |
|
594 # we report on all unhandled exceptions |
|
595 sys.excepthook = self.__unhandled_exception |
|
596 self.__interceptSignals() |
|
597 |
|
598 # generate a profile object |
|
599 self.prof = PyProfile.PyProfile(sys.argv[0]) |
|
600 |
|
601 if int(erase): |
|
602 self.prof.erase() |
|
603 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
604 sys.modules['__main__'] = self.debugMod |
|
605 fp = open(sys.argv[0], encoding=self.__coding) |
|
606 try: |
|
607 script = fp.read() |
|
608 finally: |
|
609 fp.close() |
|
610 if script: |
|
611 if not script.endswith('\n'): |
|
612 script += '\n' |
|
613 self.running = sys.argv[0] |
|
614 res = 0 |
|
615 try: |
|
616 self.prof.run(script) |
|
617 except SystemExit as exc: |
|
618 res = exc.code |
|
619 atexit._run_exitfuncs() |
|
620 self.prof.save() |
|
621 self.writestream.flush() |
|
622 self.progTerminated(res) |
|
623 return |
|
624 |
|
625 if cmd == DebugProtocol.RequestCoverage: |
|
626 from coverage import coverage |
|
627 sys.argv = [] |
|
628 wd, fn, args, erase = arg.split('@@') |
|
629 self.__setCoding(fn) |
|
630 sys.argv.append(fn) |
|
631 sys.argv.extend(eval(args.replace("u'", "'"))) |
|
632 sys.path = self.__getSysPath(os.path.dirname(sys.argv[0])) |
|
633 if wd == '': |
|
634 os.chdir(sys.path[1]) |
|
635 else: |
|
636 os.chdir(wd) |
|
637 |
|
638 # set the system exception handling function to ensure, that |
|
639 # we report on all unhandled exceptions |
|
640 sys.excepthook = self.__unhandled_exception |
|
641 self.__interceptSignals() |
|
642 |
|
643 # generate a coverage object |
|
644 self.cover = coverage( |
|
645 auto_data=True, |
|
646 data_file="{0}.coverage".format( |
|
647 os.path.splitext(sys.argv[0])[0])) |
|
648 |
|
649 if int(erase): |
|
650 self.cover.erase() |
|
651 sys.modules['__main__'] = self.debugMod |
|
652 self.debugMod.__dict__['__file__'] = sys.argv[0] |
|
653 fp = open(sys.argv[0], encoding=self.__coding) |
|
654 try: |
|
655 script = fp.read() |
|
656 finally: |
|
657 fp.close() |
|
658 if script: |
|
659 if not script.endswith('\n'): |
|
660 script += '\n' |
|
661 code = compile(script, sys.argv[0], 'exec') |
|
662 self.running = sys.argv[0] |
|
663 res = 0 |
|
664 self.cover.start() |
|
665 try: |
|
666 exec(code, self.debugMod.__dict__) |
|
667 except SystemExit as exc: |
|
668 res = exc.code |
|
669 atexit._run_exitfuncs() |
|
670 self.cover.stop() |
|
671 self.cover.save() |
|
672 self.writestream.flush() |
|
673 self.progTerminated(res) |
|
674 return |
|
675 |
|
676 if cmd == DebugProtocol.RequestShutdown: |
|
677 self.sessionClose() |
|
678 return |
|
679 |
|
680 if cmd == DebugProtocol.RequestBreak: |
|
681 fn, line, temporary, set, cond = arg.split('@@') |
|
682 line = int(line) |
|
683 set = int(set) |
|
684 temporary = int(temporary) |
|
685 |
|
686 if set: |
|
687 if cond == 'None' or cond == '': |
|
688 cond = None |
|
689 else: |
|
690 try: |
|
691 cond = compile(cond, '<string>', 'eval') |
|
692 except SyntaxError: |
|
693 self.write('{0}{1},{2:d}\n'.format( |
|
694 DebugProtocol.ResponseBPConditionError, |
|
695 fn, line)) |
|
696 return |
|
697 Breakpoint(fn, line, temporary, cond) |
|
698 else: |
|
699 Breakpoint.clear_break(fn, line) |
|
700 |
|
701 return |
|
702 |
|
703 if cmd == DebugProtocol.RequestBreakEnable: |
|
704 fn, line, enable = arg.split(',') |
|
705 line = int(line) |
|
706 enable = int(enable) |
|
707 |
|
708 bp = Breakpoint.get_break(fn, line) |
|
709 if bp is not None: |
|
710 if enable: |
|
711 bp.enable() |
|
712 else: |
|
713 bp.disable() |
|
714 |
|
715 return |
|
716 |
|
717 if cmd == DebugProtocol.RequestBreakIgnore: |
|
718 fn, line, count = arg.split(',') |
|
719 line = int(line) |
|
720 count = int(count) |
|
721 |
|
722 bp = Breakpoint.get_break(fn, line) |
|
723 if bp is not None: |
|
724 bp.ignore = count |
|
725 |
|
726 return |
|
727 |
|
728 if cmd == DebugProtocol.RequestWatch: |
|
729 cond, temporary, set = arg.split('@@') |
|
730 set = int(set) |
|
731 temporary = int(temporary) |
|
732 |
|
733 if cond.endswith(('??created??', '??changed??')): |
|
734 compiledCond, flag = cond.split() |
|
735 else: |
|
736 compiledCond = cond |
|
737 flag = '' |
|
738 |
|
739 try: |
|
740 compiledCond = compile(compiledCond, '<string>', 'eval') |
|
741 except SyntaxError: |
|
742 self.write('{0}{1}\n'.format( |
|
743 DebugProtocol.ResponseWPConditionError, cond)) |
|
744 return |
|
745 |
|
746 if set: |
|
747 Watch(cond, compiledCond, flag, temporary) |
|
748 else: |
|
749 Watch.clear_watch(cond) |
|
750 |
|
751 return |
|
752 |
|
753 if cmd == DebugProtocol.RequestWatchEnable: |
|
754 cond, enable = arg.split(',') |
|
755 enable = int(enable) |
|
756 |
|
757 bp = Watch.get_watch(cond) |
|
758 if bp is not None: |
|
759 if enable: |
|
760 bp.enable() |
|
761 else: |
|
762 bp.disable() |
|
763 |
|
764 return |
|
765 |
|
766 if cmd == DebugProtocol.RequestWatchIgnore: |
|
767 cond, count = arg.split(',') |
|
768 count = int(count) |
|
769 |
|
770 bp = Watch.get_watch(cond) |
|
771 if bp is not None: |
|
772 bp.ignore = count |
|
773 |
|
774 return |
|
775 |
|
776 if cmd == DebugProtocol.RequestEval: |
|
777 try: |
|
778 value = eval( |
|
779 arg, |
|
780 self.currentThread.getCurrentFrame().f_globals, |
|
781 self.currentThread.getFrameLocals(self.framenr)) |
|
782 self.currentThread.storeFrameLocals(self.framenr) |
|
783 except Exception: |
|
784 # Report the exception and the traceback |
|
785 try: |
|
786 type, value, tb = sys.exc_info() |
|
787 sys.last_type = type |
|
788 sys.last_value = value |
|
789 sys.last_traceback = tb |
|
790 tblist = traceback.extract_tb(tb) |
|
791 del tblist[:1] |
|
792 list = traceback.format_list(tblist) |
|
793 if list: |
|
794 list.insert(0, "Traceback (innermost last):\n") |
|
795 list[len(list):] = \ |
|
796 traceback.format_exception_only(type, value) |
|
797 finally: |
|
798 tblist = tb = None |
|
799 |
|
800 for l in list: |
|
801 self.write(l) |
|
802 |
|
803 self.write(DebugProtocol.ResponseException + '\n') |
|
804 |
|
805 else: |
|
806 self.write(str(value) + '\n') |
|
807 self.write(DebugProtocol.ResponseOK + '\n') |
|
808 |
|
809 return |
|
810 |
|
811 if cmd == DebugProtocol.RequestExec: |
|
812 _globals = self.currentThread.getCurrentFrame().f_globals |
|
813 _locals = self.currentThread.getFrameLocals(self.framenr) |
|
814 try: |
|
815 code = compile(arg + '\n', '<stdin>', 'single') |
|
816 exec(code, _globals, _locals) |
|
817 self.currentThread.storeFrameLocals(self.framenr) |
|
818 except Exception: |
|
819 # Report the exception and the traceback |
|
820 try: |
|
821 type, value, tb = sys.exc_info() |
|
822 sys.last_type = type |
|
823 sys.last_value = value |
|
824 sys.last_traceback = tb |
|
825 tblist = traceback.extract_tb(tb) |
|
826 del tblist[:1] |
|
827 list = traceback.format_list(tblist) |
|
828 if list: |
|
829 list.insert(0, "Traceback (innermost last):\n") |
|
830 list[len(list):] = \ |
|
831 traceback.format_exception_only(type, value) |
|
832 finally: |
|
833 tblist = tb = None |
|
834 |
|
835 for l in list: |
|
836 self.write(l) |
|
837 |
|
838 self.write(DebugProtocol.ResponseException + '\n') |
|
839 |
|
840 return |
|
841 |
|
842 if cmd == DebugProtocol.RequestBanner: |
|
843 self.write('{0}{1}\n'.format(DebugProtocol.ResponseBanner, |
|
844 str(("Python {0}".format(sys.version), |
|
845 socket.gethostname(), self.variant)))) |
|
846 return |
|
847 |
|
848 if cmd == DebugProtocol.RequestCapabilities: |
|
849 self.write('{0}{1:d}, "Python3"\n'.format( |
|
850 DebugProtocol.ResponseCapabilities, |
|
851 self.__clientCapabilities())) |
|
852 return |
|
853 |
|
854 if cmd == DebugProtocol.RequestCompletion: |
|
855 self.__completionList(arg.replace("u'", "'")) |
|
856 return |
|
857 |
|
858 if cmd == DebugProtocol.RequestSetFilter: |
|
859 scope, filterString = eval(arg.replace("u'", "'")) |
|
860 self.__generateFilterObjects(int(scope), filterString) |
|
861 return |
|
862 |
|
863 if cmd == DebugProtocol.RequestUTPrepare: |
|
864 fn, tn, tfn, failed, cov, covname, erase = arg.split('|') |
|
865 sys.path.insert(0, os.path.dirname(os.path.abspath(fn))) |
|
866 os.chdir(sys.path[0]) |
|
867 failed = eval(failed) |
|
868 |
|
869 # set the system exception handling function to ensure, that |
|
870 # we report on all unhandled exceptions |
|
871 sys.excepthook = self.__unhandled_exception |
|
872 self.__interceptSignals() |
|
873 |
|
874 try: |
|
875 import unittest |
|
876 utModule = imp.load_source(tn, fn) |
|
877 try: |
|
878 if failed: |
|
879 self.test = unittest.defaultTestLoader\ |
|
880 .loadTestsFromNames(failed, utModule) |
|
881 else: |
|
882 self.test = unittest.defaultTestLoader\ |
|
883 .loadTestsFromName(tfn, utModule) |
|
884 except AttributeError: |
|
885 self.test = unittest.defaultTestLoader\ |
|
886 .loadTestsFromModule(utModule) |
|
887 except Exception: |
|
888 exc_type, exc_value, exc_tb = sys.exc_info() |
|
889 self.write('{0}{1}\n'.format( |
|
890 DebugProtocol.ResponseUTPrepared, |
|
891 str((0, str(exc_type), str(exc_value))))) |
|
892 self.__exceptionRaised() |
|
893 return |
|
894 |
|
895 # generate a coverage object |
|
896 if int(cov): |
|
897 from coverage import coverage |
|
898 self.cover = coverage( |
|
899 auto_data=True, |
|
900 data_file="{0}.coverage".format( |
|
901 os.path.splitext(covname)[0])) |
|
902 if int(erase): |
|
903 self.cover.erase() |
|
904 else: |
|
905 self.cover = None |
|
906 |
|
907 self.write('{0}{1}\n'.format( |
|
908 DebugProtocol.ResponseUTPrepared, |
|
909 str((self.test.countTestCases(), "", "")))) |
|
910 return |
|
911 |
|
912 if cmd == DebugProtocol.RequestUTRun: |
|
913 from DCTestResult import DCTestResult |
|
914 self.testResult = DCTestResult(self) |
|
915 if self.cover: |
|
916 self.cover.start() |
|
917 self.test.run(self.testResult) |
|
918 if self.cover: |
|
919 self.cover.stop() |
|
920 self.cover.save() |
|
921 self.write('{0}\n'.format(DebugProtocol.ResponseUTFinished)) |
|
922 return |
|
923 |
|
924 if cmd == DebugProtocol.RequestUTStop: |
|
925 self.testResult.stop() |
|
926 return |
|
927 |
|
928 if cmd == DebugProtocol.ResponseForkTo: |
|
929 # this results from a separate event loop |
|
930 self.fork_child = (arg == 'child') |
|
931 self.eventExit = True |
|
932 return |
|
933 |
|
934 if cmd == DebugProtocol.RequestForkMode: |
|
935 self.fork_auto, self.fork_child = eval(arg) |
|
936 return |
|
937 |
|
938 # If we are handling raw mode input then reset the mode and break out |
|
939 # of the current event loop. |
|
940 if self.inRawMode: |
|
941 self.inRawMode = False |
|
942 self.rawLine = line |
|
943 self.eventExit = True |
|
944 return |
|
945 |
|
946 if self.buffer: |
|
947 self.buffer = self.buffer + '\n' + line |
|
948 else: |
|
949 self.buffer = line |
|
950 |
|
951 try: |
|
952 code = self.compile_command(self.buffer, self.readstream.name) |
|
953 except (OverflowError, SyntaxError, ValueError): |
|
954 # Report the exception |
|
955 sys.last_type, sys.last_value, sys.last_traceback = sys.exc_info() |
|
956 for l in traceback.format_exception_only( |
|
957 sys.last_type, sys.last_value): |
|
958 self.write(l) |
|
959 self.buffer = '' |
|
960 else: |
|
961 if code is None: |
|
962 self.pendingResponse = DebugProtocol.ResponseContinue |
|
963 else: |
|
964 self.buffer = '' |
|
965 |
|
966 try: |
|
967 if self.running is None: |
|
968 exec(code, self.debugMod.__dict__) |
|
969 else: |
|
970 if self.currentThread is None: |
|
971 # program has terminated |
|
972 self.running = None |
|
973 _globals = self.debugMod.__dict__ |
|
974 _locals = _globals |
|
975 else: |
|
976 cf = self.currentThread.getCurrentFrame() |
|
977 # program has terminated |
|
978 if cf is None: |
|
979 self.running = None |
663 self.running = None |
980 _globals = self.debugMod.__dict__ |
664 _globals = self.debugMod.__dict__ |
981 _locals = _globals |
665 _locals = _globals |
982 else: |
666 else: |
983 frmnr = self.framenr |
667 cf = self.currentThread.getCurrentFrame() |
984 while cf is not None and frmnr > 0: |
668 # program has terminated |
985 cf = cf.f_back |
669 if cf is None: |
986 frmnr -= 1 |
670 self.running = None |
987 _globals = cf.f_globals |
671 _globals = self.debugMod.__dict__ |
988 _locals = \ |
672 _locals = _globals |
989 self.currentThread.getFrameLocals( |
673 else: |
990 self.framenr) |
674 frmnr = self.framenr |
991 # reset sys.stdout to our redirector (unconditionally) |
675 while cf is not None and frmnr > 0: |
992 if "sys" in _globals: |
676 cf = cf.f_back |
993 __stdout = _globals["sys"].stdout |
677 frmnr -= 1 |
994 _globals["sys"].stdout = self.writestream |
678 _globals = cf.f_globals |
995 exec(code, _globals, _locals) |
679 _locals = \ |
996 _globals["sys"].stdout = __stdout |
680 self.currentThread.getFrameLocals( |
997 elif "sys" in _locals: |
681 self.framenr) |
998 __stdout = _locals["sys"].stdout |
682 # reset sys.stdout to our redirector |
999 _locals["sys"].stdout = self.writestream |
683 # (unconditionally) |
1000 exec(code, _globals, _locals) |
684 if "sys" in _globals: |
1001 _locals["sys"].stdout = __stdout |
685 __stdout = _globals["sys"].stdout |
1002 else: |
686 _globals["sys"].stdout = self.writestream |
1003 exec(code, _globals, _locals) |
687 exec(code, _globals, _locals) |
1004 |
688 _globals["sys"].stdout = __stdout |
1005 self.currentThread.storeFrameLocals(self.framenr) |
689 elif "sys" in _locals: |
1006 except SystemExit as exc: |
690 __stdout = _locals["sys"].stdout |
1007 self.progTerminated(exc.code) |
691 _locals["sys"].stdout = self.writestream |
1008 except Exception: |
692 exec(code, _globals, _locals) |
1009 # Report the exception and the traceback |
693 _locals["sys"].stdout = __stdout |
|
694 else: |
|
695 exec(code, _globals, _locals) |
|
696 |
|
697 self.currentThread.storeFrameLocals(self.framenr) |
|
698 except SystemExit as exc: |
|
699 self.progTerminated(exc.code) |
|
700 except Exception: |
|
701 # Report the exception and the traceback |
|
702 tlist = [] |
|
703 try: |
|
704 exc_type, exc_value, exc_tb = sys.exc_info() |
|
705 sys.last_type = exc_type |
|
706 sys.last_value = exc_value |
|
707 sys.last_traceback = exc_tb |
|
708 tblist = traceback.extract_tb(exc_tb) |
|
709 del tblist[:1] |
|
710 tlist = traceback.format_list(tblist) |
|
711 if tlist: |
|
712 tlist.insert( |
|
713 0, "Traceback (innermost last):\n") |
|
714 tlist.extend(traceback.format_exception_only( |
|
715 exc_type, exc_value)) |
|
716 finally: |
|
717 tblist = exc_tb = None |
|
718 |
|
719 self.sendJsonCommand("ClientOutput", { |
|
720 "text": "".join(tlist) |
|
721 }) |
|
722 |
|
723 self.sendJsonCommand("ResponseOK", {}) |
|
724 |
|
725 elif method == "RequestStep": |
|
726 self.currentThread.step(True) |
|
727 self.eventExit = True |
|
728 |
|
729 elif method == "RequestStepOver": |
|
730 self.currentThread.step(False) |
|
731 self.eventExit = True |
|
732 |
|
733 elif method == "RequestStepOut": |
|
734 self.currentThread.stepOut() |
|
735 self.eventExit = True |
|
736 |
|
737 elif method == "RequestStepQuit": |
|
738 if self.passive: |
|
739 self.progTerminated(42) |
|
740 else: |
|
741 self.set_quit() |
|
742 self.eventExit = True |
|
743 |
|
744 elif method == "RequestContinue": |
|
745 self.currentThread.go(params["special"]) |
|
746 self.eventExit = True |
|
747 |
|
748 elif method == "RawInput": |
|
749 # If we are handling raw mode input then break out of the current |
|
750 # event loop. |
|
751 self.rawLine = params["input"] |
|
752 self.eventExit = True |
|
753 |
|
754 elif method == "RequestBreakpoint": |
|
755 if params["setBreakpoint"]: |
|
756 if params["condition"] in ['None', '']: |
|
757 cond = None |
|
758 elif params["condition"] is not None: |
1010 try: |
759 try: |
1011 exc_type, exc_value, exc_tb = sys.exc_info() |
760 cond = compile(params["condition"], '<string>', 'eval') |
1012 sys.last_type = exc_type |
761 except SyntaxError: |
1013 sys.last_value = exc_value |
762 self.sendJsonCommand("ResponseBPConditionError", { |
1014 sys.last_traceback = exc_tb |
763 "filename": params["filename"], |
1015 tblist = traceback.extract_tb(exc_tb) |
764 "line": params["line"], |
1016 del tblist[:1] |
765 }) |
1017 list = traceback.format_list(tblist) |
766 return |
1018 if list: |
767 else: |
1019 list.insert(0, "Traceback (innermost last):\n") |
768 cond = None |
1020 list[len(list):] = traceback.format_exception_only( |
769 |
1021 exc_type, exc_value) |
770 Breakpoint( |
1022 finally: |
771 params["filename"], params["line"], params["temporary"], |
1023 tblist = exc_tb = None |
772 cond) |
1024 |
773 else: |
1025 for l in list: |
774 Breakpoint.clear_break(params["filename"], params["line"]) |
1026 self.write(l) |
775 |
1027 |
776 elif method == "RequestBreakpointEnable": |
|
777 bp = Breakpoint.get_break(params["filename"], params["line"]) |
|
778 if bp is not None: |
|
779 if params["enable"]: |
|
780 bp.enable() |
|
781 else: |
|
782 bp.disable() |
|
783 |
|
784 elif method == "RequestBreakpointIgnore": |
|
785 bp = Breakpoint.get_break(params["filename"], params["line"]) |
|
786 if bp is not None: |
|
787 bp.ignore = params["count"] |
|
788 |
|
789 elif method == "RequestWatch": |
|
790 if params["setWatch"]: |
|
791 if params["condition"].endswith( |
|
792 ('??created??', '??changed??')): |
|
793 compiledCond, flag = params["condition"].split() |
|
794 else: |
|
795 compiledCond = params["condition"] |
|
796 flag = '' |
|
797 |
|
798 try: |
|
799 compiledCond = compile( |
|
800 compiledCond, '<string>', 'eval') |
|
801 except SyntaxError: |
|
802 self.sendJsonCommand("ResponseWatchConditionError", { |
|
803 "condition": params["condition"], |
|
804 }) |
|
805 return |
|
806 Watch( |
|
807 params["condition"], compiledCond, flag, |
|
808 params["temporary"]) |
|
809 else: |
|
810 Watch.clear_watch(params["condition"]) |
|
811 |
|
812 elif method == "RequestWatchEnable": |
|
813 wp = Watch.get_watch(params["condition"]) |
|
814 if wp is not None: |
|
815 if params["enable"]: |
|
816 wp.enable() |
|
817 else: |
|
818 wp.disable() |
|
819 |
|
820 elif method == "RequestWatchIgnore": |
|
821 wp = Watch.get_watch(params["condition"]) |
|
822 if wp is not None: |
|
823 wp.ignore = params["count"] |
|
824 |
|
825 elif method == "RequestShutdown": |
|
826 self.sessionClose() |
|
827 |
|
828 elif method == "RequestCompletion": |
|
829 self.__completionList(params["text"]) |
|
830 |
|
831 elif method == "RequestUTPrepare": |
|
832 sys.path.insert( |
|
833 0, os.path.dirname(os.path.abspath(params["filename"]))) |
|
834 os.chdir(sys.path[0]) |
|
835 |
|
836 # set the system exception handling function to ensure, that |
|
837 # we report on all unhandled exceptions |
|
838 sys.excepthook = self.__unhandled_exception |
|
839 self.__interceptSignals() |
|
840 |
|
841 try: |
|
842 import unittest |
|
843 utModule = imp.load_source( |
|
844 params["testname"], params["filename"]) |
|
845 try: |
|
846 if params["failed"]: |
|
847 self.test = unittest.defaultTestLoader\ |
|
848 .loadTestsFromNames(params["failed"], utModule) |
|
849 else: |
|
850 self.test = unittest.defaultTestLoader\ |
|
851 .loadTestsFromName(params["testfunctionname"], |
|
852 utModule) |
|
853 except AttributeError: |
|
854 self.test = unittest.defaultTestLoader\ |
|
855 .loadTestsFromModule(utModule) |
|
856 except Exception: |
|
857 exc_type, exc_value, exc_tb = sys.exc_info() |
|
858 self.sendJsonCommand("ResponseUTPrepared", { |
|
859 "count": 0, |
|
860 "exception": exc_type.__name__, |
|
861 "message": str(exc_value), |
|
862 }) |
|
863 return |
|
864 |
|
865 # generate a coverage object |
|
866 if params["coverage"]: |
|
867 from coverage import coverage |
|
868 self.cover = coverage( |
|
869 auto_data=True, |
|
870 data_file="{0}.coverage".format( |
|
871 os.path.splitext(params["coveragefile"])[0])) |
|
872 if params["coverageerase"]: |
|
873 self.cover.erase() |
|
874 else: |
|
875 self.cover = None |
|
876 |
|
877 self.sendJsonCommand("ResponseUTPrepared", { |
|
878 "count": self.test.countTestCases(), |
|
879 "exception": "", |
|
880 "message": "", |
|
881 }) |
|
882 |
|
883 elif method == "RequestUTRun": |
|
884 from DCTestResult import DCTestResult |
|
885 self.testResult = DCTestResult(self) |
|
886 if self.cover: |
|
887 self.cover.start() |
|
888 self.test.run(self.testResult) |
|
889 if self.cover: |
|
890 self.cover.stop() |
|
891 self.cover.save() |
|
892 self.sendJsonCommand("ResponseUTFinished", {}) |
|
893 |
|
894 elif method == "RequestUTStop": |
|
895 self.testResult.stop() |
|
896 |
|
897 elif method == "ResponseForkTo": |
|
898 # this results from a separate event loop |
|
899 self.fork_child = (params["target"] == 'child') |
|
900 self.eventExit = True |
|
901 |
|
902 def sendJsonCommand(self, method, params): |
|
903 """ |
|
904 Public method to send a single command or response to the IDE. |
|
905 |
|
906 @param method command or response command name to be sent |
|
907 @type str |
|
908 @param params dictionary of named parameters for the command or |
|
909 response |
|
910 @type dict |
|
911 """ |
|
912 cmd = prepareJsonCommand(method, params) |
|
913 |
|
914 self.writestream.write_p(cmd) |
|
915 self.writestream.flush() |
|
916 |
|
917 def sendClearTemporaryBreakpoint(self, filename, lineno): |
|
918 """ |
|
919 Public method to signal the deletion of a temporary breakpoint. |
|
920 |
|
921 @param filename name of the file the bp belongs to |
|
922 @type str |
|
923 @param lineno linenumber of the bp |
|
924 @type int |
|
925 """ |
|
926 self.sendJsonCommand("ResponseClearBreakpoint", { |
|
927 "filename": filename, |
|
928 "line": lineno |
|
929 }) |
|
930 |
|
931 def sendClearTemporaryWatch(self, condition): |
|
932 """ |
|
933 Public method to signal the deletion of a temporary watch expression. |
|
934 |
|
935 @param condition condition of the watch expression to be cleared |
|
936 @type str |
|
937 """ |
|
938 self.sendJsonCommand("ResponseClearWatch", { |
|
939 "condition": condition, |
|
940 }) |
|
941 |
|
942 def sendResponseLine(self, stack): |
|
943 """ |
|
944 Public method to send the current call stack. |
|
945 |
|
946 @param stack call stack |
|
947 @type list |
|
948 """ |
|
949 self.sendJsonCommand("ResponseLine", { |
|
950 "stack": stack, |
|
951 }) |
|
952 |
|
953 def sendCallTrace(self, event, fromInfo, toInfo): |
|
954 """ |
|
955 Public method to send a call trace entry. |
|
956 |
|
957 @param event trace event (call or return) |
|
958 @type str |
|
959 @param fromInfo dictionary containing the origin info |
|
960 @type dict with 'filename', 'linenumber' and 'codename' |
|
961 as keys |
|
962 @param toInfo dictionary containing the target info |
|
963 @type dict with 'filename', 'linenumber' and 'codename' |
|
964 as keys |
|
965 """ |
|
966 self.sendJsonCommand("CallTrace", { |
|
967 "event": event[0], |
|
968 "from": fromInfo, |
|
969 "to": toInfo, |
|
970 }) |
|
971 |
|
972 def sendException(self, exceptionType, exceptionMessage, stack): |
|
973 """ |
|
974 Public method to send information for an exception. |
|
975 |
|
976 @param exceptionType type of exception raised |
|
977 @type str |
|
978 @param exceptionMessage message of the exception |
|
979 @type str |
|
980 @param stack stack trace information |
|
981 @type list |
|
982 """ |
|
983 self.sendJsonCommand("ResponseException", { |
|
984 "type": exceptionType, |
|
985 "message": exceptionMessage, |
|
986 "stack": stack, |
|
987 }) |
|
988 |
|
989 def sendSyntaxError(self, message, filename, lineno, charno): |
|
990 """ |
|
991 Public method to send information for a syntax error. |
|
992 |
|
993 @param message syntax error message |
|
994 @type str |
|
995 @param filename name of the faulty file |
|
996 @type str |
|
997 @param lineno line number info |
|
998 @type int |
|
999 @param charno character number info |
|
1000 @type int |
|
1001 """ |
|
1002 self.sendJsonCommand("ResponseSyntax", { |
|
1003 "message": message, |
|
1004 "filename": filename, |
|
1005 "linenumber": lineno, |
|
1006 "characternumber": charno, |
|
1007 }) |
|
1008 |
|
1009 def sendPassiveStartup(self, filename, exceptions): |
|
1010 """ |
|
1011 Public method to send the passive start information. |
|
1012 |
|
1013 @param filename name of the script |
|
1014 @type str |
|
1015 @param exceptions flag to enable exception reporting of the IDE |
|
1016 @type bool |
|
1017 """ |
|
1018 self.sendJsonCommand("PassiveStartup", { |
|
1019 "filename": filename, |
|
1020 "exceptions": exceptions, |
|
1021 }) |
|
1022 |
1028 def __clientCapabilities(self): |
1023 def __clientCapabilities(self): |
1029 """ |
1024 """ |
1030 Private method to determine the clients capabilities. |
1025 Private method to determine the clients capabilities. |
1031 |
1026 |
1032 @return client capabilities (integer) |
1027 @return client capabilities (integer) |
1381 elif f.f_globals is f.f_locals: |
1410 elif f.f_globals is f.f_locals: |
1382 scope = -1 |
1411 scope = -1 |
1383 else: |
1412 else: |
1384 dict = f.f_locals |
1413 dict = f.f_locals |
1385 |
1414 |
1386 varlist = [scope, var] |
1415 varlist = [] |
1387 |
1416 |
1388 if scope != -1: |
1417 if scope != -1: |
1389 # search the correct dictionary |
1418 variable = dict |
1390 i = 0 |
1419 for attribute in var: |
1391 rvar = var[:] |
1420 attribute = self.__extractIndicators(attribute)[0] |
1392 dictkeys = None |
1421 typeObject, typeName, typeStr, resolver = \ |
1393 obj = None |
1422 DebugVariables.getType(variable) |
1394 isDict = False |
1423 if resolver: |
1395 formatSequences = False |
1424 variable = resolver.resolve(variable, attribute) |
1396 access = "" |
|
1397 oaccess = "" |
|
1398 odict = dict |
|
1399 |
|
1400 qtVariable = False |
|
1401 qvar = None |
|
1402 qvtype = "" |
|
1403 |
|
1404 while i < len(var): |
|
1405 if len(dict): |
|
1406 udict = dict |
|
1407 ndict = {} |
|
1408 # this has to be in line with VariablesViewer.indicators |
|
1409 if var[i][-2:] in ["[]", "()", "{}"]: # __IGNORE_WARNING__ |
|
1410 if i + 1 == len(var): |
|
1411 if var[i][:-2] == '...': |
|
1412 dictkeys = [var[i - 1]] |
|
1413 else: |
|
1414 dictkeys = [var[i][:-2]] |
|
1415 formatSequences = True |
|
1416 if not access and not oaccess: |
|
1417 if var[i][:-2] == '...': |
|
1418 access = '["{0!s}"]'.format(var[i - 1]) |
|
1419 dict = odict |
|
1420 else: |
|
1421 access = '["{0!s}"]'.format(var[i][:-2]) |
|
1422 else: |
|
1423 if var[i][:-2] == '...': |
|
1424 if oaccess: |
|
1425 access = oaccess |
|
1426 else: |
|
1427 access = '{0!s}[{1!s}]'.format( |
|
1428 access, var[i - 1]) |
|
1429 dict = odict |
|
1430 else: |
|
1431 if oaccess: |
|
1432 access = '{0!s}[{1!s}]'.format( |
|
1433 oaccess, var[i][:-2]) |
|
1434 oaccess = '' |
|
1435 else: |
|
1436 access = '{0!s}[{1!s}]'.format( |
|
1437 access, var[i][:-2]) |
|
1438 if var[i][-2:] == "{}": # __IGNORE_WARNING__ |
|
1439 isDict = True |
|
1440 break |
|
1441 else: |
|
1442 if not access: |
|
1443 if var[i][:-2] == '...': |
|
1444 access = '["{0!s}"]'.format(var[i - 1]) |
|
1445 dict = odict |
|
1446 else: |
|
1447 access = '["{0!s}"]'.format(var[i][:-2]) |
|
1448 else: |
|
1449 if var[i][:-2] == '...': |
|
1450 access = '{0!s}[{1!s}]'.format( |
|
1451 access, var[i - 1]) |
|
1452 dict = odict |
|
1453 else: |
|
1454 if oaccess: |
|
1455 access = '{0!s}[{1!s}]'.format( |
|
1456 oaccess, var[i][:-2]) |
|
1457 oaccess = '' |
|
1458 else: |
|
1459 access = '{0!s}[{1!s}]'.format( |
|
1460 access, var[i][:-2]) |
|
1461 else: |
1425 else: |
1462 if access: |
1426 break |
1463 if oaccess: |
1427 typeObject, typeName, typeStr, resolver = \ |
1464 access = '{0!s}[{1!s}]'.format(oaccess, var[i]) |
1428 DebugVariables.getType(variable) |
1465 else: |
1429 if typeStr.startswith(("PyQt5.", "PyQt4.")): |
1466 access = '{0!s}[{1!s}]'.format(access, var[i]) |
1430 vlist = self.__formatQtVariable(variable, typeName) |
1467 if var[i - 1][:-2] == '...': |
1431 varlist.extend(vlist) |
1468 oaccess = access |
1432 elif resolver: |
1469 else: |
1433 dict = resolver.getDictionary(variable) |
1470 oaccess = '' |
1434 vlist = self.__formatVariablesList( |
1471 try: |
1435 list(dict.keys()), dict, scope, filter) |
1472 loc = {"dict": dict} |
1436 varlist.extend(vlist) |
1473 exec('mdict = dict{0!s}.__dict__\nobj = dict{0!s}' |
1437 |
1474 .format(access), globals(), loc) |
1438 self.sendJsonCommand("ResponseVariable", { |
1475 mdict = loc["mdict"] |
1439 "scope": scope, |
1476 obj = loc["obj"] |
1440 "variable": var, |
1477 if "PyQt4." in str(type(obj)) or \ |
1441 "variables": varlist, |
1478 "PyQt5." in str(type(obj)): |
1442 }) |
1479 qtVariable = True |
1443 |
1480 qvar = obj |
1444 def __extractIndicators(self, var): |
1481 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
1445 """ |
1482 ndict.update(mdict) |
1446 Private method to extract the indicator string from a variable text. |
1483 except Exception: |
1447 |
1484 pass |
1448 @param var variable text |
1485 try: |
1449 @type str |
1486 loc = {"dict": dict} |
1450 @return tuple containing the variable text without indicators and the |
1487 exec('mcdict = dict{0!s}.__class__.__dict__' |
1451 indicator string |
1488 .format(access), globals(), loc) |
1452 @rtype tuple of two str |
1489 ndict.update(loc["mcdict"]) |
1453 """ |
1490 if mdict and "sipThis" not in mdict.keys(): |
1454 for indicator in DebugClientBase.Indicators: |
1491 del rvar[0:2] |
1455 if var.endswith(indicator): |
1492 access = "" |
1456 return var[:-len(indicator)], indicator |
1493 except Exception: |
1457 |
1494 pass |
1458 return var, "" |
1495 try: |
1459 |
1496 loc = {"cdict": {}, "dict": dict} |
1460 def __formatQtVariable(self, value, qttype): |
1497 exec('slv = dict{0!s}.__slots__'.format(access), |
|
1498 globals(), loc) |
|
1499 for v in loc["slv"]: |
|
1500 try: |
|
1501 loc["v"] = v |
|
1502 exec('cdict[v] = dict{0!s}.{1!s}'.format( |
|
1503 access, v), globals, loc) |
|
1504 except Exception: |
|
1505 pass |
|
1506 ndict.update(loc["cdict"]) |
|
1507 exec('obj = dict{0!s}'.format(access), |
|
1508 globals(), loc) |
|
1509 obj = loc["obj"] |
|
1510 access = "" |
|
1511 if "PyQt4." in str(type(obj)) or \ |
|
1512 "PyQt5." in str(type(obj)): |
|
1513 qtVariable = True |
|
1514 qvar = obj |
|
1515 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
|
1516 except Exception: |
|
1517 pass |
|
1518 else: |
|
1519 try: |
|
1520 ndict.update(dict[var[i]].__dict__) |
|
1521 ndict.update(dict[var[i]].__class__.__dict__) |
|
1522 del rvar[0] |
|
1523 obj = dict[var[i]] |
|
1524 if "PyQt4." in str(type(obj)) or \ |
|
1525 "PyQt5." in str(type(obj)): |
|
1526 qtVariable = True |
|
1527 qvar = obj |
|
1528 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
|
1529 except Exception: |
|
1530 pass |
|
1531 try: |
|
1532 slv = dict[var[i]].__slots__ |
|
1533 loc = {"cdict": {}, "dict": dict, |
|
1534 "var": var, "i": i} |
|
1535 for v in slv: |
|
1536 try: |
|
1537 loc["v"] = v |
|
1538 exec('cdict[v] = dict[var[i]].{0!s}' |
|
1539 .format(v), |
|
1540 globals(), loc) |
|
1541 except Exception: |
|
1542 pass |
|
1543 ndict.update(loc["cdict"]) |
|
1544 obj = dict[var[i]] |
|
1545 if "PyQt4." in str(type(obj)) or \ |
|
1546 "PyQt5." in str(type(obj)): |
|
1547 qtVariable = True |
|
1548 qvar = obj |
|
1549 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
|
1550 except Exception: |
|
1551 pass |
|
1552 odict = dict |
|
1553 dict = ndict |
|
1554 i += 1 |
|
1555 |
|
1556 if qtVariable: |
|
1557 vlist = self.__formatQtVariable(qvar, qvtype) |
|
1558 elif ("sipThis" in dict.keys() and len(dict) == 1) or \ |
|
1559 (len(dict) == 0 and len(udict) > 0): |
|
1560 if access: |
|
1561 loc = {"udict": udict} |
|
1562 exec('qvar = udict{0!s}'.format(access), globals(), loc) |
|
1563 qvar = loc["qvar"] |
|
1564 # this has to be in line with VariablesViewer.indicators |
|
1565 elif rvar and rvar[0][-2:] in ["[]", "()", "{}"]: # __IGNORE_WARNING__ |
|
1566 loc = {"udict": udict} |
|
1567 exec('qvar = udict["{0!s}"][{1!s}]'.format(rvar[0][:-2], |
|
1568 rvar[1]), |
|
1569 globals(), loc) |
|
1570 qvar = loc["qvar"] |
|
1571 else: |
|
1572 qvar = udict[var[-1]] |
|
1573 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
|
1574 if qvtype.startswith(("PyQt4", "PyQt5")): |
|
1575 vlist = self.__formatQtVariable(qvar, qvtype) |
|
1576 else: |
|
1577 vlist = [] |
|
1578 else: |
|
1579 qtVariable = False |
|
1580 if len(dict) == 0 and len(udict) > 0: |
|
1581 if access: |
|
1582 loc = {"udict": udict} |
|
1583 exec('qvar = udict{0!s}'.format(access), |
|
1584 globals(), loc) |
|
1585 qvar = loc["qvar"] |
|
1586 # this has to be in line with VariablesViewer.indicators |
|
1587 elif rvar and rvar[0][-2:] in ["[]", "()", "{}"]: # __IGNORE_WARNING__ |
|
1588 loc = {"udict": udict} |
|
1589 exec('qvar = udict["{0!s}"][{1!s}]'.format( |
|
1590 rvar[0][:-2], rvar[1]), globals(), loc) |
|
1591 qvar = loc["qvar"] |
|
1592 else: |
|
1593 qvar = udict[var[-1]] |
|
1594 qvtype = str(type(qvar))[1:-1].split()[1][1:-1] |
|
1595 if qvtype.startswith(("PyQt4", "PyQt5")): |
|
1596 qtVariable = True |
|
1597 |
|
1598 if qtVariable: |
|
1599 vlist = self.__formatQtVariable(qvar, qvtype) |
|
1600 else: |
|
1601 # format the dictionary found |
|
1602 if dictkeys is None: |
|
1603 dictkeys = dict.keys() |
|
1604 else: |
|
1605 # treatment for sequences and dictionaries |
|
1606 if access: |
|
1607 loc = {"dict": dict} |
|
1608 exec("dict = dict{0!s}".format(access), globals(), |
|
1609 loc) |
|
1610 dict = loc["dict"] |
|
1611 else: |
|
1612 dict = dict[dictkeys[0]] |
|
1613 if isDict: |
|
1614 dictkeys = dict.keys() |
|
1615 else: |
|
1616 dictkeys = range(len(dict)) |
|
1617 vlist = self.__formatVariablesList( |
|
1618 dictkeys, dict, scope, filter, formatSequences) |
|
1619 varlist.extend(vlist) |
|
1620 |
|
1621 if obj is not None and not formatSequences: |
|
1622 try: |
|
1623 if repr(obj).startswith('{'): |
|
1624 varlist.append( |
|
1625 ('...', 'dict', "{0:d}".format(len(obj.keys())))) |
|
1626 elif repr(obj).startswith('['): |
|
1627 varlist.append( |
|
1628 ('...', 'list', "{0:d}".format(len(obj)))) |
|
1629 elif repr(obj).startswith('('): |
|
1630 varlist.append( |
|
1631 ('...', 'tuple', "{0:d}".format(len(obj)))) |
|
1632 except Exception: |
|
1633 pass |
|
1634 |
|
1635 self.write('{0}{1}\n'.format( |
|
1636 DebugProtocol.ResponseVariable, str(varlist))) |
|
1637 |
|
1638 def __formatQtVariable(self, value, vtype): |
|
1639 """ |
1461 """ |
1640 Private method to produce a formatted output of a simple Qt4/Qt5 type. |
1462 Private method to produce a formatted output of a simple Qt4/Qt5 type. |
1641 |
1463 |
1642 @param value variable to be formatted |
1464 @param value variable to be formatted |
1643 @param vtype type of the variable to be formatted (string) |
1465 @param qttype type of the Qt variable to be formatted (string) |
1644 @return A tuple consisting of a list of formatted variables. Each |
1466 @return A tuple consisting of a list of formatted variables. Each |
1645 variable entry is a tuple of three elements, the variable name, |
1467 variable entry is a tuple of three elements, the variable name, |
1646 its type and value. |
1468 its type and value. |
1647 """ |
1469 """ |
1648 qttype = vtype.split('.')[-1] |
|
1649 varlist = [] |
1470 varlist = [] |
1650 if qttype == 'QChar': |
1471 if qttype == 'QChar': |
1651 varlist.append(("", "QChar", "{0}".format(chr(value.unicode())))) |
1472 varlist.append(("", "QChar", "{0}".format(chr(value.unicode())))) |
1652 varlist.append(("", "int", "{0:d}".format(value.unicode()))) |
1473 varlist.append(("", "int", "{0:d}".format(value.unicode()))) |
1653 elif qttype == 'QByteArray': |
1474 elif qttype == 'QByteArray': |