3232import subprocess
3333import sys
3434import tempfile
35+ import time
3536import urllib .parse
3637import warnings
3738from collections .abc import Callable
@@ -1387,7 +1388,15 @@ def _create_venv_from_clone(
13871388 # Avoid hard dependency for environments where this is never used.
13881389 import clonevirtualenv
13891390 clonable_venv = cls ._create_venv_to_clone (base_python )
1390- clonevirtualenv .clone_virtualenv (clonable_venv , venv )
1391+ for attempt in range (3 ):
1392+ try :
1393+ clonevirtualenv .clone_virtualenv (clonable_venv , venv )
1394+ break
1395+ except shutil .Error :
1396+ if attempt == 2 :
1397+ raise
1398+ shutil .rmtree (venv , ignore_errors = True )
1399+ time .sleep (1 )
13911400 venv_pip = os .path .join (venv , 'bin' , 'pip' )
13921401 # Issue warning when installing packages from PyPI
13931402 _LOGGER .warning (
@@ -1412,13 +1421,7 @@ def _create_venv_from_clone(
14121421
14131422 @classmethod
14141423 def _create_venv_to_clone (cls , base_python : str ) -> str :
1415- # For '.dev', the default clone source is the venv that owns base_python.
1416- # In CI that is often the active tox/sandbox tree; clonevirtualenv can
1417- # race with ephemeral paths (tmp/, caches) under that tree. Use the
1418- # scratch clonable venv in CI instead. Locally, keep cloning the dev venv
1419- # for speed.
1420- _ci = os .environ .get ('CI' , '' ).lower () in ('true' , '1' , 'yes' )
1421- if '.dev' in beam_version and not _ci :
1424+ if '.dev' in beam_version :
14221425 base_venv = os .path .dirname (os .path .dirname (base_python ))
14231426 print ('Cloning dev environment from' , base_venv )
14241427 return base_venv
0 commit comments