Skip to content

Commit 6104e12

Browse files
committed
Django debugging, more options for debugging, partial work on remote debugging
1 parent 4667a49 commit 6104e12

32 files changed

Lines changed: 866 additions & 2661 deletions

.vscode/launch.json

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,8 @@
2828
"request": "launch",
2929
"runtimeArgs": [
3030
"--harmony"
31-
],
32-
"program": "${workspaceRoot}/out/client/debugger/vs/PythonDebugger.js",
33-
"stopOnEntry": false,
34-
"args": [
35-
"--server=4711"
36-
],
37-
"sourceMaps": true,
38-
"outDir": "${workspaceRoot}/out/client"
39-
},
40-
{
41-
"name": "Attach to python_django debug server",
42-
"type": "node",
43-
"request": "launch",
44-
"runtimeArgs": [
45-
"--harmony"
46-
],
47-
"program": "${workspaceRoot}/out/client/debugger/vs/DjangoDebugger.js",
48-
"stopOnEntry": false,
49-
"args": [
50-
"--server=4711"
51-
],
52-
"sourceMaps": true,
53-
"outDir": "${workspaceRoot}/out/client"
54-
},
55-
{
56-
"name": "Attach to old vs debug server",
57-
"type": "node",
58-
"request": "launch",
59-
"runtimeArgs": [
60-
"--harmony"
61-
],
62-
"program": "${workspaceRoot}/out/client/debugger/vs/VSDebugger.js",
31+
],
32+
"program": "${workspaceRoot}/out/client/debugger/Main.js",
6333
"stopOnEntry": false,
6434
"args": [
6535
"--server=4711"

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Works on both Windows and Mac.
1616

1717
## Issues and Feature Requests
1818
[Github Issues](https://github.com/DonJayamanne/pythonVSCode/issues)
19-
* Remote Debugging (coming soon)
19+
* Remote Debugging (in development)
20+
* Debugging Django applications (in development)
2021

2122
## Feature Details (with confiuration)
2223
* IDE Features
@@ -98,9 +99,12 @@ Works on both Windows and Mac.
9899

99100
## Change Log
100101

101-
### Version 0.2.4
102-
* Introduced experimental debugging of django (debugging templates not supported)
102+
### Version 0.2.5
103103
* Added support for optionally breaking into python code as soon as debugger starts
104+
* Added support for conditional break points
105+
* Fixed debugging when current thread if busy processing.
106+
* Added ability to display the shell window (command window in PC and Terminal window in Mac)
107+
* - Useful in accepting input from applications being debugged.
104108

105109
### Version 0.2.4
106110
* Fixed issue where debugger would break into all exceptions

package.json

Lines changed: 93 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"theme": "dark"
2020
},
2121
"engines": {
22-
"vscode": "^0.10.1"
22+
"vscode": "^0.10.8"
2323
},
2424
"categories": [
2525
"Languages",
@@ -60,7 +60,7 @@
6060
"python"
6161
]
6262
},
63-
"program": "./out/client/debugger/vs/PythonDebugger.js",
63+
"program": "./out/client/debugger/main.js",
6464
"runtime": "node",
6565
"configurationAttributes": {
6666
"launch": {
@@ -70,76 +70,85 @@
7070
"properties": {
7171
"program": {
7272
"type": "string",
73-
"description": "Workspace relative path to a text file.",
74-
"default": "${workspaceRoot}/__init__.py"
73+
"description": "Absolute path to the program.",
74+
"default": "${file}"
7575
},
7676
"pythonPath": {
7777
"type": "string",
78-
"description": "Path (fully qualified) to python executable. Use this if you want to use a custom pthon executable version.",
78+
"description": "Path (fully qualified) to python executable.",
7979
"default": ""
8080
},
8181
"args": {
8282
"type": "array",
83-
"description": "List of arguments for the program",
83+
"description": "Command line arguments passed to the program",
8484
"default": []
8585
},
8686
"stopOnEntry": {
8787
"type": "boolean",
8888
"description": "Automatically stop after launch.",
8989
"default": true
90+
},
91+
"externalConsole": {
92+
"type": "boolean",
93+
"description": "Launch debug target in external console window.",
94+
"default": false
95+
},
96+
"cwd": {
97+
"type": "string",
98+
"description": "Absolute path to the working directory of the program being debugged. Default is the root directory of the file (leave null).",
99+
"default": null
100+
},
101+
"debugOptions": {
102+
"type": "array",
103+
"description": "Advanced options, view read me for further details.",
104+
"items": {
105+
"type": "string",
106+
"enum": [
107+
"WaitOnAbnormalExit",
108+
"WaitOnNormalExit",
109+
"RedirectOutput",
110+
"DjangoDebugging",
111+
"DebugStdLib",
112+
"BreakOnSystemExitZero"
113+
]
114+
},
115+
"default": [
116+
"WaitOnAbnormalExit",
117+
"WaitOnNormalExit",
118+
"RedirectOutput"
119+
]
90120
}
91121
}
92-
}
93-
},
94-
"initialConfigurations": [
95-
{
96-
"name": "Python",
97-
"type": "python",
98-
"request": "launch",
99-
"stopOnEntry": true,
100-
"program": "${workspaceRoot}/__init__.py"
101-
}
102-
]
103-
},
104-
{
105-
"type": "python_django",
106-
"label": "Django",
107-
"enableBreakpointsFor": {
108-
"languageIds": [
109-
"python"
110-
]
111-
},
112-
"program": "./out/client/debugger/vs/vsDebugger.js",
113-
"runtime": "node",
114-
"configurationAttributes": {
115-
"launch": {
122+
},
123+
"attach": {
116124
"required": [
117-
"program"
125+
"localRoot",
126+
"remoteRoot"
118127
],
119128
"properties": {
120-
"program": {
129+
"localRoot": {
121130
"type": "string",
122-
"description": "Workspace relative path to a text file.",
123-
"default": "${workspaceRoot}/manage.py"
131+
"description": "Local source root that corrresponds to the 'remoteRoot'.",
132+
"default": "${workspaceRoot}"
124133
},
125-
"pythonPath": {
134+
"remoteRoot": {
126135
"type": "string",
127-
"description": "Path (fully qualified) to python executable. Use this if you want to use a custom pthon executable version.",
128-
"default": ""
136+
"description": "The source root of the remote host.",
137+
"default": null
129138
},
130139
"port": {
131140
"type": "number",
132-
"description": "Port number, leave empty or 0 for dyanamic generation of ports.",
133-
"default": 0
141+
"description": "Debug port to attach",
142+
"default": null
134143
},
135-
"noReload": {
136-
"type": "boolean",
137-
"description": "Whether not to reload.",
144+
"url": {
145+
"type": "string",
146+
"description": "Url of remote server.",
138147
"default": true
139148
},
140-
"settings": {
149+
"secret": {
141150
"type": "string",
142-
"description": "Settings",
151+
"description": "Secret used to authenticate for remote debugging.",
143152
"default": ""
144153
}
145154
}
@@ -150,10 +159,43 @@
150159
"name": "Python",
151160
"type": "python",
152161
"request": "launch",
162+
"stopOnEntry": true,
163+
"program": "${file}",
164+
"debugOptions": [
165+
"WaitOnAbnormalExit",
166+
"WaitOnNormalExit",
167+
"RedirectOutput"
168+
]
169+
},
170+
{
171+
"name": "Python Console App",
172+
"type": "python",
173+
"request": "launch",
174+
"pythonPath": "c:/python27/python.exe",
175+
"stopOnEntry": true,
176+
"program": "${file}",
177+
"externalConsole": true,
178+
"debugOptions": [
179+
"WaitOnAbnormalExit",
180+
"WaitOnNormalExit"
181+
]
182+
},
183+
{
184+
"name": "Django",
185+
"type": "python",
186+
"request": "launch",
153187
"program": "${workspaceRoot}/manage.py",
154-
"port": 5002,
155-
"noReload": true,
156-
"settings": ""
188+
"args": [
189+
"runserver",
190+
"--noreload",
191+
5002
192+
],
193+
"debugOptions": [
194+
"WaitOnAbnormalExit",
195+
"WaitOnNormalExit",
196+
"RedirectOutput",
197+
"DjangoDebugging"
198+
]
157199
}
158200
]
159201
}
@@ -316,7 +358,8 @@
316358
},
317359
"scripts": {
318360
"vscode:prepublish": "node ./node_modules/vscode/bin/compile",
319-
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./ && installServerIntoExtension ./out ./src/server/package.json ./src/server/tsconfig.json"
361+
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./ && installServerIntoExtension ./out ./src/server/package.json ./src/server/tsconfig.json",
362+
"postinstall": "node ./node_modules/vscode/bin/install"
320363
},
321364
"dependencies": {
322365
"line-by-line": "^0.1.4",
@@ -329,7 +372,7 @@
329372
"vscode-languageserver": "^1.1.0"
330373
},
331374
"devDependencies": {
332-
"typescript": "^1.6.2",
333-
"vscode": "0.10.x"
375+
"typescript": "^1.7.5",
376+
"vscode": "^0.11.0"
334377
}
335378
}

pythonFiles/PythonTools/visualstudio_py_debugger.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,12 @@ def line_locations(self):
646646
line_info = []
647647
file_len = 0
648648
for line in contents:
649+
line_len = len(line)
649650
if not line_info and line.startswith(BOM_UTF8):
650-
line = line[3:] # Strip the BOM, Django seems to ignore this...
651-
file_len += len(line)
651+
line_len -= len(BOM_UTF8) # Strip the BOM, Django seems to ignore this...
652+
if line.endswith(to_bytes('\r\n')):
653+
line_len -= 1 # Django normalizes newlines to \n
654+
file_len += line_len
652655
line_info.append(file_len)
653656
contents.close()
654657
self._line_locations = line_info
@@ -679,10 +682,26 @@ def should_break(self, start, end):
679682
def get_django_frame_source(frame):
680683
if frame.f_code.co_name == 'render':
681684
self_obj = frame.f_locals.get('self', None)
682-
if self_obj is not None and type(self_obj).__name__ != 'TextNode':
683-
source_obj = getattr(self_obj, 'source', None)
684-
if source_obj is not None:
685-
return source_obj
685+
if self_obj is None:
686+
return None
687+
name = type(self_obj).__name__
688+
if name in ('Template', 'TextNode'):
689+
return None
690+
source_obj = getattr(self_obj, 'source', None)
691+
if source_obj and hasattr(source_obj, '__len__') and len(source_obj) == 2:
692+
return str(source_obj[0]), source_obj[1]
693+
694+
token_obj = getattr(self_obj, 'token', None)
695+
if token_obj is None:
696+
return None
697+
template_obj = getattr(frame.f_locals.get('context', None), 'template', None)
698+
if template_obj is None:
699+
return None
700+
template_name = getattr(template_obj, 'origin', None)
701+
position = getattr(token_obj, 'position', None)
702+
if template_name and position:
703+
return str(template_name), position
704+
686705

687706
return None
688707

@@ -883,8 +902,8 @@ def handle_call(self, frame, arg):
883902
source_obj = get_django_frame_source(frame)
884903
if source_obj is not None:
885904
origin, (start, end) = source_obj
886-
887-
active_bps = DJANGO_BREAKPOINTS.get(origin.name.lower())
905+
906+
active_bps = DJANGO_BREAKPOINTS.get(origin.lower())
888907
should_break = False
889908
if active_bps is not None:
890909
should_break, bkpt_id = active_bps.should_break(start, end)

src/client/debugger/vs/Common/Contracts.ts renamed to src/client/debugger/Common/Contracts.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,48 @@
11
'use strict';
2+
import * as net from 'net';
3+
import {DebugProtocol} from 'vscode-debugprotocol';
4+
5+
export const DjangoApp = "DJANGO";
6+
export enum DebugFlags {
7+
None = 0,
8+
IgnoreCommandBursts = 1
9+
}
10+
11+
export class DebugOptions {
12+
public static get WaitOnAbnormalExit(): string { return "WaitOnAbnormalExit"; }
13+
public static get WaitOnNormalExit(): string { return "WaitOnNormalExit"; }
14+
public static get RedirectOutput(): string { return "RedirectOutput"; }
15+
public static get DjangoDebugging(): string { return "DjangoDebugging"; }
16+
public static get DebugStdLib(): string { return "DebugStdLib"; }
17+
public static get BreakOnSystemExitZero(): string { return "BreakOnSystemExitZero"; }
18+
}
19+
export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
20+
/** An absolute path to the program to debug. */
21+
program: string;
22+
pythonPath: string;
23+
/** Automatically stop target after launch. If not specified, target does not stop. */
24+
stopOnEntry?: boolean;
25+
args: string[];
26+
applicationType?: string;
27+
externalConsole?: boolean;
28+
cwd?: string;
29+
debugOptions?: string[];
30+
}
31+
//
32+
// export interface LaunchDjangoRequestArguments extends LaunchRequestArguments {
33+
// port?: number;
34+
// noReload?: boolean;
35+
// settings?: string;
36+
// }
37+
38+
export interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
39+
/** An absolute path to local directory with source. */
40+
localRoot: string;
41+
remoteRoot: string;
42+
port?: number;
43+
url?: string;
44+
secret?: string;
45+
}
246

347
export interface IDebugServer {
448
port: number;
@@ -35,8 +79,11 @@ export enum PythonEvaluationResultFlags {
3579
}
3680

3781
export interface IPythonProcess extends NodeJS.EventEmitter {
82+
Connect(buffer: Buffer, socket: net.Socket, isRemoteProcess: boolean);
83+
HandleIncomingData(buffer: Buffer);
84+
Detach();
3885
SendStepInto(threadId: number);
39-
SendStepOver(threadId: number): Promise<IPythonThread>;
86+
SendStepOver(threadId: number);
4087
SendStepOut(threadId: number);
4188
SendResumeThread(threadId: number);
4289
AutoResumeThread(threadId: number);
File renamed without changes.

0 commit comments

Comments
 (0)