@@ -4,9 +4,12 @@ import * as path from 'path';
4
4
import { DebugSession , OutputEvent } from 'vscode-debugadapter' ;
5
5
import { DebugProtocol } from 'vscode-debugprotocol' ;
6
6
import { open } from '../../common/open' ;
7
+ import { PathUtils } from '../../common/platform/pathUtils' ;
8
+ import { EnvironmentVariablesService } from '../../common/variables/environment' ;
9
+ import { EnvironmentVariables } from '../../common/variables/types' ;
7
10
import { IDebugServer , IPythonProcess } from '../Common/Contracts' ;
8
11
import { LaunchRequestArguments } from '../Common/Contracts' ;
9
- import { getCustomEnvVars } from '../Common/Utils' ;
12
+ import { IS_WINDOWS } from '../Common/Utils' ;
10
13
import { BaseDebugServer } from '../DebugServers/BaseDebugServer' ;
11
14
import { LocalDebugServer } from '../DebugServers/LocalDebugServer' ;
12
15
import { DebugClient , DebugType } from './DebugClient' ;
@@ -17,10 +20,25 @@ const VALID_DEBUG_OPTIONS = [
17
20
'BreakOnSystemExitZero' ,
18
21
'DjangoDebugging' ] ;
19
22
23
+ enum DebugServerStatus {
24
+ Unknown = 1 ,
25
+ Running = 2 ,
26
+ NotRunning = 3
27
+ }
28
+
20
29
export class LocalDebugClient extends DebugClient {
21
- protected pyProc : child_process . ChildProcess ;
30
+ protected pyProc : child_process . ChildProcess | undefined ;
22
31
protected pythonProcess : IPythonProcess ;
23
- protected debugServer : BaseDebugServer ;
32
+ protected debugServer : BaseDebugServer | undefined ;
33
+ private get debugServerStatus ( ) : DebugServerStatus {
34
+ if ( this . debugServer && this . debugServer ! . IsRunning ) {
35
+ return DebugServerStatus . Running ;
36
+ }
37
+ if ( this . debugServer && ! this . debugServer ! . IsRunning ) {
38
+ return DebugServerStatus . NotRunning ;
39
+ }
40
+ return DebugServerStatus . Unknown ;
41
+ }
24
42
// tslint:disable-next-line:no-any
25
43
constructor ( args : any , debugSession : DebugSession , private canLaunchTerminal : boolean ) {
26
44
super ( args , debugSession ) ;
@@ -38,24 +56,24 @@ export class LocalDebugClient extends DebugClient {
38
56
39
57
public Stop ( ) {
40
58
if ( this . debugServer ) {
41
- this . debugServer . Stop ( ) ;
42
- this . debugServer = null ;
59
+ this . debugServer ! . Stop ( ) ;
60
+ this . debugServer = undefined ;
43
61
}
44
62
45
63
if ( this . pyProc ) {
46
64
try {
47
- this . pyProc . send ( 'EXIT' ) ;
65
+ this . pyProc ! . send ( 'EXIT' ) ;
48
66
// tslint:disable-next-line:no-empty
49
67
} catch { }
50
68
try {
51
- this . pyProc . stdin . write ( 'EXIT' ) ;
69
+ this . pyProc ! . stdin . write ( 'EXIT' ) ;
52
70
// tslint:disable-next-line:no-empty
53
71
} catch { }
54
72
try {
55
- this . pyProc . disconnect ( ) ;
73
+ this . pyProc ! . disconnect ( ) ;
56
74
// tslint:disable-next-line:no-empty
57
75
} catch { }
58
- this . pyProc = null ;
76
+ this . pyProc = undefined ;
59
77
}
60
78
}
61
79
protected getLauncherFilePath ( ) : string {
@@ -71,7 +89,8 @@ export class LocalDebugClient extends DebugClient {
71
89
}
72
90
}
73
91
// tslint:disable-next-line:max-func-body-length member-ordering no-any
74
- public LaunchApplicationToDebug ( dbgServer : IDebugServer , processErrored : ( error : any ) => void ) : Promise < any > {
92
+ public async LaunchApplicationToDebug ( dbgServer : IDebugServer , processErrored : ( error : any ) => void ) : Promise < any > {
93
+ const environmentVariables = await this . getEnvironmentVariables ( ) ;
75
94
// tslint:disable-next-line:max-func-body-length cyclomatic-complexity no-any
76
95
return new Promise < any > ( ( resolve , reject ) => {
77
96
const fileDir = this . args && this . args . program ? path . dirname ( this . args . program ) : '' ;
@@ -83,8 +102,6 @@ export class LocalDebugClient extends DebugClient {
83
102
if ( typeof this . args . pythonPath === 'string' && this . args . pythonPath . trim ( ) . length > 0 ) {
84
103
pythonPath = this . args . pythonPath ;
85
104
}
86
- let environmentVariables = getCustomEnvVars ( this . args . env , this . args . envFile , false ) ;
87
- environmentVariables = environmentVariables ? environmentVariables : { } ;
88
105
if ( ! environmentVariables . hasOwnProperty ( 'PYTHONIOENCODING' ) ) {
89
106
environmentVariables . PYTHONIOENCODING = 'UTF-8' ;
90
107
}
@@ -103,12 +120,16 @@ export class LocalDebugClient extends DebugClient {
103
120
break ;
104
121
}
105
122
default : {
123
+ // As we're spawning the process, we need to ensure all env variables are passed.
124
+ // Including those from the current process (i.e. everything, not just custom vars).
125
+ const envParser = new EnvironmentVariablesService ( new PathUtils ( IS_WINDOWS ) ) ;
126
+ envParser . mergeVariables ( process . env as EnvironmentVariables , environmentVariables ) ;
106
127
this . pyProc = child_process . spawn ( pythonPath , args , { cwd : processCwd , env : environmentVariables } ) ;
107
- this . handleProcessOutput ( this . pyProc , reject ) ;
128
+ this . handleProcessOutput ( this . pyProc ! , reject ) ;
108
129
109
130
// Here we wait for the application to connect to the socket server.
110
131
// Only once connected do we know that the application has successfully launched.
111
- this . debugServer . DebugClientConnected
132
+ this . debugServer ! . DebugClientConnected
112
133
. then ( resolve )
113
134
. catch ( ex => console . error ( 'Python Extension: debugServer.DebugClientConnected' , ex ) ) ;
114
135
}
@@ -120,10 +141,11 @@ export class LocalDebugClient extends DebugClient {
120
141
proc . on ( 'error' , error => {
121
142
// If debug server has started, then don't display errors.
122
143
// The debug adapter will get this info from the debugger (e.g. ptvsd lib).
123
- if ( ! this . debugServer && this . debugServer . IsRunning ) {
144
+ const status = this . debugServerStatus ;
145
+ if ( status === DebugServerStatus . Running ) {
124
146
return ;
125
147
}
126
- if ( ! this . debugServer . IsRunning && typeof ( error ) === 'object' && error !== null ) {
148
+ if ( status === DebugServerStatus . NotRunning && typeof ( error ) === 'object' && error !== null ) {
127
149
return failedToLaunch ( error ) ;
128
150
}
129
151
// This could happen when the debugger didn't launch at all, e.g. python doesn't exist.
@@ -136,13 +158,14 @@ export class LocalDebugClient extends DebugClient {
136
158
137
159
// Either way, we need some code in here so we read the stdout of the python process,
138
160
// Else it just keep building up (related to issue #203 and #52).
139
- if ( this . debugServer && ! this . debugServer . IsRunning ) {
161
+ if ( this . debugServerStatus === DebugServerStatus . NotRunning ) {
140
162
return failedToLaunch ( error ) ;
141
163
}
142
164
} ) ;
143
165
proc . stdout . on ( 'data' , d => {
144
166
// This is necessary so we read the stdout of the python process,
145
167
// Else it just keep building up (related to issue #203 and #52).
168
+ // tslint:disable-next-line:prefer-const no-unused-variable
146
169
let x = 0 ;
147
170
} ) ;
148
171
}
@@ -193,12 +216,32 @@ export class LocalDebugClient extends DebugClient {
193
216
this . pyProc = proc ;
194
217
resolve ( ) ;
195
218
} , error => {
196
- if ( ! this . debugServer && this . debugServer . IsRunning ) {
219
+ if ( this . debugServerStatus === DebugServerStatus . Running ) {
197
220
return ;
198
221
}
199
222
reject ( error ) ;
200
223
} ) ;
201
224
}
202
225
} ) ;
203
226
}
227
+ private async getEnvironmentVariables ( ) : Promise < EnvironmentVariables > {
228
+ const args = this . args as LaunchRequestArguments ;
229
+ const envParser = new EnvironmentVariablesService ( new PathUtils ( IS_WINDOWS ) ) ;
230
+ const envFileVars = await envParser . parseFile ( args . envFile ) ;
231
+
232
+ const hasEnvVars = args . env && Object . keys ( args . env ) . length > 0 ;
233
+ if ( ! envFileVars && ! hasEnvVars ) {
234
+ return { } ;
235
+ }
236
+ if ( envFileVars && ! hasEnvVars ) {
237
+ return envFileVars ! ;
238
+ }
239
+ if ( ! envFileVars && hasEnvVars ) {
240
+ return args . env as EnvironmentVariables ;
241
+ }
242
+ // Merge the two sets of environment variables.
243
+ const env = { ...args . env } as EnvironmentVariables ;
244
+ envParser . mergeVariables ( envFileVars ! , env ) ;
245
+ return env ;
246
+ }
204
247
}
0 commit comments