@@ -3214,6 +3214,14 @@ def kill_process(pid):
32143214
32153215@support .requires_subprocess ()
32163216class 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+
32173225 def create_args (self , * , with_env = False , use_bytes = False ):
32183226 self .exitcode = 17
32193227
@@ -3234,115 +3242,118 @@ def create_args(self, *, with_env=False, use_bytes=False):
32343242 with open (filename , "w" , encoding = "utf-8" ) as fp :
32353243 fp .write (code )
32363244
3237- args = [sys .executable , filename ]
3245+ program = sys .executable
3246+ args = self .quote_args ([program , filename ])
32383247 if use_bytes :
3248+ program = os .fsencode (program )
32393249 args = [os .fsencode (a ) for a in args ]
32403250 self .env = {os .fsencode (k ): os .fsencode (v )
32413251 for k , v in self .env .items ()}
32423252
3243- return args
3253+ return program , args
32443254
32453255 @requires_os_func ('spawnl' )
32463256 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 )
32493259 self .assertEqual (exitcode , self .exitcode )
32503260
32513261 @requires_os_func ('spawnle' )
32523262 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 )
32553265 self .assertEqual (exitcode , self .exitcode )
32563266
32573267 @requires_os_func ('spawnlp' )
32583268 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 )
32613271 self .assertEqual (exitcode , self .exitcode )
32623272
32633273 @requires_os_func ('spawnlpe' )
32643274 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 )
32673277 self .assertEqual (exitcode , self .exitcode )
32683278
32693279 @requires_os_func ('spawnv' )
32703280 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 )
32733283 self .assertEqual (exitcode , self .exitcode )
32743284
32753285 # 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 )
32773287 self .assertEqual (exitcode , self .exitcode )
32783288
32793289 @requires_os_func ('spawnve' )
32803290 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 )
32833293 self .assertEqual (exitcode , self .exitcode )
32843294
32853295 @requires_os_func ('spawnvp' )
32863296 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 )
32893299 self .assertEqual (exitcode , self .exitcode )
32903300
32913301 @requires_os_func ('spawnvpe' )
32923302 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 )
32953305 self .assertEqual (exitcode , self .exitcode )
32963306
32973307 @requires_os_func ('spawnv' )
32983308 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 )
33013311 support .wait_process (pid , exitcode = self .exitcode )
33023312
33033313 @requires_os_func ('spawnve' )
33043314 def test_spawnve_bytes (self ):
33053315 # 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 )
33083318 self .assertEqual (exitcode , self .exitcode )
33093319
33103320 @requires_os_func ('spawnl' )
33113321 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 , '' )
33153325
33163326 @requires_os_func ('spawnle' )
33173327 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 , '' , {})
33213331
33223332 @requires_os_func ('spawnv' )
33233333 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 , ['' ])
33293339
33303340 @requires_os_func ('spawnve' )
33313341 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 , ['' ], {})
33373347
33383348 def _test_invalid_env (self , spawn ):
3339- args = [sys .executable , '-c' , 'pass' ]
3349+ program = sys .executable
3350+ args = self .quote_args ([program , '-c' , 'pass' ])
33403351
33413352 # null character in the environment variable name
33423353 newenv = os .environ .copy ()
33433354 newenv ["FRUIT\0 VEGETABLE" ] = "cabbage"
33443355 try :
3345- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3356+ exitcode = spawn (os .P_WAIT , program , args , newenv )
33463357 except ValueError :
33473358 pass
33483359 else :
@@ -3352,7 +3363,7 @@ def _test_invalid_env(self, spawn):
33523363 newenv = os .environ .copy ()
33533364 newenv ["FRUIT" ] = "orange\0 VEGETABLE=cabbage"
33543365 try :
3355- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3366+ exitcode = spawn (os .P_WAIT , program , args , newenv )
33563367 except ValueError :
33573368 pass
33583369 else :
@@ -3362,7 +3373,7 @@ def _test_invalid_env(self, spawn):
33623373 newenv = os .environ .copy ()
33633374 newenv ["FRUIT=ORANGE" ] = "lemon"
33643375 try :
3365- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3376+ exitcode = spawn (os .P_WAIT , program , args , newenv )
33663377 except ValueError :
33673378 pass
33683379 else :
@@ -3375,10 +3386,11 @@ def _test_invalid_env(self, spawn):
33753386 fp .write ('import sys, os\n '
33763387 'if os.getenv("FRUIT") != "orange=lemon":\n '
33773388 ' raise AssertionError' )
3378- args = [sys .executable , filename ]
3389+
3390+ args = self .quote_args ([program , filename ])
33793391 newenv = os .environ .copy ()
33803392 newenv ["FRUIT" ] = "orange=lemon"
3381- exitcode = spawn (os .P_WAIT , args [ 0 ] , args , newenv )
3393+ exitcode = spawn (os .P_WAIT , program , args , newenv )
33823394 self .assertEqual (exitcode , 0 )
33833395
33843396 @requires_os_func ('spawnve' )
0 commit comments