@@ -3109,6 +3109,14 @@ def kill_process(pid):
3109
3109
3110
3110
@support .requires_subprocess ()
3111
3111
class SpawnTests (unittest .TestCase ):
3112
+ @staticmethod
3113
+ def quote_args (args ):
3114
+ # On Windows, os.spawn* simply joins arguments with spaces:
3115
+ # arguments need to be quoted
3116
+ if os .name != 'nt' :
3117
+ return args
3118
+ return [f'"{ arg } "' if " " in arg .strip () else arg for arg in args ]
3119
+
3112
3120
def create_args (self , * , with_env = False , use_bytes = False ):
3113
3121
self .exitcode = 17
3114
3122
@@ -3129,115 +3137,118 @@ def create_args(self, *, with_env=False, use_bytes=False):
3129
3137
with open (filename , "w" , encoding = "utf-8" ) as fp :
3130
3138
fp .write (code )
3131
3139
3132
- args = [sys .executable , filename ]
3140
+ program = sys .executable
3141
+ args = self .quote_args ([program , filename ])
3133
3142
if use_bytes :
3143
+ program = os .fsencode (program )
3134
3144
args = [os .fsencode (a ) for a in args ]
3135
3145
self .env = {os .fsencode (k ): os .fsencode (v )
3136
3146
for k , v in self .env .items ()}
3137
3147
3138
- return args
3148
+ return program , args
3139
3149
3140
3150
@requires_os_func ('spawnl' )
3141
3151
def test_spawnl (self ):
3142
- args = self .create_args ()
3143
- exitcode = os .spawnl (os .P_WAIT , args [ 0 ] , * args )
3152
+ program , args = self .create_args ()
3153
+ exitcode = os .spawnl (os .P_WAIT , program , * args )
3144
3154
self .assertEqual (exitcode , self .exitcode )
3145
3155
3146
3156
@requires_os_func ('spawnle' )
3147
3157
def test_spawnle (self ):
3148
- args = self .create_args (with_env = True )
3149
- exitcode = os .spawnle (os .P_WAIT , args [ 0 ] , * args , self .env )
3158
+ program , args = self .create_args (with_env = True )
3159
+ exitcode = os .spawnle (os .P_WAIT , program , * args , self .env )
3150
3160
self .assertEqual (exitcode , self .exitcode )
3151
3161
3152
3162
@requires_os_func ('spawnlp' )
3153
3163
def test_spawnlp (self ):
3154
- args = self .create_args ()
3155
- exitcode = os .spawnlp (os .P_WAIT , args [ 0 ] , * args )
3164
+ program , args = self .create_args ()
3165
+ exitcode = os .spawnlp (os .P_WAIT , program , * args )
3156
3166
self .assertEqual (exitcode , self .exitcode )
3157
3167
3158
3168
@requires_os_func ('spawnlpe' )
3159
3169
def test_spawnlpe (self ):
3160
- args = self .create_args (with_env = True )
3161
- exitcode = os .spawnlpe (os .P_WAIT , args [ 0 ] , * args , self .env )
3170
+ program , args = self .create_args (with_env = True )
3171
+ exitcode = os .spawnlpe (os .P_WAIT , program , * args , self .env )
3162
3172
self .assertEqual (exitcode , self .exitcode )
3163
3173
3164
3174
@requires_os_func ('spawnv' )
3165
3175
def test_spawnv (self ):
3166
- args = self .create_args ()
3167
- exitcode = os .spawnv (os .P_WAIT , args [ 0 ] , args )
3176
+ program , args = self .create_args ()
3177
+ exitcode = os .spawnv (os .P_WAIT , program , args )
3168
3178
self .assertEqual (exitcode , self .exitcode )
3169
3179
3170
3180
# Test for PyUnicode_FSConverter()
3171
- exitcode = os .spawnv (os .P_WAIT , FakePath (args [ 0 ] ), args )
3181
+ exitcode = os .spawnv (os .P_WAIT , FakePath (program ), args )
3172
3182
self .assertEqual (exitcode , self .exitcode )
3173
3183
3174
3184
@requires_os_func ('spawnve' )
3175
3185
def test_spawnve (self ):
3176
- args = self .create_args (with_env = True )
3177
- exitcode = os .spawnve (os .P_WAIT , args [ 0 ] , args , self .env )
3186
+ program , args = self .create_args (with_env = True )
3187
+ exitcode = os .spawnve (os .P_WAIT , program , args , self .env )
3178
3188
self .assertEqual (exitcode , self .exitcode )
3179
3189
3180
3190
@requires_os_func ('spawnvp' )
3181
3191
def test_spawnvp (self ):
3182
- args = self .create_args ()
3183
- exitcode = os .spawnvp (os .P_WAIT , args [ 0 ] , args )
3192
+ program , args = self .create_args ()
3193
+ exitcode = os .spawnvp (os .P_WAIT , program , args )
3184
3194
self .assertEqual (exitcode , self .exitcode )
3185
3195
3186
3196
@requires_os_func ('spawnvpe' )
3187
3197
def test_spawnvpe (self ):
3188
- args = self .create_args (with_env = True )
3189
- exitcode = os .spawnvpe (os .P_WAIT , args [ 0 ] , args , self .env )
3198
+ program , args = self .create_args (with_env = True )
3199
+ exitcode = os .spawnvpe (os .P_WAIT , program , args , self .env )
3190
3200
self .assertEqual (exitcode , self .exitcode )
3191
3201
3192
3202
@requires_os_func ('spawnv' )
3193
3203
def test_nowait (self ):
3194
- args = self .create_args ()
3195
- pid = os .spawnv (os .P_NOWAIT , args [ 0 ] , args )
3204
+ program , args = self .create_args ()
3205
+ pid = os .spawnv (os .P_NOWAIT , program , args )
3196
3206
support .wait_process (pid , exitcode = self .exitcode )
3197
3207
3198
3208
@requires_os_func ('spawnve' )
3199
3209
def test_spawnve_bytes (self ):
3200
3210
# Test bytes handling in parse_arglist and parse_envlist (#28114)
3201
- args = self .create_args (with_env = True , use_bytes = True )
3202
- exitcode = os .spawnve (os .P_WAIT , args [ 0 ] , args , self .env )
3211
+ program , args = self .create_args (with_env = True , use_bytes = True )
3212
+ exitcode = os .spawnve (os .P_WAIT , program , args , self .env )
3203
3213
self .assertEqual (exitcode , self .exitcode )
3204
3214
3205
3215
@requires_os_func ('spawnl' )
3206
3216
def test_spawnl_noargs (self ):
3207
- args = self .create_args ()
3208
- self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , args [ 0 ] )
3209
- self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , args [ 0 ] , '' )
3217
+ program , __ = self .create_args ()
3218
+ self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , program )
3219
+ self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , program , '' )
3210
3220
3211
3221
@requires_os_func ('spawnle' )
3212
3222
def test_spawnle_noargs (self ):
3213
- args = self .create_args ()
3214
- self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , args [ 0 ] , {})
3215
- self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , args [ 0 ] , '' , {})
3223
+ program , __ = self .create_args ()
3224
+ self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , program , {})
3225
+ self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , program , '' , {})
3216
3226
3217
3227
@requires_os_func ('spawnv' )
3218
3228
def test_spawnv_noargs (self ):
3219
- args = self .create_args ()
3220
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ())
3221
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , [])
3222
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ('' ,))
3223
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ['' ])
3229
+ program , __ = self .create_args ()
3230
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ())
3231
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , [])
3232
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ('' ,))
3233
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ['' ])
3224
3234
3225
3235
@requires_os_func ('spawnve' )
3226
3236
def test_spawnve_noargs (self ):
3227
- args = self .create_args ()
3228
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , (), {})
3229
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , [], {})
3230
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , ('' ,), {})
3231
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , ['' ], {})
3237
+ program , __ = self .create_args ()
3238
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , (), {})
3239
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , [], {})
3240
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , ('' ,), {})
3241
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , ['' ], {})
3232
3242
3233
3243
def _test_invalid_env (self , spawn ):
3234
- args = [sys .executable , '-c' , 'pass' ]
3244
+ program = sys .executable
3245
+ args = self .quote_args ([program , '-c' , 'pass' ])
3235
3246
3236
3247
# null character in the environment variable name
3237
3248
newenv = os .environ .copy ()
3238
3249
newenv ["FRUIT\0 VEGETABLE" ] = "cabbage"
3239
3250
try :
3240
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3251
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3241
3252
except ValueError :
3242
3253
pass
3243
3254
else :
@@ -3247,7 +3258,7 @@ def _test_invalid_env(self, spawn):
3247
3258
newenv = os .environ .copy ()
3248
3259
newenv ["FRUIT" ] = "orange\0 VEGETABLE=cabbage"
3249
3260
try :
3250
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3261
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3251
3262
except ValueError :
3252
3263
pass
3253
3264
else :
@@ -3257,7 +3268,7 @@ def _test_invalid_env(self, spawn):
3257
3268
newenv = os .environ .copy ()
3258
3269
newenv ["FRUIT=ORANGE" ] = "lemon"
3259
3270
try :
3260
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3271
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3261
3272
except ValueError :
3262
3273
pass
3263
3274
else :
@@ -3270,10 +3281,11 @@ def _test_invalid_env(self, spawn):
3270
3281
fp .write ('import sys, os\n '
3271
3282
'if os.getenv("FRUIT") != "orange=lemon":\n '
3272
3283
' raise AssertionError' )
3273
- args = [sys .executable , filename ]
3284
+
3285
+ args = self .quote_args ([program , filename ])
3274
3286
newenv = os .environ .copy ()
3275
3287
newenv ["FRUIT" ] = "orange=lemon"
3276
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3288
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3277
3289
self .assertEqual (exitcode , 0 )
3278
3290
3279
3291
@requires_os_func ('spawnve' )
0 commit comments