0
# Interactive Console
1
2
Interactive debugging console interface that provides REPL-like functionality within debugging sessions. The console enables code evaluation, variable inspection, and interactive debugging capabilities during breakpoints and suspended execution.
3
4
## Capabilities
5
6
### Console Command Management
7
8
Core classes for managing console commands and execution in debugging contexts.
9
10
```python { .api }
11
class Command:
12
"""
13
Represents a console command for interactive debugging.
14
15
Attributes:
16
- command_id: Unique identifier for the command
17
- command_text: The actual command/code to execute
18
- frame_id: Frame identifier for execution context
19
"""
20
def __init__(self, command_id, command_text, frame_id): ...
21
```
22
23
### Standard Input Handling
24
25
Classes for managing standard input during debugging sessions to enable interactive input/output.
26
27
```python { .api }
28
class BaseStdIn:
29
"""
30
Base class for stdin handling during debugging.
31
"""
32
def readline(self, size=-1): ...
33
def read(self, size=-1): ...
34
def close(): ...
35
36
class StdIn(BaseStdIn):
37
"""
38
Standard input handler for debugging sessions.
39
"""
40
def __init__(self, original_stdin, encoding): ...
41
42
class DebugConsoleStdIn(BaseStdIn):
43
"""
44
Debug console specific input handler.
45
"""
46
def __init__(self, py_db): ...
47
```
48
49
### Code Execution
50
51
Classes for handling code fragment execution and evaluation within debugging contexts.
52
53
```python { .api }
54
class CodeFragment:
55
"""
56
Represents a code fragment for execution in debugging console.
57
58
Attributes:
59
- text: Code text to execute
60
- is_single_line: Whether this is a single line expression
61
"""
62
def __init__(self, text, is_single_line=False): ...
63
64
class BaseInterpreterInterface:
65
"""
66
Base interface for interpreter interaction during debugging.
67
"""
68
def add_exec(self, code_fragment): ...
69
def get_namespace(self): ...
70
def close(): ...
71
72
class FakeFrame:
73
"""
74
Mock frame object for console evaluation when no real frame available.
75
"""
76
def __init__(self, locals_dict, globals_dict): ...
77
```
78
79
## Usage Examples
80
81
### Basic Console Command Execution
82
83
```python
84
import pydevconsole
85
86
# Create a console command for evaluation
87
command = pydevconsole.Command(
88
command_id=1,
89
command_text="x = 42; print(f'Value is {x}')",
90
frame_id="frame_1"
91
)
92
93
# Command will be executed in the debugging context
94
print(f"Executing command: {command.command_text}")
95
```
96
97
### Custom Input Handling
98
99
```python
100
import sys
101
from pydevconsole import DebugConsoleStdIn
102
103
# Example of setting up debug console input
104
# (This would typically be done by the debugger internally)
105
class MockPyDB:
106
def __init__(self):
107
self.cmd_factory = None
108
109
mock_db = MockPyDB()
110
debug_stdin = DebugConsoleStdIn(mock_db)
111
112
# Replace standard input during debugging
113
original_stdin = sys.stdin
114
sys.stdin = debug_stdin
115
116
try:
117
# Interactive input will now go through debug console
118
user_input = input("Enter a value: ")
119
print(f"You entered: {user_input}")
120
finally:
121
# Restore original stdin
122
sys.stdin = original_stdin
123
debug_stdin.close()
124
```
125
126
### Code Fragment Evaluation
127
128
```python
129
from pydevconsole import CodeFragment, FakeFrame
130
131
# Create code fragments for evaluation
132
single_line = CodeFragment("x + y", is_single_line=True)
133
multi_line = CodeFragment("""
134
result = []
135
for i in range(5):
136
result.append(i * 2)
137
print(result)
138
""", is_single_line=False)
139
140
# Create execution context with local variables
141
locals_dict = {"x": 10, "y": 20}
142
globals_dict = {"__builtins__": __builtins__}
143
144
fake_frame = FakeFrame(locals_dict, globals_dict)
145
146
print(f"Single line fragment: {single_line.text}")
147
print(f"Multi-line fragment: {multi_line.text}")
148
print(f"Is single line: {single_line.is_single_line}")
149
```
150
151
### Interactive Debugging Session
152
153
```python
154
import pydevd
155
from pydevconsole import BaseInterpreterInterface, CodeFragment
156
157
class DebugInterpreter(BaseInterpreterInterface):
158
def __init__(self, locals_dict, globals_dict):
159
self.locals = locals_dict
160
self.globals = globals_dict
161
162
def add_exec(self, code_fragment):
163
"""Execute code fragment in debugging context."""
164
try:
165
if code_fragment.is_single_line:
166
# Evaluate expression
167
result = eval(code_fragment.text, self.globals, self.locals)
168
return result
169
else:
170
# Execute statements
171
exec(code_fragment.text, self.globals, self.locals)
172
return None
173
except Exception as e:
174
return f"Error: {e}"
175
176
def get_namespace(self):
177
return self.locals
178
179
def close(self):
180
pass
181
182
# Example usage during debugging breakpoint
183
def debug_function():
184
x = 42
185
y = "hello"
186
z = [1, 2, 3, 4, 5]
187
188
# At this point, debugger would create interpreter
189
locals_dict = locals()
190
globals_dict = globals()
191
192
interpreter = DebugInterpreter(locals_dict, globals_dict)
193
194
# Simulate console commands
195
commands = [
196
CodeFragment("x", is_single_line=True),
197
CodeFragment("len(z)", is_single_line=True),
198
CodeFragment("new_var = x * 2", is_single_line=False),
199
CodeFragment("print(f'{y} world, x={x}, new_var={new_var}')", is_single_line=False)
200
]
201
202
for cmd in commands:
203
result = interpreter.add_exec(cmd)
204
if result is not None:
205
print(f">>> {cmd.text}")
206
print(f"Result: {result}")
207
else:
208
print(f">>> {cmd.text}")
209
print("Executed")
210
211
interpreter.close()
212
213
# Run the example
214
debug_function()
215
```
216
217
### Advanced Console Integration
218
219
```python
220
import sys
221
import threading
222
from pydevconsole import StdIn, CodeFragment
223
224
# Example of integrating with existing application
225
class DebugConsoleManager:
226
def __init__(self):
227
self.original_stdin = sys.stdin
228
self.debug_stdin = None
229
self.console_thread = None
230
self.active = False
231
232
def start_console(self, encoding='utf-8'):
233
"""Start debug console with custom stdin handling."""
234
self.debug_stdin = StdIn(self.original_stdin, encoding)
235
sys.stdin = self.debug_stdin
236
self.active = True
237
238
# Start console thread
239
self.console_thread = threading.Thread(target=self._console_loop)
240
self.console_thread.daemon = True
241
self.console_thread.start()
242
243
def stop_console(self):
244
"""Stop debug console and restore stdin."""
245
self.active = False
246
if self.console_thread:
247
self.console_thread.join(timeout=1.0)
248
249
if self.debug_stdin:
250
self.debug_stdin.close()
251
252
sys.stdin = self.original_stdin
253
254
def _console_loop(self):
255
"""Console input loop (simplified example)."""
256
while self.active:
257
try:
258
line = sys.stdin.readline()
259
if not line or line.strip() == 'quit':
260
break
261
262
# Create and process command
263
fragment = CodeFragment(line.strip(), is_single_line=True)
264
print(f"Processing: {fragment.text}")
265
266
except EOFError:
267
break
268
except Exception as e:
269
print(f"Console error: {e}")
270
271
# Usage example
272
console_manager = DebugConsoleManager()
273
274
try:
275
console_manager.start_console()
276
277
# Simulate application running
278
import time
279
print("Debug console started. Type commands or 'quit' to exit.")
280
281
# In real scenario, application would continue running
282
time.sleep(10)
283
284
finally:
285
console_manager.stop_console()
286
print("Debug console stopped.")
287
```
288
289
## Implementation Notes
290
291
- **Thread Safety**: Console operations must be thread-safe for multi-threaded debugging
292
- **Encoding Handling**: Proper encoding support for international characters in console input
293
- **Frame Context**: Commands execute in the context of suspended debugging frames
294
- **Exception Handling**: Robust error handling for console command execution
295
- **Integration**: Designed to integrate with IDE debugging interfaces and protocols