99
1010__author__ = "robertbasic"
1111
12+ from collections import deque
1213from PyQt5 .QtCore import QObject , pyqtSignal
1314
1415from pugdebug .server import PugdebugServer
1516
1617
1718class PugdebugDebugger (QObject ):
19+
1820 server = None
1921
22+ connections = deque ()
23+ current_connection = None
24+
2025 init_message = None
2126 step_result = ''
2227
2328 current_file = ''
2429 current_line = 0
2530
2631 debugging_started_signal = pyqtSignal ()
27- debugging_cancelled_signal = pyqtSignal ()
2832 debugging_stopped_signal = pyqtSignal ()
2933 step_command_signal = pyqtSignal ()
3034 got_all_variables_signal = pyqtSignal (object )
@@ -39,67 +43,111 @@ class PugdebugDebugger(QObject):
3943 def __init__ (self ):
4044 """Init the debugger object
4145
42- Create a PugdebugServer object used to communicate with xdebug client
43- through TCP .
46+ Create a PugdebugServer objects that listens to new connections
47+ from xdebug .
4448
45- Connect signals to slots.
49+ Connect server signals to slots.
4650 """
4751 super (PugdebugDebugger , self ).__init__ ()
4852
4953 self .server = PugdebugServer ()
5054
55+ self .connect_server_signals ()
56+
57+ def connect_server_signals (self ):
58+ """Connect server signals to slots
59+ """
5160 self .server .server_connected_signal .connect (
5261 self .handle_server_connected
5362 )
54- self .server .server_cancelled_signal .connect (
55- self .handle_server_cancelled
63+ self .server .server_stopped_signal .connect (
64+ self .handle_server_stopped
65+ )
66+
67+ def connect_connection_signals (self , connection ):
68+ """Connect signals for a new connection
69+
70+ Connect signals that gets emitted when a connection is stopped
71+ or detached, when a step command is done, when variables are read,
72+ when stacktraces are read, when breakpoints are set or removed,
73+ when breakpoints are read, when expressions are evaluated.
74+ """
75+
76+ # Stop/detach signals
77+ connection .server_stopped_signal .connect (
78+ self .handle_server_stopped
79+ )
80+ connection .server_detached_signal .connect (
81+ self .handle_server_stopped
5682 )
57- self .server .server_stopped_signal .connect (self .handle_server_stopped )
58- self .server .server_detached_signal .connect (
59- self .handle_server_detached
83+
84+ # Step command signals
85+ connection .server_stepped_signal .connect (
86+ self .handle_server_stepped
6087 )
61- self .server .server_stepped_signal .connect (self .handle_server_stepped )
62- self .server .server_got_variables_signal .connect (
88+
89+ # Variables signals
90+ connection .server_got_variables_signal .connect (
6391 self .handle_server_got_variables
6492 )
65- self .server .server_got_stacktraces_signal .connect (
93+
94+ # Stacktraces signals
95+ connection .server_got_stacktraces_signal .connect (
6696 self .handle_server_got_stacktraces
6797 )
68- self .server .server_set_init_breakpoints_signal .connect (
98+
99+ # Breakpoints signals
100+ connection .server_set_init_breakpoints_signal .connect (
69101 self .handle_server_set_breakpoint
70102 )
71- self . server .server_set_breakpoint_signal .connect (
103+ connection .server_set_breakpoint_signal .connect (
72104 self .handle_server_set_breakpoint
73105 )
74- self . server .server_removed_breakpoint_signal .connect (
106+ connection .server_removed_breakpoint_signal .connect (
75107 self .handle_server_removed_breakpoint
76108 )
77- self . server .server_listed_breakpoints_signal .connect (
109+ connection .server_listed_breakpoints_signal .connect (
78110 self .handle_server_listed_breakpoints
79111 )
80112
81- self .server .server_expression_evaluated_signal .connect (
113+ # Expressions signals
114+ connection .server_expression_evaluated_signal .connect (
82115 self .handle_server_expression_evaluated
83116 )
84- self . server .server_expressions_evaluated_signal .connect (
117+ connection .server_expressions_evaluated_signal .connect (
85118 self .handle_server_expressions_evaluated
86119 )
87120
88121 def cleanup (self ):
89122 """Cleanup debugger when it's done
123+
124+ If there is an active connection, disconnect from it and clear
125+ all the remaining connections.
126+
127+ Stop the server from listening.
128+
129+ Clean up attributes.
90130 """
91- if self .server .is_connected ():
92- self .server .disconnect ()
131+ if self .is_connected ():
132+ self .current_connection .disconnect ()
133+ self .connections .clear ()
134+
135+ self .server .stop ()
93136
137+ self .current_connection = None
94138 self .step_result = ''
95139 self .current_file = ''
96140 self .current_line = 0
97141
98142 def is_connected (self ):
99- return self .server .is_connected ()
143+ """Is there an active connection
144+ """
145+ return self .current_connection is not None
100146
101- def is_waiting_for_connection (self ):
102- return self .server .is_waiting_for_connection ()
147+ def has_pending_connections (self ):
148+ """Are there any pending connections?
149+ """
150+ return len (self .connections ) > 0
103151
104152 def start_debug (self ):
105153 """Start a debugging session
@@ -108,61 +156,77 @@ def start_debug(self):
108156 """
109157 self .server .connect ()
110158
111- def handle_server_connected (self , init_message ):
112- """Handle when server gets connected
159+ def handle_server_connected (self , connection ):
160+ """Handle when the server establishes a new connection
161+
162+ Connect the signals for the new connection.
163+
164+ Add it to the queue of connections.
113165
114- Emit a debugging started signal .
166+ If there is no active connection, start the new connection .
115167 """
116- if 'error' not in init_message :
117- self .init_message = init_message
168+ self .connect_connection_signals (connection )
118169
119- self .debugging_started_signal .emit ()
120- else :
121- self .error_signal .emit (init_message ['error' ])
170+ self .connections .append (connection )
122171
123- def cancel_debug ( self ):
124- self .server . cancel ()
172+ if not self . is_connected ( ):
173+ self .start_new_connection ()
125174
126- def handle_server_cancelled (self ):
127- self . debugging_cancelled_signal . emit ()
175+ def start_new_connection (self ):
176+ """Start a new connection
128177
129- def stop_debug (self ):
130- """Stop a debugging session
178+ Get the first (oldest) connection from the queue, set it's init
179+ message as the init message for the session, set it as the current
180+ connection and emit the debugging started signal.
131181 """
132- self .server .stop ()
182+ connection = self .connections .popleft ()
183+ self .init_message = connection .init_message
184+ self .current_connection = connection
133185
134- def handle_server_stopped (self ):
135- """Handle when server gets disconnected
186+ self .debugging_started_signal .emit ()
136187
137- Emit a debugging stopped signal.
188+ def stop_debug (self ):
189+ """Stop a debugging session
190+
191+ If there is an active connection, stop only that one, otherwise
192+ stop the server from listening to new connections.
138193 """
139- self .debugging_stopped_signal .emit ()
194+ if self .is_connected ():
195+ self .current_connection .stop ()
196+ else :
197+ self .server .stop ()
140198
141199 def detach_debug (self ):
142- """Detach a debugging session
200+ """Detach the current connection
143201 """
144- self .server .detach ()
202+ if self .is_connected ():
203+ self .current_connection .detach ()
145204
146- def handle_server_detached (self ):
147- """Handle when server gets ditached
205+ def handle_server_stopped (self ):
206+ """Handle when a server stopped signal is received
207+
208+ If there are pending connections, start a new one.
148209
149- Emit a debugging stopped signal, as the
150- debugger should behave the same like when
151- a debugging session is stopped.
210+ Otherwise clean up and emit a server stopped signal.
152211 """
153- self .debugging_stopped_signal .emit ()
212+ if self .has_pending_connections ():
213+ self .start_new_connection ()
214+ else :
215+ self .cleanup ()
216+
217+ self .debugging_stopped_signal .emit ()
154218
155219 def run_debug (self ):
156- self .server .step_run ()
220+ self .current_connection .step_run ()
157221
158222 def step_over (self ):
159- self .server .step_over ()
223+ self .current_connection .step_over ()
160224
161225 def step_into (self ):
162- self .server .step_into ()
226+ self .current_connection .step_into ()
163227
164228 def step_out (self ):
165- self .server .step_out ()
229+ self .current_connection .step_out ()
166230
167231 def handle_server_stepped (self , step_result ):
168232 """Handle when server executes a step command
@@ -174,7 +238,7 @@ def handle_server_stepped(self, step_result):
174238 self .step_command_signal .emit ()
175239
176240 def post_step_command (self , post_step_data ):
177- self .server .post_step_command (post_step_data )
241+ self .current_connection .post_step_command (post_step_data )
178242
179243 def handle_server_got_variables (self , variables ):
180244 """Handle when server recieves all variables
@@ -191,23 +255,23 @@ def handle_server_got_stacktraces(self, stacktraces):
191255 self .got_stacktraces_signal .emit (stacktraces )
192256
193257 def set_init_breakpoints (self , breakpoints ):
194- self .server .set_init_breakpoints (breakpoints )
258+ self .current_connection .set_init_breakpoints (breakpoints )
195259
196260 def set_breakpoint (self , breakpoint ):
197- self .server .set_breakpoint (breakpoint )
261+ self .current_connection .set_breakpoint (breakpoint )
198262
199263 def handle_server_set_breakpoint (self , successful ):
200264 if successful :
201265 self .list_breakpoints ()
202266
203267 def remove_breakpoint (self , breakpoint_id ):
204- self .server .remove_breakpoint (breakpoint_id )
268+ self .current_connection .remove_breakpoint (breakpoint_id )
205269
206270 def handle_server_removed_breakpoint (self , breakpoint_id ):
207271 self .breakpoint_removed_signal .emit (breakpoint_id )
208272
209273 def list_breakpoints (self ):
210- self .server .list_breakpoints ()
274+ self .current_connection .list_breakpoints ()
211275
212276 def handle_server_listed_breakpoints (self , breakpoints ):
213277 self .breakpoints_listed_signal .emit (breakpoints )
@@ -220,11 +284,11 @@ def get_index_file(self):
220284
221285 def evaluate_expression (self , index , expression ):
222286 """Evaluates a single expression"""
223- self .server .evaluate_expression (index , expression )
287+ self .current_connection .evaluate_expression (index , expression )
224288
225289 def evaluate_expressions (self , expressions ):
226290 """Evaluates a list of expressions"""
227- self .server .evaluate_expressions (expressions )
291+ self .current_connection .evaluate_expressions (expressions )
228292
229293 def handle_server_expression_evaluated (self , index , result ):
230294 """Handle when server evaluates an expression"""
0 commit comments