Debugger/DebuggerInterfaceRuby.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2007 - 2009 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Ruby debugger interface for the debug server.
8 """
9
10 import sys
11 import os
12 import socket
13 import subprocess
14
15 from PyQt4.QtCore import *
16 from PyQt4.QtGui import QMessageBox
17
18 from E4Gui.E4Application import e4App
19
20 from DebugProtocol import *
21 import DebugClientCapabilities
22
23 import Preferences
24 import Utilities
25
26 from eric4config import getConfig
27
28
29 ClientDefaultCapabilities = \
30 DebugClientCapabilities.HasDebugger | \
31 DebugClientCapabilities.HasShell | \
32 DebugClientCapabilities.HasInterpreter | \
33 DebugClientCapabilities.HasCompleter
34
35 ClientTypeAssociations = [".rb"]
36
37 def getRegistryData():
38 """
39 Module function to get characterising data for the debugger interface.
40
41 @return list of the following data. Client type (string), client
42 capabilities (integer), client type association (list of strings)
43 """
44 return ["Ruby", ClientDefaultCapabilities, ClientTypeAssociations]
45
46 class DebuggerInterfaceRuby(QObject):
47 """
48 Class implementing the Ruby debugger interface for the debug server.
49 """
50 def __init__(self, debugServer, passive):
51 """
52 Constructor
53
54 @param debugServer reference to the debug server (DebugServer)
55 @param passive flag indicating passive connection mode (boolean)
56 """
57 QObject.__init__(self)
58
59 self.__isNetworked = True
60 self.__autoContinue = not passive
61
62 self.debugServer = debugServer
63 self.passive = passive
64 self.process = None
65
66 self.qsock = None
67 self.queue = []
68 # set default values for capabilities of clients
69 self.clientCapabilities = ClientDefaultCapabilities
70
71 self.codec = QTextCodec.codecForName(str(Preferences.getSystem("StringEncoding")))
72
73 if passive:
74 # set translation function
75 if Preferences.getDebugger("PathTranslation"):
76 self.translateRemote = \
77 Preferences.getDebugger("PathTranslationRemote")
78 self.translateLocal = \
79 Preferences.getDebugger("PathTranslationLocal")
80 self.translate = self.__remoteTranslation
81 else:
82 self.translate = self.__identityTranslation
83
84 def __identityTranslation(self, fn, remote2local = True):
85 """
86 Private method to perform the identity path translation.
87
88 @param fn filename to be translated (string)
89 @param remote2local flag indicating the direction of translation
90 (False = local to remote, True = remote to local [default])
91 @return translated filename (string)
92 """
93 return fn
94
95 def __remoteTranslation(self, fn, remote2local = True):
96 """
97 Private method to perform the path translation.
98
99 @param fn filename to be translated (string)
100 @param remote2local flag indicating the direction of translation
101 (False = local to remote, True = remote to local [default])
102 @return translated filename (string)
103 """
104 if remote2local:
105 return fn.replace(self.translateRemote, self.translateLocal)
106 else:
107 return fn.replace(self.translateLocal, self.translateRemote)
108
109 def __startProcess(self, program, arguments, environment = None):
110 """
111 Private method to start the debugger client process.
112
113 @param program name of the executable to start (string)
114 @param arguments arguments to be passed to the program (list of string)
115 @param environment dictionary of environment settings to pass (dict of string)
116 @return the process object (QProcess) or None
117 """
118 proc = QProcess()
119 if environment is not None:
120 env = []
121 for key, value in environment.items():
122 env.append("%s=%s" % (key, value))
123 proc.setEnvironment(env)
124 args = []
125 for arg in arguments:
126 args.append(arg)
127 proc.start(program, args)
128 if not proc.waitForStarted(10000):
129 proc = None
130
131 return proc
132
133 def startRemote(self, port, runInConsole):
134 """
135 Public method to start a remote Ruby interpreter.
136
137 @param port portnumber the debug server is listening on (integer)
138 @param runInConsole flag indicating to start the debugger in a
139 console window (boolean)
140 @return client process object (QProcess) and a flag to indicate
141 a network connection (boolean)
142 """
143 interpreter = Preferences.getDebugger("RubyInterpreter")
144 if interpreter == "":
145 interpreter = "/usr/bin/ruby"
146 debugClient = os.path.join(getConfig('ericDir'),
147 "DebugClients", "Ruby", "DebugClient.rb")
148
149 redirect = str(Preferences.getDebugger("RubyRedirect"))
150
151 if Preferences.getDebugger("RemoteDbgEnabled"):
152 ipaddr = self.debugServer.getHostAddress(False)[0]
153 rexec = Preferences.getDebugger("RemoteExecution")
154 rhost = Preferences.getDebugger("RemoteHost")
155 if rhost == "":
156 rhost = "localhost"
157 if rexec:
158 args = Utilities.parseOptionString(rexec) + \
159 [rhost, interpreter, os.path.abspath(debugClient),
160 str(port), redirect, ipaddr]
161 args[0] = Utilities.getExecutablePath(args[0])
162 process = self.__startProcess(args[0], args[1:])
163 if process is None:
164 QMessageBox.critical(None,
165 self.trUtf8("Start Debugger"),
166 self.trUtf8(\
167 """<p>The debugger backend could not be started.</p>"""))
168
169 # set translation function
170 if Preferences.getDebugger("PathTranslation"):
171 self.translateRemote = \
172 Preferences.getDebugger("PathTranslationRemote")
173 self.translateLocal = \
174 Preferences.getDebugger("PathTranslationLocal")
175 self.translate = self.__remoteTranslation
176 else:
177 self.translate = self.__identityTranslation
178 return process, self.__isNetworked
179
180 # set translation function
181 self.translate = self.__identityTranslation
182
183 # setup the environment for the debugger
184 if Preferences.getDebugger("DebugEnvironmentReplace"):
185 clientEnv = {}
186 else:
187 clientEnv = os.environ.copy()
188 envlist = Utilities.parseEnvironmentString(\
189 Preferences.getDebugger("DebugEnvironment"))
190 for el in envlist:
191 try:
192 key, value = el.split('=', 1)
193 if value.startswith('"') or value.startswith("'"):
194 value = value[1:-1]
195 clientEnv[str(key)] = str(value)
196 except UnpackError:
197 pass
198
199 ipaddr = self.debugServer.getHostAddress(True)
200 if runInConsole or Preferences.getDebugger("ConsoleDbgEnabled"):
201 ccmd = Preferences.getDebugger("ConsoleDbgCommand")
202 if ccmd:
203 args = Utilities.parseOptionString(ccmd) + \
204 [interpreter, os.path.abspath(debugClient),
205 str(port), '0', ipaddr]
206 args[0] = Utilities.getExecutablePath(args[0])
207 process = self.__startProcess(args[0], args[1:], clientEnv)
208 if process is None:
209 QMessageBox.critical(None,
210 self.trUtf8("Start Debugger"),
211 self.trUtf8(\
212 """<p>The debugger backend could not be started.</p>"""))
213 return process, self.__isNetworked
214
215 process = self.__startProcess(interpreter,
216 [debugClient, str(port), redirect, ipaddr],
217 clientEnv)
218 if process is None:
219 QMessageBox.critical(None,
220 self.trUtf8("Start Debugger"),
221 self.trUtf8("""<p>The debugger backend could not be started.</p>"""))
222 return process, self.__isNetworked
223
224 def startRemoteForProject(self, port, runInConsole):
225 """
226 Public method to start a remote Ruby interpreter for a project.
227
228 @param port portnumber the debug server is listening on (integer)
229 @param runInConsole flag indicating to start the debugger in a
230 console window (boolean)
231 @return pid of the client process (integer) and a flag to indicate
232 a network connection (boolean)
233 """
234 project = e4App().getObject("Project")
235 if not project.isDebugPropertiesLoaded():
236 return None, self.__isNetworked
237
238 # start debugger with project specific settings
239 interpreter = project.getDebugProperty("INTERPRETER")
240 debugClient = project.getDebugProperty("DEBUGCLIENT")
241
242 redirect = str(project.getDebugProperty("REDIRECT"))
243
244 if project.getDebugProperty("REMOTEDEBUGGER"):
245 ipaddr = self.debugServer.getHostAddress(False)[0]
246 rexec = project.getDebugProperty("REMOTECOMMAND")
247 rhost = project.getDebugProperty("REMOTEHOST")
248 if rhost == "":
249 rhost = "localhost"
250 if rexec:
251 args = Utilities.parseOptionString(rexec) + \
252 [rhost, interpreter, os.path.abspath(debugClient),
253 str(port), redirect, ipaddr]
254 args[0] = Utilities.getExecutablePath(args[0])
255 process = self.__startProcess(args[0], args[1:])
256 if process is None:
257 QMessageBox.critical(None,
258 self.trUtf8("Start Debugger"),
259 self.trUtf8(\
260 """<p>The debugger backend could not be started.</p>"""))
261 # set translation function
262 if project.getDebugProperty("PATHTRANSLATION"):
263 self.translateRemote = project.getDebugProperty("REMOTEPATH")
264 self.translateLocal = project.getDebugProperty("LOCALPATH")
265 self.translate = self.__remoteTranslation
266 else:
267 self.translate = self.__identityTranslation
268 return process, self.__isNetworked
269
270 # set translation function
271 self.translate = self.__identityTranslation
272
273 # setup the environment for the debugger
274 if project.getDebugProperty("ENVIRONMENTOVERRIDE"):
275 clientEnv = {}
276 else:
277 clientEnv = os.environ.copy()
278 envlist = Utilities.parseEnvironmentString(\
279 project.getDebugProperty("ENVIRONMENTSTRING"))
280 for el in envlist:
281 try:
282 key, value = el.split('=', 1)
283 if value.startswith('"') or value.startswith("'"):
284 value = value[1:-1]
285 clientEnv[str(key)] = str(value)
286 except UnpackError:
287 pass
288
289 ipaddr = self.debugServer.getHostAddress(True)
290 if runInConsole or project.getDebugProperty("CONSOLEDEBUGGER"):
291 ccmd = project.getDebugProperty("CONSOLECOMMAND") or \
292 Preferences.getDebugger("ConsoleDbgCommand")
293 if ccmd:
294 args = Utilities.parseOptionString(ccmd) + \
295 [interpreter, os.path.abspath(debugClient),
296 str(port), '0', ipaddr]
297 args[0] = Utilities.getExecutablePath(args[0])
298 process = self.__startProcess(args[0], args[1:], clientEnv)
299 if process is None:
300 QMessageBox.critical(None,
301 self.trUtf8("Start Debugger"),
302 self.trUtf8(\
303 """<p>The debugger backend could not be started.</p>"""))
304 return process, self.__isNetworked
305
306 process = self.__startProcess(interpreter,
307 [debugClient, str(port), redirect, ipaddr],
308 clientEnv)
309 if process is None:
310 QMessageBox.critical(None,
311 self.trUtf8("Start Debugger"),
312 self.trUtf8("""<p>The debugger backend could not be started.</p>"""))
313 return process, self.__isNetworked
314
315 def getClientCapabilities(self):
316 """
317 Public method to retrieve the debug clients capabilities.
318
319 @return debug client capabilities (integer)
320 """
321 return self.clientCapabilities
322
323 def newConnection(self, sock):
324 """
325 Public slot to handle a new connection.
326
327 @param sockreference to the socket object (QTcpSocket)
328 @return flag indicating success (boolean)
329 """
330 # If we already have a connection, refuse this one. It will be closed
331 # automatically.
332 if self.qsock is not None:
333 return False
334
335 self.connect(sock, SIGNAL('disconnected()'), self.debugServer.startClient)
336 self.connect(sock, SIGNAL('readyRead()'), self.__parseClientLine)
337
338 self.qsock = sock
339
340 # Get the remote clients capabilities
341 self.remoteCapabilities()
342 return True
343
344 def flush(self):
345 """
346 Public slot to flush the queue.
347 """
348 # Send commands that were waiting for the connection.
349 for cmd in self.queue:
350 self.qsock.write(cmd.encode('utf8'))
351
352 self.queue = []
353
354 def shutdown(self):
355 """
356 Public method to cleanly shut down.
357
358 It closes our socket and shuts down
359 the debug client. (Needed on Win OS)
360 """
361 if self.qsock is None:
362 return
363
364 # do not want any slots called during shutdown
365 self.disconnect(self.qsock, SIGNAL('disconnected()'),
366 self.debugServer.startClient)
367 self.disconnect(self.qsock, SIGNAL('readyRead()'), self.__parseClientLine)
368
369 # close down socket, and shut down client as well.
370 self.__sendCommand('%s\n' % RequestShutdown)
371 self.qsock.flush()
372
373 self.qsock.close()
374
375 # reinitialize
376 self.qsock = None
377 self.queue = []
378
379 def isConnected(self):
380 """
381 Public method to test, if a debug client has connected.
382
383 @return flag indicating the connection status (boolean)
384 """
385 return self.qsock is not None
386
387 def remoteEnvironment(self, env):
388 """
389 Public method to set the environment for a program to debug, run, ...
390
391 @param env environment settings (dictionary)
392 """
393 self.__sendCommand('%s%s\n' % (RequestEnv, str(env)))
394
395 def remoteLoad(self, fn, argv, wd, traceInterpreter = False, autoContinue = True,
396 autoFork = False, forkChild = False):
397 """
398 Public method to load a new program to debug.
399
400 @param fn the filename to debug (string)
401 @param argv the commandline arguments to pass to the program (string)
402 @param wd the working directory for the program (string)
403 @keyparam traceInterpreter flag indicating if the interpreter library should be
404 traced as well (boolean)
405 @keyparam autoContinue flag indicating, that the debugger should not stop
406 at the first executable line (boolean)
407 @keyparam autoFork flag indicating the automatic fork mode (boolean) (ignored)
408 @keyparam forkChild flag indicating to debug the child after forking
409 (boolean) (ignored)
410 """
411 self.__autoContinue = autoContinue
412
413 wd = self.translate(wd, False)
414 fn = self.translate(os.path.abspath(fn), False)
415 self.__sendCommand('%s%s|%s|%s|%d\n' % \
416 (RequestLoad, wd, fn, unicode(Utilities.parseOptionString(argv)),
417 traceInterpreter))
418
419 def remoteRun(self, fn, argv, wd):
420 """
421 Public method to load a new program to run.
422
423 @param fn the filename to run (string)
424 @param argv the commandline arguments to pass to the program (string)
425 @param wd the working directory for the program (string)
426 """
427 wd = self.translate(wd, False)
428 fn = self.translate(os.path.abspath(fn), False)
429 self.__sendCommand('%s%s|%s|%s\n' % \
430 (RequestRun, wd, fn, unicode(Utilities.parseOptionString(argv))))
431
432 def remoteCoverage(self, fn, argv, wd, erase = False):
433 """
434 Public method to load a new program to collect coverage data.
435
436 @param fn the filename to run (string)
437 @param argv the commandline arguments to pass to the program (string)
438 @param wd the working directory for the program (string)
439 @keyparam erase flag indicating that coverage info should be
440 cleared first (boolean)
441 """
442 raise NotImplementedError("Interface not available.")
443
444 def remoteProfile(self, fn, argv, wd, erase = False):
445 """
446 Public method to load a new program to collect profiling data.
447
448 @param fn the filename to run (string)
449 @param argv the commandline arguments to pass to the program (string)
450 @param wd the working directory for the program (string)
451 @keyparam erase flag indicating that timing info should be cleared first (boolean)
452 """
453 raise NotImplementedError("Interface not available.")
454
455 def remoteStatement(self, stmt):
456 """
457 Public method to execute a Ruby statement.
458
459 @param stmt the Ruby statement to execute (string). It
460 should not have a trailing newline.
461 """
462 self.__sendCommand('%s\n' % stmt)
463 self.__sendCommand(RequestOK + '\n')
464
465 def remoteStep(self):
466 """
467 Public method to single step the debugged program.
468 """
469 self.__sendCommand(RequestStep + '\n')
470
471 def remoteStepOver(self):
472 """
473 Public method to step over the debugged program.
474 """
475 self.__sendCommand(RequestStepOver + '\n')
476
477 def remoteStepOut(self):
478 """
479 Public method to step out the debugged program.
480 """
481 self.__sendCommand(RequestStepOut + '\n')
482
483 def remoteStepQuit(self):
484 """
485 Public method to stop the debugged program.
486 """
487 self.__sendCommand(RequestStepQuit + '\n')
488
489 def remoteContinue(self, special = False):
490 """
491 Public method to continue the debugged program.
492
493 @param special flag indicating a special continue operation (boolean)
494 """
495 self.__sendCommand('%s%d\n' % (RequestContinue, special))
496
497 def remoteBreakpoint(self, fn, line, set, cond = None, temp = False):
498 """
499 Public method to set or clear a breakpoint.
500
501 @param fn filename the breakpoint belongs to (string)
502 @param line linenumber of the breakpoint (int)
503 @param set flag indicating setting or resetting a breakpoint (boolean)
504 @param cond condition of the breakpoint (string)
505 @param temp flag indicating a temporary breakpoint (boolean)
506 """
507 fn = self.translate(fn, False)
508 self.__sendCommand('%s%s@@%d@@%d@@%d@@%s\n' % \
509 (RequestBreak, fn, line, temp, set, cond))
510
511 def remoteBreakpointEnable(self, fn, line, enable):
512 """
513 Public method to enable or disable a breakpoint.
514
515 @param fn filename the breakpoint belongs to (string)
516 @param line linenumber of the breakpoint (int)
517 @param enable flag indicating enabling or disabling a breakpoint (boolean)
518 """
519 fn = self.translate(fn, False)
520 self.__sendCommand('%s%s,%d,%d\n' % (RequestBreakEnable, fn, line, enable))
521
522 def remoteBreakpointIgnore(self, fn, line, count):
523 """
524 Public method to ignore a breakpoint the next couple of occurrences.
525
526 @param fn filename the breakpoint belongs to (string)
527 @param line linenumber of the breakpoint (int)
528 @param count number of occurrences to ignore (int)
529 """
530 fn = self.translate(fn, False)
531 self.__sendCommand('%s%s,%d,%d\n' % (RequestBreakIgnore, fn, line, count))
532
533 def remoteWatchpoint(self, cond, set, temp = False):
534 """
535 Public method to set or clear a watch expression.
536
537 @param cond expression of the watch expression (string)
538 @param set flag indicating setting or resetting a watch expression (boolean)
539 @param temp flag indicating a temporary watch expression (boolean)
540 """
541 # cond is combination of cond and special (s. watch expression viewer)
542 self.__sendCommand('%s%s@@%d@@%d\n' % (RequestWatch, cond, temp, set))
543
544 def remoteWatchpointEnable(self, cond, enable):
545 """
546 Public method to enable or disable a watch expression.
547
548 @param cond expression of the watch expression (string)
549 @param enable flag indicating enabling or disabling a watch expression (boolean)
550 """
551 # cond is combination of cond and special (s. watch expression viewer)
552 self.__sendCommand('%s%s,%d\n' % (RequestWatchEnable, cond, enable))
553
554 def remoteWatchpointIgnore(self, cond, count):
555 """
556 Public method to ignore a watch expression the next couple of occurrences.
557
558 @param cond expression of the watch expression (string)
559 @param count number of occurrences to ignore (int)
560 """
561 # cond is combination of cond and special (s. watch expression viewer)
562 self.__sendCommand('%s%s,%d\n' % (RequestWatchIgnore, cond, count))
563
564 def remoteRawInput(self,s):
565 """
566 Public method to send the raw input to the debugged program.
567
568 @param s the raw input (string)
569 """
570 self.__sendCommand(s + '\n')
571
572 def remoteThreadList(self):
573 """
574 Public method to request the list of threads from the client.
575 """
576 return
577
578 def remoteSetThread(self, tid):
579 """
580 Public method to request to set the given thread as current thread.
581
582 @param tid id of the thread (integer)
583 """
584 return
585
586 def remoteClientVariables(self, scope, filter, framenr = 0):
587 """
588 Public method to request the variables of the debugged program.
589
590 @param scope the scope of the variables (0 = local, 1 = global)
591 @param filter list of variable types to filter out (list of int)
592 @param framenr framenumber of the variables to retrieve (int)
593 """
594 self.__sendCommand('%s%d, %d, %s\n' % \
595 (RequestVariables, framenr, scope, unicode(filter)))
596
597 def remoteClientVariable(self, scope, filter, var, framenr = 0):
598 """
599 Public method to request the variables of the debugged program.
600
601 @param scope the scope of the variables (0 = local, 1 = global)
602 @param filter list of variable types to filter out (list of int)
603 @param var list encoded name of variable to retrieve (string)
604 @param framenr framenumber of the variables to retrieve (int)
605 """
606 self.__sendCommand('%s%s, %d, %d, %s\n' % \
607 (RequestVariable, unicode(var), framenr, scope, str(filter)))
608
609 def remoteClientSetFilter(self, scope, filter):
610 """
611 Public method to set a variables filter list.
612
613 @param scope the scope of the variables (0 = local, 1 = global)
614 @param filter regexp string for variable names to filter out (string)
615 """
616 self.__sendCommand('%s%d, "%s"\n' % (RequestSetFilter, scope, filter))
617
618 def remoteEval(self, arg):
619 """
620 Public method to evaluate arg in the current context of the debugged program.
621
622 @param arg the arguments to evaluate (string)
623 """
624 self.__sendCommand('%s%s\n' % (RequestEval, arg))
625
626 def remoteExec(self, stmt):
627 """
628 Public method to execute stmt in the current context of the debugged program.
629
630 @param stmt statement to execute (string)
631 """
632 self.__sendCommand('%s%s\n' % (RequestExec, stmt))
633
634 def remoteBanner(self):
635 """
636 Public slot to get the banner info of the remote client.
637 """
638 self.__sendCommand(RequestBanner + '\n')
639
640 def remoteCapabilities(self):
641 """
642 Public slot to get the debug clients capabilities.
643 """
644 self.__sendCommand(RequestCapabilities + '\n')
645
646 def remoteCompletion(self, text):
647 """
648 Public slot to get the a list of possible commandline completions
649 from the remote client.
650
651 @param text the text to be completed (string)
652 """
653 self.__sendCommand("%s%s\n" % (RequestCompletion, text))
654
655 def remoteUTPrepare(self, fn, tn, tfn, cov, covname, coverase):
656 """
657 Public method to prepare a new unittest run.
658
659 @param fn the filename to load (string)
660 @param tn the testname to load (string)
661 @param tfn the test function name to load tests from (string)
662 @param cov flag indicating collection of coverage data is requested
663 @param covname filename to be used to assemble the coverage caches
664 filename
665 @param coverase flag indicating erasure of coverage data is requested
666 """
667 raise NotImplementedError("Interface not available.")
668
669 def remoteUTRun(self):
670 """
671 Public method to start a unittest run.
672 """
673 raise NotImplementedError("Interface not available.")
674
675 def remoteUTStop(self):
676 """
677 public method to stop a unittest run.
678 """
679 raise NotImplementedError("Interface not available.")
680
681 def __parseClientLine(self):
682 """
683 Private method to handle data from the client.
684 """
685 while self.qsock and self.qsock.canReadLine():
686 qs = self.qsock.readLine()
687 if self.codec is not None:
688 us = self.codec.fromUnicode(unicode(qs))
689 else:
690 us = qs
691 line = str(us)
692 if line.endswith(EOT):
693 line = line[:-len(EOT)]
694 if not line:
695 continue
696
697 ## print "Server: ", line ##debug
698
699 eoc = line.find('<') + 1
700
701 # Deal with case where user has written directly to stdout
702 # or stderr, but not line terminated and we stepped over the
703 # write call, in that case the >line< will not be the first
704 # string read from the socket...
705 boc = line.find('>')
706 if boc > 0 and eoc > boc:
707 self.debugServer.clientOutput(line[:boc])
708 line = line[boc:]
709 eoc = line.find('<') + 1
710 boc = line.find('>')
711
712 if boc >= 0 and eoc > boc:
713 resp = line[boc:eoc]
714
715 if resp == ResponseLine:
716 stack = eval(line[eoc:-1])
717 for s in stack:
718 s[0] = self.translate(s[0], True)
719 cf = stack[0]
720 if self.__autoContinue:
721 self.__autoContinue = False
722 QTimer.singleShot(0, self.remoteContinue)
723 else:
724 self.debugServer.clientLine(cf[0], int(cf[1]))
725 self.debugServer.clientStack(stack)
726 continue
727
728 if resp == ResponseVariables:
729 vlist = eval(line[eoc:-1])
730 scope = vlist[0]
731 try:
732 variables = vlist[1:]
733 except IndexError:
734 variables = []
735 self.debugServer.clientVariables(scope, variables)
736 continue
737
738 if resp == ResponseVariable:
739 vlist = eval(line[eoc:-1])
740 scope = vlist[0]
741 try:
742 variables = vlist[1:]
743 except IndexError:
744 variables = []
745 self.debugServer.clientVariable(scope, variables)
746 continue
747
748 if resp == ResponseOK:
749 self.debugServer.clientStatement(False)
750 continue
751
752 if resp == ResponseContinue:
753 self.debugServer.clientStatement(True)
754 continue
755
756 if resp == ResponseException:
757 exc = line[eoc:-1]
758 exc = self.translate(exc, True)
759 try:
760 exclist = eval(exc)
761 exctype = exclist[0]
762 excmessage = exclist[1]
763 stack = exclist[2:]
764 except (IndexError, ValueError, SyntaxError):
765 exctype = None
766 excmessage = ''
767 stack = []
768 self.debugServer.clientException(exctype, excmessage, stack)
769 continue
770
771 if resp == ResponseSyntax:
772 exc = line[eoc:-1]
773 exc = self.translate(exc, True)
774 try:
775 message, (fn, ln, cn) = eval(exc)
776 if fn is None:
777 fn = ''
778 except (IndexError, ValueError):
779 message = None
780 fn = ''
781 ln = 0
782 cn = 0
783 self.debugServer.clientSyntaxError(message, fn, ln, cn)
784 continue
785
786 if resp == ResponseExit:
787 self.debugServer.clientExit(line[eoc:-1])
788 continue
789
790 if resp == ResponseClearBreak:
791 fn, lineno = line[eoc:-1].split(',')
792 lineno = int(lineno)
793 fn = self.translate(fn, True)
794 self.debugServer.clientClearBreak(fn, lineno)
795 continue
796
797 if resp == ResponseClearWatch:
798 cond = line[eoc:-1]
799 self.debugServer.clientClearWatch(cond)
800 continue
801
802 if resp == ResponseBanner:
803 version, platform, dbgclient = eval(line[eoc:-1])
804 self.debugServer.clientBanner(version, platform, dbgclient)
805 continue
806
807 if resp == ResponseCapabilities:
808 cap, clType = eval(line[eoc:-1])
809 self.clientCapabilities = cap
810 self.debugServer.clientCapabilities(cap, clType)
811 continue
812
813 if resp == ResponseCompletion:
814 clstring, text = line[eoc:-1].split('||')
815 cl = eval(clstring)
816 self.debugServer.clientCompletionList(cl, text)
817 continue
818
819 if resp == PassiveStartup:
820 fn, exc = line[eoc:-1].split('|')
821 exc = bool(exc)
822 fn = self.translate(fn, True)
823 self.debugServer.passiveStartUp(fn, exc)
824 continue
825
826 self.debugServer.clientOutput(line)
827
828 def __sendCommand(self, cmd):
829 """
830 Private method to send a single line command to the client.
831
832 @param cmd command to send to the debug client (string)
833 """
834 if self.qsock is not None:
835 self.qsock.write(cmd.encode('utf8'))
836 else:
837 self.queue.append(cmd)

eric ide

mercurial