@@ -3214,6 +3214,14 @@ def kill_process(pid):
3214
3214
3215
3215
@support .requires_subprocess ()
3216
3216
class SpawnTests (unittest .TestCase ):
3217
+ @staticmethod
3218
+ def quote_args (args ):
3219
+ # On Windows, os.spawn* simply joins arguments with spaces:
3220
+ # arguments need to be quoted
3221
+ if os .name != 'nt' :
3222
+ return args
3223
+ return [f'"{ arg } "' if " " in arg .strip () else arg for arg in args ]
3224
+
3217
3225
def create_args (self , * , with_env = False , use_bytes = False ):
3218
3226
self .exitcode = 17
3219
3227
@@ -3234,115 +3242,118 @@ def create_args(self, *, with_env=False, use_bytes=False):
3234
3242
with open (filename , "w" , encoding = "utf-8" ) as fp :
3235
3243
fp .write (code )
3236
3244
3237
- args = [sys .executable , filename ]
3245
+ program = sys .executable
3246
+ args = self .quote_args ([program , filename ])
3238
3247
if use_bytes :
3248
+ program = os .fsencode (program )
3239
3249
args = [os .fsencode (a ) for a in args ]
3240
3250
self .env = {os .fsencode (k ): os .fsencode (v )
3241
3251
for k , v in self .env .items ()}
3242
3252
3243
- return args
3253
+ return program , args
3244
3254
3245
3255
@requires_os_func ('spawnl' )
3246
3256
def test_spawnl (self ):
3247
- args = self .create_args ()
3248
- exitcode = os .spawnl (os .P_WAIT , args [ 0 ] , * args )
3257
+ program , args = self .create_args ()
3258
+ exitcode = os .spawnl (os .P_WAIT , program , * args )
3249
3259
self .assertEqual (exitcode , self .exitcode )
3250
3260
3251
3261
@requires_os_func ('spawnle' )
3252
3262
def test_spawnle (self ):
3253
- args = self .create_args (with_env = True )
3254
- exitcode = os .spawnle (os .P_WAIT , args [ 0 ] , * args , self .env )
3263
+ program , args = self .create_args (with_env = True )
3264
+ exitcode = os .spawnle (os .P_WAIT , program , * args , self .env )
3255
3265
self .assertEqual (exitcode , self .exitcode )
3256
3266
3257
3267
@requires_os_func ('spawnlp' )
3258
3268
def test_spawnlp (self ):
3259
- args = self .create_args ()
3260
- exitcode = os .spawnlp (os .P_WAIT , args [ 0 ] , * args )
3269
+ program , args = self .create_args ()
3270
+ exitcode = os .spawnlp (os .P_WAIT , program , * args )
3261
3271
self .assertEqual (exitcode , self .exitcode )
3262
3272
3263
3273
@requires_os_func ('spawnlpe' )
3264
3274
def test_spawnlpe (self ):
3265
- args = self .create_args (with_env = True )
3266
- exitcode = os .spawnlpe (os .P_WAIT , args [ 0 ] , * args , self .env )
3275
+ program , args = self .create_args (with_env = True )
3276
+ exitcode = os .spawnlpe (os .P_WAIT , program , * args , self .env )
3267
3277
self .assertEqual (exitcode , self .exitcode )
3268
3278
3269
3279
@requires_os_func ('spawnv' )
3270
3280
def test_spawnv (self ):
3271
- args = self .create_args ()
3272
- exitcode = os .spawnv (os .P_WAIT , args [ 0 ] , args )
3281
+ program , args = self .create_args ()
3282
+ exitcode = os .spawnv (os .P_WAIT , program , args )
3273
3283
self .assertEqual (exitcode , self .exitcode )
3274
3284
3275
3285
# Test for PyUnicode_FSConverter()
3276
- exitcode = os .spawnv (os .P_WAIT , FakePath (args [ 0 ] ), args )
3286
+ exitcode = os .spawnv (os .P_WAIT , FakePath (program ), args )
3277
3287
self .assertEqual (exitcode , self .exitcode )
3278
3288
3279
3289
@requires_os_func ('spawnve' )
3280
3290
def test_spawnve (self ):
3281
- args = self .create_args (with_env = True )
3282
- exitcode = os .spawnve (os .P_WAIT , args [ 0 ] , args , self .env )
3291
+ program , args = self .create_args (with_env = True )
3292
+ exitcode = os .spawnve (os .P_WAIT , program , args , self .env )
3283
3293
self .assertEqual (exitcode , self .exitcode )
3284
3294
3285
3295
@requires_os_func ('spawnvp' )
3286
3296
def test_spawnvp (self ):
3287
- args = self .create_args ()
3288
- exitcode = os .spawnvp (os .P_WAIT , args [ 0 ] , args )
3297
+ program , args = self .create_args ()
3298
+ exitcode = os .spawnvp (os .P_WAIT , program , args )
3289
3299
self .assertEqual (exitcode , self .exitcode )
3290
3300
3291
3301
@requires_os_func ('spawnvpe' )
3292
3302
def test_spawnvpe (self ):
3293
- args = self .create_args (with_env = True )
3294
- exitcode = os .spawnvpe (os .P_WAIT , args [ 0 ] , args , self .env )
3303
+ program , args = self .create_args (with_env = True )
3304
+ exitcode = os .spawnvpe (os .P_WAIT , program , args , self .env )
3295
3305
self .assertEqual (exitcode , self .exitcode )
3296
3306
3297
3307
@requires_os_func ('spawnv' )
3298
3308
def test_nowait (self ):
3299
- args = self .create_args ()
3300
- pid = os .spawnv (os .P_NOWAIT , args [ 0 ] , args )
3309
+ program , args = self .create_args ()
3310
+ pid = os .spawnv (os .P_NOWAIT , program , args )
3301
3311
support .wait_process (pid , exitcode = self .exitcode )
3302
3312
3303
3313
@requires_os_func ('spawnve' )
3304
3314
def test_spawnve_bytes (self ):
3305
3315
# Test bytes handling in parse_arglist and parse_envlist (#28114)
3306
- args = self .create_args (with_env = True , use_bytes = True )
3307
- exitcode = os .spawnve (os .P_WAIT , args [ 0 ] , args , self .env )
3316
+ program , args = self .create_args (with_env = True , use_bytes = True )
3317
+ exitcode = os .spawnve (os .P_WAIT , program , args , self .env )
3308
3318
self .assertEqual (exitcode , self .exitcode )
3309
3319
3310
3320
@requires_os_func ('spawnl' )
3311
3321
def test_spawnl_noargs (self ):
3312
- args = self .create_args ()
3313
- self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , args [ 0 ] )
3314
- self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , args [ 0 ] , '' )
3322
+ program , __ = self .create_args ()
3323
+ self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , program )
3324
+ self .assertRaises (ValueError , os .spawnl , os .P_NOWAIT , program , '' )
3315
3325
3316
3326
@requires_os_func ('spawnle' )
3317
3327
def test_spawnle_noargs (self ):
3318
- args = self .create_args ()
3319
- self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , args [ 0 ] , {})
3320
- self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , args [ 0 ] , '' , {})
3328
+ program , __ = self .create_args ()
3329
+ self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , program , {})
3330
+ self .assertRaises (ValueError , os .spawnle , os .P_NOWAIT , program , '' , {})
3321
3331
3322
3332
@requires_os_func ('spawnv' )
3323
3333
def test_spawnv_noargs (self ):
3324
- args = self .create_args ()
3325
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ())
3326
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , [])
3327
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ('' ,))
3328
- self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , args [ 0 ] , ['' ])
3334
+ program , __ = self .create_args ()
3335
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ())
3336
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , [])
3337
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ('' ,))
3338
+ self .assertRaises (ValueError , os .spawnv , os .P_NOWAIT , program , ['' ])
3329
3339
3330
3340
@requires_os_func ('spawnve' )
3331
3341
def test_spawnve_noargs (self ):
3332
- args = self .create_args ()
3333
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , (), {})
3334
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , [], {})
3335
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , ('' ,), {})
3336
- self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , args [ 0 ] , ['' ], {})
3342
+ program , __ = self .create_args ()
3343
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , (), {})
3344
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , [], {})
3345
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , ('' ,), {})
3346
+ self .assertRaises (ValueError , os .spawnve , os .P_NOWAIT , program , ['' ], {})
3337
3347
3338
3348
def _test_invalid_env (self , spawn ):
3339
- args = [sys .executable , '-c' , 'pass' ]
3349
+ program = sys .executable
3350
+ args = self .quote_args ([program , '-c' , 'pass' ])
3340
3351
3341
3352
# null character in the environment variable name
3342
3353
newenv = os .environ .copy ()
3343
3354
newenv ["FRUIT\0 VEGETABLE" ] = "cabbage"
3344
3355
try :
3345
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3356
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3346
3357
except ValueError :
3347
3358
pass
3348
3359
else :
@@ -3352,7 +3363,7 @@ def _test_invalid_env(self, spawn):
3352
3363
newenv = os .environ .copy ()
3353
3364
newenv ["FRUIT" ] = "orange\0 VEGETABLE=cabbage"
3354
3365
try :
3355
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3366
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3356
3367
except ValueError :
3357
3368
pass
3358
3369
else :
@@ -3362,7 +3373,7 @@ def _test_invalid_env(self, spawn):
3362
3373
newenv = os .environ .copy ()
3363
3374
newenv ["FRUIT=ORANGE" ] = "lemon"
3364
3375
try :
3365
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3376
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3366
3377
except ValueError :
3367
3378
pass
3368
3379
else :
@@ -3375,10 +3386,11 @@ def _test_invalid_env(self, spawn):
3375
3386
fp .write ('import sys, os\n '
3376
3387
'if os.getenv("FRUIT") != "orange=lemon":\n '
3377
3388
' raise AssertionError' )
3378
- args = [sys .executable , filename ]
3389
+
3390
+ args = self .quote_args ([program , filename ])
3379
3391
newenv = os .environ .copy ()
3380
3392
newenv ["FRUIT" ] = "orange=lemon"
3381
- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3393
+ exitcode = spawn (os .P_WAIT , program , args , newenv )
3382
3394
self .assertEqual (exitcode , 0 )
3383
3395
3384
3396
@requires_os_func ('spawnve' )
0 commit comments